fix: 对齐抖音支付失败及杀进程恢复跳转
This commit is contained in:
+39
-10
@@ -5,12 +5,13 @@ import request from './request.js';
|
||||
import { BASE_URL } from './config.js';
|
||||
import { TOKEN_NAME, USER_DATA } from './auth.js';
|
||||
import { toSdkPayInfo, queryUntilSettled } from './douyin-pay-adapter.mjs';
|
||||
import { jumpToPaymentSuccess } from './payment-navigation.js';
|
||||
import { jumpToPaymentSuccess, jumpToPaymentFailure } from './payment-navigation.js';
|
||||
|
||||
let active = false;
|
||||
let resuming = false;
|
||||
let inFlight = null;
|
||||
let checkingForeground = false;
|
||||
const failureShown = new Map();
|
||||
function accountKey() {
|
||||
if (!uni.getStorageSync(TOKEN_NAME)) return '';
|
||||
const user = uni.getStorageSync(USER_DATA) || {};
|
||||
@@ -57,12 +58,25 @@ async function showState(state, key, orderNum) {
|
||||
uni.showToast({ title: '支付成功,请在订单中查看', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
failureShown.delete(key);
|
||||
} else {
|
||||
// Same failure page as WeChat/Alipay. Ending the UI attempt is not a channel close.
|
||||
// Keep unresolved orders for reconciliation, but do not push the page on every onShow.
|
||||
const alreadyShown = failureShown.get(key) === orderNum;
|
||||
if (!alreadyShown) {
|
||||
const navigated = await jumpToPaymentFailure();
|
||||
if (key !== accountKey()) return;
|
||||
if (!navigated) {
|
||||
uni.showToast({ title: '支付未完成,请查看订单', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
failureShown.set(key, orderNum);
|
||||
} else if (state.state === 'pending') return;
|
||||
}
|
||||
if (state.state !== 'pending' && uni.getStorageSync(key) === orderNum) uni.removeStorageSync(key);
|
||||
uni.$emit('douyin-payment-result', { orderNum, state: state.state });
|
||||
if (state.state === 'paid' || state.state === 'closed') return;
|
||||
uni.showToast({ title: state.state === 'failed' ? '支付未成功,请查看订单'
|
||||
: state.message || '支付结果待确认,请稍后查看订单', icon: 'none', duration: 2500 });
|
||||
if (state.state !== 'pending') return;
|
||||
uni.showToast({ title: state.message || '支付结果待确认,请稍后查看订单', icon: 'none', duration: 2500 });
|
||||
}
|
||||
|
||||
// Called only by a user payment action, never by onShow. Renew the SAME transaction on the server.
|
||||
@@ -108,6 +122,7 @@ async function executePayment(payment, key) {
|
||||
throw new Error('支付初始化失败,请稍后重试');
|
||||
}
|
||||
// Persist before entering native code so a killed process remains recoverable.
|
||||
failureShown.delete(key);
|
||||
uni.setStorageSync(key, payment.orderNum);
|
||||
const session = { key, orderNum: payment.orderNum, settled: false, finish: null };
|
||||
inFlight = session;
|
||||
@@ -136,6 +151,7 @@ async function executePayment(payment, key) {
|
||||
// Runs on the payment click BEFORE creating an order. Resume a live original transaction directly.
|
||||
export async function prepareDouyinPay(payway) {
|
||||
if (payway !== 'douyin') return true;
|
||||
let paymentKey = '';
|
||||
try {
|
||||
// #ifndef APP-PLUS
|
||||
throw new Error('抖音支付仅支持 Android/iOS App');
|
||||
@@ -143,15 +159,17 @@ export async function prepareDouyinPay(payway) {
|
||||
// #ifdef APP-PLUS
|
||||
if (active || resuming) throw new Error('正在处理支付,请勿重复点击');
|
||||
const key = accountKey();
|
||||
paymentKey = key;
|
||||
if (!key) throw new Error('请先登录后再支付');
|
||||
const previous = uni.getStorageSync(key);
|
||||
if (previous) {
|
||||
failureShown.delete(key);
|
||||
resuming = true;
|
||||
try {
|
||||
const result = await continuePendingPayment(key, previous);
|
||||
if (result.state !== 'closed' || key !== accountKey() || uni.getStorageSync(key)) return false;
|
||||
if (!canOpenDypay()) throw new Error('请先安装或升级抖音客户端');
|
||||
return true;
|
||||
await continuePendingPayment(key, previous);
|
||||
// A completed/closed attempt has already entered its result page. Do not create
|
||||
// another order behind that page during the same click.
|
||||
return false;
|
||||
}
|
||||
finally { resuming = false; }
|
||||
}
|
||||
@@ -159,6 +177,11 @@ export async function prepareDouyinPay(payway) {
|
||||
return true;
|
||||
// #endif
|
||||
} catch (error) {
|
||||
const pending = paymentKey && paymentKey === accountKey() && uni.getStorageSync(paymentKey);
|
||||
if (pending) {
|
||||
await showState({ state: 'pending', message: error.message }, paymentKey, pending);
|
||||
return false;
|
||||
}
|
||||
uni.showToast({ title: error.message || '暂时无法支付,请稍后重试', icon: 'none' });
|
||||
return false;
|
||||
}
|
||||
@@ -183,7 +206,9 @@ export async function appDypayFun(payment) {
|
||||
}
|
||||
return await executePayment(payment, key);
|
||||
} catch (error) {
|
||||
if (key === accountKey()) uni.showToast({ title: error.message || '支付结果待确认,请查看订单', icon: 'none' });
|
||||
if (key && key === accountKey()) {
|
||||
await showState({ state: 'pending', message: error.message || '支付结果待确认,请查看订单' }, key, payment?.orderNum || '');
|
||||
}
|
||||
return { state: 'error', message: error.message || '支付结果待确认,请查看订单' };
|
||||
} finally { active = false; }
|
||||
// #endif
|
||||
@@ -217,7 +242,11 @@ export async function resumeDouyinPay() {
|
||||
if (key === accountKey() && state.state !== 'pending') resetDypay();
|
||||
await showState(state, key, pending);
|
||||
}
|
||||
catch (_) { /* Keep the order for a later onShow. Never infer a payment failure. */ }
|
||||
catch (_) {
|
||||
// The interrupted attempt uses the existing failure page, without marking the
|
||||
// server transaction failed or forgetting an order whose result is still unknown.
|
||||
await showState({ state: 'pending', message: '支付结果待确认,请稍后查看订单' }, key, pending);
|
||||
}
|
||||
finally { resuming = false; }
|
||||
// #endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user