转自:http://www.wxapp-union.com/article-5407-1.html

微信小程序微信支付官方流程图链接我简化的流程:本地发起下单请求调用云函数并传送数据云函数处理数据并返回5个参数本地接受5个参数,发起支付请求交易结束主要代码://第一步,本地发起下单请求并传送数据。这一步 ...

微信小程序微信支付官方流程图链接

我简化的流程:

  1. 本地发起下单请求调用云函数并传送数据
  2. 云函数处理数据并返回5个参数
  3. 本地接受5个参数,发起支付请求
  4. 交易结束

主要代码:

//第一步,本地发起下单请求并传送数据。这一步,在你的wxml中的某个元素
//中绑定事件<button bindtap='pay'></button>。通过这个pay函数,
//触发云函数并传递一些数据
pay: function(){//需要上传给云函数的数据let uploadData = {//此次需要支付的金额,单位是分。例如¥1.80=180"total_fee": "180",//用户端的ip地址"spbill_create_ip": "123.123.123.123"}//调用云函数wx.cloud.callFunction({//云函数的名字,这里我定义为paymentname: "payment",//需要上传的数据data: uploadData}).then(res => {//这个res就是云函数返回的5个参数//通过wx.requestPayment发起支付wx.requestPayment({timeStamp: res.result.data.timeStamp,nonceStr: res.result.data.nonceStr,package: res.result.data.package,signType: res.result.data.signType,paySign: res.result.data.paySign,success: res => {//支付成功},fail: err => {//支付失败}})
}复制代码

以上就是本地端的全部代码,接下来我们只需要搞定云函数的代码就完成全部的工作了。

云函数的内容是:

  1. 调用小程序登陆API -> Openid
  2. 生成商户订单
  3. 调用统一下单API -> prepay_id
  4. 将组合数据再次签名,返回5个参数

我创建的云函数命名为payment,此时云函数结构应该为

payment
|__index.js
|__package.json
复制代码

##每一步的详细做法

1. 调用小程序登陆API -> Openid

这一步目的是获取用户的Openid

在云函数的index.js中加上以下代码

//获取云实例
const cloud = require('wx-server-sdk')
//云初始化
cloud.init()
//获取微信调用上下文信息,其中包括Openid,Appid等
const wxContext = cloud.getWXContext()
//获取用户openid
const openid = wxContext.OPENID
复制代码

到这里我们已经达成我们第一步的目的了。

2. 生成商户订单

微信支付开发文档-统一下单

这一步的目的是为了 生成调用支付统一下单API的订单 。根据官方文档,我们需要以下数据:

  1. appid(小程序ID)

  2. openid(用户OPENID)

  3. mch_id(商户号)

  4. nonce_str(随机字符串)

  5. body(商品描述)

  6. out_trade_no(商户订单号)

  7. total_fee(标价金额)

  8. spbill_create_ip(终端IP)

  9. notify_url(通知地址)

  10. trade_type(交易类型)

  11. key(密钥)

  12. sign(签名)

我们一个一个解决。

1. appid

小程序管理员进入公众平台、使用小程序帐户登录后,点击左侧菜单中的「设置」,在「开发设置」一项,就可以查询到小程序的AppID。

示例值 wxd678efh567hg6787

在云函数的index.js中加上以下代码:

const appid='wxwxd678efh567hg6787'
复制代码

2. openid

第一步已经获得。

示例值 oUpF8uMuAJO_M2pxb1Q9zNjWeS6o

3. mch_id

登陆微信支付商户平台pay.weixin.qq.com,点击上方「账户中心」,在「个人信息」中的「登陆账号」就是mch_id。

示例值 1230000109

在云函数的index.js中加上以下代码:

const mch_id='1230000109'
复制代码

4. nonce_str

任意生成的随机数,不超过32位。你可以自己写个函数。

示例值 5K8264ILTKCH16CQ2502SI8ZNMTM67VS

我在云函数中创建了一个新的JS文件(random.js)来保存这个函数,此时云函数的结构如下

payment
|__index.js
|__package.json
|__random.js
复制代码

其中random.js的内容为:

function random(){var result = ''const wordList = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l','m', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2','3', '4', '5', '6', '7', '8', '9', '0']for(let i=0;i<31;i++){result += wordList[Math.round(Math.random()*36)]}return result
}module.exports = random()复制代码

然后在云函数index.js中加上以下代码:

const random = require("random.js")
复制代码

5. body

格式为:商家名称-销售商品类目

示例值 腾讯-游戏

在云函数index.js中加上以下代码:

const body = "腾讯-游戏"
复制代码

6. out_trade_no

商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*且 在同一个商户号下唯一 。由自己定义,推荐用当下时间+商品编号组成。

示例值 20150806125346

在云函数index.js中的exports.main函数中加上以下代码:

//这里我只使用了当下时间。只要这个数字不是重复的就可以。
const out_trade_no = Date.parse(new Date()).toString()
复制代码

7. total_fee

订单总金额,单位为分。比如当前需支付¥6.80,则total_fee为680。

示例值 88

这里需要用到我们上传过来的值,先不管

8. spbill_create_ip

支持IPV4和IPV6两种格式的IP地址。调用微信支付API的机器IP。

示例值 123.12.12.123

这里需要用到我们上传过来的值,先不管

9. notify_url

异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。在这里可以填上你自己服务器的url。

示例值 http://www.weixin.qq.com/wxpay/pay.php

在云函数index.js中加上以下代码:

//随便填写个服务器就行,我在使用中没有遇到什么问题
const notify_url = 'http://www.weixin.qq.com/wxpay/pay.php'
复制代码

10. trade_type

小程序的trade_type为JSAPI。

示例值 JSAPI

在云函数index.js中加上以下代码:

const trade_type = 'JSAPI'
复制代码

11. key

key为商户平台设置的密钥key,是由你自己设置的。key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置。

示例值 1a79a4d60de6718e8e5b326e338ae533

在云函数index.js中加上以下代码:

const key = '1a79a4d60de6718e8e5b326e338ae533'
复制代码

12. sign

将以上除key外所有信息按照参数名ASCII码从大到小拼接成字符串,用&分割,将key放在最后。

字符串示例值:

appid=wxd678efh567hg6787&body=微信-游戏&mch_
id=1230000109&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM6
7VS&notify_url=http://www.weixin.qq.com/wxpay/pay.php&
openid=oUpF8uMuAJO_M2pxb1Q9zNjWeS6o&out_trade_no=2015080
6125346&spbill_create_ip=123.12.12.123&total_fee=88&trad
e_type=JSAPI&key=1a79a4d60de6718e8e5b326e338ae533
复制代码

此字符串的MD5码的大写就是sign。因为上面的total_fee与spbill_create_ip我们还没处理,所以这个数据放到下面再处理。

MD5码示例值 C380BEC2BFD727A4B6845133519F3AD6

到此为止你的云函数结构应该为:

payment
|__index.js
|__package.json
|__random.js
复制代码

其中index.js的内容应该为:

//云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
const openid = cloud.getWXContext().OPENID
const appid = 'wxwxd678efh567hg6787'
const mch_id = '1230000109'
const random = require('random.js')
const body = "腾讯-游戏"
const notify_url = 'http://www.weixin.qq.com/wxpay/pay.php'
const trade_type = 'JSAPI'
const key = '1a79a4d60de6718e8e5b326e338ae533'//云函数入口函数
exports.main = async (event, content) => {const out_trade_no = Date.parse(new Date()).toString()
}
复制代码

接下来我们处理上面没有处理的total_fee与spbill_create_ip,以及sign。 其中total_fee和spbill_create_ip是由客户端上传的,这两个数据就在云函数入口函数的参数event中,所以我们在云函数入口函数里面加上以下代码

const total_fee = event.total_fee
const spbill_create_ip = event.spbill_create_ip
复制代码

最后,我们需要处理sign,按照12.sign提到的规则,在云函数入口函数里面加上以下代码

let stringA = `appid=${appid}&body=${body}&
mch_id=${mch_id}&nonce_str=${random}&
notify_url=${notify_url}&openid=${openid}&
out_trade_no=${out_trade_no}&
spbill_create_ip=${spbill_create_ip}&
total_fee=${total_fee}™_type=${trade_type}&
key=1a79a4d60de6718e8e5b326e338ae533`
复制代码

我们现在需要将这个字符串进行MD5码加密,所以需要安装一个npm包来完成这个任务。右键点击云函数pyament,选择「在终端打开」,输入下面的命令:

npm install --save crypto
复制代码

完成后在云函数入口文件处加上以下代码

const crypto = require("crypto")
复制代码

这样我们就成功地将crypto这个加密工具包引入我们的云函数里了。然后我们需要在云函数入口函数里使用它对刚刚的stringA进行MD5加密。所以我们在 let stringA = ... 这行代码下面添加以下代码

var sign = crypto.createHash('md5').update(stringA).digest('hex').toUpperCase()
复制代码

以上除key的11个信息就是我们调用统一下单API所需要的全部数据了

我们现在需要将这些数据转成xml格式,例如:

<xml>
<appid>wxd930ea5d5a258f4f</appid>
<mch_id>10000100</mch_id>
<device_info>1000</device_info>
<body>test</body>
<nonce_str>ibuaiVcKdpRxkhJA</nonce_str>
<sign>9A0A8659F005D6984697E2CA0A9CF3B7</sign>
...
</xml>
复制代码

在云函数中新建一个requestData.js,写下如下函数,用来完成将数据转成xml的任务

function requestData(appid,mch_id,nonce_str,sign,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid
){let data = "<xml>"data += "<appid>"+appid+"</appid>"data += "<mch_id>"+mch_id+"</mch_id>"data += "<nonce_str>"+nonce_str+"</nonce_str>"data += "<sign>"+sign+"</sign>"data += "<body>"+body+"</body>"data += "<out_trade_no>"+out_trade_no+"</out_trade_no>"data += "<total_fee>"+total_fee+"</total_fee>"data += "<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"data += "<notify_url>"+notify_url+"</notify_url>"data += "<trade_type>"+trade_type+"</trade_type>"data += "<openid>"+openid+"</openid>"data += "</xml>"return data
}module.exports = requestData
复制代码

此时云函数的结构为

payment
|__index.js
|__package.json
|__package-lock.json //由npm install产生的文件
|__random.js
|__requestData.js
复制代码

我们需要将requestData.js文件导入到我们的项目。在云函数入口文件那里添加以下代码

const requestData = require("requestData.js")
复制代码

现在,我们可以生成调用支付统一下单API的订单了,这个dataBody就是订单。

let dataBody = reqData(appid,mch_id,random,sign,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid)
复制代码

到这里我们已经达成我们第二部的目的了。

3.调用统一下单API -> prepay_id

官方文档

我们需要对官方提供的链接 https://api.mch.weixin.qq.com/pay/unifiedorder 发起统一下单,所以这里我们需要一个npm包来帮我们完成request请求,并且由于发起请求后的返回值是xml格式的,所以我们还需要一个npm包来帮助我们解析xml格式文件。故右键点击云函数payment,选择「在终端打开」,输入下面命令:

npm install --save request
npm install --save xmlreader
复制代码

在云函数入口文件中引入上面两个包:

const request = require("request")
const xmlreader = require("xmlreader")
复制代码

然后就可以在云函数入口函数中发起对统一下单API的request请求了,由于request是异步请求,所以我们需要返回一个Promise。

return new Promise(reslove => {request({//官方统一下单api的urlurl: 'https://api.mch.weixin.qq.com/pay/unifiedorder',//请求方法,postmethod: "POST",//需要传送的订单,就是刚刚我们生成的dataBodybody: dataBody}, body => {//body就是我们收到的数据,我们需要得到其中的prepay_id//使用xmlreader解析body,获得其中的prepay_idxmlreader.read(body, res => {//此时我们已经完成第三步的目的了let prepay_id = res.xml.prepay_id.text()}}
}
复制代码

第三步目的完成

4.将组合数据再次签名,返回5个参数

已知wx.requestPayment()需要五个参数,分别是

  1. timeStamp
  2. nonceStr
  3. package
  4. signType
  5. paySign

其中,timeStamp为时间戳,可由 Date.parse(new Date()).toString() 取得。 nonceStr为随机字符串,可由我们的随机函数取得。 package就是上一步获得的prepay_id, signType是签名类型,我们选择的是MD5。所以我们现在只剩下paySign未知,得到paySign的方法为

paySign = MD5(appId=wxd678efh567hg6787&nonceStr=5K826
4ILTKCH16CQ2502SI8ZNMTM67VS&package=prepay_id=wx20170
33010242291fcfe0db70013231072&signType=MD5&timeStamp=
1490840662&key=qazwsxedcrfvtgbyhnujmikolp111111) = 22D
9B4E54AB1950F51E0649E8810ACD6
复制代码

所以我们在上一步的代码中接着写

return new Promise(reslove => {request({url: 'https://api.mch.weixin.qq.com/pay/unifiedorder',method: "POST",body: dataBody}, body => {xmlreader.read(body, res => {let prepay_id = res.xml.prepay_id.text()let timeStamp = Date.parse(new Date()).toString()let str = `appId=${appid}&nonceStr=${random}&package=prepay_id=${prepay_id}&signType=MD5&timeStamp=${timeStamp}&key=1a79a4d60de6718e8e5b326e338ae533`let paySign = crypto.createHash('md5').update(str).digest('hex')//返回上面的五个参数reslove({data: {timeStamp: timeStamp,nonceStr: random,package: `prepay_id=${prepay_id}`,signType: 'MD5',paySign: paySign}})}}
}
复制代码

至此,微信小程序支付流程结束。

此时云函数结构为:

payment
|__index.js
|__package.json
|__package-lock.json
|__random.js
|__requestData.js
复制代码

index.js:

//云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
const openid = cloud.getWXContext().OPENID
const appid = 'wxwxd678efh567hg6787'
const mch_id = '1230000109'
const random = require('random.js')
const body = "腾讯-游戏"
const notify_url = 'http://www.weixin.qq.com/wxpay/pay.php'
const trade_type = 'JSAPI'
const key = '1a79a4d60de6718e8e5b326e338ae533'
const crypto = require("crypto")
const requestData = require("requestData")
const request = require("request")
const xmlreader = require("xmlreader")//云函数入口函数
exports.main = async (event, content) => {const out_trade_no = Date.parse(new Date()).toString()const total_fee = event.total_feeconst spbill_create_ip = event.spbill_create_iplet stringA = `appid=${appid}&body=${body}&mch_id=${mch_id}&nonce_str=${random}&notify_url=${notify_url}&openid=${openid}&out_trade_no=${out_trade_no}&spbill_create_ip=${spbill_create_ip}&total_fee=${total_fee}™_type=${trade_type}&key=1a79a4d60de6718e8e5b326e338ae533`var sign = crypto.createHash('md5').update(stringA).digest('hex').toUpperCase()let dataBody = reqData(appid,mch_id,random,sign,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid)return new Promise(reslove => {request({url: 'https://api.mch.weixin.qq.com/pay/unifiedorder',method: "POST",body: dataBody}, body => {xmlreader.read(body, res => {let prepay_id = res.xml.prepay_id.text()let timeStamp = Date.parse(new Date()).toString()let str = `appId=${appid}&nonceStr=${random}&package=prepay_id=${prepay_id}&signType=MD5&timeStamp=${timeStamp}&key=1a79a4d60de6718e8e5b326e338ae533`let paySign = crypto.createHash('md5').update(str).digest('hex')//返回上面的五个参数reslove({data: {timeStamp: timeStamp,nonceStr: random,package: `prepay_id=${prepay_id}`,signType: 'MD5',paySign: paySign}})}}
}
复制代码

random.js:

function random(){var result = ''const wordList = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l','m', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2','3', '4', '5', '6', '7', '8', '9', '0']for(let i=0;i<31;i++){result += wordList[Math.round(Math.random()*36)]}return result
}module.exports = random()
复制代码

requestData.js:

function requestData(appid,mch_id,nonce_str,sign,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid
){let data = "<xml>"data += "<appid>"+appid+"</appid>"data += "<mch_id>"+mch_id+"</mch_id>"data += "<nonce_str>"+nonce_str+"</nonce_str>"data += "<sign>"+sign+"</sign>"data += "<body>"+body+"</body>"data += "<out_trade_no>"+out_trade_no+"</out_trade_no>"data += "<total_fee>"+total_fee+"</total_fee>"data += "<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"data += "<notify_url>"+notify_url+"</notify_url>"data += "<trade_type>"+trade_type+"</trade_type>"data += "<openid>"+openid+"</openid>"data += "</xml>"return data
}module.exports = requestData
复制代码

微信小程序通过云函数进行微信支付相关推荐

  1. 微信小程序-使用云函数获取微信的openid

    1.新建云函数login_get_openid 云开发环境初始化参见:https://blog.csdn.net/yuxiao1121/article/details/125222407 新建云函数参 ...

  2. 微信小程序使用云函数进行mysql操作

    微信小程序使用云函数进行mysql操作 其他操纵数据库方式的一些问题 准备工作 云函数代码 调用云函数时候的代码 最后还需要注意的一些小事情: 其他操纵数据库方式的一些问题 现在使用小程序,对数据库的 ...

  3. uniapp实现微信小程序调用云函数及问题解决

    uniapp实现微信小程序调用云函数及问题解决 使用工具 HBuilder X 微信开发者工具 实现步骤 1.在项目根目录下创建functions文件夹(此为wxcloudfunctions文件夹,可 ...

  4. 微信小程序 调取云函数 信息推送失败response out of time limit or subscription is canceled hint的具体解决方法

    微信小程序 调云函数 信息推送失败,提示errcode":45015,"errmsg":"response out of time limit or subsc ...

  5. 微信小程序使用云开发实现微信支付功能 报错Error: 签名错误,史上最全解决办法,不服留言骂我

    报错背景 微信小程序使用云开发实现微信支付功能,但是报错了 报错信息 报错原因 小程序想要使用微信支付,必须满足下面几个条件的 1,必须是非个人小程序(个人小程序用不了支付) 企业小程序需要认证! 2 ...

  6. 【微信小程序】云函数使用excel-export导出excel

    1.安装nodejs环境 到官网下载安装包(node-v12.14.1-x64.msi),点击下一步一直安装到底 2.使用命令行模式进入小程序项目云函数文件夹,执行安装excel-export命令,安 ...

  7. 微信小程序 通过云函数请求http网站接口

    微信小程序正式版无法调用http类型的API接口,只有htttps类型才可以通过验证,可以利用云函数避免这一难点.下面我会给出一个小案例. 原文地址:www.920vip.net/article/70 ...

  8. 【微信小程序】云函数/云数据库 errMsg: parameter should be object instead of undefined

    以下内容仅作为学习记录,请大佬轻喷. 学习近义词反义词微信小程序课程,在尝试"add_words_correlation"云函数时,云函数本地调试在这个错误上卡了好久. 一开始没有 ...

  9. 微信小程序使用云函数发送邮件

    看完本文你将学到: 微信小程序云函数的部署与使用 nodemailer插件的使用 背景故事: hello,大家好这里是小曹同学.上个星期因为原来开发学校课程表的学长毕业了课程表小程序不能用了. 在受了 ...

最新文章

  1. 洛谷3384:【模板】树链剖分——题解
  2. 建造者模式java_java设计模式3——建造者模式
  3. 说时间不够用,CTO怒了!让我学习:GTD时间管理,番茄工作法,三八理论
  4. python函数式编程思想_以python为例,浅谈函数式编程思想
  5. flex和box、flexbox高度自适应常见坑
  6. jsp mysql在线考试系统源码_jsp+ssm+mysql实现的学生在线考试系统项目源码附带视频导入运行教程...
  7. python 如何将字符串列表合并后转换成字符串? ''.join(List(str))函数
  8. Hibernate之必须导入jar包
  9. 【华为敏捷/DevOps实践】6.架构师在新兴的DevOps组织应该扮演什么样的角色?
  10. c语言用栈实现计算器加法运算,请问,用c语言做一个计算器 包括+-*/()的运算 用栈 该怎么做...
  11. [CATARC_2017] 第八周
  12. 学 Win32 汇编[13]: 定义符号常量(=、EQU、TEXTEQU)
  13. 4.3 调度核心组件
  14. 手动抛出异常_超实用:关于Java异常设计和处理
  15. 【Codeforces Round #585 (Div. 2) E】Marbles【状压DP】
  16. 一键安装WinRAR主题界面美化
  17. itest听力答案2020_itest大学英语测试答案2019
  18. 1005打印任务取消不了 hp_(完整版)hp打印机无法取消打印的文档解决方法
  19. OpenGL第三方库:GLAD入门篇
  20. 常见蛋白质种类_生活中常见食物的营养学分类,以及不同食物的蛋白质含量

热门文章

  1. 疾风之刃服务器维护,疾风之刃
  2. amazon ses_Amazon Simple Email Service(SES)入门
  3. C#_web 项目实战第一步——装操作系统
  4. 怎么在IE11中运行VBScript
  5. linux系统怎么做快照,linux LVM快照创建步骤
  6. 什么情况下会导致内存泄露
  7. 网站运营手册_网站建设PC端开发
  8. 2012.2 今天是2012年4月12日星期四,编写程序,输入今天开始到12月31日之间的任意日期
  9. 信不信十分钟让你彻底搞懂java反射
  10. Hspice仿真验证