基于nodejs实现微信支付功能


Posted in NodeJs onDecember 20, 2017

本文实例为大家分享了nodejs实现微信支付的具体代码,供大家参考,具体内容如下

通过nodejs使用微信支付最重要的就是微信的签名,在这里md5后的字符必须转化为大写

一、回复微信通知消息模版

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 = "此处为申请微信支付的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为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 
    var crypto = require('crypto'); 
    var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex'); 
    return sign.toUpperCase(); 
  }, 
 
  // 随机字符串产生函数 
  createNonceStr: function() { 
    return Math.random().toString(36).substr(2, 15); 
  }, 
 
  // 时间戳产生函数 
  createTimeStamp: function() { 
    return parseInt(new Date().getTime() / 1000) + ''; 
  },
// 此处的attach不能为空值 否则微信提示签名错误 
  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>"; //附加数据 
    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>"; 
    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; 
  }, 
 
  //支付回调通知 
  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中调用wxpay

//微信支付demo 
router.get('/order', function(req, res, next){ 
  var attach = "1276687601"; 
  var body = "测试支付"; 
  var mch_id = "1111111"; //商户ID 
  var openid = "111111"; 
  var bookingNo = "201501806125346"; //订单号 
  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}); 
  }); 
});
//微信回调通知 采用数据流形式读取微信返回的xml数据 此处不在累赘 
router.post('/notify', function(req, res, next){ 
 
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
NodeJS遍历文件生产文件列表功能示例
Jan 22 NodeJs
nodejs学习笔记之路由
Mar 27 NodeJs
nodejs实现邮件发送服务实例分享
Mar 29 NodeJs
NodeJs使用Mysql模块实现事务处理实例
May 31 NodeJs
使用vs code开发Nodejs程序的使用方法
Sep 21 NodeJs
浅谈NodeJs之数据库异常处理
Oct 25 NodeJs
详解NODEJS的http实现
Jan 04 NodeJs
利用nodeJs anywhere搭建本地服务器环境的方法
May 12 NodeJs
nodejs同步调用获取mysql数据时遇到的大坑
Mar 02 NodeJs
在NodeJs中使用node-schedule增加定时器任务的方法
Jun 08 NodeJs
在nodejs中创建child process的方法
Jan 26 NodeJs
NodeJS和浏览器中this关键字的不同之处
Mar 03 NodeJs
nodeJS微信分享
Dec 20 #NodeJs
NodeJS爬虫实例之糗事百科
Dec 14 #NodeJs
nodejs实现爬取网站图片功能
Dec 14 #NodeJs
NodeJs form-data格式传输文件的方法
Dec 13 #NodeJs
nodejs实现截取上传视频中一帧作为预览图片
Dec 10 #NodeJs
nodejs实现大文件(在线视频)的读取
Oct 16 #NodeJs
nodejs发送http请求时遇到404长时间未响应的解决方法
Dec 10 #NodeJs
You might like
php桌面中心(四) 数据显示
2007/03/11 PHP
Yii的CDbCriteria查询条件用法实例
2014/12/04 PHP
微信公众平台开发-微信服务器IP接口实例(含源码)
2017/03/05 PHP
PHP如何搭建百度Ueditor富文本编辑器
2018/09/21 PHP
tp5(thinkPHP5)框架连接数据库的方法示例
2018/12/24 PHP
js 编写规范
2010/03/03 Javascript
offsetParent 算法分析
2010/04/05 Javascript
jquery的Theme和Theme Switcher使用小结
2010/09/08 Javascript
jquery下动态显示jqGrid以及jqGrid的属性设置容易出现问题的解决方法
2010/10/22 Javascript
javascript判断ie浏览器6/7版本加载不同样式表的实现代码
2011/12/26 Javascript
JS的get和set使用示例
2014/02/20 Javascript
JavaScript中的some()方法使用详解
2015/06/09 Javascript
jquery mobile 移动web(5)
2015/12/20 Javascript
js基于cookie记录来宾姓名的方法
2016/07/19 Javascript
nodejs创建简易web服务器与文件读写的实例
2017/09/07 NodeJs
vue-cli 引入、配置axios的方法
2018/05/08 Javascript
angular实现input输入监听的示例
2018/08/31 Javascript
在小程序/mpvue中使用flyio发起网络请求的方法
2018/09/13 Javascript
Element Input组件分析小结
2018/10/11 Javascript
vuex 中插件的编写案例解析
2019/06/10 Javascript
Vue.js递归组件实现组织架构树和选人功能案例分析
2019/07/03 Javascript
nodejs 递归拷贝、读取目录下所有文件和目录
2019/07/18 NodeJs
Python编写的com组件发生R6034错误的原因与解决办法
2013/04/01 Python
python批量添加zabbix Screens的两个脚本分享
2017/01/16 Python
Python反射的用法实例分析
2018/02/11 Python
django一对多模型以及如何在前端实现详解
2019/07/24 Python
Django权限设置及验证方式
2020/05/13 Python
Keras loss函数剖析
2020/07/06 Python
css3实现元素环绕中心点布局的方法示例
2019/01/15 HTML / CSS
前端实现打印图像功能
2019/08/27 HTML / CSS
精选奢华:THE LIST
2019/09/05 全球购物
医院护士见习期自我鉴定
2014/09/15 职场文书
个人作风建设心得体会
2014/10/22 职场文书
师德标兵先进事迹材料
2014/12/19 职场文书
php访问对象中的成员的实例方法
2021/11/17 PHP
Django中celery的使用项目实例
2022/07/07 Python