fix wechat mini program virtual payment flow

This commit is contained in:
kdletters
2026-05-28 00:41:06 +08:00
parent b43c3cd823
commit 9c6fa10301
10 changed files with 335 additions and 57 deletions

View File

@@ -1417,8 +1417,9 @@ test('profile recharge modal posts virtual payment params in mini program web-vi
'requestId',
);
expect(requestId).toBeTruthy();
expect(screen.getByRole('dialog', { name: '正在支付' })).toBeTruthy();
act(() => {
window.location.hash = `wx_pay_result=${requestId}:success`;
window.location.hash = `wx_pay_result=${requestId}:success:order-wechat-1`;
window.dispatchEvent(new HashChangeEvent('hashchange'));
});
expect(navigateUrl).toContain('order-wechat-1');
@@ -1512,6 +1513,87 @@ test('profile recharge modal posts membership goods virtual payment params in mi
expect(decodeURIComponent(navigateUrl)).toContain('"paySig":"pay-sig"');
});
test('profile recharge modal releases submitting state and shows virtual payment failure detail', async () => {
const user = userEvent.setup();
window.history.replaceState(null, '', '/?clientRuntime=wechat_mini_program');
const navigateTo = vi.fn((options: { url: string; success?: () => void }) => {
options.success?.();
});
window.wx = {
miniProgram: {
navigateTo,
},
};
mockCreateRpgProfileRechargeOrder.mockResolvedValueOnce({
order: {
orderId: 'order-wechat-sandbox-fail',
productId: 'points_60',
productTitle: '60泥点',
kind: 'points',
amountCents: 600,
status: 'pending' as const,
paymentChannel: 'wechat_mp_virtual',
paidAt: null as string | null,
providerTransactionId: null,
createdAt: '2026-04-25T10:00:00Z',
pointsDelta: 0,
membershipExpiresAt: null,
},
center: {
walletBalance: 0,
membership: {
status: 'normal',
tier: 'normal',
startedAt: null,
expiresAt: null,
updatedAt: null,
},
pointProducts: [],
membershipProducts: [],
benefits: [],
latestOrder: null,
hasPointsRecharged: false,
},
wechatMiniProgramPayParams: {
mode: 'short_series_coin',
signData:
'{"offerId":"offer-1","buyQuantity":1,"env":1,"currencyType":"CNY","outTradeNo":"order-wechat-sandbox-fail","attach":"mud_points_60"}',
paySig: 'sandbox-pay-sig',
signature: 'user-sig',
},
});
renderProfileView();
await openRechargeModal(user);
const buyButton = await screen.findByRole('button', { name: /60/u });
await user.click(buyButton);
const navigateUrl = navigateTo.mock.calls[0]?.[0].url ?? '';
const requestId = new URL(`https://mini.test${navigateUrl}`).searchParams.get(
'requestId',
);
expect(requestId).toBeTruthy();
act(() => {
window.location.hash = `wx_pay_result=${requestId}:fail:order-wechat-sandbox-fail:${encodeURIComponent('{"errCode":-1,"errMsg":"requestVirtualPayment:fail sandbox"}')}`;
window.dispatchEvent(new HashChangeEvent('hashchange'));
});
expect(
await screen.findByRole('dialog', { name: '支付未完成' }),
).toBeTruthy();
expect(
screen.getByText(/requestVirtualPayment:fail sandbox/u),
).toBeTruthy();
await waitFor(() => {
expect(
within(screen.getByRole('button', { name: /60/u })).getByText(
'购买',
{ selector: 'span' },
),
).toBeTruthy();
});
});
test('profile recharge modal waits for paid confirmation before refreshing dashboard', async () => {
const user = userEvent.setup();
const onRechargeSuccess = vi.fn();