云开发的微信支付:免鉴权、免签名计算、免 access_token,在云函数内原生调用微信支付接口。以前的实现微信支付,必须要有自己的服务器,有自己的备案域名,还有后端部分代码
微信支付关键的开发流程:
-
- 小程序调用云函数,在云函数中调用统一下单CloudPay.unifiedOrder() 接口
-
- 统一下单接口返回的成功结果中有
payment
字段,该字段即是小程序端发起支付的接口(wx.requestPayment
)所需的参数
- 统一下单接口返回的成功结果中有
-
- 支付完成后,在统一下单接口中配置的支付通知的云函数将收到支付结果通知(可以在这里更新订单状态为已支付)
一、支付云函数pay
// pay云函数
const cloud = require('wx-server-sdk')
cloud.init()
const db=cloud.database()
function genOrderNo() {
let vNow = new Date()
let sNow = String(vNow.getFullYear()) + '-'
sNow += String(vNow.getMonth() + 1) + '-'
sNow += String(vNow.getDate()) + '|'
sNow += String(vNow.getHours() + 8) + '-'
sNow += String(vNow.getMinutes())
const $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
let maxPos = $chars.length
let leftLength = 32 - sNow.length
for (i = 0; i < leftLength; i++) {
sNow += $chars.charAt(Math.floor(Math.random() * maxPos))
}
return sNow
}
// 云函数入口函数
exports.main = async (event, context) => {
let params = {
"body": event.body || "小程序支付",
"outTradeNo": event.outTradeNo || genOrderNo(),
// 小程序端可以wx.request:https://pv.sohu.com/cityjson 获取IP地址
"spbillCreateIp": event.ip || "127.0.0.1",
"totalFee": event.fee || 1, // 分为单元
// 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
"attach": event.attach
}
const res = await cloud.cloudPay.unifiedOrder({
...params,
"subMchId": "188888888",
"tradeType": 'JSAPI',
"envId": "cloud1-xxxxxxxxx",
"functionName": "pay_cb" // 支付的回调云函数名
})
if (res['errMsg'] == 'cloudPay.unifiedOrder:ok') { // 下单成功
params['nonceStr'] = res['nonceStr']
params['prepayId'] = res['prepayId']
params['sign'] = res['sign']
params['appid'] = res['appid']
params['mchId'] = res['mchId']
db.collection("pre_order").add({
data: {
...params, // 保存支付信息
openid: event.openid, // 用户openid
phone: event.phone,
orderTime: new Date().getTime(),
payStatus: 0 // 0:未支付, 1:已支付, -1:失效
}
})
}
return res
}
二、小程序端调用支付的云函数
wx.cloud.callFunction({
name: 'pay', // 对应云函数名
data: {
body: '预订xxx',
fee: 1 * 100,
ip: paddr, // ip地址
phone: phone, // 手机号
attach: phone+ ',' + 'xxxx' + ',' + 'yyyy' // 用于支付通知
},
success: res => {
const payment = res.result.payment
console.log('pay res.result', res.result)
wx.requestPayment({
...payment,
success(res) {
console.log('pay success', res)
wx.showToast({
title: '支付成功',
icon: 'none'
})
},
fail(err) {
console.log('pay fail', err)
let errStr = String(err.errMsg)
if (errStr.indexOf('cancel')) {
wx.showToast({
title: '您已取消支付',
icon: 'none'
})
}
}
})
}
})
三、支付回调的云函数pay_cb
对应上面cloud.cloudPay.unifiedOrder中的 "functionName": "pay_cb" 支付回调方法名
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database();
// 云函数入口函数
exports.main = async (event, context) => {
if (event['returnCode'] == 'SUCCESS') {
try {
db.collection('pre_order').where({
outTradeNo: event['outTradeNo']
})
.update({
data: {
transactionId: event['transactionId'],
payTime: new Date().getTime(),
payStatus: 1 // 0:未支付, 1:已支付
},
})
const attachInfo = event['attach'] && event['attach'].split(',')
// 添加 order 记录
db.collection("order").add({
data: {
_createTime: new Date().getTime(),
phone: attachInfo[0],
xxx: attachInfo[1] + '',
yyy: attachInfo[2] + '',
transactionId: event['transactionId'],
outTradeNo: event['outTradeNo'],
money: event['totalFee'] / 100
}
})
} catch (e) {
console.error(e)
}
}
return { "errcode": 0 }
}