@quantabit/payment-sdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +21 -0
- package/dist/index.cjs +1502 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.esm.js +1489 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/styles.css.map +1 -0
- package/package.json +69 -0
- package/types/index.d.ts +14 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,1502 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var antd = require('antd');
|
|
5
|
+
var icons = require('@ant-design/icons');
|
|
6
|
+
var sdkConfig = require('@quantabit/sdk-config');
|
|
7
|
+
|
|
8
|
+
function _extends() {
|
|
9
|
+
return _extends = Object.assign ? Object.assign.bind() : function (n) {
|
|
10
|
+
for (var e = 1; e < arguments.length; e++) {
|
|
11
|
+
var t = arguments[e];
|
|
12
|
+
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
|
13
|
+
}
|
|
14
|
+
return n;
|
|
15
|
+
}, _extends.apply(null, arguments);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function PricingCard({
|
|
19
|
+
name,
|
|
20
|
+
price,
|
|
21
|
+
period = '/mo',
|
|
22
|
+
description,
|
|
23
|
+
features = [],
|
|
24
|
+
cta = 'Get Started',
|
|
25
|
+
popular = false,
|
|
26
|
+
onSelect,
|
|
27
|
+
className = ''
|
|
28
|
+
}) {
|
|
29
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
30
|
+
className: `qpay-card ${popular ? 'qpay-popular' : ''} ${className}`,
|
|
31
|
+
style: {
|
|
32
|
+
padding: 28,
|
|
33
|
+
borderRadius: 16,
|
|
34
|
+
border: popular ? '2px solid #3b82f6' : '1px solid #e4e4e7',
|
|
35
|
+
background: '#fff',
|
|
36
|
+
position: 'relative',
|
|
37
|
+
boxShadow: popular ? '0 8px 32px rgba(59,130,246,0.12)' : 'none',
|
|
38
|
+
transition: 'all 0.3s'
|
|
39
|
+
}
|
|
40
|
+
}, popular && /*#__PURE__*/React.createElement("span", {
|
|
41
|
+
style: {
|
|
42
|
+
position: 'absolute',
|
|
43
|
+
top: -12,
|
|
44
|
+
left: '50%',
|
|
45
|
+
transform: 'translateX(-50%)',
|
|
46
|
+
background: '#3b82f6',
|
|
47
|
+
color: '#fff',
|
|
48
|
+
fontSize: 11,
|
|
49
|
+
fontWeight: 700,
|
|
50
|
+
padding: '3px 12px',
|
|
51
|
+
borderRadius: 20
|
|
52
|
+
}
|
|
53
|
+
}, "Most Popular"), /*#__PURE__*/React.createElement("div", {
|
|
54
|
+
style: {
|
|
55
|
+
fontSize: 18,
|
|
56
|
+
fontWeight: 700,
|
|
57
|
+
color: '#18181b'
|
|
58
|
+
}
|
|
59
|
+
}, name), description && /*#__PURE__*/React.createElement("div", {
|
|
60
|
+
style: {
|
|
61
|
+
fontSize: 13,
|
|
62
|
+
color: '#71717a',
|
|
63
|
+
marginTop: 4
|
|
64
|
+
}
|
|
65
|
+
}, description), /*#__PURE__*/React.createElement("div", {
|
|
66
|
+
style: {
|
|
67
|
+
marginTop: 16,
|
|
68
|
+
marginBottom: 16
|
|
69
|
+
}
|
|
70
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
71
|
+
style: {
|
|
72
|
+
fontSize: 36,
|
|
73
|
+
fontWeight: 800,
|
|
74
|
+
color: '#18181b'
|
|
75
|
+
}
|
|
76
|
+
}, price), /*#__PURE__*/React.createElement("span", {
|
|
77
|
+
style: {
|
|
78
|
+
fontSize: 14,
|
|
79
|
+
color: '#a1a1aa'
|
|
80
|
+
}
|
|
81
|
+
}, period)), /*#__PURE__*/React.createElement("ul", {
|
|
82
|
+
style: {
|
|
83
|
+
listStyle: 'none',
|
|
84
|
+
padding: 0,
|
|
85
|
+
margin: '0 0 20px',
|
|
86
|
+
display: 'flex',
|
|
87
|
+
flexDirection: 'column',
|
|
88
|
+
gap: 8
|
|
89
|
+
}
|
|
90
|
+
}, features.map((f, i) => /*#__PURE__*/React.createElement("li", {
|
|
91
|
+
key: i,
|
|
92
|
+
style: {
|
|
93
|
+
display: 'flex',
|
|
94
|
+
alignItems: 'center',
|
|
95
|
+
gap: 8,
|
|
96
|
+
fontSize: 13,
|
|
97
|
+
color: '#3f3f46'
|
|
98
|
+
}
|
|
99
|
+
}, /*#__PURE__*/React.createElement("svg", {
|
|
100
|
+
width: "16",
|
|
101
|
+
height: "16",
|
|
102
|
+
viewBox: "0 0 24 24",
|
|
103
|
+
fill: "none",
|
|
104
|
+
stroke: f.included !== false ? '#22c55e' : '#d4d4d8',
|
|
105
|
+
strokeWidth: "2"
|
|
106
|
+
}, /*#__PURE__*/React.createElement("polyline", {
|
|
107
|
+
points: "20 6 9 17 4 12"
|
|
108
|
+
})), /*#__PURE__*/React.createElement("span", {
|
|
109
|
+
style: {
|
|
110
|
+
opacity: f.included === false ? 0.5 : 1
|
|
111
|
+
}
|
|
112
|
+
}, typeof f === 'string' ? f : f.text)))), /*#__PURE__*/React.createElement("button", {
|
|
113
|
+
onClick: () => onSelect?.(name),
|
|
114
|
+
style: {
|
|
115
|
+
width: '100%',
|
|
116
|
+
padding: '10px',
|
|
117
|
+
borderRadius: 8,
|
|
118
|
+
border: 'none',
|
|
119
|
+
background: popular ? '#3b82f6' : '#18181b',
|
|
120
|
+
color: '#fff',
|
|
121
|
+
fontSize: 14,
|
|
122
|
+
fontWeight: 600,
|
|
123
|
+
cursor: 'pointer',
|
|
124
|
+
transition: 'all 0.2s'
|
|
125
|
+
}
|
|
126
|
+
}, cta));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function PricingTable({
|
|
130
|
+
plans = [],
|
|
131
|
+
onSelect,
|
|
132
|
+
columns = 3,
|
|
133
|
+
className = ''
|
|
134
|
+
}) {
|
|
135
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
136
|
+
className: `qpay-table ${className}`,
|
|
137
|
+
style: {
|
|
138
|
+
display: 'grid',
|
|
139
|
+
gridTemplateColumns: `repeat(${Math.min(columns, plans.length)}, 1fr)`,
|
|
140
|
+
gap: 20,
|
|
141
|
+
alignItems: 'start'
|
|
142
|
+
}
|
|
143
|
+
}, plans.map((plan, i) => /*#__PURE__*/React.createElement(PricingCard, _extends({
|
|
144
|
+
key: plan.name || i
|
|
145
|
+
}, plan, {
|
|
146
|
+
onSelect: onSelect
|
|
147
|
+
}))));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Payment SDK - 国际化 i18n
|
|
152
|
+
*/
|
|
153
|
+
|
|
154
|
+
const SUPPORTED_LANGUAGES = ['en', 'zh', 'ja', 'ko'];
|
|
155
|
+
const messages = {
|
|
156
|
+
zh: {
|
|
157
|
+
'pay.checkout': '结算',
|
|
158
|
+
'pay.total': '合计',
|
|
159
|
+
'pay.subtotal': '小计',
|
|
160
|
+
'pay.orderSummary': '订单明细',
|
|
161
|
+
'pay.discount': '折扣',
|
|
162
|
+
'pay.tax': '税费',
|
|
163
|
+
'pay.processing': '处理中...',
|
|
164
|
+
'pay.proceedToCheckout': '前往支付',
|
|
165
|
+
// 充值相关
|
|
166
|
+
'enterValidAmount': '请输入有效的金额',
|
|
167
|
+
'recharge': '充值',
|
|
168
|
+
'createOrderFailed': '创建订单失败',
|
|
169
|
+
'networkError': '网络错误,请稍后重试',
|
|
170
|
+
'paymentConfirmFailed': '支付确认失败',
|
|
171
|
+
'rechargeSuccessful': '充值成功',
|
|
172
|
+
'rechargeSuccessMsg': '已成功充值 {amount} {currency}',
|
|
173
|
+
'paymentProcessing': '支付处理中',
|
|
174
|
+
'orderNo': '订单号',
|
|
175
|
+
'waitingForPayment': '等待支付...',
|
|
176
|
+
'simulatePaySuccess': '模拟支付成功',
|
|
177
|
+
'rechargeAmount': '充值金额',
|
|
178
|
+
'paymentMethod': '支付方式',
|
|
179
|
+
'confirmRecharge': '确认充值',
|
|
180
|
+
'walletRecharge': '钱包充值',
|
|
181
|
+
// 支付方式
|
|
182
|
+
'method.card': '信用卡/借记卡',
|
|
183
|
+
'method.cardDesc': '支持 Visa, MasterCard 等',
|
|
184
|
+
'method.paypal': 'PayPal',
|
|
185
|
+
'method.paypalDesc': '快速安全的结算方式',
|
|
186
|
+
'method.crypto': '加密货币',
|
|
187
|
+
'methodCrypto': '加密货币',
|
|
188
|
+
'method.cryptoDesc': '使用 Web3 钱包支付',
|
|
189
|
+
'method.alipay': '支付宝',
|
|
190
|
+
'methodAlipay': '支付宝',
|
|
191
|
+
'method.alipayDesc': '支付宝快捷支付',
|
|
192
|
+
'method.wechat': '微信支付',
|
|
193
|
+
'methodWechat': '微信支付',
|
|
194
|
+
'method.wechatDesc': '微信快捷支付',
|
|
195
|
+
'method.apple': 'Apple Pay',
|
|
196
|
+
'method.appleDesc': '苹果设备快捷支付',
|
|
197
|
+
'method.google': 'Google Pay',
|
|
198
|
+
'method.googleDesc': '安卓设备快捷支付',
|
|
199
|
+
'method.selected': '已选择的支付方式'
|
|
200
|
+
},
|
|
201
|
+
en: {
|
|
202
|
+
'pay.checkout': 'Checkout',
|
|
203
|
+
'pay.total': 'Total',
|
|
204
|
+
'pay.subtotal': 'Subtotal',
|
|
205
|
+
'pay.orderSummary': 'Order Summary',
|
|
206
|
+
'pay.discount': 'Discount',
|
|
207
|
+
'pay.tax': 'Tax',
|
|
208
|
+
'pay.processing': 'Processing...',
|
|
209
|
+
'pay.proceedToCheckout': 'Proceed to Checkout',
|
|
210
|
+
// Recharge
|
|
211
|
+
'enterValidAmount': 'Please enter a valid amount',
|
|
212
|
+
'recharge': 'Recharge',
|
|
213
|
+
'createOrderFailed': 'Failed to create order',
|
|
214
|
+
'networkError': 'Network error, please try again',
|
|
215
|
+
'paymentConfirmFailed': 'Failed to confirm payment',
|
|
216
|
+
'rechargeSuccessful': 'Recharge Successful',
|
|
217
|
+
'rechargeSuccessMsg': 'Successfully recharged {amount} {currency}',
|
|
218
|
+
'paymentProcessing': 'Payment Processing',
|
|
219
|
+
'orderNo': 'Order No',
|
|
220
|
+
'waitingForPayment': 'Waiting for payment...',
|
|
221
|
+
'simulatePaySuccess': 'Simulate Payment Success',
|
|
222
|
+
'rechargeAmount': 'Recharge Amount',
|
|
223
|
+
'paymentMethod': 'Payment Method',
|
|
224
|
+
'confirmRecharge': 'Confirm Recharge',
|
|
225
|
+
'walletRecharge': 'Wallet Recharge',
|
|
226
|
+
// Payment Methods
|
|
227
|
+
'method.card': 'Credit Card',
|
|
228
|
+
'method.cardDesc': 'Visa, MasterCard, etc.',
|
|
229
|
+
'method.paypal': 'PayPal',
|
|
230
|
+
'method.paypalDesc': 'Fast & secure checkout',
|
|
231
|
+
'method.crypto': 'Crypto',
|
|
232
|
+
'methodCrypto': 'Crypto',
|
|
233
|
+
'method.cryptoDesc': 'Pay with Web3 wallet',
|
|
234
|
+
'method.alipay': 'Alipay',
|
|
235
|
+
'methodAlipay': 'Alipay',
|
|
236
|
+
'method.alipayDesc': 'Alipay quick pay',
|
|
237
|
+
'method.wechat': 'WeChat Pay',
|
|
238
|
+
'methodWechat': 'WeChat Pay',
|
|
239
|
+
'method.wechatDesc': 'WeChat quick pay',
|
|
240
|
+
'method.apple': 'Apple Pay',
|
|
241
|
+
'method.appleDesc': 'Quick pay on Apple devices',
|
|
242
|
+
'method.google': 'Google Pay',
|
|
243
|
+
'method.googleDesc': 'Quick pay on Android',
|
|
244
|
+
'method.selected': 'Selected payment method'
|
|
245
|
+
},
|
|
246
|
+
ja: {
|
|
247
|
+
'pay.checkout': 'チェックアウト',
|
|
248
|
+
'pay.total': '合計',
|
|
249
|
+
'pay.subtotal': '小計',
|
|
250
|
+
'pay.orderSummary': '注文の概要',
|
|
251
|
+
'pay.discount': '割引',
|
|
252
|
+
'pay.tax': '税金',
|
|
253
|
+
'pay.processing': '処理中...',
|
|
254
|
+
'pay.proceedToCheckout': '支払いに進む',
|
|
255
|
+
// Recharge
|
|
256
|
+
'enterValidAmount': '有効な金額を入力してください',
|
|
257
|
+
'recharge': 'チャージ',
|
|
258
|
+
'createOrderFailed': '注文の作成に失敗しました',
|
|
259
|
+
'networkError': 'ネットワークエラーです。後でもう一度お試しください',
|
|
260
|
+
'paymentConfirmFailed': '支払いの確認に失敗しました',
|
|
261
|
+
'rechargeSuccessful': 'チャージ成功',
|
|
262
|
+
'rechargeSuccessMsg': '{amount} {currency}のチャージに成功しました',
|
|
263
|
+
'paymentProcessing': '支払い処理中',
|
|
264
|
+
'orderNo': '注文番号',
|
|
265
|
+
'waitingForPayment': '支払いを待っています...',
|
|
266
|
+
'simulatePaySuccess': '支払いの成功をシミュレート',
|
|
267
|
+
'rechargeAmount': 'チャージ金額',
|
|
268
|
+
'paymentMethod': '支払い方法',
|
|
269
|
+
'confirmRecharge': 'チャージを確認',
|
|
270
|
+
'walletRecharge': 'ウォレットチャージ',
|
|
271
|
+
// Payment Methods
|
|
272
|
+
'method.card': 'クレジットカード',
|
|
273
|
+
'method.cardDesc': 'Visa、MasterCardなど',
|
|
274
|
+
'method.paypal': 'PayPal',
|
|
275
|
+
'method.paypalDesc': '迅速で安全な支払い',
|
|
276
|
+
'method.crypto': '暗号通貨',
|
|
277
|
+
'methodCrypto': '暗号通貨',
|
|
278
|
+
'method.cryptoDesc': 'Web3ウォレットで支払う',
|
|
279
|
+
'method.alipay': 'Alipay',
|
|
280
|
+
'methodAlipay': 'Alipay',
|
|
281
|
+
'method.alipayDesc': 'Alipayクイックペイ',
|
|
282
|
+
'method.wechat': 'WeChat Pay',
|
|
283
|
+
'methodWechat': 'WeChat Pay',
|
|
284
|
+
'method.wechatDesc': 'WeChatクイックペイ',
|
|
285
|
+
'method.apple': 'Apple Pay',
|
|
286
|
+
'method.appleDesc': 'Appleデバイスでクイックペイ',
|
|
287
|
+
'method.google': 'Google Pay',
|
|
288
|
+
'method.googleDesc': 'Androidデバイスでクイックペイ',
|
|
289
|
+
'method.selected': '選択された支払い方法'
|
|
290
|
+
},
|
|
291
|
+
ko: {
|
|
292
|
+
'pay.checkout': '결제',
|
|
293
|
+
'pay.total': '합계',
|
|
294
|
+
'pay.subtotal': '소계',
|
|
295
|
+
'pay.orderSummary': '주문 요약',
|
|
296
|
+
'pay.discount': '할인',
|
|
297
|
+
'pay.tax': '세금',
|
|
298
|
+
'pay.processing': '처리 중...',
|
|
299
|
+
'pay.proceedToCheckout': '결제 진행',
|
|
300
|
+
// Recharge
|
|
301
|
+
'enterValidAmount': '유효한 금액을 입력하세요',
|
|
302
|
+
'recharge': '충전',
|
|
303
|
+
'createOrderFailed': '주문 생성 실패',
|
|
304
|
+
'networkError': '네트워크 오류, 나중에 다시 시도하세요',
|
|
305
|
+
'paymentConfirmFailed': '결제 확인 실패',
|
|
306
|
+
'rechargeSuccessful': '충전 성공',
|
|
307
|
+
'rechargeSuccessMsg': '{amount} {currency} 충전이 완료되었습니다',
|
|
308
|
+
'paymentProcessing': '결제 처리 중',
|
|
309
|
+
'orderNo': '주문 번호',
|
|
310
|
+
'waitingForPayment': '결제 대기 중...',
|
|
311
|
+
'simulatePaySuccess': '결제 성공 시뮬레이션',
|
|
312
|
+
'rechargeAmount': '충전 금액',
|
|
313
|
+
'paymentMethod': '결제 수단',
|
|
314
|
+
'confirmRecharge': '충전 확인',
|
|
315
|
+
'walletRecharge': '지갑 충전',
|
|
316
|
+
// Payment Methods
|
|
317
|
+
'method.card': '신용카드',
|
|
318
|
+
'method.cardDesc': 'Visa, MasterCard 등',
|
|
319
|
+
'method.paypal': 'PayPal',
|
|
320
|
+
'method.paypalDesc': '빠르고 안전한 결제',
|
|
321
|
+
'method.crypto': '암호화폐',
|
|
322
|
+
'methodCrypto': '암호화폐',
|
|
323
|
+
'method.cryptoDesc': 'Web3 지갑으로 결제',
|
|
324
|
+
'method.alipay': 'Alipay',
|
|
325
|
+
'methodAlipay': 'Alipay',
|
|
326
|
+
'method.alipayDesc': 'Alipay 빠른 결제',
|
|
327
|
+
'method.wechat': 'WeChat Pay',
|
|
328
|
+
'methodWechat': 'WeChat Pay',
|
|
329
|
+
'method.wechatDesc': 'WeChat 빠른 결제',
|
|
330
|
+
'method.apple': 'Apple Pay',
|
|
331
|
+
'method.appleDesc': 'Apple 기기에서 빠른 결제',
|
|
332
|
+
'method.google': 'Google Pay',
|
|
333
|
+
'method.googleDesc': 'Android 기기에서 빠른 결제',
|
|
334
|
+
'method.selected': '선택한 결제 수단'
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
let currentLang = 'zh';
|
|
338
|
+
function setLanguage(l) {
|
|
339
|
+
if (SUPPORTED_LANGUAGES.includes(l)) currentLang = l;
|
|
340
|
+
}
|
|
341
|
+
function getLanguage() {
|
|
342
|
+
return currentLang;
|
|
343
|
+
}
|
|
344
|
+
function t(key, params) {
|
|
345
|
+
const msgs = messages[currentLang] || messages.zh;
|
|
346
|
+
let text = msgs[key] || messages.en[key] || key;
|
|
347
|
+
if (params) {
|
|
348
|
+
Object.keys(params).forEach(k => {
|
|
349
|
+
text = text.replace(new RegExp(`\\{${k}\\}`, 'g'), params[k]);
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
return text;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Payment SDK - PaymentMethodSelector
|
|
357
|
+
* 高品质支付方式选择器
|
|
358
|
+
*/
|
|
359
|
+
function PaymentMethodSelector({
|
|
360
|
+
methods = ['card', 'paypal', 'crypto'],
|
|
361
|
+
value,
|
|
362
|
+
onChange,
|
|
363
|
+
className = ''
|
|
364
|
+
}) {
|
|
365
|
+
const ICONS = {
|
|
366
|
+
card: '💳',
|
|
367
|
+
paypal: '🅿️',
|
|
368
|
+
crypto: '₿',
|
|
369
|
+
alipay: '🔷',
|
|
370
|
+
wechat: '💬',
|
|
371
|
+
apple: '🍎',
|
|
372
|
+
google: 'G'
|
|
373
|
+
};
|
|
374
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
375
|
+
className: `qpay-methods ${className}`,
|
|
376
|
+
style: {
|
|
377
|
+
display: 'flex',
|
|
378
|
+
flexDirection: 'column',
|
|
379
|
+
gap: '16px'
|
|
380
|
+
}
|
|
381
|
+
}, methods.map(key => {
|
|
382
|
+
const icon = ICONS[key] || '💰';
|
|
383
|
+
const label = t(`method.${key}`);
|
|
384
|
+
const desc = t(`method.${key}Desc`) || t('method.selected');
|
|
385
|
+
const active = value === key;
|
|
386
|
+
return /*#__PURE__*/React.createElement("button", {
|
|
387
|
+
key: key,
|
|
388
|
+
onClick: () => onChange?.(key),
|
|
389
|
+
style: {
|
|
390
|
+
display: 'flex',
|
|
391
|
+
alignItems: 'center',
|
|
392
|
+
gap: '16px',
|
|
393
|
+
padding: '20px',
|
|
394
|
+
borderRadius: '24px',
|
|
395
|
+
border: active ? '1px solid rgba(59, 130, 246, 0.8)' : '1px solid rgba(255, 255, 255, 0.4)',
|
|
396
|
+
background: active ? 'rgba(255, 255, 255, 0.85)' : 'rgba(255, 255, 255, 0.6)',
|
|
397
|
+
backdropFilter: 'blur(24px)',
|
|
398
|
+
WebkitBackdropFilter: 'blur(24px)',
|
|
399
|
+
cursor: 'pointer',
|
|
400
|
+
textAlign: 'left',
|
|
401
|
+
transition: 'all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275)',
|
|
402
|
+
boxShadow: active ? '0 15px 35px -5px rgba(59, 130, 246, 0.15), inset 0 0 0 1px rgba(255, 255, 255, 0.8)' : '0 10px 30px -10px rgba(0,0,0,0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.5)',
|
|
403
|
+
outline: 'none'
|
|
404
|
+
},
|
|
405
|
+
onMouseEnter: e => {
|
|
406
|
+
if (!active) {
|
|
407
|
+
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.75)';
|
|
408
|
+
e.currentTarget.style.transform = 'translateY(-2px)';
|
|
409
|
+
e.currentTarget.style.boxShadow = '0 15px 35px -10px rgba(0,0,0,0.08), inset 0 0 0 1px rgba(255, 255, 255, 0.8)';
|
|
410
|
+
}
|
|
411
|
+
},
|
|
412
|
+
onMouseLeave: e => {
|
|
413
|
+
if (!active) {
|
|
414
|
+
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.6)';
|
|
415
|
+
e.currentTarget.style.transform = 'none';
|
|
416
|
+
e.currentTarget.style.boxShadow = '0 10px 30px -10px rgba(0,0,0,0.05), inset 0 0 0 1px rgba(255, 255, 255, 0.5)';
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
420
|
+
style: {
|
|
421
|
+
width: '48px',
|
|
422
|
+
height: '48px',
|
|
423
|
+
borderRadius: '16px',
|
|
424
|
+
background: 'rgba(255, 255, 255, 0.9)',
|
|
425
|
+
display: 'flex',
|
|
426
|
+
alignItems: 'center',
|
|
427
|
+
justifyContent: 'center',
|
|
428
|
+
fontSize: '24px',
|
|
429
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.05)'
|
|
430
|
+
}
|
|
431
|
+
}, icon), /*#__PURE__*/React.createElement("div", {
|
|
432
|
+
style: {
|
|
433
|
+
display: 'flex',
|
|
434
|
+
flexDirection: 'column',
|
|
435
|
+
gap: '4px',
|
|
436
|
+
flex: 1
|
|
437
|
+
}
|
|
438
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
439
|
+
style: {
|
|
440
|
+
fontWeight: active ? 800 : 700,
|
|
441
|
+
color: '#0F172A',
|
|
442
|
+
fontSize: '16px',
|
|
443
|
+
letterSpacing: '-0.01em'
|
|
444
|
+
}
|
|
445
|
+
}, label), /*#__PURE__*/React.createElement("span", {
|
|
446
|
+
style: {
|
|
447
|
+
fontSize: '13px',
|
|
448
|
+
color: '#64748B',
|
|
449
|
+
fontWeight: 500
|
|
450
|
+
}
|
|
451
|
+
}, desc)), /*#__PURE__*/React.createElement("div", {
|
|
452
|
+
style: {
|
|
453
|
+
width: '28px',
|
|
454
|
+
height: '28px',
|
|
455
|
+
borderRadius: '50%',
|
|
456
|
+
border: active ? '8px solid #3B82F6' : '2px solid rgba(148, 163, 184, 0.5)',
|
|
457
|
+
background: '#fff',
|
|
458
|
+
transition: 'all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)',
|
|
459
|
+
marginLeft: 'auto',
|
|
460
|
+
boxShadow: active ? '0 4px 12px rgba(59, 130, 246, 0.3)' : 'none'
|
|
461
|
+
}
|
|
462
|
+
}));
|
|
463
|
+
}));
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function CheckoutSummary({
|
|
467
|
+
items = [],
|
|
468
|
+
subtotal,
|
|
469
|
+
discount,
|
|
470
|
+
tax,
|
|
471
|
+
total,
|
|
472
|
+
currency = '$',
|
|
473
|
+
onCheckout,
|
|
474
|
+
loading = false,
|
|
475
|
+
className = ''
|
|
476
|
+
}) {
|
|
477
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
478
|
+
className: `qpay-summary ${className}`,
|
|
479
|
+
style: {
|
|
480
|
+
padding: 24,
|
|
481
|
+
borderRadius: 16,
|
|
482
|
+
border: '1px solid #e4e4e7',
|
|
483
|
+
background: '#fafafa'
|
|
484
|
+
}
|
|
485
|
+
}, /*#__PURE__*/React.createElement("h3", {
|
|
486
|
+
style: {
|
|
487
|
+
fontSize: 16,
|
|
488
|
+
fontWeight: 700,
|
|
489
|
+
margin: '0 0 16px'
|
|
490
|
+
}
|
|
491
|
+
}, "Order Summary"), /*#__PURE__*/React.createElement("div", {
|
|
492
|
+
style: {
|
|
493
|
+
display: 'flex',
|
|
494
|
+
flexDirection: 'column',
|
|
495
|
+
gap: 8
|
|
496
|
+
}
|
|
497
|
+
}, items.map((item, i) => /*#__PURE__*/React.createElement("div", {
|
|
498
|
+
key: i,
|
|
499
|
+
style: {
|
|
500
|
+
display: 'flex',
|
|
501
|
+
justifyContent: 'space-between',
|
|
502
|
+
fontSize: 13
|
|
503
|
+
}
|
|
504
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
505
|
+
style: {
|
|
506
|
+
color: '#3f3f46'
|
|
507
|
+
}
|
|
508
|
+
}, item.name, item.qty > 1 && ` × ${item.qty}`), /*#__PURE__*/React.createElement("span", {
|
|
509
|
+
style: {
|
|
510
|
+
fontWeight: 500
|
|
511
|
+
}
|
|
512
|
+
}, currency, item.price)))), /*#__PURE__*/React.createElement("div", {
|
|
513
|
+
style: {
|
|
514
|
+
borderTop: '1px solid #e4e4e7',
|
|
515
|
+
marginTop: 12,
|
|
516
|
+
paddingTop: 12,
|
|
517
|
+
display: 'flex',
|
|
518
|
+
flexDirection: 'column',
|
|
519
|
+
gap: 6,
|
|
520
|
+
fontSize: 13
|
|
521
|
+
}
|
|
522
|
+
}, subtotal != null && /*#__PURE__*/React.createElement("div", {
|
|
523
|
+
style: {
|
|
524
|
+
display: 'flex',
|
|
525
|
+
justifyContent: 'space-between'
|
|
526
|
+
}
|
|
527
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
528
|
+
style: {
|
|
529
|
+
color: '#71717a'
|
|
530
|
+
}
|
|
531
|
+
}, "Subtotal"), /*#__PURE__*/React.createElement("span", null, currency, subtotal)), discount != null && /*#__PURE__*/React.createElement("div", {
|
|
532
|
+
style: {
|
|
533
|
+
display: 'flex',
|
|
534
|
+
justifyContent: 'space-between'
|
|
535
|
+
}
|
|
536
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
537
|
+
style: {
|
|
538
|
+
color: '#22c55e'
|
|
539
|
+
}
|
|
540
|
+
}, "Discount"), /*#__PURE__*/React.createElement("span", {
|
|
541
|
+
style: {
|
|
542
|
+
color: '#22c55e'
|
|
543
|
+
}
|
|
544
|
+
}, "-", currency, discount)), tax != null && /*#__PURE__*/React.createElement("div", {
|
|
545
|
+
style: {
|
|
546
|
+
display: 'flex',
|
|
547
|
+
justifyContent: 'space-between'
|
|
548
|
+
}
|
|
549
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
550
|
+
style: {
|
|
551
|
+
color: '#71717a'
|
|
552
|
+
}
|
|
553
|
+
}, "Tax"), /*#__PURE__*/React.createElement("span", null, currency, tax)), /*#__PURE__*/React.createElement("div", {
|
|
554
|
+
style: {
|
|
555
|
+
display: 'flex',
|
|
556
|
+
justifyContent: 'space-between',
|
|
557
|
+
fontSize: 16,
|
|
558
|
+
fontWeight: 700,
|
|
559
|
+
borderTop: '1px solid #e4e4e7',
|
|
560
|
+
paddingTop: 12,
|
|
561
|
+
marginTop: 4
|
|
562
|
+
}
|
|
563
|
+
}, /*#__PURE__*/React.createElement("span", null, "Total"), /*#__PURE__*/React.createElement("span", null, currency, total))), onCheckout && /*#__PURE__*/React.createElement("button", {
|
|
564
|
+
onClick: onCheckout,
|
|
565
|
+
disabled: loading,
|
|
566
|
+
style: {
|
|
567
|
+
width: '100%',
|
|
568
|
+
marginTop: 16,
|
|
569
|
+
padding: '12px',
|
|
570
|
+
borderRadius: 10,
|
|
571
|
+
border: 'none',
|
|
572
|
+
background: '#18181b',
|
|
573
|
+
color: '#fff',
|
|
574
|
+
fontSize: 14,
|
|
575
|
+
fontWeight: 600,
|
|
576
|
+
cursor: 'pointer'
|
|
577
|
+
}
|
|
578
|
+
}, loading ? 'Processing...' : 'Checkout'));
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Payment SDK - API 客户端
|
|
583
|
+
* 支付系统后端接口封装
|
|
584
|
+
*
|
|
585
|
+
* 使用 BaseApiClient 基类简化代码
|
|
586
|
+
*/
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* 支付 API 客户端
|
|
591
|
+
*/
|
|
592
|
+
class PaymentApiClient extends sdkConfig.BaseApiClient {
|
|
593
|
+
constructor(config = {}) {
|
|
594
|
+
super('/api/payment', config);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// ============ 支付方式 ============
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* 获取可用支付方式
|
|
601
|
+
* @param {Object} orderInfo - 订单信息
|
|
602
|
+
*/
|
|
603
|
+
async getPaymentMethods(orderInfo = {}) {
|
|
604
|
+
return this.post('/methods', orderInfo);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* 获取已绑定的支付方式
|
|
609
|
+
*/
|
|
610
|
+
async getSavedPaymentMethods() {
|
|
611
|
+
return this.get('/methods/saved');
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* 添加支付方式
|
|
616
|
+
* @param {Object} paymentMethod - 支付方式数据
|
|
617
|
+
*/
|
|
618
|
+
async addPaymentMethod(paymentMethod) {
|
|
619
|
+
return this.post('/methods/add', paymentMethod);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* 删除支付方式
|
|
624
|
+
* @param {string} methodId - 支付方式 ID
|
|
625
|
+
*/
|
|
626
|
+
async removePaymentMethod(methodId) {
|
|
627
|
+
return this.delete(`/methods/${methodId}`);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* 设置默认支付方式
|
|
632
|
+
* @param {string} methodId - 支付方式 ID
|
|
633
|
+
*/
|
|
634
|
+
async setDefaultPaymentMethod(methodId) {
|
|
635
|
+
return this.post(`/methods/${methodId}/default`);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// ============ 支付操作 ============
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* 创建支付订单
|
|
642
|
+
* @param {Object} data - 支付数据
|
|
643
|
+
*/
|
|
644
|
+
async createPayment(data) {
|
|
645
|
+
return this.post('/create', data);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* 获取支付信息
|
|
650
|
+
* @param {string} paymentId - 支付 ID
|
|
651
|
+
*/
|
|
652
|
+
async getPayment(paymentId) {
|
|
653
|
+
return this.get(`/${paymentId}`);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* 确认支付
|
|
658
|
+
* @param {string} paymentId - 支付 ID
|
|
659
|
+
* @param {Object} paymentData - 支付数据
|
|
660
|
+
*/
|
|
661
|
+
async confirmPayment(paymentId, paymentData) {
|
|
662
|
+
return this.post(`/${paymentId}/confirm`, paymentData);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* 取消支付
|
|
667
|
+
* @param {string} paymentId - 支付 ID
|
|
668
|
+
*/
|
|
669
|
+
async cancelPayment(paymentId) {
|
|
670
|
+
return this.post(`/${paymentId}/cancel`);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* 查询支付状态
|
|
675
|
+
* @param {string} paymentId - 支付 ID
|
|
676
|
+
*/
|
|
677
|
+
async getPaymentStatus(paymentId) {
|
|
678
|
+
return this.get(`/${paymentId}/status`);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// ============ 退款 ============
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* 申请退款
|
|
685
|
+
* @param {string} paymentId - 支付 ID
|
|
686
|
+
* @param {Object} refundData - 退款数据
|
|
687
|
+
*/
|
|
688
|
+
async requestRefund(paymentId, refundData) {
|
|
689
|
+
return this.post(`/${paymentId}/refund`, refundData);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* 获取退款状态
|
|
694
|
+
* @param {string} refundId - 退款 ID
|
|
695
|
+
*/
|
|
696
|
+
async getRefundStatus(refundId) {
|
|
697
|
+
return this.get(`/refunds/${refundId}`);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* 获取退款列表
|
|
702
|
+
* @param {Object} params - 查询参数
|
|
703
|
+
*/
|
|
704
|
+
async getRefunds(params = {}) {
|
|
705
|
+
return this.get('/refunds', params);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// ============ 支付记录 ============
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* 获取支付记录
|
|
712
|
+
* @param {Object} params - 查询参数
|
|
713
|
+
*/
|
|
714
|
+
async getPaymentHistory(params = {}) {
|
|
715
|
+
return this.get('/history', params);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* 获取支付统计
|
|
720
|
+
* @param {Object} params - 统计参数
|
|
721
|
+
*/
|
|
722
|
+
async getPaymentStats(params = {}) {
|
|
723
|
+
return this.get('/stats', params);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// ============ 第三方支付 ============
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* 获取微信支付参数
|
|
730
|
+
* @param {string} paymentId - 支付 ID
|
|
731
|
+
*/
|
|
732
|
+
async getWechatPayParams(paymentId) {
|
|
733
|
+
return this.get(`/${paymentId}/wechat/params`);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* 获取支付宝支付参数
|
|
738
|
+
* @param {string} paymentId - 支付 ID
|
|
739
|
+
*/
|
|
740
|
+
async getAlipayParams(paymentId) {
|
|
741
|
+
return this.get(`/${paymentId}/alipay/params`);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* 获取 Apple Pay 参数
|
|
746
|
+
* @param {string} paymentId - 支付 ID
|
|
747
|
+
*/
|
|
748
|
+
async getApplePayParams(paymentId) {
|
|
749
|
+
return this.get(`/${paymentId}/applepay/params`);
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// ============ 加密货币支付 ============
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* 获取加密货币支付地址
|
|
756
|
+
* @param {string} paymentId - 支付 ID
|
|
757
|
+
* @param {string} currency - 币种
|
|
758
|
+
*/
|
|
759
|
+
async getCryptoPaymentAddress(paymentId, currency) {
|
|
760
|
+
return this.get(`/${paymentId}/crypto/address`, {
|
|
761
|
+
currency
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* 确认加密货币支付
|
|
767
|
+
* @param {string} paymentId - 支付 ID
|
|
768
|
+
* @param {string} txHash - 交易哈希
|
|
769
|
+
*/
|
|
770
|
+
async confirmCryptoPayment(paymentId, txHash) {
|
|
771
|
+
return this.post(`/${paymentId}/crypto/confirm`, {
|
|
772
|
+
tx_hash: txHash
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// ============ 平台支付同步 (QuantaBit) ============
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* 同步支付结果到 QuantaBit
|
|
780
|
+
* 平台支付完成后调用,将支付信息同步到 QuantaBit 中台
|
|
781
|
+
* @param {Object} data - 支付同步数据
|
|
782
|
+
* @param {string} data.app_id - 来源应用 ID
|
|
783
|
+
* @param {string} data.app_order_id - 应用内订单 ID
|
|
784
|
+
* @param {string} data.payment_method - 支付方式
|
|
785
|
+
* @param {number} data.amount - 支付金额
|
|
786
|
+
* @param {string} [data.status] - 支付状态(默认 'success')
|
|
787
|
+
* @param {string} [data.user_did] - 用户 DID
|
|
788
|
+
* @param {string} [data.title] - 订单标题
|
|
789
|
+
*/
|
|
790
|
+
async syncPaymentToQbitDid(data) {
|
|
791
|
+
const baseURL = this.config?.qbitDidApiUrl || (this.baseURL.includes('/api/payment') ? this.baseURL.replace('/api/payment', '') : this.baseURL);
|
|
792
|
+
return this.post('/platform-orders/sync-payment', data, {
|
|
793
|
+
baseURL
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* 同步交易流水到 QuantaBit
|
|
799
|
+
* @param {Object} data - 交易数据
|
|
800
|
+
* @param {string} data.app_id - 应用 ID
|
|
801
|
+
* @param {string} data.tx_type - 交易类型
|
|
802
|
+
* @param {number} data.amount - 金额
|
|
803
|
+
* @param {string} data.title - 交易标题
|
|
804
|
+
* @param {string} [data.user_did] - 用户 DID
|
|
805
|
+
*/
|
|
806
|
+
async syncTransactionToQbitDid(data) {
|
|
807
|
+
const baseURL = this.config?.qbitDidApiUrl || (this.baseURL.includes('/api/payment') ? this.baseURL.replace('/api/payment', '') : this.baseURL);
|
|
808
|
+
return this.post('/platform-orders/sync-transaction', data, {
|
|
809
|
+
baseURL
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/**
|
|
814
|
+
* 扣减用户 QuantaBit 积分
|
|
815
|
+
* 用于支付时抵扣积分
|
|
816
|
+
* @param {Object} data - 扣减数据
|
|
817
|
+
* @param {string} data.app_id - 应用 ID
|
|
818
|
+
* @param {number} data.points - 积分数量
|
|
819
|
+
* @param {string} [data.user_did] - 用户 DID
|
|
820
|
+
* @param {string} [data.order_id] - 关联订单 ID
|
|
821
|
+
* @param {string} [data.reason] - 扣减原因
|
|
822
|
+
*/
|
|
823
|
+
async deductQbitDidPoints(data) {
|
|
824
|
+
const baseURL = this.config?.qbitDidApiUrl || (this.baseURL.includes('/api/payment') ? this.baseURL.replace('/api/payment', '') : this.baseURL);
|
|
825
|
+
return this.post('/platform-orders/deduct-points', data, {
|
|
826
|
+
baseURL
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/**
|
|
831
|
+
* 获取用户 QuantaBit 积分余额
|
|
832
|
+
* @param {string} userDid - 用户 DID
|
|
833
|
+
*/
|
|
834
|
+
async getQbitDidPointsBalance(userDid) {
|
|
835
|
+
const baseURL = this.config?.qbitDidApiUrl || (this.baseURL.includes('/api/payment') ? this.baseURL.replace('/api/payment', '') : this.baseURL);
|
|
836
|
+
return this.get('/modules/points/balance', {
|
|
837
|
+
did: userDid
|
|
838
|
+
}, {
|
|
839
|
+
baseURL
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* 获取用户 QuantaBit 代币余额
|
|
845
|
+
* @param {string} userDid - 用户 DID
|
|
846
|
+
* @param {string} [tokenSymbol] - 代币符号
|
|
847
|
+
*/
|
|
848
|
+
async getQbitDidTokenBalance(userDid, tokenSymbol) {
|
|
849
|
+
const baseURL = this.config?.qbitDidApiUrl || (this.baseURL.includes('/api/payment') ? this.baseURL.replace('/api/payment', '') : this.baseURL);
|
|
850
|
+
return this.get('/modules/tokens/balance', {
|
|
851
|
+
did: userDid,
|
|
852
|
+
symbol: tokenSymbol
|
|
853
|
+
}, {
|
|
854
|
+
baseURL
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/**
|
|
859
|
+
* 综合支付并同步到 QuantaBit
|
|
860
|
+
* 一次调用完成:本地支付 + QuantaBit 同步
|
|
861
|
+
* @param {Object} paymentData - 支付数据
|
|
862
|
+
* @param {Object} syncOptions - 同步选项
|
|
863
|
+
*/
|
|
864
|
+
async payAndSync(paymentData, syncOptions = {}) {
|
|
865
|
+
// 1. 执行本地支付
|
|
866
|
+
const paymentResult = await this.createPayment(paymentData);
|
|
867
|
+
|
|
868
|
+
// 2. 如果支付成功,自动同步到 QuantaBit
|
|
869
|
+
if (paymentResult.success || paymentResult.status === 'success') {
|
|
870
|
+
try {
|
|
871
|
+
await this.syncPaymentToQbitDid({
|
|
872
|
+
app_id: syncOptions.app_id || 'default',
|
|
873
|
+
app_order_id: paymentData.order_id,
|
|
874
|
+
payment_method: paymentData.payment_method,
|
|
875
|
+
amount: paymentData.amount,
|
|
876
|
+
status: 'success',
|
|
877
|
+
user_did: syncOptions.user_did,
|
|
878
|
+
title: syncOptions.title || paymentData.title
|
|
879
|
+
});
|
|
880
|
+
paymentResult.qbit_did_synced = true;
|
|
881
|
+
} catch (syncError) {
|
|
882
|
+
// 同步失败不影响支付结果,但记录错误
|
|
883
|
+
console.warn('[PaymentSDK] QuantaBit 同步失败:', syncError);
|
|
884
|
+
paymentResult.qbit_did_synced = false;
|
|
885
|
+
paymentResult.qbit_did_sync_error = syncError.message;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
return paymentResult;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// ============ 余额查询 ============
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* 获取用户余额
|
|
895
|
+
* @returns {Promise<{amount: number, points: number}>}
|
|
896
|
+
*/
|
|
897
|
+
async getBalance() {
|
|
898
|
+
return this.get('/balance');
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// ============ 余额支付 ============
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* 使用余额支付
|
|
905
|
+
* @param {string} orderId - 订单 ID
|
|
906
|
+
* @param {string} password - 支付密码
|
|
907
|
+
*/
|
|
908
|
+
async payWithBalance(orderId, password) {
|
|
909
|
+
return this.post(`/${orderId}/pay-with-balance`, {
|
|
910
|
+
password
|
|
911
|
+
});
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
// ============ 充值 ============
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* 创建充值订单
|
|
918
|
+
* @param {Object} data - 充值数据
|
|
919
|
+
* @param {number} data.amount - 充值金额
|
|
920
|
+
* @param {string} data.method - 充值方式
|
|
921
|
+
*/
|
|
922
|
+
async createRecharge(data) {
|
|
923
|
+
return this.post('/recharge', data);
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// ============ 兼容别名(供 PaymentContext 调用) ============
|
|
927
|
+
|
|
928
|
+
/** @alias getPaymentMethods */
|
|
929
|
+
async getAvailableMethods(params) {
|
|
930
|
+
return this.getPaymentMethods(params);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/** @alias createPayment */
|
|
934
|
+
async create(data) {
|
|
935
|
+
return this.createPayment(data);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/** @alias getPaymentStatus */
|
|
939
|
+
async checkStatus(paymentId) {
|
|
940
|
+
return this.getPaymentStatus(paymentId);
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
/** @alias cancelPayment */
|
|
944
|
+
async cancel(paymentId) {
|
|
945
|
+
return this.cancelPayment(paymentId);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
// ============ 隐私合规 (PCI DSS + GDPR) ============
|
|
949
|
+
|
|
950
|
+
/**
|
|
951
|
+
* 导出用户支付数据 — GDPR 第20条
|
|
952
|
+
* 导出匿名化的支付记录(不含完整卡号/密码)
|
|
953
|
+
* @returns {Promise<object>} 匿名化的支付数据
|
|
954
|
+
*/
|
|
955
|
+
async exportPaymentData() {
|
|
956
|
+
try {
|
|
957
|
+
const history = await this.getPaymentHistory({
|
|
958
|
+
page_size: 100
|
|
959
|
+
});
|
|
960
|
+
const methods = await this.getSavedPaymentMethods();
|
|
961
|
+
return {
|
|
962
|
+
exportDate: new Date().toISOString(),
|
|
963
|
+
format: 'QBit Payment Export (GDPR Art. 20)',
|
|
964
|
+
note: 'Card numbers are masked per PCI DSS requirements',
|
|
965
|
+
paymentHistory: history?.data?.items?.map(tx => ({
|
|
966
|
+
...tx,
|
|
967
|
+
// 支付密码和卡号不导出
|
|
968
|
+
card_number: tx.card_number ? `****${tx.card_number.slice(-4)}` : undefined,
|
|
969
|
+
password: undefined,
|
|
970
|
+
cvv: undefined
|
|
971
|
+
})) || [],
|
|
972
|
+
savedMethods: methods?.data?.map(m => ({
|
|
973
|
+
id: m.id,
|
|
974
|
+
type: m.type,
|
|
975
|
+
lastFour: m.last_four || m.card_number?.slice(-4),
|
|
976
|
+
expiry: m.expiry,
|
|
977
|
+
isDefault: m.is_default
|
|
978
|
+
})) || []
|
|
979
|
+
};
|
|
980
|
+
} catch (e) {
|
|
981
|
+
return {
|
|
982
|
+
error: e.message,
|
|
983
|
+
exportDate: new Date().toISOString()
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* 获取隐私数据声明
|
|
990
|
+
*/
|
|
991
|
+
getDataDisclosure() {
|
|
992
|
+
return {
|
|
993
|
+
sdk: '@quantabit/payment-sdk',
|
|
994
|
+
privacyLevel: 'functional',
|
|
995
|
+
consentRequired: false,
|
|
996
|
+
collected: [{
|
|
997
|
+
type: 'payment_methods',
|
|
998
|
+
description: 'Saved payment methods (masked)',
|
|
999
|
+
retention: 'Until deletion',
|
|
1000
|
+
encrypted: true
|
|
1001
|
+
}, {
|
|
1002
|
+
type: 'transaction_history',
|
|
1003
|
+
description: 'Payment records',
|
|
1004
|
+
retention: '5 years (legal requirement)'
|
|
1005
|
+
}, {
|
|
1006
|
+
type: 'billing_address',
|
|
1007
|
+
description: 'Billing details (if provided)',
|
|
1008
|
+
retention: 'Until deletion'
|
|
1009
|
+
}, {
|
|
1010
|
+
type: 'points_balance',
|
|
1011
|
+
description: 'QBit points and token balances',
|
|
1012
|
+
retention: 'Active'
|
|
1013
|
+
}],
|
|
1014
|
+
compliance: ['PCI DSS Level 1', 'GDPR Art. 20 (export)', 'AML/KYT'],
|
|
1015
|
+
gdprCapabilities: ['export'],
|
|
1016
|
+
note: 'Card numbers are never stored in full; only last 4 digits retained per PCI DSS.'
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// 创建默认实例
|
|
1022
|
+
const paymentApi = new PaymentApiClient();
|
|
1023
|
+
|
|
1024
|
+
/**
|
|
1025
|
+
* Payment SDK - RechargeModal 组件
|
|
1026
|
+
* 钱包充值弹窗
|
|
1027
|
+
*
|
|
1028
|
+
* 使用 i18n 国际化,不依赖 Tailwind CSS
|
|
1029
|
+
*/
|
|
1030
|
+
|
|
1031
|
+
const {
|
|
1032
|
+
Text,
|
|
1033
|
+
Title
|
|
1034
|
+
} = antd.Typography;
|
|
1035
|
+
const PAYMENT_METHODS = [{
|
|
1036
|
+
id: "alipay",
|
|
1037
|
+
nameKey: "methodAlipay",
|
|
1038
|
+
icon: /*#__PURE__*/React.createElement(icons.AlipayCircleFilled, {
|
|
1039
|
+
style: {
|
|
1040
|
+
color: "#1677FF",
|
|
1041
|
+
fontSize: '24px'
|
|
1042
|
+
}
|
|
1043
|
+
})
|
|
1044
|
+
}, {
|
|
1045
|
+
id: "wechat",
|
|
1046
|
+
nameKey: "methodWechat",
|
|
1047
|
+
icon: /*#__PURE__*/React.createElement(icons.WechatFilled, {
|
|
1048
|
+
style: {
|
|
1049
|
+
color: "#52C41A",
|
|
1050
|
+
fontSize: '24px'
|
|
1051
|
+
}
|
|
1052
|
+
})
|
|
1053
|
+
}, {
|
|
1054
|
+
id: "crypto",
|
|
1055
|
+
nameKey: "methodCrypto",
|
|
1056
|
+
icon: /*#__PURE__*/React.createElement(icons.DollarCircleFilled, {
|
|
1057
|
+
style: {
|
|
1058
|
+
color: "#F7B500",
|
|
1059
|
+
fontSize: '24px'
|
|
1060
|
+
}
|
|
1061
|
+
})
|
|
1062
|
+
}];
|
|
1063
|
+
const RechargeModal = ({
|
|
1064
|
+
visible,
|
|
1065
|
+
onCancel,
|
|
1066
|
+
onSuccess,
|
|
1067
|
+
userId,
|
|
1068
|
+
initialAmount = 100,
|
|
1069
|
+
currency = "XWIN"
|
|
1070
|
+
}) => {
|
|
1071
|
+
const [amount, setAmount] = React.useState(initialAmount);
|
|
1072
|
+
const [method, setMethod] = React.useState("alipay");
|
|
1073
|
+
const [loading, setLoading] = React.useState(false);
|
|
1074
|
+
const [step, setStep] = React.useState("select"); // select, paying, success
|
|
1075
|
+
const [paymentData, setPaymentData] = React.useState(null);
|
|
1076
|
+
React.useEffect(() => {
|
|
1077
|
+
if (visible) {
|
|
1078
|
+
setStep("select");
|
|
1079
|
+
setAmount(initialAmount);
|
|
1080
|
+
setPaymentData(null);
|
|
1081
|
+
}
|
|
1082
|
+
}, [visible, initialAmount]);
|
|
1083
|
+
const handleRecharge = async () => {
|
|
1084
|
+
if (amount <= 0) {
|
|
1085
|
+
try {
|
|
1086
|
+
const {
|
|
1087
|
+
message
|
|
1088
|
+
} = await import('antd');
|
|
1089
|
+
message.warning(t('enterValidAmount'));
|
|
1090
|
+
} catch {
|
|
1091
|
+
alert(t('enterValidAmount'));
|
|
1092
|
+
}
|
|
1093
|
+
return;
|
|
1094
|
+
}
|
|
1095
|
+
setLoading(true);
|
|
1096
|
+
try {
|
|
1097
|
+
const res = await paymentApi.createPayment({
|
|
1098
|
+
user_id: userId,
|
|
1099
|
+
amount,
|
|
1100
|
+
currency,
|
|
1101
|
+
payment_method: method,
|
|
1102
|
+
order_type: "recharge",
|
|
1103
|
+
description: `${t('recharge')} ${amount} ${currency}`
|
|
1104
|
+
});
|
|
1105
|
+
if (res.code === 0 || res.success) {
|
|
1106
|
+
setPaymentData(res.data);
|
|
1107
|
+
setStep("paying");
|
|
1108
|
+
if (method === "mock" || method === "wallet") {
|
|
1109
|
+
handleSuccess();
|
|
1110
|
+
}
|
|
1111
|
+
} else {
|
|
1112
|
+
try {
|
|
1113
|
+
const {
|
|
1114
|
+
message
|
|
1115
|
+
} = await import('antd');
|
|
1116
|
+
message.error(res.data?.msg || t('createOrderFailed'));
|
|
1117
|
+
} catch {
|
|
1118
|
+
alert(t('createOrderFailed'));
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
} catch (error) {
|
|
1122
|
+
console.error(error);
|
|
1123
|
+
try {
|
|
1124
|
+
const {
|
|
1125
|
+
message
|
|
1126
|
+
} = await import('antd');
|
|
1127
|
+
message.error(t('networkError'));
|
|
1128
|
+
} catch {
|
|
1129
|
+
alert(t('networkError'));
|
|
1130
|
+
}
|
|
1131
|
+
} finally {
|
|
1132
|
+
setLoading(false);
|
|
1133
|
+
}
|
|
1134
|
+
};
|
|
1135
|
+
const handleSuccess = () => {
|
|
1136
|
+
setStep("success");
|
|
1137
|
+
if (onSuccess) onSuccess(amount);
|
|
1138
|
+
setTimeout(() => {
|
|
1139
|
+
onCancel();
|
|
1140
|
+
}, 3000);
|
|
1141
|
+
};
|
|
1142
|
+
const handleMockPay = async () => {
|
|
1143
|
+
setLoading(true);
|
|
1144
|
+
try {
|
|
1145
|
+
await paymentApi.confirmPayment(paymentData.payment_no || paymentData.id, {
|
|
1146
|
+
status: 'success'
|
|
1147
|
+
});
|
|
1148
|
+
handleSuccess();
|
|
1149
|
+
} catch (e) {
|
|
1150
|
+
try {
|
|
1151
|
+
const {
|
|
1152
|
+
message
|
|
1153
|
+
} = await import('antd');
|
|
1154
|
+
message.error(t('paymentConfirmFailed'));
|
|
1155
|
+
} catch {
|
|
1156
|
+
alert(t('paymentConfirmFailed'));
|
|
1157
|
+
}
|
|
1158
|
+
} finally {
|
|
1159
|
+
setLoading(false);
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1162
|
+
const getMethodName = m => t(m.nameKey) || m.id;
|
|
1163
|
+
const renderContent = () => {
|
|
1164
|
+
// ============ 充值成功 ============
|
|
1165
|
+
if (step === "success") {
|
|
1166
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1167
|
+
style: {
|
|
1168
|
+
textAlign: 'center',
|
|
1169
|
+
padding: '40px 20px',
|
|
1170
|
+
animation: 'fadeIn 0.5s'
|
|
1171
|
+
}
|
|
1172
|
+
}, /*#__PURE__*/React.createElement(icons.CheckCircleFilled, {
|
|
1173
|
+
style: {
|
|
1174
|
+
fontSize: 72,
|
|
1175
|
+
color: "#52C41A",
|
|
1176
|
+
marginBottom: '24px',
|
|
1177
|
+
animation: 'scaleIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275)'
|
|
1178
|
+
}
|
|
1179
|
+
}), /*#__PURE__*/React.createElement("h2", {
|
|
1180
|
+
style: {
|
|
1181
|
+
fontSize: '24px',
|
|
1182
|
+
fontWeight: 800,
|
|
1183
|
+
color: '#0F172A',
|
|
1184
|
+
marginBottom: '8px'
|
|
1185
|
+
}
|
|
1186
|
+
}, t('rechargeSuccessful')), /*#__PURE__*/React.createElement("p", {
|
|
1187
|
+
style: {
|
|
1188
|
+
fontSize: '15px',
|
|
1189
|
+
color: '#64748B'
|
|
1190
|
+
}
|
|
1191
|
+
}, t('rechargeSuccessMsg', {
|
|
1192
|
+
amount,
|
|
1193
|
+
currency
|
|
1194
|
+
})));
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
// ============ 等待支付 ============
|
|
1198
|
+
if (step === "paying") {
|
|
1199
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1200
|
+
style: {
|
|
1201
|
+
padding: '20px',
|
|
1202
|
+
textAlign: 'center',
|
|
1203
|
+
animation: 'fadeIn 0.3s'
|
|
1204
|
+
}
|
|
1205
|
+
}, /*#__PURE__*/React.createElement("h3", {
|
|
1206
|
+
style: {
|
|
1207
|
+
fontSize: '20px',
|
|
1208
|
+
fontWeight: 700,
|
|
1209
|
+
color: '#0F172A',
|
|
1210
|
+
marginBottom: '8px'
|
|
1211
|
+
}
|
|
1212
|
+
}, t('paymentProcessing')), /*#__PURE__*/React.createElement("div", {
|
|
1213
|
+
style: {
|
|
1214
|
+
fontSize: '13px',
|
|
1215
|
+
color: '#94A3B8',
|
|
1216
|
+
marginBottom: '32px'
|
|
1217
|
+
}
|
|
1218
|
+
}, t('orderNo'), ": ", paymentData?.order_no), /*#__PURE__*/React.createElement("div", {
|
|
1219
|
+
style: {
|
|
1220
|
+
background: 'rgba(241, 245, 249, 0.5)',
|
|
1221
|
+
border: '1px solid rgba(226, 232, 240, 0.8)',
|
|
1222
|
+
borderRadius: '24px',
|
|
1223
|
+
padding: '32px',
|
|
1224
|
+
marginBottom: '32px',
|
|
1225
|
+
display: 'flex',
|
|
1226
|
+
flexDirection: 'column',
|
|
1227
|
+
alignItems: 'center'
|
|
1228
|
+
}
|
|
1229
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1230
|
+
style: {
|
|
1231
|
+
fontSize: '48px',
|
|
1232
|
+
fontWeight: 800,
|
|
1233
|
+
color: '#0F172A',
|
|
1234
|
+
lineHeight: 1,
|
|
1235
|
+
marginBottom: '16px'
|
|
1236
|
+
}
|
|
1237
|
+
}, amount, " ", /*#__PURE__*/React.createElement("span", {
|
|
1238
|
+
style: {
|
|
1239
|
+
fontSize: '20px',
|
|
1240
|
+
color: '#64748B'
|
|
1241
|
+
}
|
|
1242
|
+
}, currency)), /*#__PURE__*/React.createElement("div", {
|
|
1243
|
+
style: {
|
|
1244
|
+
display: 'flex',
|
|
1245
|
+
alignItems: 'center',
|
|
1246
|
+
gap: '8px',
|
|
1247
|
+
background: '#fff',
|
|
1248
|
+
padding: '8px 16px',
|
|
1249
|
+
borderRadius: '100px',
|
|
1250
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.05)'
|
|
1251
|
+
}
|
|
1252
|
+
}, PAYMENT_METHODS.find(m => m.id === method)?.icon, /*#__PURE__*/React.createElement("span", {
|
|
1253
|
+
style: {
|
|
1254
|
+
fontSize: '15px',
|
|
1255
|
+
fontWeight: 600,
|
|
1256
|
+
color: '#334155'
|
|
1257
|
+
}
|
|
1258
|
+
}, getMethodName(PAYMENT_METHODS.find(m => m.id === method))))), /*#__PURE__*/React.createElement("div", {
|
|
1259
|
+
style: {
|
|
1260
|
+
display: 'flex',
|
|
1261
|
+
flexDirection: 'column',
|
|
1262
|
+
gap: '24px',
|
|
1263
|
+
alignItems: 'center'
|
|
1264
|
+
}
|
|
1265
|
+
}, /*#__PURE__*/React.createElement(antd.Spin, {
|
|
1266
|
+
tip: t('waitingForPayment'),
|
|
1267
|
+
size: "large"
|
|
1268
|
+
}), /*#__PURE__*/React.createElement("button", {
|
|
1269
|
+
onClick: handleMockPay,
|
|
1270
|
+
style: {
|
|
1271
|
+
background: 'transparent',
|
|
1272
|
+
border: 'none',
|
|
1273
|
+
color: '#3B82F6',
|
|
1274
|
+
fontSize: '14px',
|
|
1275
|
+
fontWeight: 600,
|
|
1276
|
+
cursor: 'pointer',
|
|
1277
|
+
textDecoration: 'underline'
|
|
1278
|
+
}
|
|
1279
|
+
}, t('simulatePaySuccess'))));
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
// ============ 选择金额和方式 ============
|
|
1283
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
1284
|
+
style: {
|
|
1285
|
+
display: 'flex',
|
|
1286
|
+
flexDirection: 'column',
|
|
1287
|
+
gap: '32px',
|
|
1288
|
+
padding: '10px 0'
|
|
1289
|
+
}
|
|
1290
|
+
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
|
|
1291
|
+
style: {
|
|
1292
|
+
fontSize: '16px',
|
|
1293
|
+
fontWeight: 700,
|
|
1294
|
+
color: '#0F172A',
|
|
1295
|
+
marginBottom: '16px'
|
|
1296
|
+
}
|
|
1297
|
+
}, t('rechargeAmount'), " (", currency, ")"), /*#__PURE__*/React.createElement("div", {
|
|
1298
|
+
style: {
|
|
1299
|
+
display: 'grid',
|
|
1300
|
+
gridTemplateColumns: 'repeat(4, 1fr)',
|
|
1301
|
+
gap: '12px',
|
|
1302
|
+
marginBottom: '16px'
|
|
1303
|
+
}
|
|
1304
|
+
}, [100, 500, 1000, 5000].map(val => /*#__PURE__*/React.createElement("div", {
|
|
1305
|
+
key: val,
|
|
1306
|
+
onClick: () => setAmount(val),
|
|
1307
|
+
style: {
|
|
1308
|
+
padding: '16px 0',
|
|
1309
|
+
textAlign: 'center',
|
|
1310
|
+
borderRadius: '16px',
|
|
1311
|
+
cursor: 'pointer',
|
|
1312
|
+
fontSize: '16px',
|
|
1313
|
+
fontWeight: 600,
|
|
1314
|
+
transition: 'all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)',
|
|
1315
|
+
border: amount === val ? '1px solid rgba(59, 130, 246, 0.8)' : '1px solid rgba(255, 255, 255, 0.4)',
|
|
1316
|
+
background: amount === val ? 'rgba(255, 255, 255, 0.9)' : 'rgba(255, 255, 255, 0.6)',
|
|
1317
|
+
backdropFilter: 'blur(16px)',
|
|
1318
|
+
WebkitBackdropFilter: 'blur(16px)',
|
|
1319
|
+
color: amount === val ? '#2563EB' : '#475569',
|
|
1320
|
+
boxShadow: amount === val ? '0 10px 20px -5px rgba(59, 130, 246, 0.2), inset 0 0 0 1px rgba(255,255,255,0.8)' : '0 4px 12px rgba(0,0,0,0.02), inset 0 0 0 1px rgba(255,255,255,0.5)'
|
|
1321
|
+
},
|
|
1322
|
+
onMouseEnter: e => {
|
|
1323
|
+
if (amount !== val) {
|
|
1324
|
+
e.currentTarget.style.transform = 'translateY(-2px)';
|
|
1325
|
+
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.8)';
|
|
1326
|
+
}
|
|
1327
|
+
},
|
|
1328
|
+
onMouseLeave: e => {
|
|
1329
|
+
if (amount !== val) {
|
|
1330
|
+
e.currentTarget.style.transform = 'none';
|
|
1331
|
+
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.6)';
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
}, val))), /*#__PURE__*/React.createElement(antd.InputNumber, {
|
|
1335
|
+
style: {
|
|
1336
|
+
width: "100%",
|
|
1337
|
+
borderRadius: '16px',
|
|
1338
|
+
background: 'rgba(241, 245, 249, 0.5)'
|
|
1339
|
+
},
|
|
1340
|
+
size: "large",
|
|
1341
|
+
value: amount,
|
|
1342
|
+
onChange: setAmount,
|
|
1343
|
+
prefix: /*#__PURE__*/React.createElement(icons.DollarOutlined, {
|
|
1344
|
+
style: {
|
|
1345
|
+
color: '#94A3B8'
|
|
1346
|
+
}
|
|
1347
|
+
}),
|
|
1348
|
+
min: 1
|
|
1349
|
+
})), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
|
|
1350
|
+
style: {
|
|
1351
|
+
fontSize: '16px',
|
|
1352
|
+
fontWeight: 700,
|
|
1353
|
+
color: '#0F172A',
|
|
1354
|
+
marginBottom: '16px'
|
|
1355
|
+
}
|
|
1356
|
+
}, t('paymentMethod')), /*#__PURE__*/React.createElement("div", {
|
|
1357
|
+
style: {
|
|
1358
|
+
display: 'flex',
|
|
1359
|
+
flexDirection: 'column',
|
|
1360
|
+
gap: '12px'
|
|
1361
|
+
}
|
|
1362
|
+
}, PAYMENT_METHODS.map(m => /*#__PURE__*/React.createElement("div", {
|
|
1363
|
+
key: m.id,
|
|
1364
|
+
onClick: () => setMethod(m.id),
|
|
1365
|
+
style: {
|
|
1366
|
+
display: 'flex',
|
|
1367
|
+
alignItems: 'center',
|
|
1368
|
+
padding: '16px',
|
|
1369
|
+
borderRadius: '20px',
|
|
1370
|
+
cursor: 'pointer',
|
|
1371
|
+
border: method === m.id ? '1px solid rgba(59, 130, 246, 0.8)' : '1px solid rgba(255, 255, 255, 0.4)',
|
|
1372
|
+
background: method === m.id ? 'rgba(255, 255, 255, 0.85)' : 'rgba(255, 255, 255, 0.6)',
|
|
1373
|
+
backdropFilter: 'blur(16px)',
|
|
1374
|
+
WebkitBackdropFilter: 'blur(16px)',
|
|
1375
|
+
transition: 'all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)',
|
|
1376
|
+
boxShadow: method === m.id ? '0 10px 25px -5px rgba(59, 130, 246, 0.15), inset 0 0 0 1px rgba(255,255,255,0.8)' : '0 4px 12px rgba(0,0,0,0.02), inset 0 0 0 1px rgba(255,255,255,0.5)'
|
|
1377
|
+
},
|
|
1378
|
+
onMouseEnter: e => {
|
|
1379
|
+
if (method !== m.id) {
|
|
1380
|
+
e.currentTarget.style.transform = 'translateY(-2px)';
|
|
1381
|
+
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.8)';
|
|
1382
|
+
}
|
|
1383
|
+
},
|
|
1384
|
+
onMouseLeave: e => {
|
|
1385
|
+
if (method !== m.id) {
|
|
1386
|
+
e.currentTarget.style.transform = 'none';
|
|
1387
|
+
e.currentTarget.style.background = 'rgba(255, 255, 255, 0.6)';
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1391
|
+
style: {
|
|
1392
|
+
width: '40px',
|
|
1393
|
+
height: '40px',
|
|
1394
|
+
background: 'rgba(255,255,255,0.9)',
|
|
1395
|
+
borderRadius: '12px',
|
|
1396
|
+
display: 'flex',
|
|
1397
|
+
alignItems: 'center',
|
|
1398
|
+
justifyContent: 'center',
|
|
1399
|
+
boxShadow: '0 2px 8px rgba(0,0,0,0.05)'
|
|
1400
|
+
}
|
|
1401
|
+
}, m.icon), /*#__PURE__*/React.createElement("div", {
|
|
1402
|
+
style: {
|
|
1403
|
+
marginLeft: '16px',
|
|
1404
|
+
flex: 1,
|
|
1405
|
+
fontSize: '16px',
|
|
1406
|
+
fontWeight: 600,
|
|
1407
|
+
color: '#0F172A'
|
|
1408
|
+
}
|
|
1409
|
+
}, getMethodName(m)), /*#__PURE__*/React.createElement("div", {
|
|
1410
|
+
style: {
|
|
1411
|
+
width: '24px',
|
|
1412
|
+
height: '24px',
|
|
1413
|
+
borderRadius: '50%',
|
|
1414
|
+
border: method === m.id ? '7px solid #3B82F6' : '2px solid rgba(148, 163, 184, 0.5)',
|
|
1415
|
+
background: '#fff',
|
|
1416
|
+
transition: 'all 0.2s',
|
|
1417
|
+
boxShadow: method === m.id ? '0 4px 8px rgba(59, 130, 246, 0.2)' : 'none'
|
|
1418
|
+
}
|
|
1419
|
+
}))))), /*#__PURE__*/React.createElement("button", {
|
|
1420
|
+
onClick: handleRecharge,
|
|
1421
|
+
disabled: loading,
|
|
1422
|
+
style: {
|
|
1423
|
+
width: '100%',
|
|
1424
|
+
padding: '16px',
|
|
1425
|
+
borderRadius: '16px',
|
|
1426
|
+
border: 'none',
|
|
1427
|
+
background: 'linear-gradient(135deg, #1E293B 0%, #0F172A 100%)',
|
|
1428
|
+
color: '#fff',
|
|
1429
|
+
fontSize: '16px',
|
|
1430
|
+
fontWeight: 700,
|
|
1431
|
+
cursor: loading ? 'not-allowed' : 'pointer',
|
|
1432
|
+
opacity: loading ? 0.8 : 1,
|
|
1433
|
+
display: 'flex',
|
|
1434
|
+
alignItems: 'center',
|
|
1435
|
+
justifyContent: 'center',
|
|
1436
|
+
gap: '8px',
|
|
1437
|
+
boxShadow: '0 10px 25px -5px rgba(15, 23, 42, 0.3)',
|
|
1438
|
+
transition: 'all 0.2s'
|
|
1439
|
+
},
|
|
1440
|
+
onMouseEnter: e => {
|
|
1441
|
+
if (!loading) {
|
|
1442
|
+
e.currentTarget.style.transform = 'translateY(-2px)';
|
|
1443
|
+
e.currentTarget.style.boxShadow = '0 15px 35px -5px rgba(15, 23, 42, 0.4)';
|
|
1444
|
+
}
|
|
1445
|
+
},
|
|
1446
|
+
onMouseLeave: e => {
|
|
1447
|
+
if (!loading) {
|
|
1448
|
+
e.currentTarget.style.transform = 'none';
|
|
1449
|
+
e.currentTarget.style.boxShadow = '0 10px 25px -5px rgba(15, 23, 42, 0.3)';
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
}, /*#__PURE__*/React.createElement(icons.WalletFilled, null), loading ? t('pay.processing') : t('confirmRecharge')));
|
|
1453
|
+
};
|
|
1454
|
+
return /*#__PURE__*/React.createElement(antd.Modal, {
|
|
1455
|
+
open: visible,
|
|
1456
|
+
onCancel: onCancel,
|
|
1457
|
+
footer: null,
|
|
1458
|
+
width: 480,
|
|
1459
|
+
destroyOnClose: true,
|
|
1460
|
+
styles: {
|
|
1461
|
+
content: {
|
|
1462
|
+
padding: '32px',
|
|
1463
|
+
borderRadius: '32px',
|
|
1464
|
+
background: 'rgba(255, 255, 255, 0.9)',
|
|
1465
|
+
backdropFilter: 'blur(24px)',
|
|
1466
|
+
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)'
|
|
1467
|
+
},
|
|
1468
|
+
header: {
|
|
1469
|
+
background: 'transparent',
|
|
1470
|
+
marginBottom: '24px'
|
|
1471
|
+
},
|
|
1472
|
+
mask: {
|
|
1473
|
+
backdropFilter: 'blur(8px)',
|
|
1474
|
+
background: 'rgba(15, 23, 42, 0.4)'
|
|
1475
|
+
}
|
|
1476
|
+
},
|
|
1477
|
+
title: /*#__PURE__*/React.createElement("div", {
|
|
1478
|
+
style: {
|
|
1479
|
+
fontSize: '24px',
|
|
1480
|
+
fontWeight: 800,
|
|
1481
|
+
color: '#0F172A'
|
|
1482
|
+
}
|
|
1483
|
+
}, t('walletRecharge'))
|
|
1484
|
+
}, /*#__PURE__*/React.createElement("style", null, `
|
|
1485
|
+
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
|
1486
|
+
@keyframes scaleIn { from { transform: scale(0.5); opacity: 0; } to { transform: scale(1); opacity: 1; } }
|
|
1487
|
+
`), renderContent());
|
|
1488
|
+
};
|
|
1489
|
+
|
|
1490
|
+
exports.CheckoutSummary = CheckoutSummary;
|
|
1491
|
+
exports.PaymentApiClient = PaymentApiClient;
|
|
1492
|
+
exports.PaymentMethodSelector = PaymentMethodSelector;
|
|
1493
|
+
exports.PricingCard = PricingCard;
|
|
1494
|
+
exports.PricingTable = PricingTable;
|
|
1495
|
+
exports.RechargeModal = RechargeModal;
|
|
1496
|
+
exports.SUPPORTED_LANGUAGES = SUPPORTED_LANGUAGES;
|
|
1497
|
+
exports.getLanguage = getLanguage;
|
|
1498
|
+
exports.messages = messages;
|
|
1499
|
+
exports.paymentApi = paymentApi;
|
|
1500
|
+
exports.setLanguage = setLanguage;
|
|
1501
|
+
exports.t = t;
|
|
1502
|
+
//# sourceMappingURL=index.cjs.map
|