新建云函數(shù)pay,下圖是其文件列表
安裝依賴
右鍵單擊云函數(shù)患久,在終端中打開蒋失,出現(xiàn)cmd窗口桐玻,npm install --save request
依次安裝好如上圖所示依賴
index.js
// 云函數(shù)入口文件
const cloud = require('wx-server-sdk')
cloud.init()
var wechat=require("./wechat_config.js")
var body_data=require("./body_data.js")
var non_str_random=require("./non_str_random.js")
var cryptoMO=require("crypto")
var request = require('request');
var xml2js = require('xml2js');
var xmlParser = new xml2js.Parser({ explicitArray: false, ignoreAttrs: true })
var out_trade_no = Date.parse(new Date());
var non_str = non_str_random();
// 云函數(shù)入口函數(shù)
exports.main = async (event, context) => {
var payBody="fee"
const wxContext = cloud.getWXContext()
let obj = {
appid: wechat.appid,
mch_id: wechat.mch_id,
nonce_str: non_str,
body: payBody,
out_trade_no: out_trade_no,
total_fee: event.total_fee,
spbill_create_ip: wechat.ip,
notify_url: wechat.notify_url,
trade_type: 'JSAPI',
openid: event.openid
}
let arr = Object.keys(obj).sort().map(item => {
return `${item}=${obj[item]}`;
});
// 這里拼接簽名字符串的時(shí)候一定要注意: 商戶的key是要單獨(dú)拿出來(lái)拼在最后面的
let str = arr.join('&') + '&key=' + wechat.key;
//上下兩種生成str的方法都可以
// var str = `appid=${wechat.appid}&body=${payBody}&mch_id=${wechat.mch_id}&nonce_str=${non_str}¬ify_url=${wechat.notify_url}&openid=${event.openid}&out_trade_no=${out_trade_no}&spbill_create_ip=${wechat.ip}&total_fee=${event.total_fee}&trade_type=JSAPI&key=${wechat.key}`;
var sign = cryptoMO.createHash('md5').update(str).digest('hex');
var temp_body_data = body_data(wechat, payBody, non_str, event.openid, out_trade_no, event.total_fee, sign);
return new Promise((resolve, reject) => request({
url: wechat.url,
method: 'POST',
body: temp_body_data
}, (err, res, body) => {
xmlParser.parseString(body, (err, res) => {
var prepay_id = res.xml.prepay_id;
var str = `appId=${wechat.appid}&nonceStr=${non_str}&package=prepay_id=${prepay_id}&signType=MD5&timeStamp=${out_trade_no}&key=${wechat.key}`;
var paySign = cryptoMO.createHash('md5').update(str).digest('hex');
return resolve({
success: true,
data: {
timeStamp: out_trade_no.toString(),
nonceStr: non_str,
package: `prepay_id=${prepay_id}`,
paySign: paySign,
outTradeNo: out_trade_no
}
});
})
}))
}
body_data.js
function bodyData(wechat,payBody,non_str,openid,out_trade_no,total_fee,sign){
var formData='<xml>'
formData += "<appid>" + wechat.appid + "</appid>"; //appid
formData += "<body>" + payBody + "</body>";
formData += "<mch_id>" + wechat.mch_id + "</mch_id>"; //商戶號(hào)
formData += "<nonce_str>" + non_str + "</nonce_str>";
formData += "<openid>" + openid + "</openid>";
formData += "<notify_url>" + wechat.notify_url + "</notify_url>";
formData += "<out_trade_no>" + out_trade_no + "</out_trade_no>";
formData += "<spbill_create_ip>" + "127.0.0.1" + "</spbill_create_ip>";
formData += "<total_fee>" + total_fee + "</total_fee>";
formData += "<trade_type>JSAPI</trade_type>";
formData += "<sign>" + sign.toUpperCase() + "</sign>";
formData += "</xml>";
return formData;
}
module.exports=bodyData
wechat_config.js
var wechat={
appid: '########',
mch_id: '###########', //商戶ID
ip:'127.0.0.1', //終端IP铣卡,貌似隨便寫也沒(méi)啥問(wèn)題
notify_url:'https://www.baidu.com/', //回調(diào)地址煮落,便于接收微信支付返回的結(jié)果,隨便寫
key:'############', //api KEY
url:'https://api.mch.weixin.qq.com/pay/unifiedorder' //請(qǐng)求地址蝉仇,文檔上有
}
module.exports=wechat;
non_str_random.js
生成隨機(jī)字符串函數(shù)
function non_str(){
var data=''
var chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
for (var i = 0; i < 32; i++) {
var id = Math.ceil(Math.random() * chars.length-1);
data += chars[id];
}
return data;
}
module.exports=non_str
服務(wù)端寫好了褪子,接下來(lái)就是客戶端
在pages/index/index.js文件中調(diào)用云函數(shù),存儲(chǔ)openId
wx.cloud.callFunction({
name: 'register',
// 傳給云函數(shù)的參數(shù)
complete: res => {
app.globalData.openId = res.result.OPENID
wx.setStorageSync('openid', res.result.OPENID)
},
fail: console.error
})
在需要微信支付的地方調(diào)用pay云函數(shù)
wx.cloud.callFunction({
name: 'pay',
data: {
openid: wx.getStorageSync('openid'),
total_fee: this.data.totalprice * 100
},
complete: res => {
wx.requestPayment({
timeStamp: res.result.data.timeStamp,
nonceStr: res.result.data.nonceStr,
package: res.result.data.package,
signType: 'MD5',
paySign: res.result.data.paySign,
})
}
})
全部完成
剛開始呀枢,云函數(shù)一直返回簽名校驗(yàn)失敗裙秋,我利用官方校驗(yàn)工具卻是正確的琅拌,然后我就重新再運(yùn)行了一次进宝,結(jié)果又可以了,坑爹党晋,真的是看心情返回了