我們在做小程序支付相關的開發時,總會遇到這些難題。小程序調用微信支付時,必須要有自己的服務器,有自己的備案域名,有自己的后臺開發。這就導致我們做小程序支付時的成本很大。本節就來教大家如何使用小程序云開發實現小程序支付功能的開發。不用搭建自己的服務器,不用有自己的備案域名。只需要簡簡單單的使用小程序云開發。
老規矩先看效果圖:
本節知識點
1,云開發的部署和使用
2,支付相關的云函數開發
3,商品列表
4,訂單列表
5,微信支付與支付成功回調
支付成功給用戶發送推送消息的功能會在后面講解。
下面就來教大家如何借助云開發使用小程序支付功能。
支付所需要用到的配置信息
1,小程序appid
2,云開發環境id
3,微信商戶號
4,商戶密匙
一,準備工作
1,已經申請小程序,獲取小程序 AppID 和 Secret 在小程序管理后臺中,【設置】 →【開發設置】 下可以獲取微信小程序 AppID 和 Secret。
2,微信支付商戶號,獲取商戶號和商戶密鑰在微信支付商戶管理平臺中,【賬戶中心】→【商戶信息】 下可以獲取微信支付商戶號。
在【賬戶中心】 ?> 【API安全】 下可以設置商戶密鑰。
這里特殊說明下,個人小程序是沒有辦法使用微信支付的。所以如果想使用微信支付功能,必須是非個人賬號(當然個人可以辦個體戶工商執照來注冊非個人小程序賬號)
?
二,商品列表的實現
效果圖如下,由于本節重點是支付的實現,所以這里只簡單貼出關鍵代碼。
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;
const 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,
spbill_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
});
}
}
}
其實我們支付的關鍵功能都在上面這些代碼里面了。
再來看下,支付的相關流程截圖
上圖就涉及到了我們的訂單列表,支付狀態,支付成功后的回調。
今天就先講到這里,后面會繼續給大家講解支付的其他功能。比如支付成功后的消息推送,也是可以借助云開發實現的。
?
本文摘自 :https://blog.51cto.com/u

