75 lines
3.0 KiB
Dart
75 lines
3.0 KiB
Dart
// 功能描述:充值创建前持久化及到账恢复,不将支付拉起视作到账;版本: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;
|
||
}
|
||
}
|
||
}
|