基于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的前后端分离的思考与实践(二)模版探索
Sep 26 NodeJs
nodejs实现遍历文件夹并统计文件大小
May 28 NodeJs
Nodejs进阶:核心模块net入门学习与实例讲解
Nov 21 NodeJs
NodeJS遍历文件生产文件列表功能示例
Jan 22 NodeJs
详解nodeJS之二进制buffer对象
Jun 03 NodeJs
nodejs socket服务端和客户端简单通信功能
Sep 14 NodeJs
详解NODEJS基于FFMPEG视频推流测试
Nov 17 NodeJs
windows系统下更新nodejs版本的方案
Nov 24 NodeJs
NodeJS实现同步的方法
Mar 02 NodeJs
nodejs中request库使用HTTPS代理的方法
Apr 30 NodeJs
NodeJs 模仿SIP话机注册的方法
Jun 21 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
示例详解Laravel重置密码代码重构
2016/08/10 PHP
Json_decode 解析json字符串为NULL的解决方法(必看)
2017/02/17 PHP
jQuery :nth-child前有无空格的区别分析
2011/07/11 Javascript
js中的getAttribute方法使用示例
2014/08/01 Javascript
node.js中的emitter.emit方法使用说明
2014/12/10 Javascript
Nodejs学习笔记之Global Objects全局对象
2015/01/13 NodeJs
Javascript中使用A标签获取当前目录的绝对路径方法
2015/03/02 Javascript
多个js毫秒倒计时同时进行效果
2016/01/05 Javascript
jQuery树形控件zTree使用小结
2016/08/02 Javascript
js 定位到某个锚点的方法
2016/11/19 Javascript
在使用JSON格式处理数据时应该注意的问题小结
2017/05/20 Javascript
微信小程序实现action-sheet弹出底部菜单功能【附源码下载】
2017/12/09 Javascript
(模仿京东用户注册)用JQuery实现简单表单验证,初学者必看
2018/01/08 jQuery
vue.js使用v-model指令实现的数据双向绑定功能示例
2018/05/22 Javascript
如何封装了一个vue移动端下拉加载下一页数据的组件
2019/01/06 Javascript
微信小程序 如何获取网络状态
2019/07/26 Javascript
好用的Python编辑器WingIDE的使用经验总结
2016/08/31 Python
Python实现合并同一个文件夹下所有PDF文件的方法示例
2018/04/28 Python
python3模块smtplib实现发送邮件功能
2018/05/22 Python
python实现在cmd窗口显示彩色文字
2019/06/24 Python
Python 利用高德地图api实现经纬度与地址的批量转换
2019/08/14 Python
TensorBoard 计算图的查看方式
2020/02/15 Python
python编写俄罗斯方块
2020/03/13 Python
python如何停止递归
2020/09/09 Python
python中的列表和元组区别分析
2020/12/30 Python
CSS3的calc()做响应模式布局的实现方法
2017/09/06 HTML / CSS
使用分层画布来优化HTML5渲染的教程
2015/05/08 HTML / CSS
某科技软件测试面试题
2013/05/19 面试题
药学专业学生的自我评价分享
2014/02/06 职场文书
扩大国家免疫规划实施方案
2014/03/21 职场文书
产品生产计划书
2014/05/07 职场文书
作风建设剖析材料
2014/10/06 职场文书
幼儿园安全教育随笔
2015/08/14 职场文书
丧事酒宴答谢词
2015/09/30 职场文书
2016年学校“6﹒26国际禁毒日”宣传活动总结
2016/04/05 职场文书
sql查询结果列拼接成逗号分隔的字符串方法
2021/05/25 SQL Server