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


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 相关文章推荐
检测jQuery.js是否已加载的判断代码
May 20 Javascript
js和as的稳定传值问题解决
Jul 14 Javascript
超简单JS二级、多级联动的简单实例
Feb 18 Javascript
JavaScript九九乘法口诀表的简单实现
Oct 04 Javascript
jQuery事件绑定方法学习总结(推荐)
Nov 21 Javascript
详解使用fetch发送post请求时的参数处理
Apr 05 Javascript
jquery submit()不能提交表单的解决方法
Apr 24 jQuery
vue-resource调用promise取数据方式详解
Jul 21 Javascript
使用elementUI实现将图片上传到本地的示例
Sep 04 Javascript
如何安装控制器JavaScript生成插件详解
Oct 21 Javascript
javascript实现异形滚动轮播
Nov 28 Javascript
JavaScript 常见的继承方式汇总
Sep 17 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中对各种加密算法、Hash算法的速度测试对比代码
2014/07/08 PHP
codeigniter显示所有脚本执行时间的方法
2015/03/21 PHP
windows8.1下Apache+Php+MySQL配置步骤
2015/10/30 PHP
Yii2 中实现单点登录的方法
2018/03/09 PHP
详解JavaScript ES6中的模板字符串
2015/07/28 Javascript
HTML5 JS压缩图片并获取图片BASE64编码上传
2020/11/16 Javascript
基于jQuery的select下拉框选择触发事件实例分析
2016/11/18 Javascript
jquery实现图片列表鼠标移入微动
2016/12/01 Javascript
微信小程序 天气预报开发实例代码源码
2017/01/20 Javascript
node使用Mongoose类库实现简单的增删改查
2018/11/08 Javascript
小程序实现日历左右滑动效果
2019/10/21 Javascript
JavaScript设计模式--桥梁模式引入操作实例分析
2020/05/23 Javascript
JavaScript位置参数实现原理及过程解析
2020/09/14 Javascript
Python中使用bidict模块双向字典结构的奇技淫巧
2016/07/12 Python
Django中反向生成models.py的实例讲解
2018/05/30 Python
Python 类的特殊成员解析
2018/06/20 Python
python五子棋游戏的设计与实现
2019/06/18 Python
python中property属性的介绍及其应用详解
2019/08/29 Python
python request 模块详细介绍
2020/11/10 Python
HTML5之SVG 2D入门9—蒙板及mask元素介绍与应用
2013/01/30 HTML / CSS
迪士尼西班牙官方网上商店:ShopDisney西班牙
2020/02/02 全球购物
Bitiba意大利:在线宠物商店
2020/10/31 全球购物
校班主任推荐信范文
2013/12/03 职场文书
《姥姥的剪纸》教学反思
2014/02/25 职场文书
校园绿化美化方案
2014/06/08 职场文书
信用卡工资证明格式
2014/09/13 职场文书
学校纪律作风整改措施思想汇报
2014/10/11 职场文书
工程安全生产协议书
2014/11/21 职场文书
嘉宾邀请函
2015/01/31 职场文书
酒店财务部岗位职责
2015/04/14 职场文书
物业保安辞职信
2015/05/12 职场文书
爱心捐赠活动简讯
2015/07/20 职场文书
Python打包exe时各种异常处理方案总结
2021/05/18 Python
MongoDB数据库的安装步骤
2021/06/18 MongoDB
Python if else条件语句形式详解
2022/03/24 Python
Python中tqdm的使用和例子
2022/09/23 Python