介绍
仅展示微信支付订单的生成,可能需要根据你自己的业务逻辑进行修改;
代码演示 native 方式支付(即生成一个二维码,用户扫码即可支付)。
需要你提前准备好微信支付商户号信息,并按以下要求配置到环境变量中。
我们会创建两个云函数:
create-wepay-order
创建支付订单,返回支付二维码
query-wepay-order
根据订单号,查询支付结果
create-wepay-order
import cloud from '@lafjs/cloud'
import crypto from 'crypto'
import axios from 'axios'
const WechatPaySpec = {
mchid: cloud.env.WX_PAY_MCHID,
appid: cloud.env.WX_PAY_APPID,
apiV3Key: cloud.env.WX_PAY_API_V3_KEY,
certificateSerialNumber: cloud.env.WX_PAY_CERT_SERIAL_NUMBER,
privateKey: cloud.env.WX_PAY_PRIVATE_KEY,
}
export async function main(ctx: FunctionContext) {
const db = cloud.database()
const trade_order_number = "abc123"
const amount = 100
const order = {
mchid: WechatPaySpec.mchid,
appid: WechatPaySpec.appid,
description: 'payment for ' + trade_order_number,
out_trade_no: trade_order_number,
notify_url: `https://${cloud.env.APP_ID}.laf.dev/wechat-notify`,
amount: {
total: amount,
currency: 'CNY'
}
}
const res = await pay(order)
console.log(res)
await db.collection('pay_orders').add({
trade_order_number,
amount: order.amount,
state: 'PENDING',
created_at: new Date()
})
return res
}
async function pay(order: any) {
const timestamp = Math.floor(Date.now() / 1000)
const nonceStr = crypto.randomUUID()
const apiUrl = '/v3/pay/transactions/native'
const signature = createSign(apiUrl, timestamp, nonceStr, order)
const serialNo = WechatPaySpec.certificateSerialNumber
const token = `WECHATPAY2-SHA256-RSA2048 mchid="${WechatPaySpec.mchid}",nonce_str="${nonceStr}",timestamp="${timestamp}",signature="${signature}",serial_no="${serialNo}"`
const headers = { Authorization: token }
const fullUrl = `https://api.mch.weixin.qq.com${apiUrl}`
const res = await axios.post(fullUrl, order, {
headers,
})
return res.data
}
function createSign(apiUrl: string, timestamp: number, nonceStr: string, order: any) {
const method = 'POST'
const orderStr = JSON.stringify(order)
const signStr = `${method}\n${apiUrl}\n${timestamp}\n${nonceStr}\n${orderStr}\n`
const cert = WechatPaySpec.privateKey
const sign = crypto.createSign('RSA-SHA256')
sign.update(signStr)
return sign.sign(cert, 'base64')
}
query-wepay-order
import cloud from '@lafjs/cloud'
import crypto from 'crypto'
import axios from 'axios'
const WechatPaySpec = {
mchid: cloud.env.WX_PAY_MCHID,
appid: cloud.env.WX_PAY_APPID,
apiV3Key: cloud.env.WX_PAY_API_V3_KEY,
certificateSerialNumber: cloud.env.WX_PAY_CERT_SERIAL_NUMBER,
privateKey: cloud.env.WX_PAY_PRIVATE_KEY,
}
export async function main(ctx: FunctionContext) {
const db = cloud.database()
const { trade_order_number } = ctx.query
const res = await queryOrder(trade_order_number)
console.log(res)
await db.collection('pay_orders')
.where({
trade_order_number: res?.out_trade_no,
})
.update({
state: res?.trade_state,
updated_at: new Date(),
result: res
})
return res
}
async function queryOrder(orderNumber: string) {
const timestamp = Math.floor(Date.now() / 1000)
const nonceStr = crypto.randomUUID()
const apiUrl = `/v3/pay/transactions/out-trade-no/${orderNumber}?mchid=${WechatPaySpec.mchid}`
const signature = createSign(apiUrl, timestamp, nonceStr)
const serialNo = WechatPaySpec.certificateSerialNumber
const token = `WECHATPAY2-SHA256-RSA2048 mchid="${WechatPaySpec.mchid}",nonce_str="${nonceStr}",timestamp="${timestamp}",signature="${signature}",serial_no="${serialNo}"`
const headers = {
Authorization: token,
}
const fullUrl = `https://api.mch.weixin.qq.com${apiUrl}`
const res = await axios.get(fullUrl + ``, {
headers,
})
return res.data
}
function createSign(apiUrl: string, timestamp: number, nonceStr: string) {
const method = 'GET'
const signStr = `${method}\n${apiUrl}\n${timestamp}\n${nonceStr}\n\n`
const cert = WechatPaySpec.privateKey
const sign = crypto.createSign('RSA-SHA256')
sign.update(signStr)
return sign.sign(cert, 'base64')
}
其实还可以实现一个支付结果回调的函数,这样就不太需要查询支付结果的函数了,等后面再写,或者大家来补充。
生成支付订单返回的是一个 url 文本,返回给前端,让前端生成对应的支付二维码即可。