新建云函数pay,下图是其文件列表
image.png
安装依赖
image.png
右键单击云函数,在终端中打开,出现cmd窗口,npm install --save request
依次安装好如上图所示依赖
index.js
// 云函数入口文件
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();
// 云函数入口函数
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]}`;
});
// 这里拼接签名字符串的时候一定要注意: 商户的key是要单独拿出来拼在最后面的
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>"; //商户号
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,貌似随便写也没啥问题
notify_url:'https://www.baidu.com/', //回调地址,便于接收微信支付返回的结果,随便写
key:'############', //api KEY
url:'https://api.mch.weixin.qq.com/pay/unifiedorder' //请求地址,文档上有
}
module.exports=wechat;
non_str_random.js
生成随机字符串函数
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
服务端写好了,接下来就是客户端
在pages/index/index.js文件中调用云函数,存储openId
wx.cloud.callFunction({
name: 'register',
// 传给云函数的参数
complete: res => {
app.globalData.openId = res.result.OPENID
wx.setStorageSync('openid', res.result.OPENID)
},
fail: console.error
})
在需要微信支付的地方调用pay云函数
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,
})
}
})
全部完成
刚开始,云函数一直返回签名校验失败,我利用官方校验工具却是正确的,然后我就重新再运行了一次,结果又可以了,坑爹,真的是看心情返回了
网友评论