// 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 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 payload; final DateTime? expiresAt; factory PaySession.fromJson(Map j) => PaySession( renderType: j['render_type'] as String? ?? '', payload: (j['payload'] as Map?) ?? 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 j) => PayOrder( orderNo: j['order_no'] as String, session: PaySession.fromJson((j['session'] as Map?) ?? 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 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), ); }