微信小程序篇(微信小程序的支付)

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

时间: 2025-01-05 03:15:19

微信小程序篇(微信小程序的支付)的相关文章

9-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案微信小程序篇(微信配网配置_开发者基本配置_2)

https://www.cnblogs.com/yangfengwu/p/11062422.html 这一节看怎么用PHP实现上一节的功能 关掉上一节的 学了这么久,忘了告诉大家怎么关闭程序了..... 可以这样,建一个后缀名为.bat的文件   文件名字随意 里面写上 taskkill /IM python.exe /F 然后双击运行 会看到这边断开了 其它方式自行百度 咱把程序放到这里面 里面建一个token.php 的文件 <?php //http://localhost:63343/le

10-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案微信小程序篇(微信配网配置_Airkiss步骤_1)

https://www.cnblogs.com/yangfengwu/p/11066036.html 如果提交失败多提交两次,只要上一节可以,,这一节一定可以的 如果没有设备 咱就测试一下扫描二维码配网,下一节咱再看怎么嵌入到公众号里面,点击按钮实现 修改咱的程序 所有LUA开发的WIFI程序,配网的地方 以升级篇为例: (其它地方都是这样修改) 纯AT指令实现的不需要修改 稍等有点事情 原文地址:https://www.cnblogs.com/yangfengwu/p/11066472.htm

7-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案微信小程序篇(微信配网_申请微信公众号)

https://www.cnblogs.com/yangfengwu/p/11042266.html 老是学习枯燥乏味的东西容易烦躁,所以呢,接着这几节咱实现下微信配网 为了让所有人都可以都可以使用,咱就用微信订阅号实现(里面提供测试版服务号),实质上只有服务号和微信企业号才具有此功能. 咱呢注册登录订阅号 https://mp.weixin.qq.com/ 原文地址:https://www.cnblogs.com/yangfengwu/p/11062034.html

13-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案微信小程序篇(网页版MQTT)

https://www.cnblogs.com/yangfengwu/p/11148976.html 抱歉哈...最近由于做板子,,教程的进度落下了... 这些天总共做了还几块板子 首先对当前这个教程的这个板子做了修订,调整了下布局,替换换了以前用的Micro USB 接口,开关降压改为MP4462 STM32+Air720H(全网通GPRS)+以太网+422/485+4-20ma采集    https://www.cnblogs.com/yangfengwu/category/1472273.

ESA2GJK1DH1K微信小程序篇: 测试微信小程序扫描Air202上面的二维码绑定设备,并通过MQTT控制设备

前言 暂无 实现功能概要 微信小程序通过扫描GPRS上的二维码,绑定GPRS设备.然后使用小程序通过GPRS远程控制开发板上的继电器, 远程显示单片机采集的温湿度数据. 一,硬件程序 硬件程序采用基础篇 https://www.cnblogs.com/yangfengwu/p/11762609.html  的底层硬件程序 该源码已经拷贝到了当前测试目录 二,微信小程序源码 测试准备工作 一,下载单片机程序(请自行下载) 二,打开微信小程序软件,导入本节工程 三,把小程序安装到手机运行 四,调整波

微信小程序篇(微信小程序的支付)转载 “微信小程序联盟”

微信小程序的支付和微信公众号的支付是类似的,对比起来还比公众号支付简单了一些,我们只需要调用微信的统一下单接口获取prepay_id之后我们在调用微信的支付即可. 今天我们来封装一般node的支付接口!!! 首先调用统一下单接口我们需要知道一些信息 var bookingNo = 'davdian' + this.createNonceStr() + this.createTimeStamp() var deferred = Q.defer() var appid = config.appId

店铺无缝对接一号旺铺小程序 盘点微信小程序新增功能

前段时间,笔者写过一篇<不开发,商家店铺如何快速接入微信一号旺铺小程序>的文章.结果反响平平,无人问津.所以,笔者就在想,也许小程序真的大势已去. 盘点迄今为止微信小程序增加的功能:价值提升,商家福音到了! 盘点迄今为止微信小程序增加的功能:价值提升,商家福音到了! 但是,就在本人下定决心以后少关注小程序的当口,腾讯似乎终于觉醒了,张小龙也终于向现实低头妥协,微信官方宣布的小程序新增功能绝地反击,热乎了众多商家的心,也活跃了个人创业开发者的兴奋基因.其实,自小程序面市已来,其功能一直在不断完善

微信小程序与微信公众号同一用户登录问题

最近在做微信小程序与微信公众号登录合并的接口.整理相关资料以及个人认识的心得写了这篇文章与大家一起分享. 首先,简单说下我遇到的问题是我们的程序调用微信小程序得到openid,然后通过openID得到用户的唯一标识,用户得以登录,然而,当我们调用微信公众号也同样的到openid,同一以用户两个不同的openid,不能区分是否为同一用户,然后发现无论调用微信小程序还是微信公众号同一个用户的到unionid是相同的,所以我们就用unionid来区分是否为同一用户. UnionID机制说明: 如果开发

微信小程序调微信支付

今天写小程序的支付接口,参照的当然是微信支付API了.(结尾附上第二步全部代码php版) 另外,我也参照了简书上的这篇文章,浅显易懂:https://www.jianshu.com/p/72f5c1e3f8a5 其实小程序中唤起微信支付不外乎以下几个步骤: 1.获取openid 小程序获取openid是分两个步骤的 首先小程序前端通过wx.login获取code,然后用这个code通过后台接口内部访问微信官方API获取openid.session_key https://api.weixin.q