// 功能描述:充值创建前持久化及到账恢复,不将支付拉起视作到账;版本:1.0.0。 import '../repositories/client_repository.dart'; import '../../domain/models/recharge.dart'; import 'recharge_draft_store.dart'; import 'api_client.dart'; /// 单个页面使用一个实例;所有网络写入前确认存储所属账号。 class RechargeFlow { RechargeFlow(this.repository, this.store); final ClientRepository repository; final RechargeDraftStore store; bool _busy = false; Future> create(PendingRecharge draft) async { if (_busy) throw StateError('充值正在处理中'); _busy = true; try { final owner = await repository.rechargeDraftOwner(); final previous = await store.read(owner); if (previous != null && (previous.request != draft.request || previous.amount != draft.amount || previous.channel != draft.channel || previous.payType != draft.payType)) { throw StateError('请先查询待确认充值'); } if (previous != null) { // 重试先读取入账事实,避免到账后再次拉起原支付参数。 try { final result = await repository.rechargeResult(previous.request); if (result.amount != previous.amount || result.channel != previous.channel) { throw StateError('充值结果与原请求不一致'); } if (await repository.rechargeDraftOwner() != owner) throw StateError('充值账户已切换'); if (result.credited) return {'recharge_status': 23}; } on ApiException catch (error) { // 明确不存在才允许使用相同请求重发,网络异常不能推断订单不存在。 if (error.code != 1112) rethrow; } } await store.write(owner, draft); if (await repository.rechargeDraftOwner() != owner) throw StateError('充值账户已切换'); return await repository.createRecharge( request: draft.request, amount: draft.amount, channel: draft.channel, payType: draft.payType, ); } finally { _busy = false; } } /// 未到账、查询失败或业务关联异常均保留原请求,方便再次核对。 Future recover() async { if (_busy) throw StateError('充值正在处理中'); _busy = true; try { final owner = await repository.rechargeDraftOwner(); final draft = await store.read(owner); if (draft == null) return null; if (await repository.rechargeDraftOwner() != owner) throw StateError('充值账户已切换'); final result = await repository.rechargeResult(draft.request); if (result.amount != draft.amount || result.channel != draft.channel) { throw StateError('充值结果与原请求不一致'); } if (await repository.rechargeDraftOwner() != owner) throw StateError('充值账户已切换'); if (result.credited) await store.delete(owner); return result; } finally { _busy = false; } } }