nodejs后台实现app端微信支付

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

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

nodejs后台实现app端微信支付_第1张图片

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

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

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

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

xml参数(注意参数名)

 

wx2421b1c4370ec43b

支付测试

APP支付测试

10000100

1add1a30ac87aa2db72f57a2375d8fec http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php

1415659990

14.23.150.211

1

APP

0CB01533B8C1EF103065174F50BCA001

 

请求返回结果是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

 

var request = require('request');

var xml2js = require('xml2js');

function paysign(appid, attach, body, mch_id, nonce_str, notify_url, out_trade_no, spbill_create_ip, total_fee, trade_type) {

var ret = {

appid: appid,

attach: attach,

body: body,

mch_id: mch_id,

nonce_str: nonce_str,

notify_url: notify_url,

out_trade_no: out_trade_no,

spbill_create_ip: spbill_create_ip,

total_fee: total_fee,

trade_type: trade_type

};

var string = raw(ret);

var key = '密钥'; //微信商户密钥

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

var crypto = require('crypto');

var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex');

return sign.toUpperCase();

};

 

//解析xml数据

function getXMLNodeValue(node_name,xml){

var tmp = xml.split("<"+node_name+">");

var _tmp = tmp[1].split("");

var tmp1 = _tmp[0].split('[');

var _tmp1 = tmp1[2].split(']');

return _tmp1[0];

}

 

function raw(args) {

var keys = Object.keys(args);

keys = keys.sort()

var newArgs = {};

keys.forEach(function (key) {

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

});

 

var string = '';

for (var k in newArgs) {

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

}

string = string.substr(1);

console.log(string);

return string;

};

 

// 随机字符串产生函数

function createNonceStr() {

return Math.random().toString(36).substr(2, 15);

};

 

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

{

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

var appid = 'wx2421b1c4370ec43b';//应用微信中的id

var mch_id = '1511515151';//商户号

var notify_url = 'http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php';//回调通知地址

var out_trade_no = req.body.orderId;//订单号

var total_fee = req.body.orderRate;//商品价格

var attach = 'feeLT运动App';

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

var nonce_str = createNonceStr();//随机32位之内字符串

var formData = "";

formData += ""+appid+""; //appid

formData += ""+attach+""; //附加数据

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

formData += ""+mch_id+""; //商户号

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

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

formData += ""+out_trade_no+""; //订单号

formData += "120.79.65.254"; //服务端ip

formData += ""+total_fee+""; //金额

formData += "APP"; //类型APP

formData += "" + paysign(appid,attach,body,mch_id,nonce_str,notify_url,out_trade_no,'120.79.65.254',total_fee,'APP') + "";

formData += "";

request(

{

url : url,

method : 'POST',

body : formData

}, function (err, response, body){

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

console.log(body);

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

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

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

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

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}});//返回客户端数据

});

}

});

}

 

function buildXML(json){

var builder = new xml2js.Builder();

return builder.buildObject(json);

};

 

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

var ret = {

appid: appid,

noncestr: notifystr,

package: packagevalue,

partnerid: mchid,

prepayid: prepayid,

timestamp:timestamp

};

var string = raw(ret);

var key = '密钥';

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

var crypto = require('crypto');

console.log("签名");

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

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

};

 

 

再次签名参数名:

nodejs后台实现app端微信支付_第2张图片

 

 

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

 

 
  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. android:exported="true"

  2. android:launchMode="singleTop">

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

  4. android:exported="true"

  5. android:launchMode="singleTop">

  6.  


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

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

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

你可能感兴趣的:(技术性博客)