-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add wechat pay transaction jsapi order v3 interface
- Loading branch information
jay
committed
Jun 25, 2022
1 parent
712152a
commit 4de65d0
Showing
3 changed files
with
206 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
import { Injectable, Logger } from '@nestjs/common'; | ||
import axios from 'axios'; | ||
import * as crypto from 'crypto'; | ||
|
||
import { createNonceStr } from './utils'; | ||
|
||
/** | ||
* JSAPI Order Data Interface | ||
*/ | ||
export interface TransactionOrder { | ||
/** | ||
* 应用ID | ||
* 长度32 | ||
*/ | ||
appid: string; | ||
/** | ||
* 直连商户号 | ||
* 长度32 | ||
*/ | ||
mchid: string; | ||
/** | ||
* 商品描述 | ||
* 长度127 | ||
*/ | ||
description: string; | ||
/** | ||
* 商户订单号 | ||
* 长度32 | ||
*/ | ||
out_trade_no: string; | ||
/** | ||
* 交易结束时间 | ||
* yyyy-MM-DDTHH:mm:ss+TIMEZONE | ||
* 例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒 | ||
* 长度64 | ||
*/ | ||
time_expire?: string; | ||
/** | ||
* 附加数据 | ||
* 长度128 | ||
*/ | ||
attach?: string; | ||
/** | ||
* 通知地址 | ||
* 长度256 | ||
*/ | ||
notify_url: string; | ||
/** | ||
* 订单优惠标记 | ||
* 长度32 | ||
*/ | ||
goods_tag?: string; | ||
/** | ||
* 订单金额 | ||
*/ | ||
amount: { | ||
/** | ||
* 总金额,单位:分 | ||
*/ | ||
total: number | ||
/** | ||
* 货币类型,如:CNY | ||
* 长度16 | ||
*/ | ||
currency: string, | ||
}; | ||
/** | ||
* 支付者 | ||
*/ | ||
payer: { | ||
/** | ||
* OPENID | ||
* 长度128 | ||
*/ | ||
openid: string; | ||
} | ||
detail?: { | ||
/** | ||
* 订单原价 | ||
*/ | ||
cost_price?: number; | ||
|
||
/** | ||
* 商品小票ID | ||
* 长度32 | ||
*/ | ||
invoice_id?: string; | ||
goods_detail?: { | ||
/** | ||
* 商户侧商品编码 | ||
* 长度32 | ||
*/ | ||
merchant_goods_id: string; | ||
/** | ||
* 微信支付商品编码 | ||
* 长度32 | ||
*/ | ||
wechatpay_goods_id?: string; | ||
/** | ||
* 商品名称 | ||
* 长度256 | ||
*/ | ||
goods_name?: string; | ||
/** | ||
* 商品数量 | ||
* 长度32 | ||
*/ | ||
quantity: number; | ||
/** | ||
* 商品单价,单位分 | ||
*/ | ||
unit_price: number; | ||
}[]; | ||
}; | ||
/** | ||
* 场景信息 | ||
*/ | ||
scene_info?: { | ||
/** | ||
* 用户终端IP | ||
* 长度45 | ||
*/ | ||
payer_client_ip: string; | ||
/** | ||
* 商户端设备号 | ||
* 长度32 | ||
*/ | ||
device_id?: string; | ||
/** | ||
* 商户门店信息 | ||
*/ | ||
store_info?: { | ||
/** | ||
* 门店编号 | ||
* 长度32 | ||
*/ | ||
id: string; | ||
/** | ||
* 门店名称 | ||
* 长度256 | ||
*/ | ||
name?: string; | ||
/** | ||
* 地区编码 | ||
* 长度32 | ||
*/ | ||
area_code?: string; | ||
/** | ||
* 详细地址 | ||
* 长度512 | ||
*/ | ||
address?: string; | ||
}; | ||
}; | ||
/** | ||
* 结算信息 | ||
*/ | ||
settle_info?: { | ||
/** | ||
* 是否指定分账 | ||
*/ | ||
profit_sharing?: boolean; | ||
} | ||
} | ||
|
||
@Injectable() | ||
export class WePayService { | ||
|
||
private readonly logger = new Logger(WePayService.name); | ||
|
||
/** | ||
* JSAPI下单 | ||
* @param order 下单信息 | ||
* @param serialNo 私钥序列号 | ||
* @param privateKey 私钥 | ||
* @returns | ||
* @link https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml | ||
*/ | ||
async transactionsJsapi (order: TransactionOrder, serialNo: string, privateKey: Buffer | string) { | ||
const nonceStr = createNonceStr(); | ||
const timestamp = Math.floor(Date.now() / 1000); | ||
const message = `POST\n/v3/pay/transactions/jsapi\n${timestamp}\n${nonceStr}\n${JSON.stringify(order)}\n`; | ||
const signature = crypto.createSign('sha256WithRSAEncryption').update(message).sign(privateKey, 'base64'); | ||
const url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi'; | ||
return await axios.post(url, order, { | ||
headers: { | ||
'Authorization': `WECHATPAY2-SHA256-RSA2048 mchid="${order.mchid}",nonce_str="${nonceStr}",signature="${signature}",timestamp="${timestamp}",serial_no="${serialNo}"`, | ||
}, | ||
}); | ||
} | ||
} |