diff --git a/pages/recharge.vue b/pages/recharge.vue
index 4be3953..f7690e6 100644
--- a/pages/recharge.vue
+++ b/pages/recharge.vue
@@ -197,6 +197,11 @@
:class="{ active: payChannel === 'epay' }"
@click="payChannel = 'epay'"
>USDT (TRC20)
+ Ngân hàng QR
- {{ payChannel === 'epay' ? 'Nhập số tiền theo VND — hệ thống tự động quy đổi sang USDT theo tỷ giá 1 USDT ≈ 27,100 VND. Thanh toán qua mạng TRC20.' : $lang.rechargeTip }}
+ {{ payChannel === 'epay' ? 'Nhập số tiền theo VND — hệ thống tự động quy đổi sang USDT theo tỷ giá 1 USDT ≈ 27,100 VND. Thanh toán qua mạng TRC20.' : (payChannel === 'ccpay' ? 'Nhập số tiền VND — hệ thống tạo mã QR ngân hàng. Quét mã thanh toán qua ứng dụng ngân hàng.' : $lang.rechargeTip) }}
@@ -272,6 +277,45 @@
+
+
+
+
+ ×
+ Ngân hàng QR
+ {{ bankQr.statusText }}
+
+
+
+
+
+
+ Số tài khoản
+
+ {{ bankQr.data.bank_account }}
+
+ {{ epayQr.copied === 'bank_acc' ? '✓' : 'Copy' }}
+
+
+
+
+
+ Tên tài khoản — Ngân hàng
+
+ {{ bankQr.data.bank_name }} — {{ bankQr.data.bank_short }}
+
+
+
+
+ {{ Number(bankQr.data.amount).toLocaleString() }} VND
+ ⏱ {{ bankQr.countdownText }}
+
+
+
+ ⚠ Vui lòng chuyển khoản chính xác số tiền. Sai thông tin sẽ không thể xác nhận đơn hàng!
+
+
+
@@ -308,6 +352,16 @@ export default {
},
_epayPollTimer: null,
_epayCountdownTimer: null,
+ bankQr: {
+ visible: false,
+ data: { bank_account: "", bank_name: "", bank_short: "", qr_data: "", amount: 0, order_sn: "", expires_at: 0, timeout_sec: 600 },
+ qrDataUrl: "",
+ countdownText: "",
+ statusText: "",
+ statusClass: "waiting",
+ },
+ _bankPollTimer: null,
+ _bankCountdownTimer: null,
};
},
computed: {
@@ -603,9 +657,102 @@ export default {
this._epayCountdownTimer = null;
}
},
+ submitCcpay() {
+ if (!this.amount || this.amount <= 0) {
+ this.$toast({ message: 'Vui lòng nhập số tiền', duration: 2000 });
+ return;
+ }
+ if (this.amount < 1000000) {
+ this.$toast({ message: 'Số tiền tối thiểu là 1,000,000', duration: 2000 });
+ return;
+ }
+ const params = {
+ user_id: this.userInfo.id,
+ price: this.amount,
+ client: 3,
+ username: this.userInfo.username,
+ };
+ this.$toast({ type: "loading", message: `${this.$lang.submit}...`, duration: 200000 });
+ this.$api
+ .ccpayDeposit(params)
+ .then((res) => {
+ const d = res.Data || {};
+ if (d.status == 1 && d.qrcode) {
+ this.openBankQr(d.qrcode);
+ } else if (d.status == 1 && d.url) {
+ const isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
+ if (isiOS) window.location.href = d.url; else window.open(d.url, "_blank");
+ } else {
+ this.$toast({ message: d.message || 'Nạp thất bại', duration: 2000 });
+ }
+ })
+ .catch((err) => { console.log(err); })
+ .finally(() => { this.$toastHide(); });
+ },
+ openBankQr(qrcode) {
+ this.bankQr.data = qrcode;
+ this.bankQr.statusText = "Đang chờ thanh toán...";
+ this.bankQr.statusClass = "waiting";
+ try {
+ this.bankQr.qrDataUrl = qrcode.qr_data
+ ? "data:image/png;base64," + uni.arrayBufferToBase64(qr.imageSync(qrcode.qr_data, { margin: 2 }))
+ : "";
+ } catch (e) { this.bankQr.qrDataUrl = ""; }
+ this.bankQr.visible = true;
+ this.startBankCountdown();
+ this.startBankPolling();
+ },
+ startBankCountdown() {
+ const tick = () => {
+ const left = Math.max(0, this.bankQr.data.expires_at - Math.floor(Date.now() / 1000));
+ const m = Math.floor(left / 60);
+ const s = left % 60;
+ this.bankQr.countdownText = (m < 10 ? "0" : "") + m + ":" + (s < 10 ? "0" : "") + s;
+ if (left <= 0) {
+ this.bankQr.statusText = "Đơn hàng đã hết hạn";
+ this.bankQr.statusClass = "expired";
+ this.stopBankTimers();
+ }
+ };
+ tick();
+ this._bankCountdownTimer = setInterval(tick, 1000);
+ },
+ startBankPolling() {
+ const poll = () => {
+ if (!this.bankQr.visible || !this.bankQr.data.order_sn) return;
+ this.$api
+ .ccpayOrderStatus({ user_id: this.userInfo.id, order_sn: this.bankQr.data.order_sn })
+ .then((res) => {
+ const d = res.Data || {};
+ if (d.status == 1) {
+ this.bankQr.statusText = "Thanh toán thành công!";
+ this.bankQr.statusClass = "success";
+ this.stopBankTimers();
+ this.$store.dispatch("app/getUserInfo");
+ setTimeout(() => this.closeBankQr(), 2500);
+ } else if (d.status == 2) {
+ this.bankQr.statusText = "Đơn hàng đã hết hạn";
+ this.bankQr.statusClass = "expired";
+ this.stopBankTimers();
+ }
+ })
+ .catch(() => {});
+ };
+ this._bankPollTimer = setInterval(poll, 3000);
+ setTimeout(poll, 1000);
+ },
+ closeBankQr() {
+ this.bankQr.visible = false;
+ this.stopBankTimers();
+ },
+ stopBankTimers() {
+ if (this._bankPollTimer) { clearInterval(this._bankPollTimer); this._bankPollTimer = null; }
+ if (this._bankCountdownTimer) { clearInterval(this._bankCountdownTimer); this._bankCountdownTimer = null; }
+ },
},
beforeDestroy() {
this.stopEpayTimers();
+ this.stopBankTimers();
},
};
diff --git a/request/api.js b/request/api.js
index 12757f2..53e082f 100644
--- a/request/api.js
+++ b/request/api.js
@@ -65,6 +65,14 @@ let api = {
epayOrderStatus: async (params) => {
return await ajax.post("/epay_order_status", params);
},
+ // CCpay越南银行QR充值
+ ccpayDeposit: async (params) => {
+ return await ajax.post("/ccpay_online_order", params);
+ },
+ // CCpay订单状态轮询
+ ccpayOrderStatus: async (params) => {
+ return await ajax.post("/ccpay_order_status", params);
+ },
// 越南银行卡提现
applyWithdrawBank: async (params) => {
return await ajax.post("/apply_withdraw_bank", params);