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