Files
platforms/apps/user_app/lib/data/services/recharge_flow.dart

75 lines
3.0 KiB
Dart
Raw Normal View History

// 功能描述充值创建前持久化及到账恢复不将支付拉起视作到账版本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<Map<String, Object?>> 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<RechargeRecord?> 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;
}
}
}