fix(payment): restore upgrade-safe payment flows

This commit is contained in:
IanShaw027
2026-04-22 14:57:16 +08:00
parent 36aed35957
commit 1aab084ecb
14 changed files with 645 additions and 68 deletions
@@ -255,14 +255,21 @@ describe('PaymentResultView', () => {
expect(window.localStorage.getItem(PAYMENT_RECOVERY_STORAGE_KEY)).toBeNull()
})
it('does not fall back to public out_trade_no verification when resume_token recovery fails', async () => {
it('falls back to public out_trade_no verification when resume_token recovery fails in legacy return flows', async () => {
routeState.query = {
resume_token: 'resume-fail',
out_trade_no: 'legacy-should-not-run',
trade_status: 'TRADE_SUCCESS',
}
resolveOrderPublicByResumeToken.mockRejectedValueOnce(new Error('resume failed'))
mount(PaymentResultView, {
verifyOrderPublic.mockResolvedValueOnce({
data: {
...orderFactory('PAID'),
out_trade_no: 'legacy-should-not-run',
},
})
const wrapper = mount(PaymentResultView, {
global: {
stubs: {
OrderStatusBadge: true,
@@ -273,7 +280,9 @@ describe('PaymentResultView', () => {
await flushPromises()
expect(resolveOrderPublicByResumeToken).toHaveBeenCalledWith('resume-fail')
expect(verifyOrderPublic).not.toHaveBeenCalled()
expect(verifyOrderPublic).toHaveBeenCalledWith('legacy-should-not-run')
expect(pollOrderStatus).not.toHaveBeenCalled()
expect(wrapper.text()).toContain('payment.result.success')
})
it('ignores a stale global recovery snapshot when legacy return markers do not identify the order', async () => {
@@ -252,6 +252,33 @@ describe('PaymentView WeChat JSAPI flow', () => {
expect(window.localStorage.getItem(PAYMENT_RECOVERY_STORAGE_KEY)).toBeNull()
})
it('clears stale recovery state when JSAPI never becomes available', async () => {
vi.useFakeTimers()
createOrder.mockResolvedValue(jsapiOrderFixture('resume-token-missing-bridge'))
;(window as Window & { WeixinJSBridge?: { invoke: typeof bridgeInvoke } }).WeixinJSBridge = undefined
const wrapper = shallowMount(PaymentView, {
global: {
stubs: {
Teleport: true,
Transition: false,
},
},
})
await flushPromises()
await vi.advanceTimersByTimeAsync(4000)
await flushPromises()
await flushPromises()
expect(showError).toHaveBeenCalledWith(
'payment.errors.wechatJsapiUnavailable payment.errors.wechatOpenInWeChatHint',
)
expect(routerPush).not.toHaveBeenCalled()
expect(window.localStorage.getItem(PAYMENT_RECOVERY_STORAGE_KEY)).toBeNull()
expect(wrapper.html()).not.toContain('payment-status-panel-stub')
})
it('clears a stale recovery snapshot before handling wechat resume callback params', async () => {
createOrder.mockRejectedValueOnce(new Error('resume failed'))
window.localStorage.setItem(PAYMENT_RECOVERY_STORAGE_KEY, JSON.stringify({