feat: switch mini program recharge to virtual payment
This commit is contained in:
@@ -236,7 +236,7 @@ const {
|
||||
kind: 'points',
|
||||
amountCents: 600,
|
||||
status: 'paid',
|
||||
paymentChannel: 'wechat_mp',
|
||||
paymentChannel: 'wechat_mp_virtual',
|
||||
paidAt: '2026-04-25T10:01:00Z',
|
||||
providerTransactionId: 'wx-transaction-1',
|
||||
createdAt: '2026-04-25T10:00:00Z',
|
||||
@@ -275,7 +275,7 @@ const {
|
||||
kind: 'points',
|
||||
amountCents: 600,
|
||||
status: 'paid',
|
||||
paymentChannel: 'wechat_mp',
|
||||
paymentChannel: 'wechat_mp_virtual',
|
||||
providerTransactionId: 'wx-transaction-1',
|
||||
createdAt: '2026-04-25T10:00:00Z',
|
||||
paidAt: '2026-04-25T10:01:00Z',
|
||||
@@ -1319,7 +1319,7 @@ test('profile recharge modal trusts per-product first bonus display after points
|
||||
expect(screen.getByText('60+60泥点')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('profile recharge modal posts requestPayment params in mini program web-view', async () => {
|
||||
test('profile recharge modal posts virtual payment params in mini program web-view', async () => {
|
||||
const user = userEvent.setup();
|
||||
const onRechargeSuccess = vi.fn();
|
||||
window.history.replaceState(null, '', '/?clientRuntime=wechat_mini_program');
|
||||
@@ -1339,7 +1339,7 @@ test('profile recharge modal posts requestPayment params in mini program web-vie
|
||||
kind: 'points',
|
||||
amountCents: 600,
|
||||
status: 'pending' as const,
|
||||
paymentChannel: 'wechat_mp',
|
||||
paymentChannel: 'wechat_mp_virtual',
|
||||
paidAt: null as string | null,
|
||||
providerTransactionId: null,
|
||||
createdAt: '2026-04-25T10:00:00Z',
|
||||
@@ -1362,11 +1362,11 @@ test('profile recharge modal posts requestPayment params in mini program web-vie
|
||||
hasPointsRecharged: false,
|
||||
},
|
||||
wechatMiniProgramPayParams: {
|
||||
timeStamp: '1777110165',
|
||||
nonceStr: 'nonce',
|
||||
package: 'prepay_id=wx-prepay',
|
||||
signType: 'RSA',
|
||||
paySign: 'signature',
|
||||
mode: 'short_series_coin',
|
||||
signData:
|
||||
'{"offerId":"offer-1","buyQuantity":1,"env":0,"currencyType":"CNY","outTradeNo":"order-wechat-1","attach":"mud_points_60"}',
|
||||
paySig: 'pay-sig',
|
||||
signature: 'user-sig',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1377,7 +1377,7 @@ test('profile recharge modal posts requestPayment params in mini program web-vie
|
||||
await waitFor(() => {
|
||||
expect(mockCreateRpgProfileRechargeOrder).toHaveBeenCalledWith(
|
||||
'points_60',
|
||||
'wechat_mp',
|
||||
'wechat_mp_virtual',
|
||||
);
|
||||
});
|
||||
expect(navigateTo).toHaveBeenCalledWith({
|
||||
@@ -1395,7 +1395,7 @@ test('profile recharge modal posts requestPayment params in mini program web-vie
|
||||
window.dispatchEvent(new HashChangeEvent('hashchange'));
|
||||
});
|
||||
expect(navigateUrl).toContain('order-wechat-1');
|
||||
expect(decodeURIComponent(navigateUrl)).toContain('prepay_id=wx-prepay');
|
||||
expect(decodeURIComponent(navigateUrl)).toContain('short_series_coin');
|
||||
expect(await screen.findByRole('dialog', { name: '支付成功' })).toBeTruthy();
|
||||
expect(mockCreateRpgProfileRechargeOrder).not.toHaveBeenCalledWith(
|
||||
'points_60',
|
||||
@@ -1409,6 +1409,82 @@ test('profile recharge modal posts requestPayment params in mini program web-vie
|
||||
expect(onRechargeSuccess).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('profile recharge modal posts membership goods virtual payment params in mini program web-view', 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-member-virtual-1',
|
||||
productId: 'member_month',
|
||||
productTitle: '月卡',
|
||||
kind: 'membership',
|
||||
amountCents: 2800,
|
||||
status: 'pending' as const,
|
||||
paymentChannel: 'wechat_mp_virtual',
|
||||
paidAt: null as string | null,
|
||||
providerTransactionId: null,
|
||||
createdAt: '2026-04-25T10:00:00Z',
|
||||
pointsDelta: 0,
|
||||
membershipExpiresAt: '2026-06-25T10:00:00Z',
|
||||
},
|
||||
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_goods',
|
||||
signData:
|
||||
'{"offerId":"offer-1","buyQuantity":1,"env":0,"currencyType":"CNY","productId":"member_month","goodsPrice":2800,"outTradeNo":"order-member-virtual-1","attach":"member_month"}',
|
||||
paySig: 'pay-sig',
|
||||
signature: 'user-sig',
|
||||
},
|
||||
});
|
||||
|
||||
renderProfileView();
|
||||
await openRechargeModal(user);
|
||||
await user.click(screen.getByRole('button', { name: '会员卡' }));
|
||||
await user.click(await screen.findByRole('button', { name: /月卡/u }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockCreateRpgProfileRechargeOrder).toHaveBeenCalledWith(
|
||||
'member_month',
|
||||
'wechat_mp_virtual',
|
||||
);
|
||||
});
|
||||
const navigateUrl = navigateTo.mock.calls[0]?.[0].url ?? '';
|
||||
const requestId = new URL(`https://mini.test${navigateUrl}`).searchParams.get(
|
||||
'requestId',
|
||||
);
|
||||
expect(requestId).toBeTruthy();
|
||||
const payParams = JSON.parse(
|
||||
new URL(`https://mini.test${navigateUrl}`).searchParams.get('payParams') ?? '{}',
|
||||
);
|
||||
const signData = JSON.parse(payParams.signData);
|
||||
expect(payParams.mode).toBe('short_series_goods');
|
||||
expect(signData.productId).toBe('member_month');
|
||||
expect(signData.goodsPrice).toBe(2800);
|
||||
expect(decodeURIComponent(navigateUrl)).toContain('"paySig":"pay-sig"');
|
||||
});
|
||||
|
||||
test('profile recharge modal waits for paid confirmation before refreshing dashboard', async () => {
|
||||
const user = userEvent.setup();
|
||||
const onRechargeSuccess = vi.fn();
|
||||
@@ -1429,7 +1505,7 @@ test('profile recharge modal waits for paid confirmation before refreshing dashb
|
||||
kind: 'points',
|
||||
amountCents: 600,
|
||||
status: 'pending' as const,
|
||||
paymentChannel: 'wechat_mp',
|
||||
paymentChannel: 'wechat_mp_virtual',
|
||||
paidAt: null as string | null,
|
||||
providerTransactionId: null,
|
||||
createdAt: '2026-04-25T10:00:00Z',
|
||||
@@ -1452,11 +1528,11 @@ test('profile recharge modal waits for paid confirmation before refreshing dashb
|
||||
hasPointsRecharged: false,
|
||||
},
|
||||
wechatMiniProgramPayParams: {
|
||||
timeStamp: '1777110165',
|
||||
nonceStr: 'nonce',
|
||||
package: 'prepay_id=wx-prepay',
|
||||
signType: 'RSA',
|
||||
paySign: 'signature',
|
||||
mode: 'short_series_coin',
|
||||
signData:
|
||||
'{"offerId":"offer-1","buyQuantity":1,"env":0,"currencyType":"CNY","outTradeNo":"order-wechat-pending-then-paid","attach":"mud_points_60"}',
|
||||
paySig: 'pay-sig',
|
||||
signature: 'user-sig',
|
||||
},
|
||||
});
|
||||
mockConfirmWechatRpgProfileRechargeOrder
|
||||
@@ -1468,7 +1544,7 @@ test('profile recharge modal waits for paid confirmation before refreshing dashb
|
||||
kind: 'points',
|
||||
amountCents: 600,
|
||||
status: 'pending' as const,
|
||||
paymentChannel: 'wechat_mp',
|
||||
paymentChannel: 'wechat_mp_virtual',
|
||||
paidAt: null,
|
||||
providerTransactionId: null,
|
||||
createdAt: '2026-04-25T10:00:00Z',
|
||||
@@ -1499,7 +1575,7 @@ test('profile recharge modal waits for paid confirmation before refreshing dashb
|
||||
kind: 'points',
|
||||
amountCents: 600,
|
||||
status: 'paid' as const,
|
||||
paymentChannel: 'wechat_mp',
|
||||
paymentChannel: 'wechat_mp_virtual',
|
||||
paidAt: '2026-04-25T10:01:00Z',
|
||||
providerTransactionId: 'wx-transaction-2',
|
||||
createdAt: '2026-04-25T10:00:00Z',
|
||||
@@ -1563,7 +1639,7 @@ test('profile recharge modal loads wechat js sdk before mini program payment bri
|
||||
kind: 'points',
|
||||
amountCents: 600,
|
||||
status: 'pending' as const,
|
||||
paymentChannel: 'wechat_mp',
|
||||
paymentChannel: 'wechat_mp_virtual',
|
||||
paidAt: null as string | null,
|
||||
providerTransactionId: null,
|
||||
createdAt: '2026-04-25T10:00:00Z',
|
||||
@@ -1586,11 +1662,11 @@ test('profile recharge modal loads wechat js sdk before mini program payment bri
|
||||
hasPointsRecharged: false,
|
||||
},
|
||||
wechatMiniProgramPayParams: {
|
||||
timeStamp: '1777110165',
|
||||
nonceStr: 'nonce',
|
||||
package: 'prepay_id=wx-prepay',
|
||||
signType: 'RSA',
|
||||
paySign: 'signature',
|
||||
mode: 'short_series_coin',
|
||||
signData:
|
||||
'{"offerId":"offer-1","buyQuantity":1,"env":0,"currencyType":"CNY","outTradeNo":"order-wechat-sdk-1","attach":"mud_points_60"}',
|
||||
paySig: 'pay-sig',
|
||||
signature: 'user-sig',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1649,7 +1725,7 @@ test('profile recharge modal releases submitting state after cancelled wechat pa
|
||||
kind: 'points',
|
||||
amountCents: 600,
|
||||
status: 'pending' as const,
|
||||
paymentChannel: 'wechat_mp',
|
||||
paymentChannel: 'wechat_mp_virtual',
|
||||
paidAt: null as string | null,
|
||||
providerTransactionId: null,
|
||||
createdAt: '2026-04-25T10:00:00Z',
|
||||
@@ -1672,11 +1748,11 @@ test('profile recharge modal releases submitting state after cancelled wechat pa
|
||||
hasPointsRecharged: false,
|
||||
},
|
||||
wechatMiniProgramPayParams: {
|
||||
timeStamp: '1777110165',
|
||||
nonceStr: 'nonce',
|
||||
package: 'prepay_id=wx-prepay-cancel',
|
||||
signType: 'RSA',
|
||||
paySign: 'signature',
|
||||
mode: 'short_series_coin',
|
||||
signData:
|
||||
'{"offerId":"offer-1","buyQuantity":1,"env":0,"currencyType":"CNY","outTradeNo":"order-wechat-cancel-1","attach":"mud_points_60"}',
|
||||
paySig: 'pay-sig',
|
||||
signature: 'user-sig',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1688,7 +1764,7 @@ test('profile recharge modal releases submitting state after cancelled wechat pa
|
||||
await waitFor(() => {
|
||||
expect(mockCreateRpgProfileRechargeOrder).toHaveBeenCalledWith(
|
||||
'points_60',
|
||||
'wechat_mp',
|
||||
'wechat_mp_virtual',
|
||||
);
|
||||
});
|
||||
expect(
|
||||
|
||||
Reference in New Issue
Block a user