已完成用户APP首期功能开发
交付用户端首期页面、配套接口、后台资源及测试文档。用户APP构建、静态分析和三个管理后台构建通过;完整测试仍有2项失败,后端模型注释检查未通过,详见交付记录。
This commit is contained in:
74
apps/user_app/lib/data/services/recharge_flow.dart
Normal file
74
apps/user_app/lib/data/services/recharge_flow.dart
Normal file
@@ -0,0 +1,74 @@
|
||||
// 功能描述:充值创建前持久化及到账恢复,不将支付拉起视作到账;版本: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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user