经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » 微信小程序 » 查看文章
怎么借助小程序云开发实现小程序支付功能
来源:cnblogs  作者:腾讯云开发TCB  时间:2019/7/9 9:24:27  对本文有异议

我们在做小程序支付相关的开发时,总会遇到这些难题——

1.小程序调用微信支付时必须要有自己的服务器

2.有自己的备案域名

3.有自己的后台开发

这就导致我们做小程序支付时的成本很大

本节就来教大家如何使用小程序云开发实现小程序支付功能的开发——不用搭建自己的服务器,不用有自己的备案域名,只需要简简单单的使用小程序云开发

老规矩先看效果图:

本节知识点

1.云开发的部署和使用
2.支付相关的云函数开发
3.商品列表
4.订单列表
5.微信支付与支付成功回调

支付成功给用户发送推送消息的功能会在后面讲解

下面就来教大家如何借助云开发使用小程序支付功能

支付所需要用到的配置信息

1.小程序appid
2.云开发环境id
3.微信商户号
4.商户密匙

一、准备工作

1.已经申请小程序,获取小程序 AppID 和 Secret 在小程序管理后台中【设置】 →【开发设置】 可以获取微信小程序 AppID 和 Secret

 

2.微信支付商户号,获取商户号和商户密钥在微信支付商户管理平台中【账户中心】→【商户信息】 可以获取微信支付商户号

 

在【账户中心】 ?> 【API安全】 可以设置商户密钥

这里特殊说明——个人小程序是没有办法使用微信支付的,所以如果想使用微信支付功能必须是非个人账号(当然个人可以办个体户工商执照来注册非个人小程序账号)

 

3、微信开发者 IDE

 

4、开通小程序云开发功能

 

二、商品列表的展现

效果图如下

由于本节重点是支付的实现,所以这里只简单贴出关键代码

 

wxml布局如下:

<view class="container">
<view class="good-item" wx:for="{{goods}}" wx:key="*this" ontap="getDetail" data-goodid="{{item._id}}">
<view class="good-image">
<image src="{{pic}}"></image>
</view>
<view class="good-detail">
<view class="title">商品: {{item.name}}</view>
<view class="content">价格: {{item.price / 100}} 元 </view>
<button
class="button"
type="primary"
bindtap="makeOrder"
data-goodid="{{item._id}}"
>下单</button>
</view>
</view></view>


  1. 我们所需要做的就是借助云开发获取云数据库里的商品信息然后展示到商品列表,关于云开发获取商品列表并展示本节不做讲解(感兴趣的同学可以翻看作者历史博客,有写过)

三、支付云函数的创建

首先看下我们支付云函数都包含那些内容

 

简单先讲解下每个的用处
config下的index.js是做支付配置用的,主要配置支付相关的账号信息
lib是用的第三方的支付库,这里不做讲解
重点讲解的是云函数入口 index.js

下面就来教大家如何去配置

1.配置config下的index.js,
这一步所需要做的就是把小程序appid、云开发环境ID、商户id、商户密匙填进去

 

2.配置入口云函数

 

详细代码如下,代码里注释很清楚了这里不再做单独讲解

  1. const cloud = require('wx-server-sdk')
  2. cloud.init()const app = require('tcb-admin-node');const pay = require('./lib/pay');const {
  3. mpAppId,
  4. KEY
  5. } = require('./config/index');const {
  6. WXPayConstants,
  7. WXPayUtil
  8. } = require('wx-js-utils');const Res = require('./lib/res');const ip = require('ip');/**
  9. *
  10. * @param {obj} event
  11. * @param {string} event.type 功能类型
  12. * @param {} userInfo.openId 用户的openid
  13. */exports.main = async function(event, context) { const {
  14. type,
  15. data,
  16. userInfo
  17. } = event; const wxContext = cloud.getWXContext() const openid = userInfo.openId;
  18. app.init(); const db = app.database(); const goodCollection = db.collection('goods'); const orderCollection = db.collection('order'); // 订单文档的status 0 未支付 1 已支付 2 已关闭
  19. switch (type) { // [在此处放置 unifiedorder 的相关代码]
  20. case 'unifiedorder':
  21. { // 查询该商品 ID 是否存在于数据库中,并将数据提取出来
  22. const goodId = data.goodId let goods = await goodCollection.doc(goodId).get(); if (!goods.data.length) { return new Res({ code: 1, message: '找不到商品'
  23. });
  24. } // 在云函数中提取数据,包括名称、价格才更合理安全,
  25. // 因为从端里传过来的商品数据都是不可靠的
  26. let good = goods.data[0]; // 拼凑微信支付统一下单的参数
  27. const curTime = Date.now(); const tradeNo = `${goodId}-${curTime}`; const body = good.name; const spbill_create_ip = ip.address() || '127.0.0.1'; // 云函数暂不支付 http 触发器,因此这里回调 notify_url 可以先随便填。
  28. const notify_url = 'http://www.qq.com'; //'127.0.0.1';
  29. const total_fee = good.price; const time_stamp = '' + Math.ceil(Date.now() / 1000); const out_trade_no = `${tradeNo}`; const sign_type = WXPayConstants.SIGN_TYPE_MD5; let orderParam = {
  30. body,
  31. spbill_create_ip,
  32. notify_url,
  33. out_trade_no,
  34. total_fee,
  35. openid, trade_type: 'JSAPI', timeStamp: time_stamp,
  36. }; // 调用 wx-js-utils 中的统一下单方法
  37. const {
  38. return_code,
  39. ...restData
  40. } = await pay.unifiedOrder(orderParam); let order_id = null; if (return_code === 'SUCCESS' && restData.result_code === 'SUCCESS') { const {
  41. prepay_id,
  42. nonce_str
  43. } = restData; // 微信小程序支付要单独进地签名,并返回给小程序端
  44. const sign = WXPayUtil.generateSignature({ appId: mpAppId, nonceStr: nonce_str, package: `prepay_id=${prepay_id}`, signType: 'MD5', timeStamp: time_stamp
  45. }, KEY); let orderData = {
  46. out_trade_no,
  47. time_stamp,
  48. nonce_str,
  49. sign,
  50. sign_type,
  51. body,
  52. total_fee,
  53. prepay_id,
  54. sign, status: 0, // 订单文档的status 0 未支付 1 已支付 2 已关闭
  55. _openid: openid,
  56. }; let order = await orderCollection.add(orderData);
  57. order_id = order.id;
  58. } return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: {
  59. out_trade_no,
  60. time_stamp,
  61. order_id,
  62. ...restData
  63. }
  64. });
  65. } // [在此处放置 payorder 的相关代码]
  66. case 'payorder':
  67. { // 从端里出来相关的订单相信
  68. const {
  69. out_trade_no,
  70. prepay_id,
  71. body,
  72. total_fee
  73. } = data; // 到微信支付侧查询是否存在该订单,并查询订单状态,看看是否已经支付成功了。
  74. const {
  75. return_code,
  76. ...restData
  77. } = await pay.orderQuery({
  78. out_trade_no
  79. }); // 若订单存在并支付成功,则开始处理支付
  80. if (restData.trade_state === 'SUCCESS') { let result = await orderCollection
  81. .where({
  82. out_trade_no
  83. })
  84. .update({ status: 1, trade_state: restData.trade_state, trade_state_desc: restData.trade_state_desc
  85. }); let curDate = new Date(); let time = `${curDate.getFullYear()}-${curDate.getMonth() + 1}-${curDate.getDate()} ${curDate.getHours()}:${curDate.getMinutes()}:${curDate.getSeconds()}`;
  86. } return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: restData
  87. });
  88. } case 'orderquery':
  89. { const {
  90. transaction_id,
  91. out_trade_no
  92. } = data; // 查询订单
  93. const { data: dbData
  94. } = await orderCollection
  95. .where({
  96. out_trade_no
  97. })
  98. .get(); const {
  99. return_code,
  100. ...restData
  101. } = await pay.orderQuery({
  102. transaction_id,
  103. out_trade_no
  104. }); return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: { ...restData,
  105. ...dbData[0]
  106. }
  107. });
  108. } case 'closeorder':
  109. { // 关闭订单
  110. const {
  111. out_trade_no
  112. } = data; const {
  113. return_code,
  114. ...restData
  115. } = await pay.closeOrder({
  116. out_trade_no
  117. }); if (return_code === 'SUCCESS' &&
  118. restData.result_code === 'SUCCESS') { await orderCollection
  119. .where({
  120. out_trade_no
  121. })
  122. .update({ status: 2, trade_state: 'CLOSED', trade_state_desc: '订单已关闭'
  123. });
  124. } return new Res({ code: return_code === 'SUCCESS' ? 0 : 1, data: restData
  125. });
  126. }
  127. }
  128. }

 其实我们支付的关键功能都在上面这些代码里面了

再来看下支付的相关流程截图

 

上图就涉及到了我们的订单列表、支付状态、支付成功后的回调
今天就先讲到这里,后面会继续给大家讲解支付的其他功能——比如支付成功后的消息推送也是可以借助云开发实现的。

由于源码里涉及到一些私密信息这里就不单独贴出源码下载链接了,大家感兴趣的话可以留言或添加作者微信(微信2501902696)获取源码

原文链接:http://www.cnblogs.com/CloudBase/p/11133438.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号