42 lines
1.5 KiB
TypeScript
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 };
|
|
}
|
|
}
|