纵有疾风起
人生不言弃

借助小程序云开发实现小程序支付功能(含源码)

我们在做小程序支付相关的开发时,总会遇到这些难题。小程序调用微信支付时,必须要有自己的服务器,有自己的备案域名,有自己的后台开发。这就导致我们做小程序支付时的成本很大。本节就来教大家如何使用小程序云开发实现小程序支付功能的开发。不用搭建自己的服务器,不用有自己的备案域名。只需要简简单单的使用小程序云开发。

老规矩先看效果图:

借助小程序云开发实现小程序支付功能(含源码)插图

本节知识点

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

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

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

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

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

一,准备工作

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

借助小程序云开发实现小程序支付功能(含源码)插图(1)

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

借助小程序云开发实现小程序支付功能(含源码)插图(2)

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

借助小程序云开发实现小程序支付功能(含源码)插图(3)

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

3,微信开发者 IDE https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
4,开通小程序云开发功能:https://edu.csdn.net/course/play/9604/204526

二,商品列表的实现

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

借助小程序云开发实现小程序支付功能(含源码)插图(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>

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

借助小程序云开发实现小程序支付功能(含源码)插图(5)

三,支付云函数的创建

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

借助小程序云开发实现小程序支付功能(含源码)插图(6)

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

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

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

借助小程序云开发实现小程序支付功能(含源码)插图(7)

2,配置入口云函数

借助小程序云开发实现小程序支付功能(含源码)插图(8)

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

const cloud = require('wx-server-sdk')cloud.init()const app = require('tcb-admin-node');const pay = require('./lib/pay');const { mpAppId, KEY} = require('./config/index');const { WXPayConstants, WXPayUtil} = require('wx-js-utils');const Res = require('./lib/res');const ip = require('ip');/** * * @param {obj} event * @param {string} event.type 功能类型 * @param {} userInfo.openId 用户的openid */exports.main = async function(event, context) { const {  type,  data,  userInfo } = event; const wxContext = cloud.getWXContext() const openid = userInfo.openId;  app.init(); const db = app.database(); const goodCollection = db.collection('goods'); const orderCollection = db.collection('order'); // 订单文档的status 0 未支付 1 已支付 2 已关闭 switch (type) {  // [在此处放置 unifiedorder 的相关代码]  case 'unifiedorder':   {    // 查询该商品 ID 是否存在于数据库中,并将数据提取出来    const goodId = data.goodId    let goods = await goodCollection.doc(goodId).get();    if (!goods.data.length) {     return new Res({      code: 1,      message: '找不到商品'     });    }    // 在云函数中提取数据,包括名称、价格才更合理安全,    // 因为从端里传过来的商品数据都是不可靠的    let good = goods.data[0];    // 拼凑微信支付统一下单的参数    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 可以先随便填。    const notify_url = 'http://www.qq.com'; //'127.0.0.1';    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 = {     body,     spbill_create_ip,     notify_url,     out_trade_no,     total_fee,     openid,     trade_type: 'JSAPI',     timeStamp: time_stamp,    };    // 调用 wx-js-utils 中的统一下单方法    const {     return_code,     ...restData    } = await pay.unifiedOrder(orderParam);    let order_id = null;    if (return_code === 'SUCCESS' && restData.result_code === 'SUCCESS') {     const {      prepay_id,      nonce_str     } = restData;     // 微信小程序支付要单独进地签名,并返回给小程序端     const sign = WXPayUtil.generateSignature({      appId: mpAppId,      nonceStr: nonce_str,      package: `prepay_id=${prepay_id}`,      signType: 'MD5',      timeStamp: time_stamp     }, KEY);     let orderData = {      out_trade_no,      time_stamp,      nonce_str,      sign,      sign_type,      body,      total_fee,      prepay_id,      sign,      status: 0, // 订单文档的status 0 未支付 1 已支付 2 已关闭      _openid: openid,     };     let order = await orderCollection.add(orderData);     order_id = order.id;    }    return new Res({     code: return_code === 'SUCCESS' ? 0 : 1,     data: {      out_trade_no,      time_stamp,      order_id,      ...restData     }    });   }   // [在此处放置 payorder 的相关代码]  case 'payorder':   {    // 从端里出来相关的订单相信    const {     out_trade_no,     prepay_id,     body,     total_fee    } = data;    // 到微信支付侧查询是否存在该订单,并查询订单状态,看看是否已经支付成功了。    const {     return_code,     ...restData    } = await pay.orderQuery({     out_trade_no    });    // 若订单存在并支付成功,则开始处理支付    if (restData.trade_state === 'SUCCESS') {     let result = await orderCollection      .where({       out_trade_no      })      .update({       status: 1,       trade_state: restData.trade_state,       trade_state_desc: restData.trade_state_desc      });     let curDate = new Date();     let time = `${curDate.getFullYear()}-${curDate.getMonth() +          1}-${curDate.getDate()} ${curDate.getHours()}:${curDate.getMinutes()}:${curDate.getSeconds()}`;       }    return new Res({     code: return_code === 'SUCCESS' ? 0 : 1,     data: restData    });   }  case 'orderquery':   {    const {     transaction_id,     out_trade_no    } = data;    // 查询订单    const {     data: dbData    } = await orderCollection    .where({     out_trade_no    })    .get();    const {     return_code,     ...restData    } = await pay.orderQuery({     transaction_id,     out_trade_no    });    return new Res({     code: return_code === 'SUCCESS' ? 0 : 1,     data: { ...restData,      ...dbData[0]     }    });   }  case 'closeorder':   {    // 关闭订单    const {     out_trade_no    } = data;    const {     return_code,     ...restData    } = await pay.closeOrder({     out_trade_no    });    if (return_code === 'SUCCESS' &&     restData.result_code === 'SUCCESS') {     await orderCollection      .where({       out_trade_no      })      .update({       status: 2,       trade_state: 'CLOSED',       trade_state_desc: '订单已关闭'      });    }    return new Res({     code: return_code === 'SUCCESS' ? 0 : 1,     data: restData    });   } }}

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

借助小程序云开发实现小程序支付功能(含源码)插图(9)

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

借助小程序云开发实现小程序支付功能(含源码)插图(10)

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

由于源码里涉及到一些私密信息,这里就不单独贴出源码下载链接了,大家感兴趣的话,可以私信我,或者在底部留言。单独找我要源码也行(微信2501902696)

视频讲解地址:https://edu.csdn.net/course/detail/24770

文章转载于:https://www.jianshu.com/p/ddccf5f95e8c

原著是一个有趣的人,若有侵权,请通知删除

未经允许不得转载:起风网 » 借助小程序云开发实现小程序支付功能(含源码)

分享到: 生成海报
avatar

评论 抢沙发

评论前必须登录!

立即登录   注册

切换注册

登录

忘记密码 ?

切换登录

注册

我们将发送一封验证邮件至你的邮箱, 请正确填写以完成账号注册和激活