fix: 隔离抖音当前支付订单与缓存旧单
This commit is contained in:
+13
-24
@@ -79,7 +79,8 @@ async function showState(state, key, orderNum) {
|
||||
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.
|
||||
// Only called when the CURRENT server response names the cached transaction.
|
||||
// A payment click for another product must never authorize this old transaction.
|
||||
async function continuePendingPayment(key, orderNum) {
|
||||
const response = await request({ url: '/payment/douyin/resume', method: 'POST',
|
||||
data: { orderNum }, isShowLoading: false, timeout: 60000 });
|
||||
@@ -148,10 +149,10 @@ async function executePayment(payment, key) {
|
||||
// #endif
|
||||
}
|
||||
|
||||
// Runs on the payment click BEFORE creating an order. Resume a live original transaction directly.
|
||||
// Like WeChat/Alipay, let the current checkout/recharge/order-payment request
|
||||
// choose the transaction. The account-wide recovery record is NOT that choice.
|
||||
export async function prepareDouyinPay(payway) {
|
||||
if (payway !== 'douyin') return true;
|
||||
let paymentKey = '';
|
||||
try {
|
||||
// #ifndef APP-PLUS
|
||||
throw new Error('抖音支付仅支持 Android/iOS App');
|
||||
@@ -159,29 +160,11 @@ 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 {
|
||||
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; }
|
||||
}
|
||||
if (!canOpenDypay()) throw new Error('请先安装或升级抖音客户端');
|
||||
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;
|
||||
}
|
||||
@@ -200,10 +183,16 @@ export async function appDypayFun(payment) {
|
||||
try {
|
||||
if (!key || !payment.orderNum) throw new Error('登录身份或支付订单编号缺失');
|
||||
const previous = uni.getStorageSync(key);
|
||||
if (previous) {
|
||||
// Even legacy callers must not open a different payment while the saved one is unresolved.
|
||||
return await continuePendingPayment(key, previous);
|
||||
if (previous === payment.orderNum) {
|
||||
// An explicit retry of this same server-selected order still needs reconciliation.
|
||||
failureShown.delete(key);
|
||||
return await continuePendingPayment(key, payment.orderNum);
|
||||
}
|
||||
// Validate the CURRENT response before releasing any stale native callback.
|
||||
// This only resets the client bridge, not the previous server order. Its
|
||||
// settlement remains handled by backend callbacks/query jobs/order details.
|
||||
toSdkPayInfo(payment);
|
||||
if (previous) resetDypay();
|
||||
return await executePayment(payment, key);
|
||||
} catch (error) {
|
||||
if (key && key === accountKey()) {
|
||||
|
||||
Reference in New Issue
Block a user