微信小程序> 微信小程序通过云函数进行微信支付-微信小程序实现微信支付功能-微信小程序支付代码

微信小程序通过云函数进行微信支付-微信小程序实现微信支付功能-微信小程序支付代码

浏览量:1532 时间: 来源:gf771115
1.

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

2.

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

3.

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

我简化的流程:本地发起下单请求调用云函数并传送数据云函数处理数据并返回5个参数本地接受5个参数,发起支付请求交易结束4.

主要代码:

//第一步,本地发起下单请求并传送数据。这一步,在你的wxml中的某个元素//中绑定事件buttonbindtap'pay'/button。通过这个pay函数,//触发云函数并传递一些数据pay:function(){//需要上传给云函数的数据letuploadData{//此次需要支付的金额,单位是分。例如¥1.80180"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{//支付失败}})}复制代码以上就是本地端的全部代码,接下来我们只需要搞定云函数的代码就完成全部的工作了。云函数的内容是:调用小程序登陆API-Openid生成商户订单调用统一下单API-prepay_id将组合数据再次签名,返回5个参数5.

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

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

##每一步的详细做法

1.调用小程序登陆API-Openid7.

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

8.

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

//获取云实例constcloudrequire('wx-server-sdk')//云初始化cloud.init()//获取微信调用上下文信息,其中包括Openid,Appid等constwxContextcloud.getWXContext()//获取用户openidconstopenidwxContext.OPENID复制代码到这里我们已经达成我们第一步的目的了。2.生成商户订单9.

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

10.

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

11.

appid(小程序ID)

12.

openid(用户OPENID)

13.

mch_id(商户号)

14.

nonce_str(随机字符串)

15.

body(商品描述)

16.

out_trade_no(商户订单号)

17.

total_fee(标价金额)

18.

spbill_create_ip(终端IP)

19.

notify_url(通知地址)

20.

trade_type(交易类型)

21.

key(密钥)

22.

sign(签名)

23.

我们一个一个解决。

24.

1.appid

25.

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

26.

示例值wxd678efh567hg6787

27.

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

constappid'wxwxd678efh567hg6787'复制代码28.

2.openid

29.

第一步已经获得。

30.

示例值oUpF8uMuAJO_M2pxb1Q9zNjWeS6o

31.

3.mch_id

32.

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

33.

示例值1230000109

34.

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

constmch_id'1230000109'复制代码35.

4.nonce_str

36.

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

37.

示例值5K8264ILTKCH16CQ2502SI8ZNMTM67VS

38.

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

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

其中random.js的内容为:

functionrandom(){varresult''constwordList['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(leti0;i31;i++){result+wordList[Math.round(Math.random()*36)]}returnresult}module.exportsrandom()复制代码40.

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

constrandomrequire("random.js")复制代码41.

5.body

42.

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

43.

示例值腾讯-游戏

44.

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

constbody"腾讯-游戏"复制代码45.

6.out_trade_no

46.

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

47.

示例值20150806125346

48.

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

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

7.total_fee

50.

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

51.

示例值88

52.

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

53.

8.spbill_create_ip

54.

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

55.

示例值123.12.12.123

56.

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

57.

9.notify_url

58.

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

59.

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

60.

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

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

10.trade_type

62.

小程序的trade_type为JSAPI。

63.

示例值JSAPI

64.

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

consttrade_type'JSAPI'复制代码65.

11.key

66.

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

67.

示例值1a79a4d60de6718e8e5b326e338ae533

68.

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

constkey'1a79a4d60de6718e8e5b326e338ae533'复制代码69.

12.sign

70.

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

71.

字符串示例值:

appidwxd678efh567hg6787body微信-游戏mch_id1230000109nonce_str5K8264ILTKCH16CQ2502SI8ZNMTM67VSnotify_urlhttp://www.weixin.qq.com/wxpay/pay.phpopenidoUpF8uMuAJO_M2pxb1Q9zNjWeS6oout_trade_no20150806125346spbill_create_ip123.12.12.123total_fee88trade_typeJSAPIkey1a79a4d60de6718e8e5b326e338ae533复制代码72.

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

73.

MD5码示例值C380BEC2BFD727A4B6845133519F3AD6

74.

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

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

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

//云函数入口文件constcloudrequire('wx-server-sdk')cloud.init()constopenidcloud.getWXContext().OPENIDconstappid'wxwxd678efh567hg6787'constmch_id'1230000109'constrandomrequire('random.js')constbody"腾讯-游戏"constnotify_url'http://www.weixin.qq.com/wxpay/pay.php'consttrade_type'JSAPI'constkey'1a79a4d60de6718e8e5b326e338ae533'//云函数入口函数exports.mainasync(event,content){constout_trade_noDate.parse(newDate()).toString()}复制代码76.

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

consttotal_feeevent.total_feeconstspbill_create_ipevent.spbill_create_ip复制代码77.

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

letstringA`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}key1a79a4d60de6718e8e5b326e338ae533`复制代码78.

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

npminstall--savecrypto复制代码79.

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

constcryptorequire("crypto")复制代码80.

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

varsigncrypto.createHash('md5').update(stringA).digest('hex').toUpperCase()复制代码以上除key的11个信息就是我们调用统一下单API所需要的全部数据了81.

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

xmlappidwxd930ea5d5a258f4f/appidmch_id10000100/mch_iddevice_info1000/device_infobodytest/bodynonce_stribuaiVcKdpRxkhJA/nonce_strsign9A0A8659F005D6984697E2CA0A9CF3B7/sign.../xml复制代码82.

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

functionrequestData(appid,mch_id,nonce_str,sign,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid){letdata"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"returndata}module.exportsrequestData复制代码83.

此时云函数的结构为

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

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

constrequestDatarequire("requestData.js")复制代码85.

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

letdataBodyreqData(appid,mch_id,random,sign,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid)复制代码到这里我们已经达成我们第二部的目的了。3.调用统一下单API-prepay_id86.

官方文档

87.

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

npminstall--saverequestnpminstall--savexmlreader复制代码88.

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

constrequestrequire("request")constxmlreaderrequire("xmlreader")复制代码89.

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

returnnewPromise(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{//此时我们已经完成第三步的目的了letprepay_idres.xml.prepay_id.text()}}}复制代码第三步目的完成4.将组合数据再次签名,返回5个参数90.

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

timeStampnonceStrpackagesignTypepaySign91.

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

paySignMD5(appIdwxd678efh567hg6787nonceStr5K8264ILTKCH16CQ2502SI8ZNMTM67VSpackageprepay_idwx2017033010242291fcfe0db70013231072signTypeMD5timeStamp1490840662keyqazwsxedcrfvtgbyhnujmikolp111111)22D9B4E54AB1950F51E0649E8810ACD6复制代码92.

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

returnnewPromise(reslove{request({url:'https://api.mch.weixin.qq.com/pay/unifiedorder',method:"POST",body:dataBody},body{xmlreader.read(body,res{letprepay_idres.xml.prepay_id.text()lettimeStampDate.parse(newDate()).toString()letstr`appId${appid}nonceStr${random}packageprepay_id${prepay_id}signTypeMD5timeStamp${timeStamp}key1a79a4d60de6718e8e5b326e338ae533`letpaySigncrypto.createHash('md5').update(str).digest('hex')//返回上面的五个参数reslove({data:{timeStamp:timeStamp,nonceStr:random,package:`prepay_id${prepay_id}`,signType:'MD5',paySign:paySign}})}}}复制代码至此,微信小程序支付流程结束。93.

此时云函数结构为:

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

index.js:

//云函数入口文件constcloudrequire('wx-server-sdk')cloud.init()constopenidcloud.getWXContext().OPENIDconstappid'wxwxd678efh567hg6787'constmch_id'1230000109'constrandomrequire('random.js')constbody"腾讯-游戏"constnotify_url'http://www.weixin.qq.com/wxpay/pay.php'consttrade_type'JSAPI'constkey'1a79a4d60de6718e8e5b326e338ae533'constcryptorequire("crypto")constrequestDatarequire("requestData")constrequestrequire("request")constxmlreaderrequire("xmlreader")//云函数入口函数exports.mainasync(event,content){constout_trade_noDate.parse(newDate()).toString()consttotal_feeevent.total_feeconstspbill_create_ipevent.spbill_create_ipletstringA`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}key1a79a4d60de6718e8e5b326e338ae533`varsigncrypto.createHash('md5').update(stringA).digest('hex').toUpperCase()letdataBodyreqData(appid,mch_id,random,sign,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid)returnnewPromise(reslove{request({url:'https://api.mch.weixin.qq.com/pay/unifiedorder',method:"POST",body:dataBody},body{xmlreader.read(body,res{letprepay_idres.xml.prepay_id.text()lettimeStampDate.parse(newDate()).toString()letstr`appId${appid}nonceStr${random}packageprepay_id${prepay_id}signTypeMD5timeStamp${timeStamp}key1a79a4d60de6718e8e5b326e338ae533`letpaySigncrypto.createHash('md5').update(str).digest('hex')//返回上面的五个参数reslove({data:{timeStamp:timeStamp,nonceStr:random,package:`prepay_id${prepay_id}`,signType:'MD5',paySign:paySign}})}}}复制代码95.

random.js:

functionrandom(){varresult''constwordList['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(leti0;i31;i++){result+wordList[Math.round(Math.random()*36)]}returnresult}module.exportsrandom()复制代码96.

requestData.js:

functionrequestData(appid,mch_id,nonce_str,sign,body,out_trade_no,total_fee,spbill_create_ip,notify_url,trade_type,openid){letdata"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"returndata}module.exportsrequestData复制代码

版权声明

即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。

  • 头条
  • 搜狐
  • 微博
  • 百家
  • 一点资讯
  • 知乎