This commit is contained in:
macbook_max
2026-10-15 20:36:59 +08:00
commit 6bf949949c
7923 changed files with 1369582 additions and 0 deletions
+225
View File
@@ -0,0 +1,225 @@
import '../core/network/api_client.dart';
import '../core/network/endpoints.dart';
/// 充值套餐档位(《03-接口文档》8.1,后台实时可配,前端不硬编码)
class RechargePackage {
const RechargePackage({
required this.id,
required this.amountYuan,
required this.points,
this.bonus = 0,
});
final int id;
final int amountYuan;
final int points;
/// 赠送积分(角标「赠 x 积分」)
final int bonus;
/// 到账总积分 = 基础 + 赠送
int get totalPoints => points + bonus;
factory RechargePackage.fromJson(Map<String, dynamic> json) =>
RechargePackage(
id: (json['id'] as num).toInt(),
amountYuan: (json['amount_yuan'] as num).toInt(),
points: (json['points'] as num).toInt(),
bonus: (json['bonus'] as num?)?.toInt() ?? 0,
);
}
/// 自定义金额配置
class CustomRechargeConfig {
const CustomRechargeConfig({
this.enabled = false,
this.minYuan = 1,
this.maxYuan = 10000,
this.pointsPerYuan = 10,
});
final bool enabled;
final int minYuan;
final int maxYuan;
final int pointsPerYuan;
bool inRange(int yuan) => yuan >= minYuan && yuan <= maxYuan;
factory CustomRechargeConfig.fromJson(Map<String, dynamic> json) =>
CustomRechargeConfig(
enabled: json['enabled'] as bool? ?? false,
minYuan: (json['min_yuan'] as num?)?.toInt() ?? 1,
maxYuan: (json['max_yuan'] as num?)?.toInt() ?? 10000,
pointsPerYuan: (json['points_per_yuan'] as num?)?.toInt() ?? 10,
);
}
/// 支付方式(1支付宝 2微信 3USDT)
class PayMethod {
const PayMethod({required this.method, required this.name});
final int method;
final String name;
bool get isUsdt => method == 3;
factory PayMethod.fromJson(Map<String, dynamic> json) => PayMethod(
method: (json['method'] as num).toInt(),
name: json['name'] as String,
);
}
/// 8.1 套餐列表响应
class PackagesResult {
const PackagesResult({
this.packages = const [],
this.custom = const CustomRechargeConfig(),
this.payMethods = const [],
this.usdtRate = 0,
});
final List<RechargePackage> packages;
final CustomRechargeConfig custom;
final List<PayMethod> payMethods;
final double usdtRate;
factory PackagesResult.fromJson(Map<String, dynamic> json) => PackagesResult(
packages: ((json['packages'] as List?) ?? const [])
.whereType<Map<String, dynamic>>()
.map(RechargePackage.fromJson)
.toList(),
custom: CustomRechargeConfig.fromJson(
(json['custom'] as Map<String, dynamic>?) ?? const {},
),
payMethods: ((json['pay_methods'] as List?) ?? const [])
.whereType<Map<String, dynamic>>()
.map(PayMethod.fromJson)
.toList(),
usdtRate: (json['usdt_rate'] as num?)?.toDouble() ?? 0,
);
}
/// 8.2 创建充值订单响应
/// 支付宝/微信:pay_params 供 SDK 调起;USDT:地址 + 金额(含尾差)+ 网络
class RechargeOrderInfo {
const RechargeOrderInfo({
required this.orderNo,
required this.payMethod,
required this.amountYuan,
required this.points,
this.expireAt = '',
this.payParams = const {},
this.usdtRate,
this.usdtAmount,
this.receiveAddress,
this.network,
});
final String orderNo;
final int payMethod;
final int amountYuan;
final int points;
final String expireAt;
/// 支付宝 order_string / 微信 appid+prepayid 等
final Map<String, dynamic> payParams;
final double? usdtRate;
final String? usdtAmount;
final String? receiveAddress;
final String? network;
bool get isUsdt => payMethod == 3;
factory RechargeOrderInfo.fromJson(Map<String, dynamic> json) =>
RechargeOrderInfo(
orderNo: json['order_no'] as String,
payMethod: (json['pay_method'] as num).toInt(),
amountYuan: (json['amount_yuan'] as num).toInt(),
points: (json['points'] as num).toInt(),
expireAt: (json['expire_at'] as String?) ?? '',
payParams:
(json['pay_params'] as Map<String, dynamic>?) ?? const {},
usdtRate: (json['usdt_rate'] as num?)?.toDouble(),
usdtAmount: json['usdt_amount'] as String?,
receiveAddress: json['receive_address'] as String?,
network: json['network'] as String?,
);
}
/// 8.3 查询订单响应(App 轮询用)
class OrderStatusInfo {
const OrderStatusInfo({
required this.orderNo,
required this.status,
this.statusText = '',
this.points = 0,
this.paidAt,
this.walletPoints = 0,
});
final String orderNo;
/// 0待支付 1已支付 2已关闭 3已退款
final int status;
final String statusText;
final int points;
final String? paidAt;
/// 查单时服务端附带的当前钱包积分
final int walletPoints;
bool get isPending => status == 0;
bool get isPaid => status == 1;
factory OrderStatusInfo.fromJson(Map<String, dynamic> json) =>
OrderStatusInfo(
orderNo: json['order_no'] as String,
status: (json['status'] as num).toInt(),
statusText: (json['status_text'] as String?) ?? '',
points: (json['points'] as num?)?.toInt() ?? 0,
paidAt: json['paid_at'] as String?,
walletPoints: (json['wallet_points'] as num?)?.toInt() ?? 0,
);
}
/// 支付服务(《03-接口文档》第 8 章,均需登录)
class PaymentService {
PaymentService._();
/// 8.1 充值套餐列表
static Future<PackagesResult> fetchPackages() async {
final data =
await ApiClient.get<Map<String, dynamic>>(Endpoints.payPackages);
return PackagesResult.fromJson(data);
}
/// 8.2 创建充值订单
/// 错误码:1001 金额不在可选档位
static Future<RechargeOrderInfo> createRecharge({
required int amountYuan,
required int payMethod,
}) async {
final data = await ApiClient.post<Map<String, dynamic>>(
Endpoints.recharge,
data: {'amount_yuan': amountYuan, 'pay_method': payMethod},
);
return RechargeOrderInfo.fromJson(data);
}
/// 8.3 查询订单状态
/// 错误码:3001 订单不存在
static Future<OrderStatusInfo> fetchOrder(String orderNo) async {
final data = await ApiClient.get<Map<String, dynamic>>(
Endpoints.orderDetail(orderNo),
);
return OrderStatusInfo.fromJson(data);
}
/// 8.4 取消订单(仅待支付可取消)
/// 错误码:3001 订单不存在,3002 订单状态异常
static Future<void> cancelOrder(String orderNo) async {
await ApiClient.post<Map<String, dynamic>>(
Endpoints.orderCancel(orderNo),
);
}
}