155 lines
5.0 KiB
Dart
155 lines
5.0 KiB
Dart
import 'package:autosos_flutter/provider/providers.dart';
|
||
import 'package:autosos_flutter/util/toast.dart';
|
||
import 'package:autosos_flutter/widget/qr_image.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||
import 'package:fluwx/fluwx.dart';
|
||
|
||
/// 充值页(对应 Android RechargeActivity)
|
||
class RechargePage extends ConsumerStatefulWidget {
|
||
const RechargePage({super.key});
|
||
|
||
@override
|
||
ConsumerState<RechargePage> createState() => _RechargePageState();
|
||
}
|
||
|
||
class _RechargePageState extends ConsumerState<RechargePage> {
|
||
final _amount = TextEditingController();
|
||
String _payMethod = 'wx';
|
||
String? _qrUrl;
|
||
bool _loading = false;
|
||
|
||
final _presets = [50.0, 100.0, 200.0, 500.0, 1000.0, 2000.0];
|
||
|
||
@override
|
||
void dispose() {
|
||
_amount.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
Future<void> _submit() async {
|
||
final amount = double.tryParse(_amount.text.trim());
|
||
if (amount == null || amount <= 0) {
|
||
Toast.error('请输入充值金额');
|
||
return;
|
||
}
|
||
setState(() => _loading = true);
|
||
EasyLoading.show(status: '生成订单中…');
|
||
try {
|
||
final r = await ref.read(userApiProvider).recharge(
|
||
amount: amount,
|
||
payMethod: _payMethod,
|
||
);
|
||
EasyLoading.dismiss();
|
||
if (!r.isSuccess || r.data == null) {
|
||
Toast.error(r.message ?? '下单失败');
|
||
return;
|
||
}
|
||
// 微信支付(带 sign 的预支付)
|
||
if (_payMethod == 'wx' && r.data is Map) {
|
||
final m = r.data as Map;
|
||
await Fluwx().pay(
|
||
which: Payment(
|
||
appId: m['appid'] ?? '',
|
||
partnerId: m['partnerid'] ?? '',
|
||
prepayId: m['prepayid'] ?? '',
|
||
packageValue: m['package'] ?? 'Sign=WXPay',
|
||
nonceStr: m['noncestr'] ?? '',
|
||
timestamp: int.tryParse(m['timestamp']?.toString() ?? '') ?? 0,
|
||
sign: m['sign'] ?? '',
|
||
),
|
||
);
|
||
return;
|
||
}
|
||
// 二维码
|
||
if (r.data is Map && (r.data as Map)['qr_code_url'] != null) {
|
||
setState(() => _qrUrl = (r.data as Map)['qr_code_url']);
|
||
} else {
|
||
Toast.success('订单已生成');
|
||
}
|
||
} catch (e) {
|
||
EasyLoading.dismiss();
|
||
Toast.error('充值失败:$e');
|
||
} finally {
|
||
if (mounted) setState(() => _loading = false);
|
||
}
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
appBar: AppBar(title: const Text('充值')),
|
||
body: SingleChildScrollView(
|
||
padding: const EdgeInsets.all(16),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||
children: [
|
||
const Text('选择充值金额',
|
||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||
const SizedBox(height: 8),
|
||
Wrap(
|
||
spacing: 8,
|
||
runSpacing: 8,
|
||
children: _presets
|
||
.map(
|
||
(a) => ChoiceChip(
|
||
label: Text('¥${a.toStringAsFixed(0)}'),
|
||
selected: _amount.text == a.toStringAsFixed(0),
|
||
onSelected: (_) =>
|
||
setState(() => _amount.text = a.toStringAsFixed(0)),
|
||
),
|
||
)
|
||
.toList(),
|
||
),
|
||
const SizedBox(height: 12),
|
||
TextField(
|
||
controller: _amount,
|
||
keyboardType:
|
||
const TextInputType.numberWithOptions(decimal: true),
|
||
inputFormatters: [
|
||
FilteringTextInputFormatter.allow(RegExp(r'[0-9.]')),
|
||
],
|
||
decoration: const InputDecoration(
|
||
labelText: '其他金额',
|
||
prefixText: '¥ ',
|
||
border: OutlineInputBorder(),
|
||
),
|
||
),
|
||
const SizedBox(height: 16),
|
||
const Text('支付方式',
|
||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||
RadioListTile<String>(
|
||
title: const Text('微信支付'),
|
||
value: 'wx',
|
||
groupValue: _payMethod,
|
||
onChanged: (v) => setState(() => _payMethod = v ?? 'wx'),
|
||
),
|
||
if (_qrUrl != null) ...[
|
||
const SizedBox(height: 16),
|
||
Center(
|
||
child: QrImageView(data: _qrUrl!, size: 200),
|
||
),
|
||
const SizedBox(height: 8),
|
||
const Center(
|
||
child: Text('请使用微信扫码支付',
|
||
style: TextStyle(color: Colors.grey)),
|
||
),
|
||
],
|
||
const SizedBox(height: 24),
|
||
ElevatedButton(
|
||
onPressed: _loading ? null : _submit,
|
||
style: ElevatedButton.styleFrom(
|
||
backgroundColor: Colors.green,
|
||
minimumSize: const Size.fromHeight(48),
|
||
),
|
||
child: Text(_loading ? '处理中…' : '立即充值'),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|