mirror of
https://github.com/certd/certd.git
synced 2026-07-28 23:57:41 +08:00
8517a0b564
将alipay-sdk、openid-client、otplib、wechatpay-node-v3改为动态导入,从dependencies移到devDependencies?不,是改为通过importRuntime动态加载,移除顶层静态引入,优化启动时依赖加载,减少初始包体积和启动耗时
138 lines
4.4 KiB
TypeScript
138 lines
4.4 KiB
TypeScript
import { IPaymentProvider, TradeEntity, UpdateTrade, UpdateTradeInfo } from "@certd/commercial-core";
|
||
import dayjs from "dayjs";
|
||
import { logger } from "@certd/basic";
|
||
import { WxpayAccess } from "../../../plugins/plugin-plus/wxpay/access.js";
|
||
export class PaymentWxpay implements IPaymentProvider {
|
||
access: WxpayAccess;
|
||
constructor(access: WxpayAccess) {
|
||
this.access = access;
|
||
}
|
||
async getDetail(tradeNo: string): Promise<UpdateTradeInfo> {
|
||
/**
|
||
* const result = await pay.query({out_trade_no: '1609914303237'});
|
||
* # 或者 const result = await pay.query({transaction_id: ''});
|
||
* console.log(result);
|
||
* {
|
||
* status: 200,
|
||
* appid: 'appid',
|
||
* attach: '',
|
||
* mchid: '商户号',
|
||
* out_trade_no: '1609899981750',
|
||
* payer: {},
|
||
* promotion_detail: [],
|
||
* trade_state: 'CLOSED',
|
||
* trade_state_desc: '订单已关闭'
|
||
* }
|
||
*/
|
||
|
||
const pay = await this.createSdk();
|
||
|
||
const result: any = await pay.query({ out_trade_no: tradeNo });
|
||
logger.info(`微信支付查询订单返回:${JSON.stringify(result)}`);
|
||
if (result.status !== 200) {
|
||
throw new Error("查询微信支付订单失败:" + result.status);
|
||
}
|
||
const data = result.data;
|
||
let status: string = undefined;
|
||
let payTime: number = undefined;
|
||
let amount: number = undefined;
|
||
if (data.trade_state === "SUCCESS") {
|
||
status = "paid";
|
||
payTime = dayjs(data.success_time).valueOf();
|
||
amount = data.amount.total;
|
||
} else if (data.trade_state === "CLOSED") {
|
||
status = "closed";
|
||
} else {
|
||
logger.info("微信支付订单状态为:" + data.trade_state);
|
||
}
|
||
|
||
return {
|
||
tradeNo: data.out_trade_no,
|
||
status,
|
||
amount,
|
||
payNo: data.transaction_id,
|
||
payTime,
|
||
};
|
||
}
|
||
async createOrder(trade: TradeEntity, opts: { bindUrl: string; clientIp: string }) {
|
||
const notify_url = `${opts.bindUrl}/api/payment/notify/wxpay`;
|
||
|
||
const pay = await this.createSdk();
|
||
|
||
const params = {
|
||
description: trade.title,
|
||
out_trade_no: trade.tradeNo,
|
||
notify_url,
|
||
amount: {
|
||
total: trade.amount,
|
||
},
|
||
scene_info: {
|
||
payer_client_ip: "ip",
|
||
},
|
||
};
|
||
|
||
logger.info(`微信支付下单请求:${JSON.stringify(params)}`);
|
||
const result: any = await pay.transactions_native(params);
|
||
logger.info(`微信支付下单返回:${JSON.stringify(result)}`);
|
||
if (result.status !== 200) {
|
||
throw new Error("请求微信支付失败:" + result.status);
|
||
}
|
||
return {
|
||
qrcode: result.data.code_url,
|
||
};
|
||
}
|
||
|
||
private async createSdk() {
|
||
const WxPayLib = await this.access.importRuntime("wechatpay-node-v3");
|
||
const WxPay = WxPayLib.default;
|
||
const pay = new WxPay({
|
||
appid: this.access.appId,
|
||
mchid: this.access.mchid,
|
||
publicKey: Buffer.from(this.access.publicKey), // 公钥
|
||
privateKey: Buffer.from(this.access.privateKey), // 秘钥
|
||
});
|
||
return pay;
|
||
}
|
||
|
||
async onNotify(notifyData: any, updateTrade: UpdateTrade) {
|
||
const pay = await this.createSdk();
|
||
const { ciphertext, associated_data, nonce } = notifyData.resource;
|
||
logger.info(`微信支付notify:${JSON.stringify(notifyData)}`);
|
||
const key = this.access.key;
|
||
const result: any = pay.decipher_gcm(ciphertext, associated_data, nonce, key);
|
||
logger.info(`微信支付解析结果:${JSON.stringify(result)}`);
|
||
/**
|
||
* mchid: '商户号',
|
||
* # appid: 'appid',
|
||
* # out_trade_no: '1610419296553',
|
||
* # transaction_id: '4200000848202101120290526543',
|
||
* # trade_type: 'NATIVE',
|
||
* # trade_state: 'SUCCESS',
|
||
* # trade_state_desc: '支付成功',
|
||
* # bank_type: 'OTHERS',
|
||
* # attach: '',
|
||
* # success_time: '2021-01-12T10:43:43+08:00',
|
||
* # payer: { openid: '' },
|
||
* # amount: { total: 1, payer_total: 1, currency: 'CNY', payer_currency: 'CNY' }
|
||
*/
|
||
const data: any = result;
|
||
if (data.trade_state === "SUCCESS") {
|
||
await updateTrade({
|
||
tradeNo: data.out_trade_no,
|
||
status: "paid",
|
||
amount: data.amount.total,
|
||
payNo: data.transaction_id,
|
||
payTime: dayjs(data.success_time).valueOf(),
|
||
});
|
||
} else if (data.trade_state === "CLOSED") {
|
||
await updateTrade({
|
||
tradeNo: data.out_trade_no,
|
||
status: "closed",
|
||
payNo: data.transaction_id,
|
||
});
|
||
}
|
||
|
||
return "success";
|
||
}
|
||
}
|