本文将介绍如何通过微搭应用编辑器搭建微信支付小程序。
注意:
通过模板中心下载的应用,因为微信支付-小程序 APIs 需要关联开发者自己小程序 appid、商户号、商户 API 证书序列号、商户 API 私钥和 API V3密钥,所以在搭建小程序时,需要将调用连接器的部分替换为开发者自身的连接器信息。
操作步骤
步骤1:创建小程序应用
1. 登录 微搭控制台,进入主页-创建应用页面,选择从空白创建。

2. 进入应用后将名称录入完成应用创建。


步骤2:搭建首页,发起支付
1. 进入首页 > 设置,配置页面样式,这里选择导航栏为白色,标题为黑色。
2. 首页内容展示商品信息,选择用文本、数据列表和 Tab 栏组件搭建主要内容。


3. 数据列表选择步骤1创建好的微信支付商品信息数据模型,配置好排序字段、方式、显示条数、分页等相关信息。


4. 数据列表内显示对应内容组件,单击选择绑定数据。


5. 接下来配置支付按钮,也是主要的功能展示,需要重点关注。
6. 支付功能最简化模拟生成订单、支付商品、更新订单状态整个流程。按照微信支付接口要求,需要执行以下操作:


6.1 生成订单,为发起支付做准备。
单击事件,调用微信支付模板订单数据数据源创建订单方法,创建一个新的订单信息,传入对应商品名称、价格、支付状态,尤其是支付状态,在不同支付流程阶段,需要根据状态变化进行更新操作。
注意:
支付状态字段为数字,1:表示未支付,2:表示已支付,3:表示退款中,4:表示已退款。


创建订单成功后,新建一个文本变量 orderId。


通过变量赋值的事件,将创建订单成功所返回值的数据唯一标识赋值给 orderId。


调用数据源方法,数据标识填入变量 orderId,查询订单信息。


查询成功回调,返回值赋值给提前设置好的全局变量,用于接下来发起支付时传输订单号。


6.2 发起支付。
注意:
6.2.1 创建方法时,通知回调有两种方式,一种是工作流创建,指通过工作流方式实现回调逻辑;另一种则是自有服务,可供放入微信支付工作流的回调 url,或者放入用户自定义回调逻辑的 url。当前微搭低代码暂时仅支持配置自有服务。这里选择云函数作自有服务。


6.2.2 接下来到同环境下的云开发 CloudBase,切换到云函数,单击新建云函数,命名为 wechatPayback。


6.2.3 创建完成后,在函数配置中编辑信息。


6.2.4 ApiV3:写入从微信支付侧获取到的 ApiV3 密钥。环境变量
collectionName
可以在 云开发平台 云数据库模块对应的数据模型基础信息中查看到对应的正式和预览数据表标识。
6.2.5 跳转到云开发管理页面后展开环境菜单,切换到访问服务模块。


6.2.6 单击新建,填下以下信息后确认。


6.2.7 在访问服务模块,可以查看到默认域名,复制该域名获取到统一下单的回调地址,完整路径为:默认域名/wechatPayback。


6.2.8 获取申请退款的回调 url 与统一下单的途径相同,命名为 wechatRefund。


订单和商品信息准备好后,接下来调用创建好的微信支付-小程序 APIs,JSAPI 下单,传入商品描述、商户订单号、支付总金额相关信息。


调用成功后,才能使用自定义方法,调用编辑器写好的发起支付命令,发起微信支付。(当支付失败或者未支付时,需将订单状态修改为未支付的状态)


export default function ({ event, data }) {wx.requestPayment({...event.detail,package: event.detail.packageVal,async success(res) { // 在这里处理支付接口回调成功的逻辑,支付成功与否在统一下单接口的回调云函数处处理console.log('pay success', res);},async fail(err) { // 在这里处理支付接口回调失败的逻辑console.error('pay fail', err)await $w.cloud.callDataSource({dataSourceName: '',methodName: 'wedaUpdate',params: {_id: $page.dataset.state.orderId,zfzt: 1}});app.showToast({title: "支付失败",icon: "error",duration: 2000})},});}
应用调用如下图:


6.3 根据支付结果更新订单状态。特别强调: 微信支付成功和失败结果,并不会在发起支付后直接返回支付结果,而是通过在微信支付-小程序接口的统一下单回调函数中,异步通知支付结果,所以对订单支付结果的更新需要在上文创建的 wechatPayback 云函数中操作。
进入函数代码配置。


代码如下:
'use strict';const crypto = require('crypto')const cloudbase = require("@cloudbase/node-sdk");const app = cloudbase.init({env: cloudbase.SYMBOL_CURRENT_ENV});const db = app.database();exports.main = async (event, context) => {try {const JsonEnvironment = JSON.parse(context.environment);const collectionName = JsonEnvironment.collectionName;const ApiV3 = JsonEnvironment.ApiV3;// 解密获取订单详情信息const backBody = JSON.parse(event.body);let encrypted = Buffer.from(backBody.resource.ciphertext, 'base64');let decipher = crypto.createDecipheriv('AES-256-GCM', ApiV3, backBody.resource.nonce);decipher.setAuthTag(encrypted.slice(-16));decipher.setAAD(Buffer.from(backBody.resource.associated_data));let res = Buffer.concat([decipher.update(encrypted.slice(0, -16)),decipher.final()]);const JsonRes = JSON.parse(res.toString());if (Object.keys(JsonRes).length !== 0) {// 当交易状态为支付成功时,修改订单状态为2if (JsonRes.trade_state === 'SUCCESS') {const updateRes = await db.collection(collectionName).where({ ddh: JsonRes.out_trade_no }).update({ transaction_id: JsonRes.transaction_id, zfzt: 2 });} else {return {code: -2,msg: "未完成付款"}}} else {return {code: -3,msg: '获取数据失败'}}return JsonRes;} catch (err) {console.error('decrypted Err', err)return {code: -1,msg: err}}};
步骤3:搭建订单管理页,支持退款
流程2已完成发起支付和生成订单的完整流程,接下来针对不同订单状态来模拟订单流转,完成发起退款操作。
注意:
订单页内容显示全部订单、已支付订单、未支付订单、已退款订单,该页面主要演示退款功能,所以未根据订单所属人进行数据记录和筛选,实际应用中开发者可以根据用户 openid 或手机号等用户唯一标识做数据存储和筛选。
订单页选择用选项卡和 Tab 栏进行搭建,选项卡内放入数据列表,数据列表选择步骤1创建好的微信支付模板订单数据模型,根据不同选项,配置好数据筛选条件、排序字段、方式、显示条数、分页等相关信息,如已支付页面,数据以支付状态等于2来筛选,其余页面逻辑类似。


接下来重点介绍下发起退款流程,主要包括发起退款、更新订单状态、退款通知、查询退款结果、再次更新订单状态。
按照微信退款接口要求,退款需要执行以下操作:


1. 已支付订单,显示申请退款按钮。
注意:
支付状态字段为数字,1:表示未支付,2:表示已支付,3:表示退款中,4:表示已退款。
申请退款按钮的显示条件为:支付状态字段等于2时,显示退款按钮。


2. 单击申请退款。
首先打开弹窗,由用户确认是否发起退款。


弹窗确认状态根据 confirm 字段判断,若为 true,则确定退款;若为 false,则取消退款,用逻辑分支绑定表达式为
If(event.detail?.confirm === true, true, false)
。

确认发起退款后,调用 APIs 微信支付模板功能申请退款方法。


3. 根据退款结果更新订单状态。
申请退款接口调用成功的回调,更新支付状态为3退款中。


4. 最后对数据列表进行刷新,及时更新订单状态。


注意:
退款成功和失败结果,并不会在发起退款后直接返回结果,而是通过在微信支付-小程序接口的申请退款回调函数中,异步通知退款结果,所以对订单支付结果的更新需要在上文创建的 wechatRefund 云函数中操作。
进入函数代码配置。


申请退款函数中,接收到退款通知后,根据返回的退款值,更新订单状态,失败更新为2已支付,退款成功更新为4已退款。
代码如下:
'use strict';const crypto = require('crypto')const cloudbase = require("@cloudbase/node-sdk");const app = cloudbase.init({env: cloudbase.SYMBOL_CURRENT_ENV});const db = app.database();exports.main = async (event, context) => {try {const JsonEnvironment = JSON.parse(context.environment);const collectionName = JsonEnvironment.collectionName;const ApiV3 = JsonEnvironment.ApiV3;// 解密获取订单详情信息const backBody = JSON.parse(event.body);let encrypted = Buffer.from(backBody.resource.ciphertext, 'base64');let decipher = crypto.createDecipheriv('AES-256-GCM', ApiV3, backBody.resource.nonce);decipher.setAuthTag(encrypted.slice(-16));decipher.setAAD(Buffer.from(backBody.resource.associated_data));let res = Buffer.concat([decipher.update(encrypted.slice(0, -16)),decipher.final()]);const JsonRes = JSON.parse(res.toString());if (Object.keys(JsonRes).length !== 0) {// 当退款状态为退款成功时,更新订单状态为4if (JsonRes.refund_status === 'SUCCESS') {const updateRes = await db.collection(collectionName).where({ ddh: JsonRes.out_refund_no }).update({ zfzt: 4 });} else {return {code: -2,msg: "未完成退款"}}} else {return {code: -3,msg: '获取数据失败'}}return JsonRes;} catch (err) {console.error('decrypted Err', err)return {code: -1,msg: err}}};
5. 调试样式,发布应用。
选择发布小程序,如果测试验证可以通过体验版进行发布。
发布小程序。


至此,已模拟完成一个简单的商品售卖支付和退款完整流程,实际应用搭建时,您可以根据自己的业务特性,灵活调整各功能模块流程。