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;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|