微信小程式--使用雲開發完成支付閉環
阿新 • • 發佈:2021-02-01
#### 微信小程式--使用雲開發完成支付閉環
#### 1.流程介紹
![](https://img2020.cnblogs.com/blog/1141382/202102/1141382-20210201004552059-1922933214.png)
![](https://img2020.cnblogs.com/blog/1141382/202102/1141382-20210201004607414-743313710.png)
#### 2. 程式碼實現和邏輯思想描述
> 雲函式統一下單 對應雲函式 **unipay**
> [【CloudPay.unifiedOrder】](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/open/pay/CloudPay.unifiedOrder.html)
> **函式思路** : 呼叫雲函式封裝功能,用時間戳生成對應訂單號,進行統一下單處理,如果兩個返回結果都是`SUCCESS`,那麼將該訂單記錄寫入資料庫,狀態設定為`waiting`
1. body填寫商戶名稱
2. subMchId填寫商戶ID,在雲函式環境管理後臺獲取
~~~js
const cloud = require('wx-server-sdk')
cloud.init({
env: ''
})
const db = cloud.database();
const _ = db.command;
exports.main = async (event, context) => {
var fee = parseInt(event.fee);
let paydata = event.paydata;
let tradeno = GetTradeNo();
const res = await cloud.cloudPay.unifiedOrder({
"body": "",
"outTradeNo": tradeno,
"spbillCreateIp": "127.0.0.1",
"subMchId": "",
"totalFee": fee,
"envId": "雲函式環境ID",
"functionName": "unipaynotify"
})
res.outTradeNo = tradeno
res.totalFee = fee
//在此處寫入訂單表
paydata.paytimestamp = res.payment.timeStamp;
paydata.orderid = res.outTradeNo;//訂單號
paydata.paystatus = 'waiting'
paydata.orderamount = fee
paydata.paytime = TimeCode()
paydata.mchid = res.subMchId
if(res.returnCode=='SUCCESS' && res.resultCode=='SUCCESS'){
db.collection('pay_record').add({
data:paydata
})
}
return res
}
function GetTradeNo() {
var outTradeNo = ""; //訂單號
for (var i = 0; i < 6; i++) //6位隨機數,用以加在時間戳後面。
{
outTradeNo += Math.floor(Math.random() * 10);
}
outTradeNo = "LHZHWY" + new Date().getTime() + outTradeNo; //時間戳,用來生成訂單號。
return outTradeNo;
}
function TimeCode() {
var date = new Date();
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds()
return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
function TimeCodeYmd(){
var date = new Date();
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
return [year, month, day].map(formatNumber).join('-');
}
function formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
}
~~~
> 根據**統一下單**返回引數,呼叫微信支付介面
1. fee 需要根據訂單計算 fee單位為`0.01`
2. paydata是商品訂單引數,形式為`Object`,可存放顧客手機號,支付總金額,支付哪一項費用等資訊
3. TimerQuery是定時器,查詢支付結果
~~~js
let fee = 1
//該費用只是代指,以實際開發為準
wx.cloud.callFunction({
name: 'unipay',
data: {
fee: fee,
paydata: paydata
},
success: res => {
const payment = res.result.payment
console.log(res)
//在此處獲得支付訂單號資訊,支付時間,支付狀態
var tradeno = res.result.outTradeNo
wx.requestPayment({
...payment,
success(res) {
//成功回撥,這個時候微信支付後臺會觸發回撥函式
console.log(res)
that.TimerQuery(tradeno, paydata);
},
fail(res) {
that.setData({
error: '支付失敗'
})
}
})
},
fail: r => {
console.log(r)
that.setData({
error: '雲伺服器錯誤'
})
}
})
~~~
>回撥函式**unipaynotify**
>
>[【Cloud.paymentCallback】](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/open/pay/paymentCallback.html)
訂單在**支付成功**時會觸發該回調函式
該回調函式**必須有返回值**,且必須是固定格式
根據回撥函式攜帶的訂單號,修改對應訂單號的`waiting`狀態為`success`,並且返回對應格式的返回資訊
| 欄位名 | 變數名 | 必填 | 型別 | 描述 |
| :------- | :------ | :--- | :----- | :--- |
| 錯誤碼 | errcode | 是 | Number | 0 |
| 錯誤資訊 | errmsg | 是 | String | |
回撥函式攜帶引數如下
~~~json
{
appid: '',
bankType: 'OTHERS',
cashFee: 1,
feeType: 'CNY',
isSubscribe: 'N',
mchId: '',
nonceStr: '',
openid: '',
outTradeNo: '',
resultCode: 'SUCCESS',
returnCode: 'SUCCESS',
subAppid: '',
subIsSubscribe: 'N',
subMchId: '',
subOpenid: '',
timeEnd: '',
totalFee: 1,
tradeType: 'JSAPI',
transactionId: '',
userInfo:
{
appId: '',
openId: ''
}
}
~~~
~~~js
const cloud = require('wx-server-sdk')
cloud.init({
env: '填寫你的雲環境ID'
})
const db = cloud.database();
const _ = db.command;
// 雲函式入口函式
exports.main = async (event, context) => {
console.log('支付成功回撥函式觸發')
console.log(event)
let tradeno = event.outTradeNo;
console.log(tradeno)
try {
let res = await db.collection('pay_record').where({
orderid:tradeno
}).update({
data:{
paystatus:'success'
}
})
console.log(res)
} catch (error) {
return {
errmsg: 'SERVER_ERROR',
errcode: -1
}
}
return {
errmsg: 'SUCCESS',
errcode: 0
}
}
~~~
> 定時查詢器,查詢結果**TimerQuery**
1. 沒間隔一秒查詢一次,查詢到該訂單記錄為`success`清除定時觸發器,並展示成功資訊
2. 可以使用遞迴疊加器,計算請求次數,到幾次就終止,可自行完成
~~~js
TimerQuery(tradeno, paydata) {
//查詢訂單支付結果
var that = this;
//將計時器賦值給setInter
that.data.setInter = setInterval(
function () {
db.collection('pay_record').where({
orderid: tradeno,
paystatus: 'success'
}).get({
success: res => {
if (res.data.length > 0) {
that.setData({
sinfo: '繳費成功'
})
clearInterval(that.data.setInter)
}
}
})
}, 1000);
}
~~~
> 參考 - 我的未開源專案
>
> Gitee地址:https://gitee.com/Kindear
>
> 寫文不易,求個