| 1 | enum CakePayPaymentMethod { BTC, BTC_LN, XMR, LTC, LTC_MWEB, ZEC } |
| 2 | |
| 3 | extension CakePayPaymentMethodLabel on CakePayPaymentMethod { |
| 4 | String get label => switch (this) { |
| 5 | CakePayPaymentMethod.BTC => 'Bitcoin', |
| 6 | CakePayPaymentMethod.BTC_LN => 'Lightning', |
| 7 | CakePayPaymentMethod.XMR => 'Monero', |
| 8 | CakePayPaymentMethod.LTC => 'Litecoin', |
| 9 | CakePayPaymentMethod.LTC_MWEB => 'MWEB', |
| 10 | CakePayPaymentMethod.ZEC => 'Zcash', |
| 11 | }; |
| 12 | } |
| 13 | |
| 14 | class CakePayOrder { |
| 15 | final String orderId; |
| 16 | final List<OrderCard> cards; |
| 17 | final String? externalId; |
| 18 | final double amountUsd; |
| 19 | final String totalReceiveAmount; |
| 20 | final int quantity; |
| 21 | final String status; |
| 22 | final String? vouchers; |
| 23 | final String fiatCurrencyCode; |
| 24 | final PaymentData paymentData; |
| 25 | |
| 26 | CakePayOrder({ |
| 27 | required this.orderId, |
| 28 | required this.cards, |
| 29 | required this.externalId, |
| 30 | required this.amountUsd, |
| 31 | required this.totalReceiveAmount, |
| 32 | required this.quantity, |
| 33 | required this.status, |
| 34 | required this.vouchers, |
| 35 | required this.fiatCurrencyCode, |
| 36 | required this.paymentData, |
| 37 | }); |
| 38 | |
| 39 | factory CakePayOrder.fromMap(Map<String, dynamic> map) { |
| 40 | final cards = map['cards'] as List<dynamic>; |
| 41 | final firstCard = cards.isNotEmpty ? cards.first as Map<String, dynamic> : {}; |
| 42 | |
| 43 | return CakePayOrder( |
| 44 | orderId: map['order_id'] as String, |
| 45 | cards: cards.map((x) => OrderCard.fromMap(x as Map<String, dynamic>)).toList(), |
| 46 | externalId: map['external_id'] as String?, |
| 47 | amountUsd: map['amount_usd'] as double, |
| 48 | totalReceiveAmount: firstCard['subtotal'] as String? ?? '', |
| 49 | quantity: firstCard['quantity'] as int, |
| 50 | status: map['status'] as String, |
| 51 | vouchers: map['vouchers'] as String?, |
| 52 | fiatCurrencyCode: firstCard['currency_code'] as String? ?? '', |
| 53 | paymentData: PaymentData.fromMap(map['payment_data'] as Map<String, dynamic>)); |
| 54 | } |
| 55 | |
| 56 | static CryptoPaymentData? getPaymentDataFor({CakePayPaymentMethod? method, CakePayOrder? order}) { |
| 57 | if (order == null || method == null) return null; |
| 58 | |
| 59 | final data = switch (method) { |
| 60 | CakePayPaymentMethod.BTC => order.paymentData.btc, |
| 61 | CakePayPaymentMethod.XMR => order.paymentData.xmr, |
| 62 | CakePayPaymentMethod.LTC => order.paymentData.ltc, |
| 63 | CakePayPaymentMethod.LTC_MWEB => order.paymentData.ltc_mweb, |
| 64 | CakePayPaymentMethod.ZEC => order.paymentData.zec, |
| 65 | CakePayPaymentMethod.BTC_LN => order.paymentData.btc_ln, |
| 66 | }; |
| 67 | |
| 68 | if (data == null) return null; |
| 69 | |
| 70 | final bip21 = data.paymentUrls?.bip21; |
| 71 | if (bip21 != null && bip21.isNotEmpty) { |
| 72 | final uri = Uri.parse(bip21); |
| 73 | final addr = uri.path; |
| 74 | final price = uri.queryParameters['amount'] ?? data.price; |
| 75 | |
| 76 | return CryptoPaymentData( |
| 77 | price: price, address: addr, amount: data.amount, paymentUrls: data.paymentUrls); |
| 78 | } |
| 79 | |
| 80 | return data; |
| 81 | } |
| 82 | |
| 83 | static String getCurrencyCodeFromPaymentMethod(CakePayPaymentMethod method) { |
| 84 | return switch (method) { |
| 85 | CakePayPaymentMethod.BTC => 'BTC', |
| 86 | CakePayPaymentMethod.BTC_LN => 'BTC', |
| 87 | CakePayPaymentMethod.XMR => 'XMR', |
| 88 | CakePayPaymentMethod.LTC => 'LTC', |
| 89 | CakePayPaymentMethod.LTC_MWEB => 'LTC', |
| 90 | CakePayPaymentMethod.ZEC => 'ZEC', |
| 91 | }; |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | class OrderCard { |
| 96 | final int cardId; |
| 97 | final int? externalId; |
| 98 | final String price; |
| 99 | final int quantity; |
| 100 | final String currencyCode; |
| 101 | final String? cardName; |
| 102 | final String? cardImagePath; |
| 103 | |
| 104 | OrderCard({ |
| 105 | required this.cardId, |
| 106 | required this.externalId, |
| 107 | required this.price, |
| 108 | required this.quantity, |
| 109 | required this.currencyCode, |
| 110 | required this.cardName, |
| 111 | required this.cardImagePath, |
| 112 | }); |
| 113 | |
| 114 | factory OrderCard.fromMap(Map<String, dynamic> map) { |
| 115 | return OrderCard( |
| 116 | cardId: map['card_id'] as int, |
| 117 | externalId: map['external_id'] as int?, |
| 118 | price: map['price'] as String, |
| 119 | quantity: map['quantity'] as int, |
| 120 | currencyCode: map['currency_code'] as String, |
| 121 | cardName: map['name'] as String?, |
| 122 | cardImagePath: map['card_image_url'] as String?, |
| 123 | ); |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | class PaymentData { |
| 128 | final CryptoPaymentData? btc; |
| 129 | final CryptoPaymentData? btc_ln; |
| 130 | final CryptoPaymentData? xmr; |
| 131 | final CryptoPaymentData? ltc; |
| 132 | final CryptoPaymentData? ltc_mweb; |
| 133 | final CryptoPaymentData? zec; |
| 134 | final DateTime invoiceTime; |
| 135 | final DateTime expirationTime; |
| 136 | final int? commission; |
| 137 | |
| 138 | PaymentData({ |
| 139 | required this.btc, |
| 140 | required this.btc_ln, |
| 141 | required this.xmr, |
| 142 | required this.ltc, |
| 143 | required this.ltc_mweb, |
| 144 | required this.zec, |
| 145 | required this.invoiceTime, |
| 146 | required this.expirationTime, |
| 147 | required this.commission, |
| 148 | }); |
| 149 | |
| 150 | factory PaymentData.fromMap(Map<String, dynamic> map) { |
| 151 | return PaymentData( |
| 152 | btc: |
| 153 | map['BTC'] != null ? CryptoPaymentData.fromMap(map['BTC'] as Map<String, dynamic>) : null, |
| 154 | btc_ln: map['BTC_LN'] != null |
| 155 | ? CryptoPaymentData.fromMap(map['BTC_LN'] as Map<String, dynamic>) |
| 156 | : null, |
| 157 | xmr: |
| 158 | map['XMR'] != null ? CryptoPaymentData.fromMap(map['XMR'] as Map<String, dynamic>) : null, |
| 159 | ltc: |
| 160 | map['LTC'] != null ? CryptoPaymentData.fromMap(map['LTC'] as Map<String, dynamic>) : null, |
| 161 | ltc_mweb: map['LTC_MWEB'] != null |
| 162 | ? CryptoPaymentData.fromMap(map['LTC_MWEB'] as Map<String, dynamic>) |
| 163 | : null, |
| 164 | zec: map['ZEC_CHAIN'] != null |
| 165 | ? CryptoPaymentData.fromMap(map['ZEC_CHAIN'] as Map<String, dynamic>) |
| 166 | : null, |
| 167 | invoiceTime: DateTime.fromMillisecondsSinceEpoch(map['invoice_time'] as int), |
| 168 | expirationTime: DateTime.fromMillisecondsSinceEpoch(map['expiration_time'] as int), |
| 169 | commission: map['commission'] as int?, |
| 170 | ); |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | class CryptoPaymentData { |
| 175 | final String price; |
| 176 | final String amount; |
| 177 | final PaymentUrl? paymentUrls; |
| 178 | final String address; |
| 179 | |
| 180 | CryptoPaymentData({ |
| 181 | required this.price, |
| 182 | required this.amount, |
| 183 | this.paymentUrls, |
| 184 | required this.address, |
| 185 | }); |
| 186 | |
| 187 | factory CryptoPaymentData.fromMap(Map<String, dynamic> map) { |
| 188 | return CryptoPaymentData( |
| 189 | price: map['price'] as String, |
| 190 | amount: (map['amount_from'] as double?)?.toString() ?? '', |
| 191 | paymentUrls: PaymentUrl.fromMap(map['paymentUrls'] as Map<String, dynamic>?), |
| 192 | address: map['address'] as String, |
| 193 | ); |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | class PaymentUrl { |
| 198 | final String? bip21; |
| 199 | final String? bip72; |
| 200 | final String? bip72b; |
| 201 | final String? bip73; |
| 202 | final String? bolt11; |
| 203 | |
| 204 | PaymentUrl({ |
| 205 | this.bip21, |
| 206 | this.bip72, |
| 207 | this.bip72b, |
| 208 | this.bip73, |
| 209 | this.bolt11, |
| 210 | }); |
| 211 | |
| 212 | factory PaymentUrl.fromMap(Map<String, dynamic>? map) { |
| 213 | return PaymentUrl( |
| 214 | bip21: map?['BIP21'] as String?, |
| 215 | bip72: map?['BIP72'] as String?, |
| 216 | bip72b: map?['BIP72b'] as String?, |
| 217 | bip73: map?['BIP73'] as String?, |
| 218 | bolt11: map?['BOLT11'] as String?, |
| 219 | ); |
| 220 | } |
| 221 | } |