微信小程序 支付简单实例及注意事项
微信小程序支付
微信小程序的支付和微信公众号的支付是类似的,对比起来还比公众号支付简单了一些,我们只需要调用微信的统一下单接口获取prepay_id之后我们在调用微信的支付即可。
今天我们来封装一般node的支付接口!!!
首先调用统一下单接口我们需要知道一些信息
varbookingNo='davdian'+this.createNonceStr()+this.createTimeStamp() vardeferred=Q.defer() varappid=config.appId varnonce_str=this.createNonceStr() vartimeStamp=this.createTimeStamp() varurl="https://api.mch.weixin.qq.com/pay/unifiedorder" varformData="<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>" formData+="<openid>"+openid+"</openid>" formData+="<out_trade_no>"+bookingNo+"</out_trade_no>" formData+="<spbill_create_ip>61.50.221.43</spbill_create_ip>" formData+="<total_fee>"+total_fee+"</total_fee>" formData+="<trade_type>JSAPI</trade_type>" formData+="<sign>"+this.paysignjsapi(appid,attach,body,mch_id,nonce_str,notify_url,openid,bookingNo,'61.50.221.43',total_fee,'JSAPI')+"</sign>" formData+="</xml>" varself=this request({ url:url, method:'POST', body:formData },function(err,response,body){ if(!err&&response.statusCode==200){ varprepay_id=self.getXMLNodeValue('prepay_id',body.toString("utf-8")) vartmp=prepay_id.split('[') vartmp1=tmp[2].split(']') //签名 var_paySignjs=self.paysignjs(appid,nonce_str,'prepay_id='+tmp1[0],'MD5',timeStamp) varargs={ appId:appid, timeStamp:timeStamp, nonceStr:nonce_str, signType:"MD5", package:tmp1[0], paySign:_paySignjs } deferred.resolve(args) }else{ console.log(body) } }) returndeferred.promise
这个是一个统一下单接口的代码,我们需要appid小程序公众号id,mch_id商户号id,openid小程序的唯一标实,key支付用的密码,剩下的参数都是订单的信息和价格之类的,本人require进q模块使用promise,这个因人而异,可以根据自己需要来。我们需要请求https://api.mch.weixin.qq.com/pay/unifiedorder接口
注意:这里我们传递的formdata是一个xml而不是json
然后我们需要签名方法,这里我们需要封装两个方法,一个是签名方法调用统一下单接口会用到,另一个是调用小程序支付用到
统一下单接口sign:
varret={ appid:appid, attach:attach, body:body, mch_id: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 } varstring=this.raw(ret) string=string+'&key='+key varcrypto=require('crypto') varsign=crypto.createHash('md5').update(string,'utf8').digest('hex') returnsign.toUpperCase()
支付sign:
varret={ appId:appid, nonceStr:nonceStr, package:package, signType:signType, timeStamp:timeStamp } varstring=this.raw(ret) string=string+'&key='+key varsign=crypto.createHash('md5').update(string,'utf8').digest('hex') returnsign.toUpperCase()
注意加密的时候我们获取的是string而不是一个json,所以我们需要吧json转换成string,代码如下:
varkeys=Object.keys(args) keys=keys.sort() varnewArgs={} keys.forEach(function(key){ newArgs[key]=args[key] }) varstring='' for(varkinnewArgs){ string+='&'+k+'='+newArgs[k] } string=string.substr(1) returnstring
统一下单接口返回的是带有prepay_id的xml,所以我们需要一个方法进行解析,代码如下:
vartmp=xml.split("<"+node_name+">") var_tmp=tmp[1].split("</"+node_name+">") return_tmp[0]
最后我们只需要把这些连接到一起就是可以获取所有微信支付所需参数,代码如下:
//微信小程序支付封装,暂支持md5加密,不支持sha1 /** ***createorderbyjianchep2016/11/22 **/ varconfig=require('../config/weapp.js') varQ=require("q") varrequest=require("request") varcrypto=require('crypto') varejs=require('ejs') varfs=require('fs') varkey=config.key module.exports={ //获取prepay_id getXMLNodeValue:function(node_name,xml){ vartmp=xml.split("<"+node_name+">") var_tmp=tmp[1].split("</"+node_name+">") return_tmp[0] }, //object-->string raw:function(args){ varkeys=Object.keys(args) keys=keys.sort() varnewArgs={} keys.forEach(function(key){ newArgs[key]=args[key] }) varstring='' for(varkinnewArgs){ string+='&'+k+'='+newArgs[k] } string=string.substr(1) returnstring }, //随机字符串产生函数 createNonceStr:function(){ returnMath.random().toString(36).substr(2,15) }, //时间戳产生函数 createTimeStamp:function(){ returnparseInt(newDate().getTime()/1000)+'' }, //支付md5加密获取sign paysignjs:function(appid,nonceStr,package,signType,timeStamp){ varret={ appId:appid, nonceStr:nonceStr, package:package, signType:signType, timeStamp:timeStamp } varstring=this.raw(ret) string=string+'&key='+key varsign=crypto.createHash('md5').update(string,'utf8').digest('hex') returnsign.toUpperCase() }, //统一下单接口加密获取sign paysignjsapi:function(appid,attach,body,mch_id,nonce_str,notify_url,openid,out_trade_no,spbill_create_ip,total_fee,trade_type){ varret={ appid:appid, attach:attach, body:body, mch_id: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 } varstring=this.raw(ret) string=string+'&key='+key varcrypto=require('crypto') varsign=crypto.createHash('md5').update(string,'utf8').digest('hex') returnsign.toUpperCase() }, //下单接口 order:function(attach,body,mch_id,openid,total_fee,notify_url){ varbookingNo='davdian'+this.createNonceStr()+this.createTimeStamp() vardeferred=Q.defer() varappid=config.appId varnonce_str=this.createNonceStr() vartimeStamp=this.createTimeStamp() varurl="https://api.mch.weixin.qq.com/pay/unifiedorder" varformData="<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>" formData+="<openid>"+openid+"</openid>" formData+="<out_trade_no>"+bookingNo+"</out_trade_no>" formData+="<spbill_create_ip>61.50.221.43</spbill_create_ip>" formData+="<total_fee>"+total_fee+"</total_fee>" formData+="<trade_type>JSAPI</trade_type>" formData+="<sign>"+this.paysignjsapi(appid,attach,body,mch_id,nonce_str,notify_url,openid,bookingNo,'61.50.221.43',total_fee,'JSAPI')+"</sign>" formData+="</xml>" varself=this request({ url:url, method:'POST', body:formData },function(err,response,body){ if(!err&&response.statusCode==200){ varprepay_id=self.getXMLNodeValue('prepay_id',body.toString("utf-8")) vartmp=prepay_id.split('[') vartmp1=tmp[2].split(']') //签名 var_paySignjs=self.paysignjs(appid,nonce_str,'prepay_id='+tmp1[0],'MD5',timeStamp) varargs={ appId:appid, timeStamp:timeStamp, nonceStr:nonce_str, signType:"MD5", package:tmp1[0], paySign:_paySignjs } deferred.resolve(args) }else{ console.log(body) } }) returndeferred.promise } }
之后我们封装下单接口:
unifiedorder:function(req,res){ varbody="测试支付" varopenid="openid" vartotal_fee=1 varnotify_url="http://localhost/notify" varmch_id=config.shopId varattach="测试" wxpay.order(attach,body,mch_id,openid,total_fee,notify_url) .then(function(data){ console.log('data--->',data,123123) res.json(data) }) },
然后我们只需要在小程序里面调用这个接口,就会获取到所有的支付需要信息,再掉微信支付即可。
这里说几个小程序支付的坑:
1.统一下单接口是xml(这个不只是小程序,公众号也是),返回值也是xml格式需要自己获取prepay_id,
2.签名算法要带上key,最后要转换成大些
3.微信支付的sign算法也要带上appid(这个不科学,深坑)
4.签名算法一定不要用json拼接key
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!