feat(client): pay 支付领域模型 + PaymentApi + 支付流控制器(轮询 activated)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
// payment.dart — pay v2 支付领域模型(server 代理端点的响应形状)。
|
||||
// 金额只读展示:price_minor 为 CNY 分;crypto 精确金额在 session.payload 里。
|
||||
|
||||
class PayCatalogItem {
|
||||
const PayCatalogItem({
|
||||
required this.sku,
|
||||
required this.plan,
|
||||
required this.days,
|
||||
required this.priceMinor,
|
||||
required this.currency,
|
||||
});
|
||||
|
||||
final String sku;
|
||||
final String plan;
|
||||
final int days;
|
||||
final int priceMinor;
|
||||
final String currency;
|
||||
|
||||
factory PayCatalogItem.fromJson(Map<String, dynamic> j) => PayCatalogItem(
|
||||
sku: j['sku'] as String,
|
||||
plan: j['plan'] as String? ?? 'pro',
|
||||
days: (j['days'] as num?)?.toInt() ?? 0,
|
||||
priceMinor: (j['price_minor'] as num?)?.toInt() ?? 0,
|
||||
currency: j['currency'] as String? ?? 'CNY',
|
||||
);
|
||||
|
||||
String priceLabel() => '¥${(priceMinor / 100).toStringAsFixed(2)}';
|
||||
}
|
||||
|
||||
class PaySession {
|
||||
const PaySession({required this.renderType, required this.payload, this.expiresAt});
|
||||
|
||||
final String renderType; // crypto_address | redirect | qr
|
||||
final Map<String, dynamic> payload;
|
||||
final DateTime? expiresAt;
|
||||
|
||||
factory PaySession.fromJson(Map<String, dynamic> j) => PaySession(
|
||||
renderType: j['render_type'] as String? ?? '',
|
||||
payload: (j['payload'] as Map<String, dynamic>?) ?? const {},
|
||||
expiresAt: j['expires_at'] == null ? null : DateTime.tryParse(j['expires_at'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
class PayOrder {
|
||||
const PayOrder({required this.orderNo, required this.session});
|
||||
|
||||
final String orderNo;
|
||||
final PaySession session;
|
||||
|
||||
factory PayOrder.fromJson(Map<String, dynamic> j) => PayOrder(
|
||||
orderNo: j['order_no'] as String,
|
||||
session: PaySession.fromJson((j['session'] as Map<String, dynamic>?) ?? const {}),
|
||||
);
|
||||
}
|
||||
|
||||
class PayOrderStatus {
|
||||
const PayOrderStatus({
|
||||
required this.orderNo,
|
||||
required this.payStatus,
|
||||
required this.activated,
|
||||
this.expiresAt,
|
||||
});
|
||||
|
||||
final String orderNo;
|
||||
final String payStatus;
|
||||
final bool activated; // server 台账已消费 = 权益已开通(轮询成功判据)
|
||||
final DateTime? expiresAt;
|
||||
|
||||
factory PayOrderStatus.fromJson(Map<String, dynamic> j) => PayOrderStatus(
|
||||
orderNo: j['order_no'] as String? ?? '',
|
||||
payStatus: j['pay_status'] as String? ?? '',
|
||||
activated: j['activated'] as bool? ?? false,
|
||||
expiresAt: j['expires_at'] == null ? null : DateTime.tryParse(j['expires_at'] as String),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user