基于nodejs實(shí)現(xiàn)微信支付功能
本文實(shí)例為大家分享了nodejs實(shí)現(xiàn)微信支付的具體代碼,供大家參考,具體內(nèi)容如下
通過(guò)nodejs使用微信支付最重要的就是微信的簽名,在這里md5后的字符必須轉(zhuǎn)化為大寫
一、回復(fù)微信通知消息模版
message.ejs
<xml> <return_code><![CDATA[<%-return_code%>]]></return_code> <return_msg><![CDATA[<%=return_msg%>]]></return_msg> </xml>
二、微信支付model文件代碼
wxpay.js
var config = require('../config'); //配置文件 appid 等信息
var Q = require("q");
var request = require("request");
var crypto = require('crypto');
var ejs = require('ejs');
var fs = require('fs');
var key = "此處為申請(qǐng)微信支付的API密碼";
var messageTpl = fs.readFileSync(__dirname + '/message.ejs', 'utf-8');
var WxPay = {
getXMLNodeValue: function(node_name, xml) {
var tmp = xml.split("<" + node_name + ">");
var _tmp = tmp[1].split("</" + node_name + ">");
return _tmp[0];
},
raw: function(args) {
var keys = Object.keys(args);
keys = keys.sort()
var newArgs = {};
keys.forEach(function(key) {
newArgs[key] = args[key];
});
var string = '';
for (var k in newArgs) {
string += '&' + k + '=' + newArgs[k];
}
string = string.substr(1);
return string;
},
paysignjs: function(appid, nonceStr, package, signType, timeStamp) {
var ret = {
appId: appid,
nonceStr: nonceStr,
package: package,
signType: signType,
timeStamp: timeStamp
};
var string = this.raw(ret);
string = string + '&key=' + key;
var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex');
return sign.toUpperCase();
},
paysignjsapi: function(appid, attach, body, mch_id, nonce_str, notify_url, openid, 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,
openid: openid,
out_trade_no: out_trade_no,
spbill_create_ip: spbill_create_ip,
total_fee: total_fee,
trade_type: trade_type
};
var string = this.raw(ret);
string = string + '&key=' + key; //key為在微信商戶平臺(tái)(pay.weixin.qq.com)-->賬戶設(shè)置-->API安全-->密鑰設(shè)置
var crypto = require('crypto');
var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex');
return sign.toUpperCase();
},
// 隨機(jī)字符串產(chǎn)生函數(shù)
createNonceStr: function() {
return Math.random().toString(36).substr(2, 15);
},
// 時(shí)間戳產(chǎn)生函數(shù)
createTimeStamp: function() {
return parseInt(new Date().getTime() / 1000) + '';
},
// 此處的attach不能為空值 否則微信提示簽名錯(cuò)誤
order: function(attach, body, mch_id, openid, bookingNo, total_fee, notify_url) {
var deferred = Q.defer();
var appid = config.member_config.appid;
var nonce_str = this.createNonceStr();
var timeStamp = this.createTimeStamp();
var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
var formData = "<xml>";
formData += "<appid>" + appid + "</appid>"; //appid
formData += "<attach>" + attach + "</attach>"; //附加數(shù)據(jù)
formData += "<body>" + body + "</body>";
formData += "<mch_id>" + mch_id + "</mch_id>"; //商戶號(hào)
formData += "<nonce_str>" + nonce_str + "</nonce_str>"; //隨機(jī)字符串,不長(zhǎng)于32位。
formData += "<notify_url>" + notify_url + "</notify_url>";
formData += "<openid>" + openid + "</openid>";
formData += "<out_trade_no>" + bookingNo + "</out_trade_no>";
formData += "<spbill_create_ip>61.50.221.43</spbill_create_ip>";
formData += "<total_fee>" + total_fee + "</total_fee>";
formData += "<trade_type>JSAPI</trade_type>";
formData += "<sign>" + this.paysignjsapi(appid, attach, body, mch_id, nonce_str, notify_url, openid, bookingNo, '61.50.221.43', total_fee, 'JSAPI') + "</sign>";
formData += "</xml>";
var self = this;
request({
url: url,
method: 'POST',
body: formData
}, function(err, response, body) {
if (!err && response.statusCode == 200) {
console.log(body);
var prepay_id = self.getXMLNodeValue('prepay_id', body.toString("utf-8"));
var tmp = prepay_id.split('[');
var tmp1 = tmp[2].split(']');
//簽名
var _paySignjs = self.paysignjs(appid, nonce_str, 'prepay_id=' + tmp1[0], 'MD5', timeStamp);
var args = {
appId: appid,
timeStamp: timeStamp,
nonceStr: nonce_str,
signType: "MD5",
package: tmp1[0],
paySign: _paySignjs
};
deferred.resolve(args);
} else {
console.log(body);
}
});
return deferred.promise;
},
//支付回調(diào)通知
notify: function(obj) {
var output = "";
if (obj.return_code == "SUCCESS") {
var reply = {
return_code: "SUCCESS",
return_msg: "OK"
};
} else {
var reply = {
return_code: "FAIL",
return_msg: "FAIL"
};
}
output = ejs.render(messageTpl, reply);
return output;
},
};
module.exports = WxPay;
三、在express router中調(diào)用wxpay
//微信支付demo
router.get('/order', function(req, res, next){
var attach = "1276687601";
var body = "測(cè)試支付";
var mch_id = "1111111"; //商戶ID
var openid = "111111";
var bookingNo = "201501806125346"; //訂單號(hào)
var total_fee = 10;
var notify_url = "http://localhost/wxpay/notify"; //通知地址
wxpay.order(attach, body, mch_id, openid, bookingNo, total_fee, notify_url).then(function(data){
res.render('wxpay', {args: data});
});
});
//微信回調(diào)通知 采用數(shù)據(jù)流形式讀取微信返回的xml數(shù)據(jù) 此處不在累贅
router.post('/notify', function(req, res, next){
});
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解node HTTP請(qǐng)求客戶端 - Request
Request是一個(gè)Node.jsNPM模塊,它是一個(gè)HTTP客戶端,使用簡(jiǎn)單功能確十分強(qiáng)大2017-05-05
淺析node應(yīng)用的timing-attack安全漏洞
本篇文章給大家通過(guò)原理的原因分析了node應(yīng)用的timing-attack安全漏洞問(wèn)題,有興趣的朋友閱讀參考下。2018-02-02
配置node服務(wù)器并且鏈接微信公眾號(hào)接口配置步驟詳解
這篇文章主要介紹了配置node服務(wù)器并且鏈接微信公眾號(hào)接口配置步驟詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下2019-06-06
Node.js用Socket.IO做聊天軟件的實(shí)現(xiàn)示例
本文主要介紹了Node.js用Socket.IO做聊天軟件的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
node.js中的fs.closeSync方法使用說(shuō)明
這篇文章主要介紹了node.js中的fs.closeSync方法使用說(shuō)明,本文介紹了fs.closeSync方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12
Node.js上傳文件功能之服務(wù)端如何獲取文件上傳進(jìn)度
這篇文章主要介紹如何利用progress-stream獲取文件上傳進(jìn)度,以及該組件使用過(guò)程中的注意事項(xiàng)2018-02-02

