微信小程序篇(微信小程序的支付)
微信小程序的支付和微信公众号的支付是类似的,对比起来还比公众号支付简单了一些,我们只需要调用微信的统一下单接口获取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 == ) {
var prepay_id = self.getXMLNodeValue('prepay_id', body.toString("utf-8"))
var tmp = prepay_id.split('[')
var tmp1 = tmp[].split(']')
//签名
var _paySignjs = self.paysignjs(appid, nonce_str, 'prepay_id=' + tmp1[], 'MD5', timeStamp)
var args = {
appId: appid,
timeStamp: timeStamp,
nonceStr: nonce_str,
signType: "MD5",
package: tmp1[],
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()
return string
统一下单接口返回的是带有prepay_id的xml,所以我们需要一个方法进行解析,代码如下:
var tmp = xml.split("<" + node_name + ">")
    var _tmp = tmp[].split("</" + node_name + ">")
    return _tmp[]  
最后我们只需要把这些连接到一起就是可以获取所有微信支付所需参数,代码如下:
//微信小程序支付封装,暂支持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[].split("</" + node_name + ">")
return _tmp[]
},
// 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()
return string
},
// 随机字符串产生函数
createNonceStr: function() {
return Math.random().toString().substr(, )
},
// 时间戳产生函数
createTimeStamp: function() {
return parseInt(new Date().getTime() / ) + ''
},
// 支付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 == ) {
var prepay_id = self.getXMLNodeValue('prepay_id', body.toString("utf-8"))
var tmp = prepay_id.split('[')
var tmp1 = tmp[].split(']')
//签名
var _paySignjs = self.paysignjs(appid, nonce_str, 'prepay_id=' + tmp1[], 'MD5', timeStamp)
var args = {
appId: appid,
timeStamp: timeStamp,
nonceStr: nonce_str,
signType: "MD5",
package: tmp1[],
paySign: _paySignjs
}
deferred.resolve(args)
} else {
console.log(body)
}
})
return deferred.promise
}
}
之后我们封装下单接口:
unifiedorder: function (req, res) {
    var body = "测试支付"
    var openid = "openid"
    var total_fee =
    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, )
        res.json(data)
      })
  },
然后我们只需要在小程序里面调用这个接口,就会获取到所有的支付需要信息,再掉微信支付即可。
这里说几个小程序支付的坑:
1.统一下单接口是xml(这个不只是小程序,公众号也是),返回值也是xml格式需要自己获取prepay_id,
2.签名算法要带上key,最后要转换成大些
3.微信支付的sign算法也要带上appid(这个不科学,深坑)
4.签名算法一定不要用json拼接key
微信小程序篇(微信小程序的支付)的更多相关文章
- 微信小程序 | 49,小程序入门集锦系列文章20篇
		
以下20篇文章,都是关于微信小程序的文章,以入门常见问题为主.如发现谬误,请与笔者联系. [小程序入门集锦]1,微信小程序在哪里打开 [小程序入门集锦]2,小程序商店 [小程序入门集锦]3,微信小程序 ...
 - ESA2GJK1DH1K微信小程序篇:  测试微信小程序扫描Air202上面的二维码绑定设备,并通过MQTT控制设备
		
前言 一,微信小程序篇小程序下载(该功能为小程序篇基础功能源码) 实现功能概要 微信小程序通过扫描GPRS上的二维码,绑定GPRS设备.然后使用小程序通过GPRS远程控制开发板上的继电器, 远程显示单 ...
 - ESA2GJK1DH1K微信小程序篇: 测试微信小程序APUConfig给WI-Fi模块配网并绑定设备,并通过MQTT控制设备
		
前言(源码使用介绍在最后) 一,微信小程序篇小程序下载(该源码为这节测试源代码) 二.有多少人一直在期盼着小程序可以实现SmartConfig或者Airkiss的功能? 来吧!我的这种方式包您满意. ...
 - vue+uni-app商城实战 | 第一篇:【有来小店】微信小程序快速开发接入Spring Cloud OAuth2认证中心完成授权登录
		
一. 前言 本篇通过实战来讲述如何使用uni-app快速进行商城微信小程序的开发以及小程序如何接入后台Spring Cloud微服务. 有来商城 youlai-mall 项目是一套全栈商城系统,技术栈 ...
 - 微信小程序之微信登陆 —— 微信小程序教程系列(20)
		
简介: 微信登陆,在新建一个微信小程序Hello World项目的时候,就可以看到项目中出现了我们的微信头像,其实这个Hello World项目,就有一个简化版的微信登陆.只不过是,还没有写入到咱们自 ...
 - 详解封装微信小程序组件及小程序坑(附带解决方案)
		
一.序 上一篇介绍了如何从零开发微信小程序,博客园审核变智障了,每次代码都不算篇幅,好好滴一篇原创,不到3分钟从首页移出来了.这篇介绍一下组件封装和我的踩坑历程. 二.封装微信小程序可复用组件 首先模 ...
 - 微信小程序调微信支付
		
今天写小程序的支付接口,参照的当然是微信支付API了.(结尾附上第二步全部代码php版) 另外,我也参照了简书上的这篇文章,浅显易懂:https://www.jianshu.com/p/72f5c1e ...
 - 微信小程序与微信公众号同一用户登录问题
		
微信小程序与微信公众号同一用户登录问题 最近在做微信小程序与微信公众号登录合并的接口.整理相关资料以及个人认识的心得写了这篇文章与大家一起分享. 首先,简单说下我遇到的问题是我们的程序调用微信小程序得 ...
 - 微信小程序红包开发 小程序发红包 开发过程中遇到的坑 微信小程序红包接口的
		
微信小程序红包开发 小程序发红包 开发过程中遇到的坑 微信小程序红包接口的 最近公司在开发一个小程序红包系统,客户抢到红包需要提现.也就是通过小程序来给用户发红包. 小程序如何来发红包呢?于是我想 ...
 
随机推荐
- 【剑指offer-12】矩阵中的路径
			
题目描述 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经过了矩阵中 ...
 - https://blog.csdn.net/u012150179/article/details/38091411
			
一 scrapy-redis实现分布式爬取分析 所谓的scrapy-redis实际上就是scrapy+redis其中对redis的操作采用redis-py客户端.这里的redis的作用以及在scrap ...
 - tp 缓存,前台提速
 - MySQL 5.7.18的安装与主从复制(转自:https://www.baidu.com/home/news/data/newspage?nid=9485770887287731252&n_typ)
			
CentOS6.7安装mysql5.7.18 1. 解压到/usr/local目录 # tar -zxvf mysql-5.7.18-linux-glibc2.5-i686.tar.gz -C /us ...
 - 统计学(检验、分布)的 python(numpy/pandas/scipy) 实现
			
scipy 中统计相关的 api:https://docs.scipy.org/doc/scipy/reference/stats.html https://zhuanlan.zhihu.com/p/ ...
 - Tomcat下JSP、Servlet和JavaBean环境的配置
			
经常看到jsp的初学者问tomcat下如何配置jsp.servlet和bean的问题,于是总结了一下如何tomcat下配置jsp.servlet和ben,希望对那些初学者有所帮助. 第一步:下载j2s ...
 - Unity3D-实现连续点击两次返回键退出游戏(安卓/IOS)
			
Unity3D-连续点击两次返回键退出游戏 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 1 Count ...
 - Laravel学习之旅(二)
			
控制器 一.怎么编写控制器? 1.控制器文件存放路径:app\Http\Controllers: 2.命名规范如:TestController.php 3.完整的控制器例子如下: <?php n ...
 - Sql语句中两个比较迷糊的概念:“连接查询” 与 “外键约束”
			
Sql语句中两个比较迷糊的概念:“连接查询” 与 “外键约束 Sql 中的连接查询:就是为了避免笛卡尔积,因为涉及到多表查询的化,不使用连接查询,会先将多个互相乘,求出笛卡尔积,然后在在里面查询符合的 ...
 - 在有 UI 线程参与的同步锁(如 AutoResetEvent)内部使用 await 可能导致死锁
			
AutoResetEvent.ManualResetEvent.Monitor.lock 等等这些用来做同步的类,如果在异步上下文(await)中使用,需要非常谨慎. 本文将说一个在同步上下文中非常常 ...