其实参照官方文档一步一步操作不是很难,但很多人在签名这个地方就总是出现问题,因为文档中签名时使用的字段大小写时错误的。。。。好坑啊!!然而PHP版本的代码官方有封装SDK包,不用操心那么多细节。
NODEJS版本的只能自己写了。
1.签名方法(简单不会错)
//签名; //mchkey是你在支付平台设置的一个API密钥 function MSign(param, mchkey){ var string = raw(param); string = string + '&key=' + mchkey; //key拼接在字符串最后面 var crypto = require('crypto'); return crypto.createHash('md5').update(string, 'utf8').digest('hex').toUpperCase(); } //args是一个JSON,方法将json中的字段按照ASCII码从小到大排序,生成一个字符串key1=value1&key2=value2。 function raw(args) { var keys = Object.keys(args); keys = keys.sort(); var newArgs = {}; keys.forEach(function (key) { newArgs[key] = args[key]; }); var string = ''; for (var k in newArgs) { string += '&' + k + '=' + newArgs[k]; } string = string.substr(1); return string; }
2.创建订单
//创建随机数; getRandomNumberSection(begin, end) { return Math.floor(Math.random() * (begin - end) + end); } //创建随机字符串; getRandomStr(length) { let value = ['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', '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; let result = ""; for (let i = 0; i < length; i++) { let v = value[getRandomNumberSection(0, value.length - 1)]; while (i === 0 && v === '0') { v = value[getRandomNumberSection(0, value.length - 1)]; } result += v; } return result; } //创建JSAPI订单; //openid:微信用户的OPENID //body: 订单信息; //out_trade_no: 你自己生产的商户订单号; //spbill_create_ip: 客户端IP地址 //total_fee: 支付金额(单位分) async CreateJSAPIpay(openid, body, out_trade_no, spbill_create_ip, total_fee, callback) { let that = this; let notify_url = '你需要设置支付完成后的回调URL'; let WxAppid = '微信APPID'; let mch_id = '商户ID'; let trade_type = 'JSAPI'; let sign_type = 'MD5'; let noncestr = (new Date()).getTime() + '_'; noncestr += getRandomStr(31 - noncestr.length); //产生32位随机字符串; //1.签名参数; let sign = MSign({ appid: WxAppid, mch_id: mch_id, nonce_str: noncestr, notify_url: notify_url, trade_type: trade_type, sign_type: sign_type, openid: openid, //微信用户的OPENID body: body, //订单信息; out_trade_no: out_trade_no,//你自己生产的商户订单号; spbill_create_ip: spbill_create_ip,//客户端IP地址 total_fee: total_fee //金额(单位分) }, this.mchkey);
//2.生成XML格式; let formData = "<xml>"; formData += "<appid>" + WxAppid + "</appid>"; formData += "<body><![CDATA[" + body + "]]></body>"; formData += "<mch_id>" + mch_id + "</mch_id>"; formData += "<nonce_str>" + noncestr + "</nonce_str>"; formData += "<notify_url>" + notify_url + "</notify_url>"; formData += "<out_trade_no>" + out_trade_no + "</out_trade_no>"; formData += "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"; formData += "<total_fee>" + total_fee + "</total_fee>"; formData += "<trade_type>" + trade_type + "</trade_type>"; formData += "<openid>" + openid + "</openid>"; formData += "<sign_type>" + sign_type + "</sign_type>"; formData += "<sign>" + sign + "</sign>"; //sign是上一步签名产生的; formData += "</xml>";
//3.请求微信 let url = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; request({ url: url, method: 'POST', body: formData }, function (err, response, body) { if (!err && response.statusCode == 200) { xmlreader.read(body.toString("utf-8"), function (errors, response) { if (null !== errors) { callback(false, errors, null); } else { if (response.xml.return_msg.text().toLocaleUpperCase() == 'OK') { //此时返回的数据并不能直接用在客户端,需要再次签名; let prepay_id = response.xml.prepay_id.text(); let timestamp = parseInt(new Date().getTime() / 1000) + ''; //4.签名 let finalsign = MSign({ appId: WxAppid, timeStamp: timestamp, nonceStr: noncestr, package: 'prepay_id=' + prepay_id, signType: sign_type }, mchkey); //这才是客户端最后使用的数据; let clientParam = { 'appId': WxAppid, 'nonceStr': noncestr, 'timeStamp': timestamp, 'package': 'prepay_id=' + prepay_id, 'signType': that.sign_type, 'sign': finalsign }; callback(true, clientParam); } else { callback(false, null); } } }); } else { callback(false, null); } }); }
3.公众号网页唤起支付页面
如果要在WEB端使用微信的功能,则需要在页面打开时使用JSAPI签名进行初始化,服务端JSAPI签名的方法如下,其中,jsapi参数是使用全局access_token获取的,url是网页的地址。
//获取JSAPI签名; static GetJSAPISign(appid, jsapi, url) { var ret = { jsapi_ticket: jsapi, noncestr: Math.random().toString(36).substr(2, 15), timestamp: parseInt(new Date().getTime() / 1000) + '', url: url };
var string = raw(ret);
let jsSHA = require('jssha'); let shaObj = new jsSHA(string, 'TEXT'); let signature = shaObj.getHash('SHA-1', 'HEX'); return { appid:appid, nonceStr:ret.noncestr, timestamp:ret.timestamp, signature:signature, url: url }; }
网页端初始化微信JSAPI代码 需要引入
<script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script> //我使用的EJS,参数在请求页面时就生成好了; var jsapiSign = JSON.parse('<%- JSON.stringify(jsapiSign)%>'); var paymentSign = JSON.parse('<%- JSON.stringify(paymentSign)%>'); //初始化JSAPI; function init(){ wx.config({ debug: true, appId: jsapiSign.appid, timestamp: jsapiSign.timestamp, nonceStr: jsapiSign.nonceStr, signature: jsapiSign.signature, jsApiList : [ 'chooseWXPay' //请求微信支付权限 ] });
wx.ready(function () { wx.hideOptionMenu(); //隐藏菜单; onBridgeReady(); //初始化完成后立即调用微信支付; });
wx.error(function(res){ console.log('初始化失败了,请稍后重试'); }); } //唤起支付; function onBridgeReady(){ var param = { appid:paymentSign.appId, timestamp: paymentSign.timeStamp, nonceStr: paymentSign.nonceStr, package: paymentSign.package, signType: paymentSign.signType, paySign: paymentSign.sign, success: function (res) { console.log("支付完成,请稍候"); }, cancel: function(res){ console.log("用户取消支付"); }, fail: function(msg){ console.log("支付调用失败"); } }; //API唤起支付; wx.chooseWXPay(param); } init(); </script>
目前学到了一种方法!
一:cd到文件夹对应的项目中 在cmd中输入 你npm run build
二:此时项目中会生成一个文件夹dist,在dist文件夹下的index文件里每个路径前加 ./ 如下图
三:在HBuilder X中 点击文件---新建--项目---选择5+App---定义名称--模板选空项目
四:删除刚刚新建项目里面的 除了manifest.json 这个文件的其他文件
五:打开原来项目并复制dist中的文件,不包括dist,粘贴到,在HBuilder X中创建的项目里
六:点击HBuilder X中的 发行---原生APP云打包 ----Android(apk包)----使用公共测试证书
七:点击打包
八:打包成功后会显示下载地址
|
请发表评论