This commit is contained in:
zhx 2026-06-22 16:55:31 +08:00
parent 00cdea1a49
commit 82f430c83d

View File

@ -1055,10 +1055,12 @@
<script src="../common/toast.js"></script>
<script>
(function () {
var PENDING_MIFAPAY_ORDER_KEY =
var PENDING_EXTERNAL_ORDER_KEY =
'hyapp_recharge_pending_external_order';
var LEGACY_PENDING_MIFAPAY_ORDER_KEY =
'hyapp_recharge_pending_mifapay_order';
var RETURN_MIFAPAY_ORDER_QUERY_KEY = 'hyapp_order_id';
var PENDING_MIFAPAY_MAX_AGE_MS = 24 * 60 * 60 * 1000;
var PENDING_EXTERNAL_MAX_AGE_MS = 24 * 60 * 60 * 1000;
var state = {
context: null,
options: null,
@ -1069,8 +1071,8 @@
pollingTimer: 0,
loading: false,
orderNoticeKey: '',
confirmingMifaPay: false,
lastMifaPayResumeAtMS: 0,
confirmingExternalPayment: false,
lastExternalResumeAtMS: 0,
};
var nodes = {};
@ -1141,7 +1143,7 @@
? window.HyAppParams.parse()
: { raw: currentRawParams() };
var raw = current.raw || currentRawParams();
var pendingOrder = readPendingMifaPayOrder();
var pendingOrder = readPendingExternalOrder();
var displayUserID =
raw.get('display_user_id') ||
(pendingOrder && pendingOrder.display_user_id) ||
@ -1181,11 +1183,11 @@
nodes.copyAddress.addEventListener('click', copyAddress);
nodes.copyOrderID.addEventListener('click', copyOrderID);
nodes.txForm.addEventListener('submit', submitTx);
window.addEventListener('pageshow', resumeMifaPayOrder);
window.addEventListener('focus', resumeMifaPayOrder);
window.addEventListener('pageshow', resumeExternalOrder);
window.addEventListener('focus', resumeExternalOrder);
document.addEventListener(
'visibilitychange',
resumeVisibleMifaPayOrder
resumeVisibleExternalOrder
);
window.addEventListener('hyapp:i18n-ready', function () {
document.title = t(
@ -1228,7 +1230,7 @@
state.order = null;
state.orderModalOpen = false;
render();
restorePendingMifaPayOrder();
restorePendingExternalOrder();
})
.catch(function (error) {
toast(
@ -1366,7 +1368,7 @@
});
}
// 支付方式展示由当前商品驱动USDT 用订单美元金额,MiFaPay 用后台汇率换算本币金额。
// 支付方式展示由当前商品驱动USDT 用订单美元金额,三方本地支付用后台汇率换算本币金额。
function renderMethods() {
var methods = availableMethods();
var hasProduct = !!selectedProduct();
@ -1455,9 +1457,7 @@
nodes.usdtPanel.classList.toggle('hidden', !isUSDT);
nodes.mifapayPanel.classList.toggle(
'hidden',
order.provider_code !== 'mifapay' ||
!order.pay_url ||
isTerminalOrder(order)
!isRedirectPaymentOrder(order)
);
if (order.provider_code === 'usdt_trc20') {
nodes.receiveAddress.textContent =
@ -1477,10 +1477,10 @@
order.failure_reason ||
t('recharge.orderFailed', 'Order failed')
);
} else if (order.provider_code === 'mifapay') {
} else if (isRedirectPaymentProvider(order.provider_code)) {
setStatus(
nodes.orderMessage,
state.confirmingMifaPay
state.confirmingExternalPayment
? t(
'recharge.confirmingPayment',
'Confirming payment status...'
@ -1496,7 +1496,7 @@
}
// 可用支付方式只在选中商品后生成,避免用户先选支付方式再切商品造成金额不一致。
// MiFaPay 方式必须是 activeUSDT 必须同时有开关和收款地址,缺地址时不展示。
// 三方本地支付方式必须是 activeUSDT 必须同时有开关和收款地址,缺地址时不展示。
function availableMethods() {
var product = selectedProduct();
if (!product) return [];
@ -1517,7 +1517,7 @@
}
((state.options && state.options.payment_methods) || [])
.filter(function (method) {
// GLOBAL 是 MiFaPay 跨国兜底方式,当前充值页只展示用户所在国家的具体支付方式。
// GLOBAL 是跨国兜底方式,当前充值页只展示用户所在国家的具体支付方式。
return (
method.status === 'active' &&
String(
@ -1527,7 +1527,10 @@
})
.forEach(function (method) {
methods.push({
key: 'mifapay:' + method.method_id,
key:
(method.provider_code || 'mifapay') +
':' +
method.method_id,
icon: method.currency_code || 'PAY',
name:
method.method_name ||
@ -1537,7 +1540,6 @@
'Local payment'
),
meta: [
method.provider_name,
method.country_name || method.country_code,
method.pay_type,
]
@ -1545,7 +1547,8 @@
.join(' · '),
logoURL: method.logo_url || '',
amount: convertedAmount(product, method),
providerCode: 'mifapay',
providerCode:
method.provider_code || 'mifapay',
methodID: method.method_id,
});
});
@ -1565,7 +1568,7 @@
}
// 创建订单时只提交 product_id、provider 和 method_id金额、金币、币商/普通钱包都由服务端订单快照决定。
// MiFaPay 创建成功后必须立刻跳三方收银台;本页保存 order_id支付完成 return 回来后继续轮询状态。
// 三方支付创建成功后必须立刻跳收银台;本页保存 order_id支付完成 return 回来后继续轮询状态。
function createOrder() {
var product = selectedProduct();
var method = selectedMethod();
@ -1582,7 +1585,7 @@
provider_code: method.providerCode,
payment_method_id: method.methodID || 0,
command_id: commandID(product, method),
return_url: mifaPayReturnURL(),
return_url: externalPayReturnURL(),
})
.then(function (payload) {
state.order = payload.order || payload;
@ -1594,10 +1597,9 @@
}
startPolling();
if (
state.order.provider_code === 'mifapay' &&
state.order.pay_url
isRedirectPaymentOrder(state.order)
) {
savePendingMifaPayOrder(state.order);
savePendingExternalOrder(state.order);
window.location.href = state.order.pay_url;
}
})
@ -1688,8 +1690,8 @@
applyOrderTerminalSideEffects(state.order);
return Promise.resolve(state.order);
}
if (state.order.provider_code === 'mifapay') {
state.confirmingMifaPay = true;
if (isRedirectPaymentProvider(state.order.provider_code)) {
state.confirmingExternalPayment = true;
state.orderModalOpen = true;
renderOrder();
}
@ -1704,8 +1706,8 @@
.catch(function () {});
}
function restorePendingMifaPayOrder() {
var pending = readPendingMifaPayOrder();
function restorePendingExternalOrder() {
var pending = readPendingExternalOrder();
if (!pending) return;
if (
state.order &&
@ -1726,13 +1728,13 @@
state.order &&
state.order.order_id === pending.order_id
) {
state.confirmingMifaPay = true;
state.confirmingExternalPayment = true;
state.orderModalOpen = true;
renderOrder();
startPolling();
return;
}
state.confirmingMifaPay = true;
state.confirmingExternalPayment = true;
window.HyAppAPI.recharge
.getOrder(
pending.order_id,
@ -1748,46 +1750,46 @@
}
})
.catch(function () {
clearPendingMifaPayOrder(pending.order_id);
clearPendingExternalOrder(pending.order_id);
});
}
function resumeVisibleMifaPayOrder() {
function resumeVisibleExternalOrder() {
if (
document.visibilityState &&
document.visibilityState !== 'visible'
) {
return;
}
resumeMifaPayOrder();
resumeExternalOrder();
}
function resumeMifaPayOrder() {
function resumeExternalOrder() {
if (!state.context) return;
if (Date.now() - state.lastMifaPayResumeAtMS < 800) {
if (Date.now() - state.lastExternalResumeAtMS < 800) {
return;
}
state.lastMifaPayResumeAtMS = Date.now();
state.lastExternalResumeAtMS = Date.now();
if (
state.order &&
state.order.provider_code === 'mifapay' &&
isRedirectPaymentProvider(state.order.provider_code) &&
!isTerminalOrder(state.order)
) {
state.confirmingMifaPay = true;
state.confirmingExternalPayment = true;
state.orderModalOpen = true;
renderOrder();
startPolling();
return;
}
restorePendingMifaPayOrder();
restorePendingExternalOrder();
}
function applyOrderTerminalSideEffects(order) {
if (!isTerminalOrder(order)) {
return;
}
state.confirmingMifaPay = false;
clearPendingMifaPayOrder(order.order_id);
state.confirmingExternalPayment = false;
clearPendingExternalOrder(order.order_id);
clearReturnedMifaPayOrderQuery();
window.clearInterval(state.pollingTimer);
if (order.status === 'credited') {
@ -1807,37 +1809,40 @@
}
}
function savePendingMifaPayOrder(order) {
function savePendingExternalOrder(order) {
if (!order || !order.order_id) return;
storageSet(
PENDING_MIFAPAY_ORDER_KEY,
PENDING_EXTERNAL_ORDER_KEY,
JSON.stringify({
order_id: order.order_id,
display_user_id: currentAccountDisplayUserID(),
created_at_ms: Date.now(),
})
);
storageRemove(LEGACY_PENDING_MIFAPAY_ORDER_KEY);
}
function readPendingMifaPayOrder() {
function readPendingExternalOrder() {
var returned = readReturnedMifaPayOrder();
if (returned) return returned;
try {
var raw = storageGet(PENDING_MIFAPAY_ORDER_KEY);
var raw =
storageGet(PENDING_EXTERNAL_ORDER_KEY) ||
storageGet(LEGACY_PENDING_MIFAPAY_ORDER_KEY);
if (!raw) return null;
var parsed = JSON.parse(raw);
if (!parsed || !parsed.order_id) return null;
if (
Number(parsed.created_at_ms || 0) > 0 &&
Date.now() - Number(parsed.created_at_ms) >
PENDING_MIFAPAY_MAX_AGE_MS
PENDING_EXTERNAL_MAX_AGE_MS
) {
clearPendingMifaPayOrder(parsed.order_id);
clearPendingExternalOrder(parsed.order_id);
return null;
}
return parsed;
} catch (error) {
clearPendingMifaPayOrder('');
clearPendingExternalOrder('');
return null;
}
}
@ -1857,11 +1862,13 @@
};
}
function clearPendingMifaPayOrder(orderID) {
function clearPendingExternalOrder(orderID) {
var pending = null;
try {
pending = JSON.parse(
storageGet(PENDING_MIFAPAY_ORDER_KEY) || 'null'
storageGet(PENDING_EXTERNAL_ORDER_KEY) ||
storageGet(LEGACY_PENDING_MIFAPAY_ORDER_KEY) ||
'null'
);
} catch (error) {
pending = null;
@ -1872,7 +1879,8 @@
!pending.order_id ||
pending.order_id === orderID
) {
storageRemove(PENDING_MIFAPAY_ORDER_KEY);
storageRemove(PENDING_EXTERNAL_ORDER_KEY);
storageRemove(LEGACY_PENDING_MIFAPAY_ORDER_KEY);
}
}
@ -2076,7 +2084,21 @@
);
}
function mifaPayReturnURL() {
function isRedirectPaymentProvider(providerCode) {
var normalized = String(providerCode || '').toLowerCase();
return !!normalized && normalized !== 'usdt_trc20';
}
function isRedirectPaymentOrder(order) {
return (
!!order &&
isRedirectPaymentProvider(order.provider_code) &&
!!order.pay_url &&
!isTerminalOrder(order)
);
}
function externalPayReturnURL() {
try {
var url = new URL(window.location.href);
var displayUserID =
@ -2170,7 +2192,7 @@
return Math.random().toString(36).slice(2, 14);
}
// MiFaPay 国家方式按后台 USD->本币汇率展示;无有效汇率时回退 USD 展示但后端仍会拒绝不可用配置。
// 本地三方支付按后台 USD->本币汇率展示;无有效汇率时回退 USD 展示但后端仍会拒绝不可用配置。
function convertedAmount(product, method) {
var usd = productUSD(product);
var rate = Number(method.usd_to_currency_rate || 0);