fix: 修复微信支付回跳刷新与查单确认
This commit is contained in:
@@ -70,6 +70,7 @@ import {
|
||||
import { copyTextToClipboard } from '../../services/clipboard';
|
||||
import {
|
||||
claimRpgProfileTaskReward,
|
||||
confirmWechatRpgProfileRechargeOrder,
|
||||
createRpgProfileRechargeOrder,
|
||||
getRpgProfileReferralInviteCenter,
|
||||
getRpgProfileRechargeCenter,
|
||||
@@ -216,6 +217,11 @@ const WECHAT_JS_SDK_URL = 'https://res.wx.qq.com/open/js/jweixin-1.6.0.js';
|
||||
type ProfilePopupPanel = 'invite' | 'redeem' | 'community';
|
||||
type RechargeTab = 'points' | 'membership';
|
||||
type WechatMiniProgramPaymentStatus = 'success' | 'fail' | 'cancel';
|
||||
type WechatPayResult = {
|
||||
requestId: string;
|
||||
orderId: string | null;
|
||||
status: WechatMiniProgramPaymentStatus;
|
||||
};
|
||||
type DiscoverChannel =
|
||||
| 'recommend'
|
||||
| 'today'
|
||||
@@ -2342,6 +2348,37 @@ function clearWechatPayResultHash() {
|
||||
window.history.replaceState(null, '', nextUrl);
|
||||
}
|
||||
|
||||
function readWechatPayResultFromHash(): WechatPayResult | null {
|
||||
if (typeof window === 'undefined') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const result = new URLSearchParams(
|
||||
window.location.hash.replace(/^#/, ''),
|
||||
).get('wx_pay_result');
|
||||
if (!result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [requestId = '', rawStatus = ''] = result.split(':');
|
||||
const orderId = requestId
|
||||
.replace(/^wechat_pay_/, '')
|
||||
.replace(/_\d+$/, '')
|
||||
.trim();
|
||||
const status =
|
||||
rawStatus === 'success'
|
||||
? 'success'
|
||||
: rawStatus === 'cancel'
|
||||
? 'cancel'
|
||||
: 'fail';
|
||||
|
||||
return {
|
||||
requestId,
|
||||
orderId: orderId || null,
|
||||
status,
|
||||
};
|
||||
}
|
||||
|
||||
function loadWechatJsSdk() {
|
||||
if (typeof window === 'undefined') {
|
||||
return Promise.reject(new Error('请在微信小程序内完成支付'));
|
||||
@@ -2385,7 +2422,7 @@ function loadWechatJsSdk() {
|
||||
async function requestWechatMiniProgramPayment(
|
||||
payload: WechatMiniProgramPayParams | null | undefined,
|
||||
orderId: string,
|
||||
) {
|
||||
): Promise<void> {
|
||||
if (!payload) {
|
||||
return Promise.reject(new Error('请在微信小程序内完成支付'));
|
||||
}
|
||||
@@ -2396,35 +2433,20 @@ async function requestWechatMiniProgramPayment(
|
||||
}
|
||||
const navigateTo = miniProgram.navigateTo;
|
||||
|
||||
return new Promise<WechatMiniProgramPaymentStatus>((resolve) => {
|
||||
const requestId = `wechat_pay_${orderId}_${Date.now()}`;
|
||||
const handleHashChange = () => {
|
||||
const params = new URLSearchParams(
|
||||
window.location.hash.replace(/^#/, ''),
|
||||
);
|
||||
const result = params.get('wx_pay_result') ?? '';
|
||||
const [resultRequestId, status] = result.split(':');
|
||||
if (resultRequestId !== requestId) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.removeEventListener('hashchange', handleHashChange);
|
||||
resolve(
|
||||
status === 'success'
|
||||
? 'success'
|
||||
: status === 'cancel'
|
||||
? 'cancel'
|
||||
: 'fail',
|
||||
);
|
||||
};
|
||||
|
||||
window.addEventListener('hashchange', handleHashChange);
|
||||
const requestId = `wechat_pay_${orderId}_${Date.now()}`;
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
navigateTo({
|
||||
url: `/pages/wechat-pay/index?requestId=${encodeURIComponent(requestId)}&orderId=${encodeURIComponent(orderId)}&payParams=${encodeURIComponent(JSON.stringify(payload))}`,
|
||||
success() {
|
||||
resolve();
|
||||
},
|
||||
fail(error) {
|
||||
window.removeEventListener('hashchange', handleHashChange);
|
||||
console.error('[wechat-pay] navigateTo failed', error);
|
||||
resolve('fail');
|
||||
reject(
|
||||
error instanceof Error
|
||||
? error
|
||||
: new Error('请在微信小程序内完成支付'),
|
||||
);
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -3368,6 +3390,7 @@ export function RpgEntryHomeView({
|
||||
useState<LegalDocumentId | null>(null);
|
||||
const profileCopyResetTimerRef = useRef<number | null>(null);
|
||||
const avatarFileInputRef = useRef<HTMLInputElement | null>(null);
|
||||
const pendingWechatRechargeOrderIdRef = useRef<string | null>(null);
|
||||
const [isNicknameModalOpen, setIsNicknameModalOpen] = useState(false);
|
||||
const [nicknameInput, setNicknameInput] = useState('');
|
||||
const [nicknameError, setNicknameError] = useState<string | null>(null);
|
||||
@@ -3823,6 +3846,55 @@ export function RpgEntryHomeView({
|
||||
})
|
||||
.finally(() => setIsLoadingRechargeCenter(false));
|
||||
};
|
||||
const refreshRechargeState = useCallback(
|
||||
() => {
|
||||
loadRechargeCenter();
|
||||
setSubmittingRechargeProductId(null);
|
||||
pendingWechatRechargeOrderIdRef.current = null;
|
||||
},
|
||||
[loadRechargeCenter],
|
||||
);
|
||||
const handleWechatPayResult = useCallback(() => {
|
||||
const payResult = readWechatPayResultFromHash();
|
||||
if (!payResult) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
pendingWechatRechargeOrderIdRef.current &&
|
||||
payResult.orderId &&
|
||||
payResult.orderId !== pendingWechatRechargeOrderIdRef.current
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (payResult.status === 'success') {
|
||||
setRechargeSuccess('支付已提交');
|
||||
if (payResult.orderId) {
|
||||
void confirmWechatRpgProfileRechargeOrder(payResult.orderId)
|
||||
.then((response) => {
|
||||
setRechargeCenter(response.center);
|
||||
setRechargeSuccess(
|
||||
response.order.status === 'paid' ? '已到账' : '支付已提交',
|
||||
);
|
||||
setSubmittingRechargeProductId(null);
|
||||
pendingWechatRechargeOrderIdRef.current = null;
|
||||
})
|
||||
.catch(() => refreshRechargeState());
|
||||
} else {
|
||||
refreshRechargeState();
|
||||
}
|
||||
void onRechargeSuccess?.();
|
||||
} else if (payResult.status === 'cancel') {
|
||||
setRechargeSuccess('支付已取消');
|
||||
refreshRechargeState();
|
||||
} else {
|
||||
setRechargeError('微信支付未完成');
|
||||
refreshRechargeState();
|
||||
}
|
||||
|
||||
clearWechatPayResultHash();
|
||||
}, [onRechargeSuccess, refreshRechargeState]);
|
||||
const openRechargeModal = () => {
|
||||
if (!authUi?.user) {
|
||||
authUi?.openLoginModal();
|
||||
@@ -3847,63 +3919,44 @@ export function RpgEntryHomeView({
|
||||
void createRpgProfileRechargeOrder(product.productId, paymentChannel)
|
||||
.then(async (response) => {
|
||||
if (paymentChannel === WECHAT_MINI_PROGRAM_PAYMENT_CHANNEL) {
|
||||
const status = await requestWechatMiniProgramPayment(
|
||||
pendingWechatRechargeOrderIdRef.current = response.order.orderId;
|
||||
await requestWechatMiniProgramPayment(
|
||||
response.wechatMiniProgramPayParams,
|
||||
response.order.orderId,
|
||||
);
|
||||
if (status === 'cancel') {
|
||||
setRechargeCenter(response.center);
|
||||
setRechargeSuccess('支付已取消');
|
||||
return;
|
||||
}
|
||||
if (status !== 'success') {
|
||||
throw new Error('微信支付未完成');
|
||||
}
|
||||
setRechargeSuccess('支付已提交');
|
||||
loadRechargeCenter();
|
||||
setRechargeCenter(response.center);
|
||||
return;
|
||||
} else {
|
||||
setRechargeCenter(response.center);
|
||||
setRechargeSuccess('已到账');
|
||||
pendingWechatRechargeOrderIdRef.current = null;
|
||||
setSubmittingRechargeProductId(null);
|
||||
}
|
||||
void onRechargeSuccess?.();
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
pendingWechatRechargeOrderIdRef.current = null;
|
||||
setRechargeError(error instanceof Error ? error.message : '充值失败');
|
||||
})
|
||||
.finally(() => setSubmittingRechargeProductId(null));
|
||||
setSubmittingRechargeProductId(null);
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
if (!isRechargeOpen) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const handleWechatPayResult = () => {
|
||||
const result = new URLSearchParams(
|
||||
window.location.hash.replace(/^#/, ''),
|
||||
).get('wx_pay_result');
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
const [, status] = result.split(':');
|
||||
if (status === 'success') {
|
||||
setRechargeSuccess('支付已提交');
|
||||
loadRechargeCenter();
|
||||
void onRechargeSuccess?.();
|
||||
clearWechatPayResultHash();
|
||||
} else if (status === 'cancel') {
|
||||
setRechargeSuccess('支付已取消');
|
||||
clearWechatPayResultHash();
|
||||
} else {
|
||||
setRechargeError('微信支付未完成');
|
||||
clearWechatPayResultHash();
|
||||
}
|
||||
const handleResume = () => {
|
||||
handleWechatPayResult();
|
||||
};
|
||||
|
||||
window.addEventListener('hashchange', handleWechatPayResult);
|
||||
handleWechatPayResult();
|
||||
return () =>
|
||||
window.removeEventListener('hashchange', handleWechatPayResult);
|
||||
}, [isRechargeOpen, onRechargeSuccess]);
|
||||
window.addEventListener('hashchange', handleResume);
|
||||
window.addEventListener('focus', handleResume);
|
||||
window.addEventListener('pageshow', handleResume);
|
||||
document.addEventListener('visibilitychange', handleResume);
|
||||
handleResume();
|
||||
return () => {
|
||||
window.removeEventListener('hashchange', handleResume);
|
||||
window.removeEventListener('focus', handleResume);
|
||||
window.removeEventListener('pageshow', handleResume);
|
||||
document.removeEventListener('visibilitychange', handleResume);
|
||||
};
|
||||
}, [handleWechatPayResult]);
|
||||
const loadTaskCenter = () => {
|
||||
setTaskCenterError(null);
|
||||
setIsLoadingTaskCenter(true);
|
||||
|
||||
Reference in New Issue
Block a user