Files
dukang/apps/mini-user/src/lib/pay-wechat.weapp.ts
T
jacy 233ed0af3b
CI / verify (pull_request) Has been cancelled
v3.5.1 版本更新
2026-08-19 15:54:51 +08:00

90 lines
2.6 KiB
TypeScript

import type {
ClientRuntimeConfig,
WechatJsapiPrepayParams,
WechatLoginResult,
WechatPayOrderResult,
} from '@dukang/shared-types';
import { WECHAT_AUTH_REQUIRED, isWxAuthorizeEnabled } from '@dukang/shared-types';
import Taro from '@tarojs/taro';
import { request, saveAuth, type UserProfile } from './api';
import { isWechatEnv } from './weixin';
export function isMiniWechatEnv(): boolean {
return true;
}
export function isWechatAuthRequiredError(err: unknown): boolean {
return err instanceof Error && err.message === WECHAT_AUTH_REQUIRED;
}
export async function fetchClientConfig(): Promise<ClientRuntimeConfig> {
return request<ClientRuntimeConfig>('/common/client-config');
}
export async function fetchUserProfile(): Promise<UserProfile> {
return request<UserProfile>('/auth/me');
}
export function needsWechatAuthForPay(
config: ClientRuntimeConfig,
profile: UserProfile | null,
): boolean {
if (!isWxAuthorizeEnabled(config)) return false;
return !config.mockPay && config.wechatPayEnabled && isWechatEnv() && !profile?.hasWechat;
}
export function saveWechatLoginResult(result: WechatLoginResult): boolean {
if (!result.accessToken) return false;
saveAuth({
accessToken: result.accessToken,
refreshToken: result.refreshToken,
});
return true;
}
export async function authorizeWechatForPay(): Promise<WechatLoginResult | void> {
throw new Error('请使用小程序微信授权');
}
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export async function waitOrderPaid(orderId: string, maxAttempts = 15): Promise<boolean> {
for (let i = 0; i < maxAttempts; i += 1) {
const order = await request<{ payStatus?: string }>(`/trade/orders/${orderId}`);
if (order.payStatus === 'PAID') return true;
await sleep(2000);
}
return false;
}
async function invokeMiniPay(prepay: WechatJsapiPrepayParams) {
await Taro.requestPayment({
timeStamp: prepay.timeStamp,
nonceStr: prepay.nonceStr,
package: prepay.package,
signType: prepay.signType,
paySign: prepay.paySign,
});
}
export async function payOrder(orderId: string): Promise<'paid' | 'pending'> {
const result = await request<WechatPayOrderResult>(`/trade/orders/${orderId}/pay`, {
method: 'POST',
});
if (result.mode === 'jsapi' && result.prepay) {
await invokeMiniPay(result.prepay as WechatJsapiPrepayParams);
const paid = await waitOrderPaid(orderId);
return paid ? 'paid' : 'pending';
}
return 'paid';
}
export type WechatBindResult =
| { ok: true; profile?: UserProfile }
| { ok: false; needBindPhone: true; wxSessionKey: string }
| { ok: false; redirecting: true };