Files
dukang/server/dukang-api/src/integrations/pay/pay.wechat.provider.ts
T
2026-07-01 19:56:44 +08:00

42 lines
1.5 KiB
TypeScript

import { Inject, Injectable } from '@nestjs/common';
import { loadAppConfig } from '@dukang/shared-types';
import { PrismaService } from '../../common/prisma/prisma.module';
import { WECHAT_PROVIDER } from '../integrations.constants';
import type { IWechatProvider } from '../wechat/wechat.interface';
import type { IPayProvider, PayOrderResult } from './pay.interface';
@Injectable()
export class PayWechatProvider implements IPayProvider {
private readonly config = loadAppConfig();
constructor(
private readonly prisma: PrismaService,
@Inject(WECHAT_PROVIDER) private readonly wechat: IWechatProvider,
) {}
async payOrder(orderId: bigint, openId?: string): Promise<PayOrderResult> {
if (this.config.mockPay) {
return { mode: 'mock', externalNo: `MOCK-${Date.now()}` };
}
if (!openId) {
throw new Error('微信支付需要用户 openId,请先完成微信授权登录');
}
if (!this.wechat.isEnabled()) {
throw new Error('微信能力未启用,请配置 WECHAT_AUTH_ENABLED 与 WX_APP_ID/SECRET');
}
const order = await this.prisma.order.findUnique({ where: { id: orderId } });
if (!order) throw new Error('订单不存在');
const amountFen = Math.round(Number(order.payAmount) * 100);
const prepay = await this.wechat.createJsapiPrepay({
orderNo: order.orderNo,
description: `杜康好客订单 ${order.orderNo}`,
amountFen,
openId,
notifyUrl: process.env.WX_PAY_NOTIFY_URL ?? '',
});
return { mode: 'jsapi', prepay };
}
}