我們在做小程式支付相關的開發時總會遇到這些難題
1.小程式呼叫微信支付時必須要有自己的伺服器
2.有自己的備案域名
3.有自己的後臺開發
這就導致我們做小程式支付時的成本很大
本節就來教大家如何使用小程式雲開發實現小程式支付功能的開發,不用搭建自己的伺服器,不用有自己的備案域名,只需要簡簡單單的使用小程式雲開發。
老規矩先看效果圖
本節知識點
1.雲開發的部署和使用
2.支付相關的雲函式開發
3.商品列表
4.訂單列表
5.微信支付與支付成功回撥
支付成功給使用者傳送推送訊息的功能會在後面講解
下面就來教大家如何藉助雲開發使用小程式支付功能
支付所需要用到的配置資訊
1.小程式appid
2.雲開發環境id
3.微信商戶號
4.商戶密匙
一、準備工作
1.已經申請小程式,獲取小程式 AppID 和 Secret 在小程式管理後臺中——【設定】 →【開發設定】 可以獲取微信小程式 AppID 和 Secret。
2.微信支付商戶號,獲取商戶號和商戶金鑰在微信支付商戶管理平臺中——【賬戶中心】→【商戶資訊】 可以獲取微信支付商戶號。
在【賬戶中心】 ‒> 【API安全】 可以設定商戶金鑰。
這裡特殊說明下——個人小程式是沒有辦法使用微信支付的,所以如果想使用微信支付功能必須是非個人賬號(當然個人可以辦個體戶工商執照來註冊非個人小程式賬號)
3.微信開發者 IDE
https://developers.weixin.qq.com/miniprogr...
4.開通小程式雲開發功能
https://edu.csdn.net/course/play/9604/2045...
二、商品列表的實現
效果圖如下
由於本節重點是支付的實現所以這裡只簡單貼出關鍵程式碼
wxml佈局如下:
<view class="container">
<view class="good-item" wx:for="{{goods}}" wx:key="*this" ontap="getDetail" data-goodid="{{item._id}}">
<view class="good-image">
<image src="{{pic}}"></image>
</view>
<view class="good-detail">
<view class="title">商品: {{item.name}}</view>
<view class="content">價格: {{item.price / 100}} 元 </view>
<button
class="button"
type="primary"
bindtap="makeOrder"
data-goodid="{{item._id}}"
>下單</button>
</view>
</view></view>
我們所需要做的就是藉助雲開發獲取雲資料庫裡的商品資訊然後展示到商品列表,關於雲開發獲取商品列表並展示本節不做講解(感興趣的同學可以翻看我的歷史部落格,有寫過)
三、支付雲函式的建立
首先看下我們支付雲函式都包含那些內容
簡單先講解下每個的用處
config下的index.js是做支付配置用的,主要配置支付相關的賬號資訊
lib是用的第三方的支付庫,這裡不做講解。
重點講解的是雲函式入口 index.js
下面就來教大家如何去配置
1.配置config下的index.js,
這一步所需要做的就是把小程式appid、雲開發環境ID、商戶id、商戶密匙填進去
2.配置入口雲函式
詳細程式碼如下,程式碼裡註釋很清楚了這裡不再做單獨講解:
const cloud = require('wx-server-sdk')
cloud.init()const app = require('tcb-admin-node');const pay = require('./lib/pay');const {
mpAppId,
KEY
} = require('./config/index');const {
WXPayConstants,
WXPayUtil
} = require('wx-js-utils'); const Res= require('./lib/res'); const ip = require('ip');/**
*
* @param {obj} event
* @param {string} event.type 功能型別
* @param {} userInfo.openId 使用者的openid
*/exports.main = async function(event, context) { const {
type,
data,
userInfo
} = event; onst wxContext = cloud.getWXContext() const openid = userInfo.openId;
app.init(); const db = app.database (); const goodCollection = db.collection('goods'); const orderCollection = db.collection('order');// 訂單文件的status 0 未支付 1 已支付 2 已關閉
switch (type) { // [在此處放置 unifiedorder 的相關程式碼]
case 'unifiedorder':
{ // 查詢該商品 ID 是否存在於資料庫中,並將資料提取出來
const goodId = data.goodId let goods = await goodCollection.doc(goodId).get(); if (!goods.data.length) { return new Res ({ code: 1, message: '找不到商品'
});
} // 在雲函式中提取資料,包括名稱、價格才更合理安全,
// 因為從端裡傳過來的商品資料都是不可靠的
let good = goods.data[0]; // 拼湊微信支付統一下單的引數
const curTime = Date.now(); const tradeNo =`${goodId}-${curTime}`; const body = good.name; const spbill_create_ip = ip.address() || '127.0.0.1'; // 雲函式暫不支付 http 觸發器,因此這裡回撥 notify_url 可以先隨便填。
const notify_url = 'http://www.qq.com'; // '127.0.0.1';
const total_fee = good.price; const time_stamp = '' + Math.ceil(Date.now() / 1000); const out_trade_no = `${tradeNo}`; const sign_type = WXPayConstants.SIGN_TYPE_MD5; let orderParam = {
body,
spill_create_ip,
notify_url,
out_trade_no,
total_fee,
openid, trade_type: 'JSAPI', timeStamp: time_stamp,
}; // 呼叫 wx-js-utils 中的統一下單方法
const {
return_code,
...restData
} = await pay.unifiedOrder(orderParam); let order_id = null; if (return_code === 'SUCCESS' && restData.result_code === 'SUCCESS') { const {
prepay_id,
nonce_str
} = restData; // 微信小程式支付要單獨進地簽名,並返回給小程式端
const sign = WXPayUtil.generateSignature ({ appId: mpAppId, nonceStr: nonce_str, package: `prepay_id=${prepay_id}`, signType: 'MD5', timeStamp: time_stamp
}, KEY); let orderData = {
out_trade_no,
time_stamp,
nonce_str,
sign,
sign_type,
body,
total_fee,
prepay_id,
sign, status: 0, // 訂單文件的status 0 未支付 1 已支付 2 已關閉
_openid: openid,
}; let order = await orderCollection.add(orderData);
order_id = order.id;
} return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: {
out_trade_no,
time_stamp,
order_id,
...restData
}
});
} // [在此處放置 payorder 的相關程式碼]
case 'payorder':
{ // 從端裡出來相關的訂單相信
const {
out_trade_no,
prepay_id,
body,
total_fee
} = data; // 到微信支付側查詢是否存在該訂單,並查詢訂單狀態,看看是否已經支付成功了。
const {
return_code,
...restData
} = await pay.orderQuery({
out_trade_no
}); // 若訂單存在並支付成功,則開始處理支付
if (restData.trade_state === 'SUCCESS') { let result = await orderCollection
.where({
out_trade_no
})
.update({ status: 1, trade_state: restData.trade_state, trade_state_desc: restData.trade_state_desc
}); let curDate = new Date(); let time = `${curDate.getFullYear()}-${curDate.getMonth() + 1}-${curDate.getDate()} ${curDate.getHours()}:${curDate.getMinutes()}:${curDate.getSeconds()}`;
} return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: restData
});
} case 'orderquery':
{ const {
transaction_id,
out_trade_no
} = data; // 查詢訂單
const { data: dbData
} = await orderCollection
.where({
out_trade_no
}).get(); const {
return_code,
...restData
} = await pay.orderQuery({
transaction_id,
out_trade_no
}); return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: { ...restData,
...dbData[0]
}
});
} case 'closeorder':
{ // 關閉訂單
const {
out_trade_no
} = data; const {
return_code,
...restData
} = await pay.closeOrder({
out_trade_no
}); if (return_code === 'SUCCESS' &&
restData.result_code === 'SUCCESS') { await orderCollection
.where({
out_trade_no
})
.update({ status: 2, trade_state: 'CLOSED', trade_state_desc: '訂單已關閉'
});
} return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: restData
});
}
}
}
其實我們支付的關鍵功能都在上面這些程式碼裡面了
再來看下,支付的相關流程截圖
上圖就涉及到了我們的訂單列表、支付狀態、支付成功後的回撥
今天就先講到這裡
後面會繼續給大家講解支付的其他功能——比如支付成功後的訊息推送也是可以藉助雲開發實現的
由於原始碼裡涉及到一些私密資訊這裡就不單獨貼出原始碼下載連結了,大家感興趣的話可以留言或新增作者微信(微信2501902696)獲取原始碼
如果你有關於使用雲開發CloudBase相關的技術故事/技術實戰經驗想要跟大家分享,歡迎留言聯絡我們哦!比心!
雲開發 Tencent CloudBase
關注我可以說是相當酷了~