简单来说通过WAP浏览器调用微信进行支付
一、账号
需要先开通威富通账号
开通账号你会得到 商户号、密匙 这个在后面的配置中会用到
这里先使用测试账号测试账号信息
测试商户号 175510359638
测试密钥 61307e5f2aebcacecbcca6fe5296df9c
金额 1
二、模块
接口中使用到的模块:
var crypto = require(‘crypto’);
var async = require(“async”);
var xml2js = require(“xml2js”);
var request = require(“request”);
三、流程
流程说明:
1、支付API地址API参数
2、MD5加密支付参数(参数顺序好像是按照A-Z的顺序来的,没实际测试) 得到一个签名
3、XML支付参数(需要和加密支付参数相同)+**签名**sign
4、拿到XML后的数据 POST请 https://pay.swiftpass.cn/pay/gateway (这个是支付的API接口)
5、POST请求后判断字段 status 和 result_code 都为 0的时候返回支付接口
6、打开支付接口进行支付
7、支付成功后返回到 前台地址 callback_url
8、通知地址 notify_url 需要接收支付状态信息(我们用POST的方法接收就可以了)通过API
9、接收的格式为XML,解析后判断 字段在 status 和 result_code 都为 0 返回支付信息
10、做你爱做的事吧
四、部分代码
1、POST请求支付API
//web端带参数POST请求
$.post("/pay_data",{"money":10},function(data){
if (data.code == 0){
//接收服务端返回的支付地址
//alert('支付地址:',data.url)
window.location.href = data.url;
} else {
alert('接口参数异常')
return;
};
});
//Server端接收参数
var crypto = require('crypto');
var async = require("async");
var xml2js = require("xml2js");
var request = require("request");
exports.post_pay_data = function(req, res) {
var r = {code:0,message:'成功!'};
var pars = req.body;
async.auto({
get_xml:function(cb){
var out_trade_no = (''+Math.random() * 10).substr(2);
var nonce_str = (''+Math.random() * 10).substr(2);
//MD5
//可按照a-z顺序添加
var sig=
'attach=123459'+ //注意长度限制
'&body=接口测试'+
'&callback_url=http://127.0.0.1/test?type=10'+ //支付成功后返回的页面
'&device_info=AND_WAP'+
'&mch_app_id=http://127.0.0.1'+
'&mch_app_name=接口'+
'&mch_create_ip=127.0.0.1'+ //IP地址
'&mch_id=175510359638'+ //商户号
'&nonce_str='+nonce_str+
'¬ify_url=http://127.0.0.1/notice'+ //接收支付成功的地址
'&out_trade_no='+out_trade_no+
'&service=pay.weixin.wappay' +
'&total_fee='+pars.money+
'&key=61307e5f2aebcacecbcca6fe5296df9c' //密匙
var md5 = crypto.createHash('md5')
var hash = md5.update(sig).digest('hex').toUpperCase();
/**
* 先通过MD5加密
* 再XML上传
*/
console.log("Hash===>",hash);
//Hash===>: <xml><attach>123459</attach><body>接口测试</body><callback_url>http://127.0.0.1/test?type=10</callback_url><device_info>AND_WAP</device_info><mch_app_id>http://127.0.0.1</mch_app_id><mch_app_name>接口</mch_app_name><mch_create_ip>127.0.0.1</mch_create_ip><mch_id>175510359638</mch_id><nonce_str>730683948100785</nonce_str><notify_url>http://127.0.0.1/notice</notify_url><out_trade_no>105123797831968</out_trade_no><service>pay.weixin.wappay</service><sign>7E2895859DD9D2808A5F1B905B2C599D</sign><total_fee>100</total_fee></xml>
var data = '<xml>' +
'<attach>123459</attach>' +
'<body>接口测试</body>' +
'<callback_url>http://127.0.0.1/test?type=10</callback_url>' +
'<device_info>AND_WAP</device_info>' +
'<mch_app_id>http://127.0.0.1</mch_app_id>' +
'<mch_app_name>接口</mch_app_name>' +
'<mch_create_ip>127.0.0.1</mch_create_ip>' +
'<mch_id>175510359638</mch_id>' +
'<nonce_str>'+nonce_str+'</nonce_str>' +
'<notify_url>http://127.0.0.1/notice</notify_url>' +
'<out_trade_no>'+out_trade_no+'</out_trade_no>' +
'<service>pay.weixin.wappay</service>' +
'<sign>'+hash+'</sign>' +
'<total_fee>'+pars.money+'</total_fee>' +
'</xml>';
console.log('xmlDate===>>>', data);
// Body===>>> <xml><charset><![CDATA[UTF-8]]></charset>
// <mch_id><![CDATA[175510359638]]></mch_id>
// <nonce_str><![CDATA[730683948100785]]></nonce_str>
// <pay_info><![CDATA[https://statecheck.swiftpass.cn/pay/wappay?token_id=1b13b4915e002be46813f872163c0661d&service=pay.weixin.wappayv2]]></pay_info>
// <result_code><![CDATA[0]]></result_code>
// <sign><![CDATA[BE31C898E82C35F3637F6BD726A40BFE]]></sign>
// <sign_type><![CDATA[MD5]]></sign_type>
// <status><![CDATA[0]]></status>
// <version><![CDATA[2.0]]></version>
// </xml>
cb(null, data)
},
req_get_data:['get_xml',function(cb, result){
var data = result.get_xml;
var xmlParser = new xml2js.Parser({explicitArray: false, ignoreAttrs: true}); // xml -> json
request({
url: 'https://pay.swiftpass.cn/pay/gateway',
method: 'POST',
body: data
}, function(err, response, body) {
if (!err && response.statusCode == 200) {
console.log("Body===>>>", body)
xmlParser.parseString(body, function (err, result) {
if (result.xml.status == 0){
if (result.xml.result_code == 0){
var pay_info_url = result.xml.pay_info; //返回支付接口
cb(null, pay_info_url)
} else {
cb('接口参数异常')
}
} else {
cb('接口参数异常')
};
});
} else {
cb('接口参数异常')
}
});
}]
}, function (errror, results) {
if (errror) {
console.log(errror);
r.code = 200;
r.message = errror;
}
r.url= results.req_get_data;
res.json(r);
});
}
//服务端接收notify_url 通知地址 POST请求
var xml2js = require("xml2js");
var crypto = require('crypto');
exports.notice = function (req, res) {
var r = {code: 0, message: 'success'};
req.on("data",function(data){
async.auto({
get_xml:function (cb){
var xmlParser = new xml2js.Parser({explicitArray: false, ignoreAttrs: true}); // xml -> json
var xmls = data.toString("utf-8");
xmlParser.parseString(xmls, function (err, result) {
if (result.xml.status == 0){
if (result.xml.result_code == 0){
/**
* 接收参数,提取你需要的
* 可在备注里加入其它参数 attach
*/
cb(null, result.xml)
} else {
cb('接口参数异常')
}
} else {
cb('接口参数异常')
};
});
},
Make_love:['get_xml',function (cb, result) {
/**
* 做爱做的事
* **************
* **************
*/
cb(null, [])
}]
}, function (errror, results) {
if (errror) {
console.log(errror);
r.code = 200;
r.message = errror;
};
});
});
req.on("end",function(){
res.send('success');
});
};