nodejs后台实现app端微信支付

实现微信支付有很多方式,至于开始菜鸟的我使用app支付,后期考虑安全性问题,只好把统一下单,得到prepay_id之后再次签名sign全在服务端写了,废话不多说,进入操作。

做任何东西,我喜欢了解整个流程,然后一步一步做起来,开始看清微信支付业务流程图

业务流程步骤写的很清楚。下面一步一步操作:

服务端提供接口,服务端需要拿到订单号、商品介绍、商品价格(单位是分)

服务端对微信服务端发出统一下单请求

https://api.mch.weixin.qq.com/pay/unifiedorder

xml参数(注意参数名)

 
  1. <xml>

  2. <appid>wx2421b1c4370ec43b</appid>

  3. <attach>支付测试</attach>

  4. <body>APP支付测试</body>

  5. <mch_id>10000100</mch_id>

  6. <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>

  7. <notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>

  8. <out_trade_no>1415659990</out_trade_no>

  9. <spbill_create_ip>14.23.150.211</spbill_create_ip>

  10. <total_fee>1</total_fee>

  11. <trade_type>APP</trade_type>

  12. <sign>0CB01533B8C1EF103065174F50BCA001</sign>

  13. </xml>

请求返回结果是success说明签名成功

快捷测试方法:

使用微信支付签名测试工具https://pay.weixin.qq.com/wiki/tools/signverify/

得到xml参数签名之后请求看返回结果

推荐一个在线http接口测试工具  http://coolaf.com/

在里面放入http地址https://api.mch.weixin.qq.com/pay/unifiedorder

post参数放签名xml参数

返回结果就可以检测签名是否成功,成功之后差不多成功了一半

服务端代码:weixinpay.js

 
  1. var request = require('request');

  2. var xml2js = require('xml2js');

  3.  
  4. function paysign(appid,attach,body,mch_id,nonce_str,notify_url,out_trade_no,spbill_create_ip,total_fee,trade_type) { //统一下单签名

  5. var ret = {

  6. appid: appid,

  7. attach: attach,

  8. body: body,

  9. mch_id: mch_id,

  10. nonce_str: nonce_str,

  11. notify_url:notify_url,

  12. out_trade_no:out_trade_no,

  13. spbill_create_ip:spbill_create_ip,

  14. total_fee:total_fee,

  15. trade_type:trade_type

  16. };

  17. var string = raw(ret);

  18. var key = '微信商户密钥';

  19. string = string + '&key='+key; //key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置

  20. var crypto = require('crypto');

  21. console.log("签名");

  22. console.log(crypto.createHash('md5').update(string,'utf8').digest('hex').toUpperCase());

  23. return crypto.createHash('md5').update(string,'utf8').digest('hex').toUpperCase();

  24. };

  25.  
  26. function raw(args) {

  27. var keys = Object.keys(args);

  28. keys = keys.sort()

  29. var newArgs = {};

  30. keys.forEach(function (key) {

  31. newArgs[key.toLowerCase()] = args[key];

  32. });

  33.  
  34. var string = '';

  35. for (var k in newArgs) {

  36. string += '&' + k + '=' + newArgs[k];

  37. }

  38. string = string.substr(1);

  39. console.log(string);

  40. return string;

  41. };

  42. exports.pay = function (req, res) //微信支付函数

  43. {

  44. var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

  45. var appid = '应用微信中的id';

  46. var mch_id = '商户号';

  47. var notify_url = 'www.spamao.com';

  48. var out_trade_no = req.query.orderId;<span style="background-color: rgb(255, 255, 102);"><span style="color:#FFFF66;"><span style="background-color: rgb(255, 255, 255);"></span></span></span>//客户端<span style="background-color: rgb(255, 255, 102);"><span style="color:#FFFF66;"><span style="background-color: rgb(255, 255, 255);"></span></span></span>订单号

  49. var total_fee = req.query.orderRate;<span style="background-color: rgb(255, 255, 102);"><span style="color:#FFFF66;"><span style="background-color: rgb(255, 255, 255);"></span></span></span>//客户端<span style="background-color: rgb(255, 255, 102);"><span style="color:#FFFF66;"><span style="background-color: rgb(255, 255, 255);"></span></span></span>商品价格

  50. var attach = 'spamao用户版app';

  51. var body = req.query.content; //客户端商品描述

  52. var nonce_str = '随机32位之内字符串';

  53. var formData = "<xml>";

  54. formData += "<appid>"+appid+"</appid>"; //appid

  55. formData += "<attach>"+attach+"</attach>"; //附加数据

  56. formData += "<body>"+body+"</body>"; //商品或支付单简要描述

  57. formData += "<mch_id>"+mch_id+"</mch_id>"; //商户号

  58. formData += "<nonce_str>"+nonce_str+"</nonce_str>"; //随机字符串,不长于32位

  59. formData += "<notify_url>"+notify_url+"</notify_url>"; //支付成功后微信服务器通过POST请求通知这个地址

  60.  
  61. formData += "<out_trade_no>"+out_trade_no+"</out_trade_no>"; //订单号

  62. formData += "<spbill_create_ip>112.124.60.251</spbill_create_ip>"; //服务端ip

  63. formData += "<total_fee>"+total_fee+"</total_fee>"; //金额

  64. formData += "<trade_type>APP</trade_type>"; //类型APP

  65. formData += "<sign>" + paysign(appid,attach,body,mch_id,nonce_str,notify_url,out_trade_no,'112.124.60.251',total_fee,'APP') + "</sign>";

  66. formData += "</xml>";

  67. request(

  68. {

  69. url : url,

  70. method : 'POST',

  71. body : formData

  72. }, function (err, response, body)

  73. {

  74. if (!err && response.statusCode == 200)

  75. {

  76. console.log(body);

  77. var parser = new xml2js.Parser({ trim:true, explicitArray:false, explicitRoot:false });//解析签名结果xml转json

  78. parser.parseString(body, function(err, result){

  79. var timeStamp = Date.parse(new Date()) / 1000;

  80. var sign = paySignTwo(appid,nonce_str,'Sign=WXPay',mch_id,result['prepay_id'],timeStamp);//得到prepay再次签名

  81. res.send({result: {'appid':appid, 'mch_id': mch_id, 'prepay_id': result['prepay_id'], 'nonce_str': nonce_str, 'time_stamp':timeStamp, 'package_value':'Sign=WXPay', 'sign': sign}});//返回客户端数据

  82. });

  83.  
  84. }

  85. }

  86. );

  87. }

  88. function buildXML(json){

  89. var builder = new xml2js.Builder();

  90. return builder.buildObject(json);

  91. };

  92. function paySignTwo(appid,notifystr,packagevalue,mchid,prepayid,timestamp) { //参数名不可改,必须严格一模一样(在此我掉坑一次)

  93. var ret = {

  94. appid: appid,

  95. noncestr: notifystr,

  96. package: packagevalue,

  97. partnerid: mchid,

  98. prepayid: prepayid,

  99. timestamp:timestamp

  100. };

  101. var string = raw(ret);

  102. var key = '商户密钥';

  103. string = string + '&key='+key; //key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置

  104. var crypto = require('crypto');

  105. console.log("签名");

  106. console.log(crypto.createHash('md5').update(string,'utf8').digest('hex').toUpperCase());

  107. return crypto.createHash('md5').update(string,'utf8').digest('hex').toUpperCase();

  108. };

再次签名参数名:

剩下就是客户端的事了,短短几行代码调起微信支付接口请求。

 
  1. req = new PayReq();

  2. req.appId = weixinOrder.getString("appid");

  3. req.partnerId = weixinOrder.getString("mch_id");

  4. req.prepayId = weixinOrder.getString("prepay_id");

  5. req.nonceStr = weixinOrder.getString("nonce_str");

  6. req.timeStamp = weixinOrder.getString("time_stamp");

  7. req.packageValue = weixinOrder.getString("package_value");

  8. req.sign = weixinOrder.getString("sign");

  9. Log.i("sign-----jieguo", weixinOrder.getString("sign"));

  10. Toast.makeText(WorkPay.this, "正常调起支付", Toast.LENGTH_SHORT).show();

  11. // 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信

  12. api.registerApp(Constants.APP_ID);

  13. api.sendReq(req);


manifest需要配置:

 
  1. <activity android:name="app包名.WorkPay" <!--支付类需加上以下intent-filter内容-->

  2. android:exported="true"

  3. android:launchMode="singleTop">

  4. <intent-filter>

  5. <action android:name="android.intent.action.VIEW"/>

  6. <category android:name="android.intent.category.DEFAULT"/>

  7. <data android:scheme="wxb6ff1aa7f0350ccf"/>

  8. </intent-filter>

  9. </activity>

  10. <activity

  11. android:name="aizhinong.yys.sbm.wxapi.WXPayEntryActivity"

  12. android:exported="true"

  13. android:launchMode="singleTop">

  14.  
  15. </activity>


提醒:所有参数必须跟微信给的参数名一致(参数个数不能少),(使用微信签名工具是一定需要分辨测试包签名还是正式发布签名)

如果一切顺利,恭喜你接入支付成功。

发这个目的是为了node.js服务端的同胞们多点资源共享

猜你喜欢

转载自blog.csdn.net/pengfeng111833/article/details/81667171