微信小程序 支付简单实例及注意事项


Posted in Javascript onJanuary 06, 2017

微信小程序 支付

微信小程序的支付和微信公众号的支付是类似的,对比起来还比公众号支付简单了一些,我们只需要调用微信的统一下单接口获取prepay_id之后我们在调用微信的支付即可。

今天我们来封装一般node的支付接口!!!

首先调用统一下单接口我们需要知道一些信息

var bookingNo = 'davdian' + this.createNonceStr() + this.createTimeStamp()
  var deferred = Q.defer() 
  var appid = 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) { 
    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

这个是一个统一下单接口的代码,我们需要appid小程序公众号id,mch_id商户号id,openid小程序的唯一标实,key支付用的密码,剩下的参数都是订单的信息和价格之类的,本人require进q模块使用promise,这个因人而异,可以根据自己需要来。我们需要请求https://api.mch.weixin.qq.com/pay/unifiedorder接口

注意:这里我们传递的formdata是一个xml而不是json

然后我们需要签名方法,这里我们需要封装两个方法,一个是签名方法调用统一下单接口会用到,另一个是调用小程序支付用到

统一下单接口sign:

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 
  var crypto = require('crypto') 
  var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex') 
  return sign.toUpperCase()

支付sign:

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()

注意加密的时候我们获取的是string而不是一个json,所以我们需要吧json转换成string,代码如下:

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

统一下单接口返回的是带有prepay_id的xml,所以我们需要一个方法进行解析,代码如下:

var tmp = xml.split("<" + node_name + ">") 
  var _tmp = tmp[1].split("</" + node_name + ">") 
  return _tmp[0]

最后我们只需要把这些连接到一起就是可以获取所有微信支付所需参数,代码如下:

//微信小程序支付封装,暂支持md5加密,不支持sha1
/**
***create order by jianchep 2016/11/22   
 **/
var config = require('../config/weapp.js')
var Q = require("q") 
var request = require("request") 
var crypto = require('crypto') 
var ejs = require('ejs')
var fs = require('fs') 
var key = config.key
module.exports = {
 // 获取prepay_id
 getXMLNodeValue: function(node_name, xml) { 
  var tmp = xml.split("<" + node_name + ">") 
  var _tmp = tmp[1].split("</" + node_name + ">") 
  return _tmp[0] 
 },
 // object-->string
 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 
 }, 
  // 随机字符串产生函数 
 createNonceStr: function() { 
   return Math.random().toString(36).substr(2, 15) 
 }, 
 // 时间戳产生函数 
 createTimeStamp: function() { 
   return parseInt(new Date().getTime() / 1000) + '' 
 },
 // 支付md5加密获取sign
 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() 
 },
 // 统一下单接口加密获取sign
 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 
  var crypto = require('crypto') 
  var sign = crypto.createHash('md5').update(string, 'utf8').digest('hex') 
  return sign.toUpperCase() 
 },
 // 下单接口
 order: function(attach, body, mch_id, openid, total_fee, notify_url) {
  var bookingNo = 'davdian' + this.createNonceStr() + this.createTimeStamp()
  var deferred = Q.defer() 
  var appid = 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) { 
    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 
 }
}

之后我们封装下单接口:

unifiedorder: function (req, res) {
  var body = "测试支付" 
  var openid = "openid"
  var total_fee = 1
  var notify_url = "http://localhost/notify"
  var mch_id = config.shopId
  var attach = "测试" 
  wxpay.order(attach, body, mch_id, openid, total_fee, notify_url)
   .then(function(data){ 
    console.log('data--->', data, 123123)
    res.json(data)
   }) 
 },

然后我们只需要在小程序里面调用这个接口,就会获取到所有的支付需要信息,再掉微信支付即可。

这里说几个小程序支付的坑:

1.统一下单接口是xml(这个不只是小程序,公众号也是),返回值也是xml格式需要自己获取prepay_id,

2.签名算法要带上key,最后要转换成大些

3.微信支付的sign算法也要带上appid(这个不科学,深坑)

4.签名算法一定不要用json拼接key

感谢阅读,希望能帮助到大家,谢谢大家对本站 的支持!

Javascript 相关文章推荐
js和jquery对dom节点的操作(创建/追加)
Apr 21 Javascript
多个jquery.datatable共存,checkbox全选异常的快速解决方法
Dec 10 Javascript
JS图像无缝滚动脚本非常好用
Feb 10 Javascript
下拉框select的绑定示例
Sep 04 Javascript
node.js中的fs.readdirSync方法使用说明
Dec 17 Javascript
详解javascript实现瀑布流绝对式布局
Jan 29 Javascript
从零学习node.js之简易的网络爬虫(四)
Feb 22 Javascript
JS利用cookies设置每隔24小时弹出框
Apr 20 Javascript
angular 基于ng-messages的表单验证实例
May 04 Javascript
用Vue写一个分页器的示例代码
Apr 22 Javascript
layui点击左侧导航栏,实现不刷新整个页面,只刷新局部的方法
Sep 25 Javascript
ReactRouter的实现方法
Jan 25 Javascript
微信小程序-拍照或选择图片并上传文件
Jan 06 #Javascript
ajax异步请求详解
Jan 06 #Javascript
微信小程序 限制1M的瘦身技巧与方法详解
Jan 06 #Javascript
微信小程序 二维码canvas绘制实例详解
Jan 06 #Javascript
微信小程序 小程序制作及动画(animation样式)详解
Jan 06 #Javascript
JS调用Android、Ios原生控件
Jan 06 #Javascript
JS正则匹配中文的方法示例
Jan 06 #Javascript
You might like
PHP通过iconv将字符串从GBK转换为UTF8字符集
2011/07/18 PHP
深入解析php中的foreach问题
2013/06/30 PHP
PHP实现基于PDO扩展连接PostgreSQL对象关系数据库示例
2018/03/31 PHP
php无限级评论嵌套实现代码
2018/04/18 PHP
Javascript String对象扩展HTML编码和解码的方法
2009/06/02 Javascript
基于Jquery实现的一个图片滚动切换
2012/06/21 Javascript
用js写了一个类似php的print_r输出换行功能
2013/02/18 Javascript
Js实现无刷新删除内容
2015/04/29 Javascript
JavaScript实现Flash炫光波动特效
2015/05/14 Javascript
JQuery替换DOM节点的方法
2015/06/11 Javascript
JavaScript中模拟实现jsonp
2015/06/19 Javascript
浅析javascript函数表达式
2016/02/10 Javascript
javascript中的 object 和 function小结
2016/08/14 Javascript
Angular.JS学习之依赖注入$injector详析
2016/10/20 Javascript
AngularJS 中使用Swiper制作滚动图不能滑动的解决方法
2016/11/15 Javascript
jQuery模拟淘宝购物车功能
2017/02/27 Javascript
用nodeJS搭建本地文件服务器的几种方法小结
2017/03/16 NodeJs
Vue.js最佳实践(五招助你成为vuejs大师)
2018/05/04 Javascript
React 实现车牌键盘的示例代码
2019/12/20 Javascript
详解element-ui动态限定的日期范围选择器代码片段
2020/07/03 Javascript
[39:11]DOTA2上海特级锦标赛C组资格赛#2 LGD VS Newbee第二局
2016/02/28 DOTA
轻松掌握python设计模式之策略模式
2016/11/18 Python
基于python 处理中文路径的终极解决方法
2018/04/12 Python
Python对多属性的重复数据去重实例
2018/04/18 Python
浅述python中深浅拷贝原理
2018/09/18 Python
python批量下载网站马拉松照片的完整步骤
2018/12/05 Python
Python3.5多进程原理与用法实例分析
2019/04/05 Python
用python写一个定时提醒程序的实现代码
2019/07/22 Python
Html5实现移动端、PC端 刮刮卡效果
2016/06/30 HTML / CSS
德国自行车商店:Tretwerk
2019/06/21 全球购物
2014三八妇女节活动总结
2014/03/01 职场文书
学习雷锋精神心得体会范文
2014/03/12 职场文书
毕业生求职信
2014/06/10 职场文书
2014年学校工会工作总结
2014/12/06 职场文书
转让协议书
2015/01/27 职场文书
Python爬虫框架之Scrapy中Spider的用法
2021/06/28 Python