fix(user): correct WeChat JSAPI pay invoke params and JSSDK init
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -121,7 +121,6 @@ export default function PayPage() {
|
|||||||
|
|
||||||
if (result.mode === 'jsapi' && result.prepay) {
|
if (result.mode === 'jsapi' && result.prepay) {
|
||||||
setMockMode(false);
|
setMockMode(false);
|
||||||
await weixinSdk.init();
|
|
||||||
await weixinSdk.pay(result.prepay);
|
await weixinSdk.pay(result.prepay);
|
||||||
const paid = await waitOrderPaid(orderId);
|
const paid = await waitOrderPaid(orderId);
|
||||||
if (!paid) {
|
if (!paid) {
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ export function createWeixinSdk(config: WeixinSdkConfig) {
|
|||||||
chooseImages: (options?: Parameters<typeof chooseWechatImages>[1]) =>
|
chooseImages: (options?: Parameters<typeof chooseWechatImages>[1]) =>
|
||||||
chooseWechatImages(config, options),
|
chooseWechatImages(config, options),
|
||||||
pay: (prepay: Parameters<typeof invokeWechatPay>[0]) =>
|
pay: (prepay: Parameters<typeof invokeWechatPay>[0]) =>
|
||||||
invokeWechatPay(prepay, { apiBase: config.apiBase, clientApp: config.clientApp }),
|
invokeWechatPay(prepay, {
|
||||||
|
apiBase: config.apiBase ?? '/api/v1',
|
||||||
|
clientApp: config.clientApp,
|
||||||
|
getAccessToken: config.getAccessToken,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,23 @@ import type { WechatJsapiPrepayParams } from '@dukang/shared-types';
|
|||||||
import { getRuntimePlatform } from './env';
|
import { getRuntimePlatform } from './env';
|
||||||
import { ensureJssdkReady } from './jssdk';
|
import { ensureJssdkReady } from './jssdk';
|
||||||
|
|
||||||
|
export type WechatPayInvokeConfig = {
|
||||||
|
apiBase?: string;
|
||||||
|
clientApp?: string;
|
||||||
|
getAccessToken?: () => string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** wx.chooseWXPay 要求 timestamp 小写;服务端签名与 Bridge 使用 timeStamp */
|
||||||
|
function toChooseWxPayOptions(prepay: WechatJsapiPrepayParams) {
|
||||||
|
return {
|
||||||
|
timestamp: prepay.timeStamp,
|
||||||
|
nonceStr: prepay.nonceStr,
|
||||||
|
package: prepay.package,
|
||||||
|
signType: prepay.signType,
|
||||||
|
paySign: prepay.paySign,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function invokeBridgePay(params: WechatJsapiPrepayParams): Promise<void> {
|
function invokeBridgePay(params: WechatJsapiPrepayParams): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const bridge = window.WeixinJSBridge;
|
const bridge = window.WeixinJSBridge;
|
||||||
@@ -29,10 +46,19 @@ function invokeBridgePay(params: WechatJsapiPrepayParams): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function waitForWeixinBridge(): Promise<void> {
|
||||||
|
if (window.WeixinJSBridge) return;
|
||||||
|
if (typeof document === 'undefined') return;
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
if (window.WeixinJSBridge) resolve();
|
||||||
|
else document.addEventListener('WeixinJSBridgeReady', () => resolve(), { once: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** 调起微信支付 */
|
/** 调起微信支付 */
|
||||||
export async function invokeWechatPay(
|
export async function invokeWechatPay(
|
||||||
prepay: WechatJsapiPrepayParams,
|
prepay: WechatJsapiPrepayParams,
|
||||||
config?: { apiBase?: string; clientApp?: string },
|
config?: WechatPayInvokeConfig,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const platform = getRuntimePlatform();
|
const platform = getRuntimePlatform();
|
||||||
|
|
||||||
@@ -55,28 +81,28 @@ export async function invokeWechatPay(
|
|||||||
await ensureJssdkReady({
|
await ensureJssdkReady({
|
||||||
apiBase: config.apiBase ?? '/api/v1',
|
apiBase: config.apiBase ?? '/api/v1',
|
||||||
clientApp: config.clientApp,
|
clientApp: config.clientApp,
|
||||||
|
getAccessToken: config.getAccessToken,
|
||||||
|
url: typeof window !== 'undefined' ? window.location.href.split('#')[0] : undefined,
|
||||||
|
jsApiList: ['chooseWXPay'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bridge 参数与商户签名一致,优先于 chooseWXPay
|
||||||
|
await waitForWeixinBridge();
|
||||||
|
if (window.WeixinJSBridge) {
|
||||||
|
return invokeBridgePay(prepay);
|
||||||
|
}
|
||||||
|
|
||||||
if (window.wx?.chooseWXPay) {
|
if (window.wx?.chooseWXPay) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
window.wx!.chooseWXPay!({
|
window.wx!.chooseWXPay!({
|
||||||
...prepay,
|
...toChooseWxPayOptions(prepay),
|
||||||
success: () => resolve(),
|
success: () => resolve(),
|
||||||
fail: (err) => reject(new Error(err.errMsg || '支付失败')),
|
fail: (err) => reject(new Error(err.errMsg || '支付失败')),
|
||||||
cancel: () => reject(new Error('用户取消支付')),
|
cancel: () => reject(new Error('用户取消支付')),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (window.WeixinJSBridge) {
|
|
||||||
return invokeBridgePay(prepay);
|
|
||||||
}
|
|
||||||
if (typeof document !== 'undefined') {
|
|
||||||
await new Promise<void>((resolve) => {
|
|
||||||
if (window.WeixinJSBridge) resolve();
|
|
||||||
else document.addEventListener('WeixinJSBridgeReady', () => resolve(), { once: true });
|
|
||||||
});
|
|
||||||
return invokeBridgePay(prepay);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('当前环境不支持微信支付');
|
throw new Error('当前环境不支持微信支付');
|
||||||
|
|||||||
@@ -31,7 +31,12 @@ export type WxApi = {
|
|||||||
success?: (res: { resultStr: string }) => void;
|
success?: (res: { resultStr: string }) => void;
|
||||||
fail?: (res: { errMsg: string }) => void;
|
fail?: (res: { errMsg: string }) => void;
|
||||||
}) => void;
|
}) => void;
|
||||||
chooseWXPay: (options: WechatJsapiPrepayParams & {
|
chooseWXPay: (options: {
|
||||||
|
timestamp: string;
|
||||||
|
nonceStr: string;
|
||||||
|
package: string;
|
||||||
|
signType: string;
|
||||||
|
paySign: string;
|
||||||
success?: () => void;
|
success?: () => void;
|
||||||
fail?: (res: { errMsg: string }) => void;
|
fail?: (res: { errMsg: string }) => void;
|
||||||
cancel?: () => void;
|
cancel?: () => void;
|
||||||
|
|||||||
Reference in New Issue
Block a user