基于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读取memcache示例分享
Jan 02 NodeJs
NodeJS学习笔记之MongoDB模块
Jan 13 NodeJs
NodeJS学习笔记之Connect中间件应用实例
Jan 27 NodeJs
NodeJS和BootStrap分页效果的实现代码
Nov 07 NodeJs
NodeJS基础API搭建服务器详细过程记录
Apr 01 NodeJs
Nodejs中Express 常用中间件 body-parser 实现解析
May 22 NodeJs
nodejs 搭建简易服务器的图文教程(推荐)
Jul 18 NodeJs
解决Nodejs全局安装模块后找不到命令的问题
May 15 NodeJs
nodejs高大上的部署方式(PM2)
Sep 11 NodeJs
nodejs require js文件入口,在package.json中指定默认入口main方法
Oct 10 NodeJs
Nodejs中使用puppeteer控制浏览器中视频播放功能
Aug 26 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
echo(),print(),print_r()之间的区别?
2006/11/19 PHP
PHP中查询SQL Server或Sybase时TEXT字段被截断的解决方法
2009/03/10 PHP
如何用phpmyadmin设置mysql数据库用户的权限
2012/01/09 PHP
php命名空间学习详解
2014/02/27 PHP
php制作基于xml的RSS订阅源功能示例
2017/02/08 PHP
PHP实现的redis主从数据库状态检测功能示例
2017/07/20 PHP
jquery 学习之二 属性(html()与html(val))
2010/11/25 Javascript
jQuery数据显示插件整合实现代码
2011/10/24 Javascript
深入理解JavaScript系列(2) 揭秘命名函数表达式
2012/01/15 Javascript
Jquery 数据选择插件Pickerbox使用介绍
2012/08/24 Javascript
js实现上传图片之上传前预览图片
2013/03/25 Javascript
node.js+Ajax实现获取HTTP服务器返回数据
2014/11/26 Javascript
浅析JavaScript中的事件机制
2015/06/04 Javascript
关于JavaScript 原型链的一点个人理解
2016/07/31 Javascript
JScript实现表格的简单操作
2017/08/15 Javascript
在 Angular 中使用Chart.js 和 ng2-charts的示例代码
2017/08/17 Javascript
解决iView中时间控件选择的时间总是少一天的问题
2018/03/15 Javascript
使用 webpack 插件自动生成 vue 路由文件的方法
2019/08/20 Javascript
Node.js中出现未捕获异常的处理方法
2020/06/29 Javascript
element跨分页操作选择详解
2020/06/29 Javascript
在vue中动态修改css其中一个属性值操作
2020/12/07 Vue.js
[01:33:59]真人秀《加油 DOTA》 第六期
2014/09/09 DOTA
python实现矩阵乘法的方法
2015/06/28 Python
pytorch中tensor的合并与截取方法
2018/07/26 Python
利用Python将图片中扭曲矩形的复原
2020/09/07 Python
带你认识HTML5中的WebSocket
2015/05/22 HTML / CSS
九州传奇上机题
2014/07/10 面试题
给导游的表扬信
2014/01/10 职场文书
2014年资料员工作总结
2014/11/18 职场文书
店面出租协议书范本
2014/11/28 职场文书
小学中队活动总结
2015/05/11 职场文书
怎样写观后感
2015/06/19 职场文书
放飞理想主题班会
2015/08/14 职场文书
《从现在开始》教学反思
2016/02/16 职场文书
MySQL中CURRENT_TIMESTAMP的使用方式
2021/11/27 MySQL
nginx日志格式分析和修改
2022/04/28 Servers