android 微信支付 + node.js 服务端

2 篇文章 0 订阅
1 篇文章 0 订阅

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

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

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

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

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

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

xml参数(注意参数名)

<xml>
   <appid>wx2421b1c4370ec43b</appid>
   <attach>支付测试</attach>
   <body>APP支付测试</body>
   <mch_id>10000100</mch_id>
   <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
   <notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>
   <out_trade_no>1415659990</out_trade_no>
   <spbill_create_ip>14.23.150.211</spbill_create_ip>
   <total_fee>1</total_fee>
   <trade_type>APP</trade_type>
   <sign>0CB01533B8C1EF103065174F50BCA001</sign>
</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

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');
    console.log("签名");
    console.log(crypto.createHash('md5').update(string,'utf8').digest('hex').toUpperCase());
    return crypto.createHash('md5').update(string,'utf8').digest('hex').toUpperCase();
};

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;
};
exports.pay = function (req, res)    //微信支付函数
{
    var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    var appid = '应用微信中的id';
    var mch_id = '商户号';
    var notify_url = 'www.spamao.com';   
    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>订单号
    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>商品价格
    var attach = 'spamao用户版app';
    var body = req.query.content;  //客户端商品描述
    var nonce_str = '随机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 += "<out_trade_no>"+out_trade_no+"</out_trade_no>"; //订单号
    formData += "<spbill_create_ip>112.124.60.251</spbill_create_ip>"; //服务端ip
    formData += "<total_fee>"+total_fee+"</total_fee>"; //金额
    formData += "<trade_type>APP</trade_type>"; //类型APP
    formData += "<sign>" + paysign(appid,attach,body,mch_id,nonce_str,notify_url,out_trade_no,'112.124.60.251',total_fee,'APP') + "</sign>";
    formData += "</xml>";
    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();
};

再次签名参数名:



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

req = new PayReq();
							req.appId			= weixinOrder.getString("appid");
							req.partnerId		= weixinOrder.getString("mch_id");
							req.prepayId		= weixinOrder.getString("prepay_id");
							req.nonceStr		= weixinOrder.getString("nonce_str");
							req.timeStamp		= weixinOrder.getString("time_stamp");
							req.packageValue	= weixinOrder.getString("package_value");
							req.sign			= weixinOrder.getString("sign");
							Log.i("sign-----jieguo", weixinOrder.getString("sign"));
							Toast.makeText(WorkPay.this, "正常调起支付", Toast.LENGTH_SHORT).show();
							// 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
							api.registerApp(Constants.APP_ID);
							api.sendReq(req);

manifest需要配置:

 <activity android:name="app包名.WorkPay"   <!--支付类需加上以下intent-filter内容-->
             android:exported="true"
            android:launchMode="singleTop">
           <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="wxb6ff1aa7f0350ccf"/>
            </intent-filter> 
        </activity>
        <activity
            android:name="aizhinong.yys.sbm.wxapi.WXPayEntryActivity"
            android:exported="true"
            android:launchMode="singleTop">
             
        </activity>

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

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

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







  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值