wechatH5Pay(transactionId, totalPrice, ip, openid) { var self = this ; let data; var url = "https://api.mch.weixin.qq.com/pay/unifiedorder" ; var appid = settings.appid; //应用微信中的id var mch_id = settings.mch_id; //商户号 var notify_url = 'http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php' ;//回调通知地址 var out_trade_no = transactionId; //订单号 var total_fee = totalPrice * 100; //商品价格 var attach = 'Butchart布查德' ; var body = "花束产品" ; //客户端商品描述 var nonce_str = self.randomWord( false , 32); //随机32位之内字符串 var formData = "<xml>" ; formData += "<appid>" + appid + "</appid>" ; //appid formData += "<attach>" + attach + "</attach>" ; //附加数据 formData += "<body>" + body + "</body>" ; //商品或支付单简要描述 formData += "<mch_id>" + mch_id + "</mch_id>" ; //商户号 formData += "<nonce_str>" + nonce_str + "</nonce_str>" ; //随机字符串,不长于32位 formData += "<notify_url>" + notify_url + "</notify_url>" ; //支付成功后微信服务器通过POST请求通知这个地址 formData += "<openid>" + openid + "</openid>" ; //openid formData += "<out_trade_no>" + out_trade_no + "</out_trade_no>" ; //订单号 formData += "<spbill_create_ip>" + ip + "</spbill_create_ip>" ; //服务端ip formData += "<total_fee>" + total_fee + "</total_fee>" ; //金额 formData += "<trade_type>" + settings.trade_type + "</trade_type>" ; //类型APP formData += "<sign>" + self.generatePaySignment(attach, body, nonce_str, notify_url, out_trade_no, ip, total_fee, settings.trade_type, openid) + "</sign>" ; formData += "</xml>" ; console.log(formData); let option = { method: 'POST' , url: url, body: formData } return rp(option).then(result => { let resp; console.log(result); var parser = new xml2js.Parser({ trim: true , explicitArray: false , explicitRoot: false }); //解析签名结果xml转json parser.parseString(result, function (err, data) { resp = data; return ; }); data = { "appId" : settings.appid, //公众号名称,由商户传入 "timeStamp" : moment().unix().toString(), //时间戳,自1970年以来的秒数 "nonceStr" : nonce_str, //随机串 // 通过统一下单接口获取 "package" : "prepay_id=" + resp.prepay_id, "signType" : "MD5" , //微信签名方式: } console.log( "二次加密data: " + JSON.stringify(data)); data.paySign = self.sign(data); return self.getSignature(data.timeStamp, data.nonceStr) }).then(result => { data.jsapi_ticket = global.settings.wxConfig.jsapi_ticket; data.access_token = global.settings.wxConfig.jsapi_ticket; data.signature = result; console.log( "signature: " + result + ", paySign: " + data.paySign); return data; }). catch (err => { throw err; }) } generatePaySignment(attach, body, nonce_str, notify_url, out_trade_no, spbill_create_ip, total_fee, trade_type, openid) { var data = { appid: settings.appid, attach: attach, body: body, mch_id: settings.mch_id, nonce_str: nonce_str, notify_url: notify_url, openid: openid, out_trade_no: out_trade_no, spbill_create_ip: spbill_create_ip, total_fee: total_fee, trade_type: trade_type }; return this .sign(data); } sign(data) { var string = this .raw(data); string = string + '&key=' + settings.key; //key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 var sign = crypto.createHash( 'md5' ).update(string, 'utf8' ).digest( 'hex' ); return sign.toUpperCase(); } randomWord(randomFlag, min, max) { var str = "" , range = min, arr = [ '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' , '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' ]; // 随机产生 if (randomFlag) { let range = Math.round(Math.random() * (max - min)) + min; } for ( var i = 0; i < range; i++) { let pos = Math.round(Math.random() * (arr.length - 1)); str += arr[pos]; } return str; } getSignature(timestamp, noncestr) { let data = { url: "https://www.thebutchart.cn/pay/" , timestamp: timestamp, noncestr: noncestr, jsapi_ticket: global.settings.wxConfig.jsapi_ticket } let str = "jsapi_ticket=" + data.jsapi_ticket + "&noncestr=" + data.noncestr + "×tamp=" + data.timestamp + "&url=" + data.url; return crypto.createHash( 'sha1' ).update(str, 'utf8' ).digest( 'hex' ); } |
前端代码:
export default { name: "pay" , data () { return { appId: this .$store.state.payParam.appId, // 必填,公众号的唯一标识 timestamp: this .$store.state.payParam.timestamp, // 必填,生成签名的时间戳 nonceStr: this .$store.state.payParam.nonceStr, // 支付签名随机串,不长于 32 位 signature: this .$store.state.payParam.signature, // 必填,签名 timeStamp: this .$store.state.payParam.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 package: this .$store.state.payParam.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\* signType: this .$store.state.payParam.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5' paySign: this .$store.state.payParam.paySign // 支付签名 } }, methods: { pay () { wx.config({ debug: true , // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId: this .appId, // 必填,公众号的唯一标识 timestamp: this .timestamp, // 必填,生成签名的时间戳 nonceStr: this .nonceStr, // 必填,生成签名的随机串 signature: this .signature, // 必填,签名 jsApiList: [ 'chooseWXPay' ] // 必填,需要使用的JS接口列表 }) wx.chooseWXPay({ timestamp: this .timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 nonceStr: this .nonceStr, // 支付签名随机串,不长于 32 位 package: this .package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*) signType: this .signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5' paySign: this .paySign, // 支付签名 success: function (res) { // 支付成功后的回调函数 console.log(res) } }) } }, mounted () { console.log( '6:' , this .appId, this .$store.state.payParam.appId) this .pay() } } |
生成signature的参数总共只有4个,timestamp和noncestr是调用生成统一下单API时候生成的,jsapi_ticket在系统缓存中,url是https://www.thebutchart.cn/pay试了在最后加上'/'但是依然报错,有没有大神帮忙看看问题出在哪里?小弟跪谢了
云开发的支付代码,部分代码是相通的,仅供参考:
https://developers.weixin.qq.com/community/develop/doc/000620ec5acb482103b7bf41d51804