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


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中使用replace方法完成某个字符的转换
Aug 20 Javascript
JQuery中extend的用法实例分析
Feb 08 Javascript
js实现精确到毫秒的倒计时效果
Aug 05 Javascript
Vue.js实现一个自定义分页组件vue-paginaiton
Sep 05 Javascript
js 转json格式的字符串为对象或数组(前后台)的方法
Nov 02 Javascript
js倒计时小实例(多次定时)
Dec 08 Javascript
简单实现jquery焦点图
Dec 12 Javascript
jQuery文字轮播特效
Feb 12 Javascript
vue通信方式EventBus的实现代码详解
Jun 10 Javascript
Vue 打包体积优化方案小结
May 20 Javascript
浅谈JavaScript窗体Window.ShowModalDialog使用
Jul 22 Javascript
vue-cil之axios的二次封装与proxy反向代理使用说明
Apr 07 Vue.js
微信小程序-拍照或选择图片并上传文件
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输出表格的实现代码(修正版)
2010/12/29 PHP
PHP is_subclass_of函数的一个BUG和解决方法
2014/06/01 PHP
py文件转exe时包含paramiko模块出错解决方法
2016/08/12 PHP
PHP设计模式之单例模式定义与用法分析
2019/03/26 PHP
JQuery $.each遍历JavaScript数组对象实例
2014/09/01 Javascript
jQuery实现仿腾讯迷你首页选项卡效果代码
2015/09/17 Javascript
理解 JavaScript Scoping &amp; Hoisting(二)
2015/11/18 Javascript
[原创]Javascript 实现广告后加载 可加载百度谷歌联盟广告
2016/05/11 Javascript
JS实现可编辑的后台管理菜单功能【附demo源码下载】
2016/09/13 Javascript
node.js版本管理工具n无效的原理和解决方法
2016/11/24 Javascript
Jqprint实现页面打印
2017/01/06 Javascript
Angular中点击li标签实现更改颜色的核心代码
2017/12/08 Javascript
php 解压zip压缩包内容到指定目录的实例
2018/01/23 Javascript
windows系统中python使用rar命令压缩多个文件夹示例
2014/05/06 Python
python 通过 socket 发送文件的实例代码
2018/08/14 Python
Python控制键盘鼠标pynput的详细用法
2019/01/28 Python
python输出带颜色字体实例方法
2019/09/01 Python
python基于opencv检测程序运行效率
2019/12/28 Python
Python下利用BeautifulSoup解析HTML的实现
2020/01/17 Python
python为Django项目上的每个应用程序创建不同的自定义404页面(最佳答案)
2020/03/09 Python
解决python多线程报错:AttributeError: Can't pickle local object问题
2020/04/08 Python
Python Pillow(PIL)库的用法详解
2020/09/19 Python
Django haystack实现全文搜索代码示例
2020/11/28 Python
OpenCV+Python3.5 简易手势识别的实现
2020/12/21 Python
开业庆典主持词
2014/03/21 职场文书
简单租房协议书
2014/04/09 职场文书
党员民主生活会个人整改措施材料
2014/09/16 职场文书
2014年质检工作总结
2014/11/26 职场文书
公司清洁工岗位职责
2015/04/15 职场文书
工程合作意向书范本
2015/05/09 职场文书
婚宴父母致辞
2015/07/27 职场文书
2016年优秀党员教师先进事迹材料
2016/02/29 职场文书
如何用PHP实现分布算法之一致性哈希算法
2021/05/26 PHP
Python道路车道线检测的实现
2021/06/27 Python
Java字符串逆序方法详情
2022/03/21 Java/Android
2022漫威和DC电影上映作品
2022/04/05 欧美动漫