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

网络编程 2021-07-04 19:20www.168986.cn编程入门
这篇文章主要介绍了微信小程序 支付简单实例的相关资料,这里参考官方文档写的简单实例,并提出注意事项,需要的朋友可以参考下

微信小程序 支付

微信小程序的支付和微信公众号的支付是类似的,对比起来还比公众号支付简单了一些,我们只需要调用微信的统一下单接口获取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./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./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./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

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

Copyright © 2016-2025 www.168986.cn 狼蚁网络 版权所有 Power by