版权声明:本文为博主原创文章,未经博主允许不得转载。
概述
目前微信官方的微信支付demo没有node版本,这几天一直折腾微信支付,当做笔记记录下来;
参考资料微信支付官方文档
签名
微信支付的签名采用MD5加密,下面微信支付的签名算法,及统一下单:
首先先建立一个wechatPay.js 文件(在该文件中包括签名算法,统一下单等)
/**
** 引入依赖包
**/
var config = require('../config');
var request = require("request");
var moment = require('moment'),
_ = require('underscore'),
https = require('https'),
fs = require('fs'),
URL = require('url'),
CryptoJS = require("crypto-js"),
jsontoxml = require('jsontoxml'),
xml2js = require('xml2js');
var crypto = require('crypto');
/**
** 签名算法
**/
var generateSign = exports.genrateSign = function(obj) {
var tmpObj = {}; // 取非空的key
_.each(obj, function(value, key){
if(value) {
tmpObj[key] = value;
}
});
var keys = _.keys(tmpObj); // key 字典排序
keys = keys.sort();
var tmpArr = [];
_.each(keys, function(key) {
tmpArr.push(key + "=" + tmpObj[key])
})
tmpArr.push("key=" + config.wxmcn.mcnsecret); // //key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
var tmpStr = tmpArr.join('&'); // 拼接字符串
var sign = crypto.createHash('md5').update(tmpStr, 'utf8').digest('hex');
return sign.toUpperCase();
}
//统一下单,获取code_url后期生成二维码
var paysign = exports.paysign = function(params,callback) {
if(_.isEmpty(params)) {
callback('参数不能为空');
}
var currentTime = moment().valueOf().toString();
var nonce_str = [
config.wxmcn.mcnid,
currentTime
].join(''); // 随机字符串
var mch_billno = [
config.wxmcn.mcnid,
moment().format("YYYYMMDD"),
moment().unix()
].join(''); // 订单号
var ret = {
appid: config.H5.appid,
body: params.body, // 商品描述
attach: params.attach, // 用户的身份intid
mch_id: config.wxmcn.mcnid, // 商户号
nonce_str: nonce_str, // 随机字符串
notify_url:params.notify_url, // 通知地址
out_trade_no:mch_billno, // 商户订单号
spbill_create_ip:params.spbill_create_ip, // 终端ip
total_fee:params.total_fee, // 标价金额
trade_type:params.trade_type // 交易类型
};
if(!_.isEmpty(params.openid)){
_.extend(ret,{openid: params.openid});
}
var sign = generateSign(ret);
_.extend(ret,{sign: sign});
var body = jsontoxml(ret);
body = '<xml>' + body + '</xml>';
request({
url:'https://api.mch.weixin.qq.com/pay/unifiedorder',
method: 'POST',
body: body
},function (err, response, body)
{
if (!err && response.statusCode == 200)
{
// xml2js将返回xml 转换成json,但是后面都是都数组
xml2js.parseString(body, function(err, json) {
if (err) {
callback(new Error("解析xml报错"));
} else {
var result = formMessage(json.xml); // 转换成正常的json 数据
if(result.return_code === 'SUCCESS' && result.result_code === 'SUCCESS') {
callback(null,result);
}else {
callback(new Error('wechat err'))
}
}
})
}
});
};
// 将xml2js 转换成json数据进一步转换
var formMessage = function(result) {
var message = {};
if (typeof result === 'object') {
var keys = Object.keys(result);
for (var i = 0; i < keys.length; i++) {
var item = result[keys[i]];
var key = keys[i];
if (!(item instanceof Array) || item.length === 0) {
continue;
}
if (item.length === 1) {
var val = item[0];
if (typeof val === 'object') {
message[key] = formMessage(val);
} else {
message[key] = (val || '').trim();
}
} else {
message[key] = [];
for (var j = 0, k = item.length; j < k; j++) {
message[key].push(formMessage(itemp[j]));
}
}
}
}
return message;
}
在router 调用
本次开发用的express框架,创建一个wxpayRouter.js(包括获取微信支付的二维码等)
/*
** 引入依赖
*/
var express = require('express');
var wxPayRouter = express.Router();
var mongoose = require('mongoose'),
ObjectId = mongoose.Schema.Types.ObjectId;
var wechatPay = require('./wechatpay')
var URL = require('url'),
async = require('async'),
_ = require('underscore'),
qr = require('qr-image'),
jsontoxml = require('jsontoxml'),
moment = require('moment');
wxPayRouter.get('/order',function(req, res, next){
var params = URL.parse(req.url, true);
var queryParams = req.query;
total_fee = queryParams.total_fee; // 前端金额
var status = 400,
errmsg = "";
if(_.isEmpty(total_fee)) {
errmsg = 'total_fee is empty';
}
if(errmsg){
return res.end({status: status, msg: errmsg});
}
async.auto({
getCodeUrl: function(callback) {
var condition = {body: '订单名称',attach:'附加信息'}; // attach 会在支付成功的后的原封不动的返回
if(!_.isEmpty(total_fee)) {
_.extend(condition, {total_fee: total_fee});
}
_.extend(condition, {spbill_create_ip: tools.getLocalIP(),trade_type: 'NATIVE'});
// notify_url 为微信回调的地址,将支付成功的信息以数据流的形式返回
_.extend(condition,{notify_url: 'http://49727c15.ngrok.io/wxpay/orderpay'});
wechatPay.paysign(condition, function(err, result){
if(err) {
return callback(new Error('connect wechat service is fail'));
}
callback(null,result );
});
}
}, function(err, results) {
if(err) {
return res.end({status: status, msg: err.message});
}
var data = results.getCodeUrl;
if(_.isEmpty(data)){
status = 404;
}else{
status = 200;
}
res.end({status: status, data: data});
})
});
module.exports = wxPayRouter;
后台微信的支付接口已经完成,前端调用order接口同时需要将支付金额一并传递过来;然后后台返回相关信息,code_url通过第三方工具生成二维码,用户扫码即可完成支付。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。