@2kog/pkg-widget 0.1.17 → 0.1.19
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/package.json +1 -1
- package/src/App.vue +17 -11
- package/src/components/common/payment.vue +116 -25
- package/src/locale/en-us/payment.js +11 -3
- package/src/locale/zh-cn/payment.js +6 -1
package/package.json
CHANGED
package/src/App.vue
CHANGED
|
@@ -3,21 +3,27 @@
|
|
|
3
3
|
<h1>IRuxu Pkg Widget</h1>
|
|
4
4
|
<Logo></Logo>
|
|
5
5
|
|
|
6
|
-
<UploadImage
|
|
6
|
+
<UploadImage
|
|
7
|
+
:upload-fn="uploadImage"
|
|
8
|
+
:domain="domain"
|
|
9
|
+
:url="avatar"
|
|
10
|
+
></UploadImage>
|
|
7
11
|
|
|
8
|
-
<langSelect
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
<langSelect
|
|
13
|
+
:show-flag="false"
|
|
14
|
+
:show-name="true"
|
|
15
|
+
:optionsWithFlag="false"
|
|
16
|
+
></langSelect>
|
|
11
17
|
<pay></pay>
|
|
12
18
|
|
|
13
|
-
<payment ></payment>
|
|
19
|
+
<payment term-link="/doc/terms"></payment>
|
|
14
20
|
</div>
|
|
15
21
|
</template>
|
|
16
22
|
|
|
17
23
|
<script>
|
|
18
24
|
import Logo from "./components/common/logo.vue";
|
|
19
25
|
import UploadImage from "./components/common/upload-image.vue";
|
|
20
|
-
import {upload} from "./assets/data/upload";
|
|
26
|
+
import { upload } from "./assets/data/upload";
|
|
21
27
|
import langSelect from "./components/common/lang-select.vue";
|
|
22
28
|
import pay from "./demo/pay-dialog-demo.vue";
|
|
23
29
|
import payment from "./components/common/payment.vue";
|
|
@@ -28,7 +34,7 @@ export default {
|
|
|
28
34
|
UploadImage,
|
|
29
35
|
langSelect,
|
|
30
36
|
pay,
|
|
31
|
-
payment
|
|
37
|
+
payment,
|
|
32
38
|
},
|
|
33
39
|
data() {
|
|
34
40
|
return {
|
|
@@ -38,14 +44,14 @@ export default {
|
|
|
38
44
|
domain: "https://cdn.iruxu.com/",
|
|
39
45
|
avatar: "user/avatar/2024/11/27/81348085.jpeg",
|
|
40
46
|
|
|
41
|
-
show: true
|
|
47
|
+
show: true,
|
|
42
48
|
};
|
|
43
49
|
},
|
|
44
50
|
methods: {
|
|
45
51
|
uploadImage(file) {
|
|
46
|
-
return upload(file)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
52
|
+
return upload(file);
|
|
53
|
+
},
|
|
54
|
+
},
|
|
49
55
|
};
|
|
50
56
|
</script>
|
|
51
57
|
|
|
@@ -8,14 +8,21 @@
|
|
|
8
8
|
<div class="modal-main m-purchase-pay-main">
|
|
9
9
|
<!-- 支付方式切换 -->
|
|
10
10
|
<div class="payment-methods-grid">
|
|
11
|
-
<slot
|
|
11
|
+
<slot
|
|
12
|
+
name="payment-methods"
|
|
13
|
+
:methods="paymentMethods"
|
|
14
|
+
:active="activeMethod"
|
|
15
|
+
:switch="switchPay"
|
|
16
|
+
>
|
|
12
17
|
<button
|
|
13
18
|
v-for="method in paymentMethods"
|
|
14
19
|
:key="method.value"
|
|
15
20
|
@click="switchPay(method.value)"
|
|
16
21
|
class="pay-method-btn"
|
|
17
22
|
:class="[
|
|
18
|
-
activeMethod === method.value
|
|
23
|
+
activeMethod === method.value
|
|
24
|
+
? 'active ' + method.activeClass
|
|
25
|
+
: '',
|
|
19
26
|
method.customClass || '',
|
|
20
27
|
]"
|
|
21
28
|
>
|
|
@@ -33,7 +40,9 @@
|
|
|
33
40
|
<!-- Loading 状态 -->
|
|
34
41
|
<div v-if="loading" class="loading-overlay">
|
|
35
42
|
<slot name="loading">
|
|
36
|
-
<i
|
|
43
|
+
<i
|
|
44
|
+
class="fas fa-spinner fa-spin loading-icon"
|
|
45
|
+
></i>
|
|
37
46
|
</slot>
|
|
38
47
|
</div>
|
|
39
48
|
|
|
@@ -47,17 +56,28 @@
|
|
|
47
56
|
/>
|
|
48
57
|
|
|
49
58
|
<!-- 默认图标 -->
|
|
50
|
-
<slot
|
|
59
|
+
<slot
|
|
60
|
+
v-else
|
|
61
|
+
name="placeholder"
|
|
62
|
+
:activeMethod="activeMethod"
|
|
63
|
+
>
|
|
51
64
|
<i
|
|
52
65
|
class="placeholder-icon"
|
|
53
|
-
:class="
|
|
66
|
+
:class="
|
|
67
|
+
currentPaymentMethod?.icon ||
|
|
68
|
+
'fas fa-qrcode'
|
|
69
|
+
"
|
|
54
70
|
></i>
|
|
55
71
|
</slot>
|
|
56
72
|
</div>
|
|
57
73
|
</div>
|
|
58
74
|
<div class="secure-badge">
|
|
59
|
-
<i class="fas fa-
|
|
60
|
-
{{
|
|
75
|
+
<i class="fas fa-qrcode"></i>
|
|
76
|
+
<span>{{
|
|
77
|
+
t(
|
|
78
|
+
`pay.${activeMethod === "wepay" ? "wechatScan" : "alipayScan"}`,
|
|
79
|
+
)
|
|
80
|
+
}}</span>
|
|
61
81
|
</div>
|
|
62
82
|
|
|
63
83
|
<!-- 错误提示 -->
|
|
@@ -70,7 +90,18 @@
|
|
|
70
90
|
|
|
71
91
|
<!-- 底部插槽 -->
|
|
72
92
|
<div class="footer-slot">
|
|
73
|
-
<slot name="footer" :texts="texts"
|
|
93
|
+
<slot name="footer" :texts="texts">
|
|
94
|
+
<div class="m-agreement">
|
|
95
|
+
<i class="fas fa-shield-halved agreement-icon"></i>
|
|
96
|
+
<span class="agreement-text">
|
|
97
|
+
{{ t("pay.agreement_prefix") }}
|
|
98
|
+
<a class="u-link" :href="termLink">{{
|
|
99
|
+
t("pay.agreement_link")
|
|
100
|
+
}}</a>
|
|
101
|
+
{{ t("pay.agreement_suffix") }}
|
|
102
|
+
</span>
|
|
103
|
+
</div>
|
|
104
|
+
</slot>
|
|
74
105
|
</div>
|
|
75
106
|
</div>
|
|
76
107
|
</div>
|
|
@@ -84,13 +115,13 @@ import zhCn from "../../locale/zh-cn/payment";
|
|
|
84
115
|
|
|
85
116
|
// 创建独立的 i18n 实例
|
|
86
117
|
const getLocale = () => {
|
|
87
|
-
const storedLanguage = localStorage.getItem(
|
|
118
|
+
const storedLanguage = localStorage.getItem("lang");
|
|
88
119
|
if (!storedLanguage) {
|
|
89
120
|
return navigator.language;
|
|
90
121
|
} else {
|
|
91
122
|
return storedLanguage;
|
|
92
123
|
}
|
|
93
|
-
}
|
|
124
|
+
};
|
|
94
125
|
|
|
95
126
|
const payI18n = createI18n({
|
|
96
127
|
locale: getLocale(),
|
|
@@ -141,6 +172,10 @@ export default {
|
|
|
141
172
|
type: Boolean,
|
|
142
173
|
default: false,
|
|
143
174
|
},
|
|
175
|
+
termLink: {
|
|
176
|
+
type: String,
|
|
177
|
+
default: "/doc/terms",
|
|
178
|
+
},
|
|
144
179
|
},
|
|
145
180
|
data() {
|
|
146
181
|
return {
|
|
@@ -209,11 +244,15 @@ export default {
|
|
|
209
244
|
},
|
|
210
245
|
computed: {
|
|
211
246
|
isMobile() {
|
|
212
|
-
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
247
|
+
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
248
|
+
navigator.userAgent,
|
|
249
|
+
);
|
|
213
250
|
},
|
|
214
251
|
|
|
215
252
|
currentPaymentMethod() {
|
|
216
|
-
return this.paymentMethods.find(
|
|
253
|
+
return this.paymentMethods.find(
|
|
254
|
+
(m) => m.value === this.activeMethod,
|
|
255
|
+
);
|
|
217
256
|
},
|
|
218
257
|
|
|
219
258
|
actualPayChannel() {
|
|
@@ -225,7 +264,9 @@ export default {
|
|
|
225
264
|
}
|
|
226
265
|
|
|
227
266
|
if (typeof method.channel === "object") {
|
|
228
|
-
return this.isMobile
|
|
267
|
+
return this.isMobile
|
|
268
|
+
? method.channel.mobile
|
|
269
|
+
: method.channel.pc;
|
|
229
270
|
}
|
|
230
271
|
|
|
231
272
|
return this.activeMethod;
|
|
@@ -311,13 +352,17 @@ export default {
|
|
|
311
352
|
try {
|
|
312
353
|
this.orderPollingRetries++;
|
|
313
354
|
|
|
314
|
-
if (
|
|
355
|
+
if (
|
|
356
|
+
this.orderPollingRetries > this.pollingConfig.maxRetries
|
|
357
|
+
) {
|
|
315
358
|
this.clearTimer("order");
|
|
316
359
|
this.handleError(this.texts.orderTimeout);
|
|
317
360
|
return;
|
|
318
361
|
}
|
|
319
362
|
|
|
320
|
-
const response = await this.api.getOrderStatus(
|
|
363
|
+
const response = await this.api.getOrderStatus(
|
|
364
|
+
this.pendingOrderId,
|
|
365
|
+
);
|
|
321
366
|
|
|
322
367
|
if (response && response.status === 2) {
|
|
323
368
|
this.clearTimer("order");
|
|
@@ -326,7 +371,9 @@ export default {
|
|
|
326
371
|
await this.getPaymentQrcode();
|
|
327
372
|
} else if (response && response.status === -1) {
|
|
328
373
|
this.clearTimer("order");
|
|
329
|
-
this.handleError(
|
|
374
|
+
this.handleError(
|
|
375
|
+
response.message || this.texts.orderFailed,
|
|
376
|
+
);
|
|
330
377
|
}
|
|
331
378
|
} catch (err) {
|
|
332
379
|
console.error("Failed to poll order status:", err);
|
|
@@ -346,7 +393,11 @@ export default {
|
|
|
346
393
|
params.qr_pay_mode = QR_PAY_MODE_ALIPAY_PC;
|
|
347
394
|
}
|
|
348
395
|
|
|
349
|
-
const response = await this.api.getPaymentQRCode(
|
|
396
|
+
const response = await this.api.getPaymentQRCode(
|
|
397
|
+
this.paymentId,
|
|
398
|
+
this.actualPayChannel,
|
|
399
|
+
params,
|
|
400
|
+
);
|
|
350
401
|
|
|
351
402
|
if (response) {
|
|
352
403
|
this.qrcode = response.qrcode || response;
|
|
@@ -372,14 +423,19 @@ export default {
|
|
|
372
423
|
try {
|
|
373
424
|
this.paymentPollingRetries++;
|
|
374
425
|
|
|
375
|
-
if (
|
|
426
|
+
if (
|
|
427
|
+
this.paymentPollingRetries >
|
|
428
|
+
this.pollingConfig.maxRetries
|
|
429
|
+
) {
|
|
376
430
|
this.clearTimer("payment");
|
|
377
431
|
this.warningVisible = true;
|
|
378
432
|
this.handleError(this.texts.paymentTimeout);
|
|
379
433
|
return;
|
|
380
434
|
}
|
|
381
435
|
|
|
382
|
-
const response = await this.api.queryPaymentStatus(
|
|
436
|
+
const response = await this.api.queryPaymentStatus(
|
|
437
|
+
this.paymentId,
|
|
438
|
+
);
|
|
383
439
|
|
|
384
440
|
if (response && response.status === 1) {
|
|
385
441
|
this.clearTimer("payment");
|
|
@@ -432,14 +488,46 @@ export default {
|
|
|
432
488
|
<style lang="less">
|
|
433
489
|
.c-payment-component {
|
|
434
490
|
// max-width: 28rem;
|
|
435
|
-
flex: 1;
|
|
436
491
|
width: 100%;
|
|
437
|
-
background-color: #
|
|
438
|
-
color:
|
|
492
|
+
background-color: #fff;
|
|
493
|
+
color: #333;
|
|
439
494
|
// border-radius: 1rem;
|
|
440
495
|
padding: 2rem;
|
|
441
496
|
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
442
497
|
border: 1px solid rgb(31 41 55);
|
|
498
|
+
|
|
499
|
+
.m-agreement {
|
|
500
|
+
display: flex;
|
|
501
|
+
align-items: flex-start;
|
|
502
|
+
justify-content: center;
|
|
503
|
+
gap: 0.6rem;
|
|
504
|
+
font-size: 0.75rem;
|
|
505
|
+
color: #94a3b8;
|
|
506
|
+
line-height: 1.5;
|
|
507
|
+
max-width: 80%;
|
|
508
|
+
margin: 0 auto;
|
|
509
|
+
padding: 0.8rem 1rem;
|
|
510
|
+
border-radius: 0.75rem;
|
|
511
|
+
transition: all 0.3s ease;
|
|
512
|
+
|
|
513
|
+
.agreement-icon {
|
|
514
|
+
margin-top: 0.15rem;
|
|
515
|
+
color: #64748b;
|
|
516
|
+
font-size: 0.875rem;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
.agreement-text {
|
|
520
|
+
text-align: left;
|
|
521
|
+
|
|
522
|
+
.u-link {
|
|
523
|
+
color: #6777ef;
|
|
524
|
+
font-weight: 600;
|
|
525
|
+
cursor: pointer;
|
|
526
|
+
text-decoration: underline;
|
|
527
|
+
text-underline-offset: 2px;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
443
531
|
}
|
|
444
532
|
|
|
445
533
|
.c-payment__header {
|
|
@@ -463,7 +551,7 @@ export default {
|
|
|
463
551
|
align-items: center;
|
|
464
552
|
gap: 0.5rem;
|
|
465
553
|
cursor: pointer;
|
|
466
|
-
border: 2px solid rgba(
|
|
554
|
+
border: 2px solid rgba(0, 0, 0, 0.05);
|
|
467
555
|
transition: all 0.3s;
|
|
468
556
|
background: transparent;
|
|
469
557
|
|
|
@@ -475,7 +563,6 @@ export default {
|
|
|
475
563
|
font-size: 0.75rem;
|
|
476
564
|
font-weight: 500;
|
|
477
565
|
}
|
|
478
|
-
|
|
479
566
|
}
|
|
480
567
|
.wepay-icon {
|
|
481
568
|
color: #10b981;
|
|
@@ -594,7 +681,11 @@ export default {
|
|
|
594
681
|
content: "";
|
|
595
682
|
position: absolute;
|
|
596
683
|
inset: 0;
|
|
597
|
-
background: linear-gradient(
|
|
684
|
+
background: linear-gradient(
|
|
685
|
+
180deg,
|
|
686
|
+
rgba(15, 23, 42, 0.85) 0%,
|
|
687
|
+
rgba(15, 23, 42, 0.95) 100%
|
|
688
|
+
);
|
|
598
689
|
z-index: 1;
|
|
599
690
|
}
|
|
600
691
|
|
|
@@ -3,12 +3,20 @@ export default {
|
|
|
3
3
|
wechat: "WeChat Pay",
|
|
4
4
|
alipay: "Alipay",
|
|
5
5
|
secureChannel: "Official Encrypted Payment Channel, Active Immediately",
|
|
6
|
+
wechatScan: "Scan the QR code with WeChat to pay",
|
|
7
|
+
alipayScan: "Scan the QR code with Alipay to pay",
|
|
6
8
|
|
|
7
9
|
createOrderFailed: "Failed to create order, please try again",
|
|
8
|
-
orderTimeout:
|
|
10
|
+
orderTimeout:
|
|
11
|
+
"Order processing timed out, please refresh and try again",
|
|
9
12
|
orderFailed: "Order processing failed, please try again",
|
|
10
13
|
getQrcodeFailed: "Failed to get payment QR code, please try again",
|
|
11
|
-
paymentTimeout:
|
|
14
|
+
paymentTimeout:
|
|
15
|
+
"Payment timed out, please contact customer service if you have paid",
|
|
12
16
|
paymentFailed: "Payment failed, please try again",
|
|
17
|
+
agreement_prefix: "Payment signifies agreement to the",
|
|
18
|
+
agreement_link: "Service Terms",
|
|
19
|
+
agreement_suffix:
|
|
20
|
+
", Virtual services are not eligible for 7-day unconditional refunds.",
|
|
13
21
|
},
|
|
14
|
-
}
|
|
22
|
+
};
|
|
@@ -3,6 +3,8 @@ export default {
|
|
|
3
3
|
wechat: "微信支付",
|
|
4
4
|
alipay: "支付宝",
|
|
5
5
|
secureChannel: "官方加密支付通道,即开即用",
|
|
6
|
+
wechatScan: "打开微信扫一扫即可支付",
|
|
7
|
+
alipayScan: "打开支付宝扫一扫即可支付",
|
|
6
8
|
|
|
7
9
|
createOrderFailed: "创建订单失败,请重试",
|
|
8
10
|
orderTimeout: "订单处理超时,请刷新重试",
|
|
@@ -10,5 +12,8 @@ export default {
|
|
|
10
12
|
getQrcodeFailed: "获取支付二维码失败,请重试",
|
|
11
13
|
paymentTimeout: "支付超时,如已支付请联系客服",
|
|
12
14
|
paymentFailed: "支付失败,请重试",
|
|
15
|
+
agreement_prefix: "支付即视为同意",
|
|
16
|
+
agreement_link: "服务条款",
|
|
17
|
+
agreement_suffix: ",虚拟服务不支持7天无理由退款",
|
|
13
18
|
},
|
|
14
|
-
}
|
|
19
|
+
};
|