首頁 >微信小程式 >小程式開發 >分享小程式支付功能的實例程式碼教學

分享小程式支付功能的實例程式碼教學

零下一度
零下一度原創
2017-05-26 09:45:322592瀏覽

微信小程式的支付和微信公眾號的支付是類似的,對比起來還比公眾號支付簡單了一些,我們只需要調用微信的統一下單接口獲取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, &#39;61.50.221.43&#39;, total_fee, &#39;JSAPI&#39;) + "</sign>"  
    formData += "</xml>"  
    var self = this
    request({  
      url: url,  
      method: &#39;POST&#39;,  
      body: formData  
    }, function(err, response, body) {  
      if (!err && response.statusCode == 200) {  
        var prepay_id = self.getXMLNodeValue(&#39;prepay_id&#39;, body.toString("utf-8")) 
        var tmp = prepay_id.split(&#39;[&#39;)  
        var tmp1 = tmp[2].split(&#39;]&#39;)  
        //签名  
        var _paySignjs = self.paysignjs(appid, nonce_str, &#39;prepay_id=&#39; + tmp1[0], &#39;MD5&#39;, 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,這個因人而異,可以根據自己需要來。我們需要請求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 + &#39;&key=&#39; + key  
    var crypto = require(&#39;crypto&#39;)  
    var sign = crypto.createHash(&#39;md5&#39;).update(string, &#39;utf8&#39;).digest(&#39;hex&#39;)  
    return sign.toUpperCase() 

支付sign:
var ret = {  
        appId: appid,  
        nonceStr: nonceStr,  
        package: package,  
        signType: signType,  
        timeStamp: timeStamp  
    }  
    var string = this.raw(ret)  
    string = string + &#39;&key=&#39; + key  
    var sign = crypto.createHash(&#39;md5&#39;).update(string, &#39;utf8&#39;).digest(&#39;hex&#39;)  
    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 = &#39;&#39;  
    for (var k in newArgs) {  
        string += &#39;&&#39; + k + &#39;=&#39; + 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("")  
    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 = &#39;davdian&#39; + 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, &#39;61.50.221.43&#39;, total_fee, &#39;JSAPI&#39;) + "</sign>"  
    formData += "</xml>"  
    var self = this
    request({  
      url: url,  
      method: &#39;POST&#39;,  
      body: formData  
    }, function(err, response, body) {  
      if (!err && response.statusCode == 200) {  
        var prepay_id = self.getXMLNodeValue(&#39;prepay_id&#39;, body.toString("utf-8")) 
        var tmp = prepay_id.split(&#39;[&#39;)  
        var tmp1 = tmp[2].split(&#39;]&#39;)  
        //签名  
        var _paySignjs = self.paysignjs(appid, nonce_str, &#39;prepay_id=&#39; + tmp1[0], &#39;MD5&#39;, 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(&#39;data--->&#39;, data, 123123)
        res.json(data)
      })  
  },

然後我們只需要在小程式裡面調用這個接口,就會獲取到所有的支付需要信息,再掉微信支付即可。

這裡說幾個小程序支付的坑:

1.統一下單接口是xml(這個不只是小程序,公眾號也是),返回值也是xml格式需要自己獲取prepay_id,

2.簽章演算法要帶key,最後要轉換成大些

#3.微信支付的sign演算法也要帶上appid(這個不科學,深坑)

4.簽章演算法一定不要用json拼接key

【相關推薦】

#1. 

微信小程式微信支付接取開發

2.

 小程式開發之實作樓層錨點跳躍實例詳解

#3. 

實作微信小程式的線上支付功能碼解析

3. ###實作微信小程式的線上支付功能碼解析#######

以上是分享小程式支付功能的實例程式碼教學的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn