關(guān)于微信小程序?qū)崿F(xiàn)云支付那些事兒
一、前言
稍微玩過(guò)微信小程序云開(kāi)發(fā)的同學(xué)都基本知道微信小程序云開(kāi)發(fā)目前已經(jīng)支持云支付這一能力。
那么在云支付的能力支持之下,整個(gè)支付的流程是怎樣的呢?
例如:用戶(hù)發(fā)起支付前、支付中、支付后的邏輯處理應(yīng)該是怎樣的,該如何設(shè)計(jì)會(huì)比較保險(xiǎn),降低出錯(cuò)的概率。
那么本文主要介紹云支付的使用以及在云支付下的訂單系統(tǒng)、支付流程該如何設(shè)計(jì)。
順便提一下:微信支付功能僅支持企業(yè)主體調(diào)用。
二、思路分析
云支付的調(diào)用流程大致分為以下四步:
1、獲取免鑒權(quán)參數(shù)
小程序端傳入金額、商品信息等基本參數(shù)后,調(diào)用云函數(shù)獲取免鑒權(quán)參數(shù)。
2、將免鑒權(quán)參數(shù)傳入小程序端的支付API
云函數(shù)返回免鑒權(quán)參數(shù),作為小程序端支付API的入?yún)ⅰ?/p>
3、用戶(hù)支付
調(diào)起微信支付,用戶(hù)進(jìn)行支付/取消支付操作
4、微信端回調(diào)指定的云函數(shù)
支付成功后回調(diào)此云函數(shù)。
如果用戶(hù)取消支付,則不會(huì)回調(diào)此云函數(shù)。
那么,根據(jù)以上四個(gè)步驟就可以分析出,訂單的創(chuàng)建、訂單支付狀態(tài)的改變應(yīng)該是在什么時(shí)候了。
訂單的創(chuàng)建應(yīng)該是在第一步的獲取免鑒權(quán)參數(shù)的時(shí)候,獲取免鑒權(quán)參數(shù)后將訂單號(hào)等信息插入數(shù)據(jù)庫(kù)。
此時(shí)的訂單支付狀態(tài)應(yīng)該是待支付狀態(tài)。
同時(shí)也可以知道,訂單支付狀態(tài)的改變,應(yīng)該是在第四步中去進(jìn)行改變,如果支付成功,將訂單的支付狀態(tài)改為支付成功即可。
相關(guān)的官方文檔鏈接:
三、云支付小案例
1.云函數(shù)
1-1.獲取免鑒權(quán)參數(shù)云函數(shù)(wxPay)
此云函數(shù)主要是獲取支付API所需的參數(shù),以及創(chuàng)建訂單插入數(shù)據(jù)庫(kù)。
成功調(diào)用示例結(jié)果截圖

實(shí)現(xiàn)代碼
// 云函數(shù)入口文件
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()
exports.main = async (event) => {
const wxContent = cloud.getWXContext() // openid等信息
const openid = wxContent.OPENID
const appid = wxContent.APPID
const totalFee = event.totalFee // 支付金額(單位:分)
const body = event.body // 商品名
const outTradeNo = createOutTradeNo() // 訂單號(hào)
// 獲取免鑒權(quán)支付參數(shù)
const payMent = await cloud.cloudPay.unifiedOrder({
"body": body,
"outTradeNo": outTradeNo,
"spbillCreateIp": "127.0.0.1",
"subMchId": "商戶(hù)號(hào)", // 商戶(hù)號(hào)
"totalFee": totalFee,
"envId": "對(duì)應(yīng)的云環(huán)境id", // 云環(huán)境id
"functionName": "payCallBack" // 支付回調(diào)云函數(shù)
})
// 創(chuàng)建訂單
const nowTime = new Date().getTime()
const orderObj = {
_openid: openid,
appid: appid,
outTradeNo: outTradeNo,
totalFee: totalFee * 0.01,
payStatus: 'wait',
createTime: nowTime,
updateTime: nowTime,
deleteTime: null,
}
await addOrder(orderObj)
return payMent
}
/** 創(chuàng)建隨機(jī)的唯一訂單號(hào)(32位) */
const createOutTradeNo = () => {
let outTradeNo = new Date().getTime() // 獲取當(dāng)前13位時(shí)間戳
let numStr = '0123456789';
let randomStr = '';
for (let i = (32 - 13); i > 0; --i) {
randomStr += numStr[Math.floor(Math.random() * numStr.length)];
}
outTradeNo += randomStr
return outTradeNo
}
/** 向數(shù)據(jù)庫(kù)創(chuàng)建訂單 */
const addOrder = async (orderObj) => {
return await db.collection('order')
.add({
data: orderObj
})
.then(res => {
console.log("創(chuàng)建訂單成功 =====>", res, orderObj)
})
.catch(err => {
console.log("創(chuàng)建訂單異常 =====>", err, orderObj)
})
}
1-2.支付回調(diào)云函數(shù)(payCallBack)
在用戶(hù)支付成功后微信服務(wù)端將會(huì)調(diào)用此云函數(shù),并攜帶支付方的訂單號(hào)、openid、appid等信息。
開(kāi)發(fā)者可以根據(jù)這個(gè)來(lái)判斷當(dāng)前回調(diào)的是哪個(gè)訂單。
成功回調(diào)結(jié)果示例截圖

實(shí)現(xiàn)代碼
// 云函數(shù)入口文件
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
const db = cloud.database()
// 云函數(shù)入口函數(shù)
exports.main = async (event) => {
console.log("回調(diào)返回對(duì)象 =====>", event)
// 判斷條件
if (event.returnCode == 'SUCCESS') {
if (event.resultCode == 'SUCCESS') {
// 查詢(xún)條件
const whereObj = {
appid: event.subAppid, // 小程序的APPID
_openid: event.subOpenid, // 小程序用戶(hù)的openid
outTradeNo: event.outTradeNo, // 商戶(hù)號(hào)的訂單號(hào)
}
// 更新對(duì)象
const updateObj = {
transactionId: event.transactionId, // 微信方的訂單號(hào)
totalFee: event.totalFee * 0.01, // 微信方收到的金額
timeEnd: event.timeEnd, // 支付結(jié)束時(shí)間
payStatus: 'success',
updateTime: new Date().getTime()
}
// 更新訂單
await updateOrder(whereObj, updateObj)
}
}
// 支付回調(diào)的返回協(xié)議和入?yún)f(xié)議(必須返回此結(jié)構(gòu)體,詳見(jiàn)文檔)
return {
errcode: 0,
errmsg: event.resultCode
}
}
/** 更新訂單的支付狀態(tài) */
const updateOrder = async (whereObj, updateObj) => {
return await db.collection('order')
.where(whereObj)
.update({
data: updateObj
})
}
2.小程序端(js代碼)
// pages/wxPay/wxPay.js
Page({
/**
* 頁(yè)面的初始數(shù)據(jù)
*/
data: {
},
/**
* 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面加載
*/
onLoad() {},
/**
* 生命周期函數(shù)--監(jiān)聽(tīng)頁(yè)面顯示
*/
onShow() {},
/** 支付點(diǎn)擊監(jiān)聽(tīng) */
async payTap() {
const totalFee = 2
const body = '支付測(cè)試'
wx.showLoading({
title: '調(diào)起微信支付中',
mask: true
})
// 獲取支付免鑒權(quán)參數(shù)
const payMentRes = await this.getPayMent(totalFee, body)
wx.hideLoading({
success: (res) => {},
})
// 小程序支付API
const payRes = await this.wxPay(payMentRes.result.payment)
// 支付API返回結(jié)果打印
console.log(payRes)
},
/**
* 小程序支付API
* @param {object} payment 支付免鑒權(quán)參數(shù)
*/
wxPay(payment) {
return new Promise((resolve, rejects) => {
wx.requestPayment({
...payment,
success(res) {
resolve({
status: 'success',
res: res
})
},
fail(err) {
resolve({
status: 'fail',
res: err
})
}
})
})
},
/**
* 獲取支付免鑒權(quán)參數(shù)
* @param {number} totalFee 支付金額, 單位:分
* @param {string} body 商品名稱(chēng)
*/
getPayMent(totalFee, body) {
return new Promise((resolve, rejects) => {
wx.cloud.callFunction({
name: 'wxPay',
data: {
totalFee,
body
},
success(res) {
resolve(res)
},
fail(err) {
resolve(err)
}
})
})
},
})
3.支付結(jié)果
用戶(hù)端

商家端

4、代碼目錄結(jié)構(gòu)

四、為什么這樣寫(xiě)
或許有的同學(xué)也使用過(guò)微信云支付的能力,但是不曾使用到上面說(shuō)到的支付回調(diào)云函數(shù)。
但是也可以做到獲取用戶(hù)的支付結(jié)果。
如下圖

事實(shí)上,小程序端的支付API(wx.requestPayment())也可以返回當(dāng)前的支付結(jié)果。也確實(shí)可以使用這個(gè)回調(diào)的結(jié)果來(lái)判斷支付是否成功。
那既然這樣,為什么還要多此一舉寫(xiě)個(gè)支付回調(diào)云函數(shù)來(lái)獲取支付的結(jié)果呢?
看到這里也說(shuō)明你看完了整個(gè)實(shí)現(xiàn)過(guò)程了,如果你有為什么要用這種方式實(shí)現(xiàn)的疑問(wèn),也應(yīng)該多少能夠自己給自己找到一些答案。
除去開(kāi)發(fā)規(guī)范、優(yōu)化相關(guān)的小問(wèn)題,我這里說(shuō)一個(gè)很致命的原因。
微信小程序支付API(wx.requestPayment())在IOS端有一個(gè)致命的問(wèn)題,
當(dāng)用戶(hù)支付后會(huì)進(jìn)入下面這個(gè)頁(yè)面

當(dāng)用戶(hù)不點(diǎn)擊完成按鈕,微信小程序的支付API(wx.requestPayment())回調(diào)是不會(huì)觸發(fā)的。
也就說(shuō),小程序自身拿不到用戶(hù)的支付結(jié)果了。
假設(shè)用戶(hù)直接退出了微信,小程序也就銷(xiāo)毀了。這時(shí),訂單狀態(tài)該如何改變呢?
tips: 在安卓端不會(huì)出現(xiàn)這個(gè)問(wèn)題。有興趣的同學(xué)可以自己去實(shí)踐以下。
五、結(jié)語(yǔ)
思路是這樣的,但是一些異常處理,需要開(kāi)發(fā)者在開(kāi)發(fā)過(guò)程中自行處理,例如訂單插入失敗、更新失敗等異常問(wèn)題。雖然概率不大,而且也有打印調(diào)用記錄,如果出現(xiàn)問(wèn)題,也是可以查到調(diào)用記錄以及相關(guān)信息。
到此這篇關(guān)于關(guān)于微信小程序?qū)崿F(xiàn)云支付那些事兒的文章就介紹到這了,更多相關(guān)微信小程序云支付內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 微信小程序-詳解微信登陸、微信支付、模板消息
- 微信小程序 支付后臺(tái)java實(shí)現(xiàn)實(shí)例
- PHP:微信小程序 微信支付服務(wù)端集成實(shí)例詳解及源碼下載
- 微信小程序 支付功能開(kāi)發(fā)錯(cuò)誤總結(jié)
- 微信小程序 支付簡(jiǎn)單實(shí)例及注意事項(xiàng)
- 微信小程序支付及退款流程詳解
- 微信小程序 支付功能實(shí)現(xiàn)PHP實(shí)例詳解
- 微信小程序微信支付接入開(kāi)發(fā)實(shí)例詳解
- 微信小程序調(diào)用微信支付接口的實(shí)現(xiàn)方法
- 微信小程序 支付功能(前端)的實(shí)現(xiàn)
相關(guān)文章
小程序登錄/注冊(cè)頁(yè)面設(shè)計(jì)的實(shí)現(xiàn)代碼
這篇文章主要介紹了小程序登錄/注冊(cè)頁(yè)面設(shè)計(jì)的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
JS支付頁(yè)面倒計(jì)時(shí)的實(shí)現(xiàn)示例
本文主要介紹了JS支付頁(yè)面倒計(jì)時(shí)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03
可以用鼠標(biāo)拖動(dòng)的DIV實(shí)現(xiàn)思路及代碼
DIV可以拖動(dòng)的效果,想必大家都有見(jiàn)到過(guò)吧,在本文也為大家實(shí)現(xiàn)一個(gè)不錯(cuò)的可以用鼠標(biāo)拖動(dòng)的div,感興趣的各位不要錯(cuò)過(guò)2013-10-10
js defineSetter -給js的 "class"自動(dòng)增加一個(gè)set的屬性(方法)
js defineSetter -給js的 "class"自動(dòng)增加一個(gè)set的屬性(方法)...2007-06-06
javascript實(shí)現(xiàn)鼠標(biāo)點(diǎn)擊頁(yè)面 移動(dòng)DIV
本篇文章主要介紹javascript實(shí)現(xiàn)鼠標(biāo)點(diǎn)擊頁(yè)面,移動(dòng)DIV。話不多說(shuō),附上代碼實(shí)例。需要的朋友來(lái)看下吧2016-12-12
js實(shí)現(xiàn)前端分頁(yè)頁(yè)碼管理
本文主要介紹了js實(shí)現(xiàn)前端分頁(yè)頁(yè)碼管理的具體方法。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01
javascript fullscreen全屏實(shí)現(xiàn)代碼
用了實(shí)現(xiàn)打開(kāi)一個(gè)滿屏的代碼2009-04-04
LayUi中接口傳數(shù)據(jù)成功,表格不顯示數(shù)據(jù)的解決方法
今天小編就為大家分享一篇LayUi中接口傳數(shù)據(jù)成功,表格不顯示數(shù)據(jù)的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
小程序?qū)崿F(xiàn)頁(yè)面跳轉(zhuǎn)與數(shù)據(jù)傳遞方案
在開(kāi)發(fā)過(guò)程中經(jīng)常會(huì)遇到在微信小程序的頁(yè)面跳轉(zhuǎn)以及數(shù)據(jù)傳遞的知識(shí)點(diǎn),所以下面這篇文章主要給大家介紹了關(guān)于小程序?qū)崿F(xiàn)頁(yè)面跳轉(zhuǎn)與數(shù)據(jù)傳遞的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09
微信小程序開(kāi)發(fā)實(shí)戰(zhàn)快速入門(mén)教程
這篇文章主要為大家介紹了開(kāi)發(fā)一個(gè)微信小程序?qū)崙?zhàn)快速入門(mén)教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04

