实现微信支付有很多方式,至于开始菜鸟的我使用app支付,后期考虑安全性问题,只好把统一下单,得到prepay_id之后再次签名sign全在服务端写了,废话不多说,进入操作。
做任何东西,我喜欢了解整个流程,然后一步一步做起来,开始看清微信支付业务流程图
业务流程步骤写的很清楚。下面一步一步操作:
服务端提供接口,服务端需要拿到订单号、商品介绍、商品价格(单位是分)
服务端对微信服务端发出统一下单请求
https://api.mch.weixin.qq.com/pay/unifiedorder
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');
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(""+node_name+">");
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 += "
formData += "
formData += "
"+body+""; //商品或支付单简要描述formData += "
formData += "
formData += "
formData += "
formData += "
formData += "
formData += "
formData += "
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();
};
再次签名参数名:
剩下就是客户端的事了,短短几行代码调起微信支付接口请求。
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需要配置:
android:exported="true"
android:launchMode="singleTop">
android:name="aizhinong.yys.sbm.wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop">
提醒:所有参数必须跟微信给的参数名一致(参数个数不能少),(使用微信签名工具是一定需要分辨测试包签名还是正式发布签名)
如果一切顺利,恭喜你接入支付成功。
发这个目的是为了node.js服务端的同胞们多点资源共享