# 工作流实现微信支付付款、接收事件回调

开发者可使用云开发工作流能力,快速对接微信支付下单、接收支付回调的接口,完成微信支付的对接开发。

# 流程概览

本文档中我们将会实现下图中的步骤,实现最简单的微信支付直连模式的支付流程:

# 第 1 步:部署微信支付下单模板,完成初始配置,并发布工作流

打开云开发控制台-「云函数」 - 新建 - 工作流,选择工作流「使用微信支付API发起支付」模板,并安装模板。

# 第 2 步:完成「JSAPI下单」工作流的配置

模板部署完成后,进入工作流编辑器内完成配置。

在微信支付下单节点内,完成 API 的配置。

方法选择:JSAPI下单

注意 更新 APIs 或方法后,入参需要重新配置为如下:

({
    ...manualTrigger.output,
    payer: {
      openid: $env.WX_OPENID || manualTrigger.output?.payer?.openid  //利用前端调用时带入的openid,或者云函数调用时传递的openid参数
    }
}) 

另外,首次使用的用户如果没有可用的微信支付 API 实例,可以新建凭证+API 实例。

支付通知回调的配置,可以配置成另一个工作流,或者已有 HTTP 服务的 URL:

# 第 3 步:完成「支付成功回调」工作流的配置

如果在第 2 步中,把支付通知回调配置为了另一条工作流,那么我们同样需要完成「支付成功回调」工作流的配置工作。

例如,我们可以使用自定义代码的节点,在支付回调中,修改云数据库内的订单状态:

const cloudbase = require("@cloudbase/node-sdk");

cloud.init({
  env: "<环境ID>",
});

const db = cloud.database();

// 示例:向 orders 集合中插入一条记录
const result = await db.collection("orders").add(wxpayTrigger.output.resource);

# 第 4 步:完成客户端代码

工作流配置完成后,接下来我们通过小程序来调用工作流,完成全套场景。

在小程序中,通过调用工作流,获取预付单信息,使用 wx.requestPayment 调起客户端支付控件:

其中,调用工作流使用了 callFunction 的方法,在其中有 FlowID参数,此参数可以通过在云函数列表点击选择已创建的工作流,获取工作流的ID并填写在代码中。

获取到流程ID后,在小程序中通过如下代码调用工作流,获取到工作流返回,并通过返回参数调用 wx.requestPayment 拉起客户端支付控件。

// 1. 小程序端调用
wx.cloud.callFunction({
  name: 'cloudbase_module',
  data: {
    // 工作流ID, 需从工作流属性中获取
    name: 'xxxxxxx',
    data: {
      /**
       * 注:appid 和 mchid 工作流已自动注入,无需传递
       * 本示例只传递了必要的参数,其他详细参数可参考微信支付文档:
       * https://pay.weixin.qq.com/docs/merchant/apis/mini-program-payment/mini-prepay.html
       */
      description: "商品描述",
      // 商户订单号,业务自行生成,此处仅为示例
      out_trade_no: Math.round(Math.random() * (10 ** 13)) + Date.now(),
      amount: {
        total: 1,
        currency: "CNY"
      }
    }
  },
  success: res => {
    console.log('下单结果: ', res);
    // 获取到预付单信息
    const paymentData = res.result?.data;
    // 唤起微信支付组件,完成支付
    wx.requestPayment({
      timeStamp: paymentData?.timeStamp,
      nonceStr: paymentData?.nonceStr,
      package: paymentData?.packageVal,
      paySign: paymentData?.paySign,
      signType: "RSA", // 该参数为固定值
      success(res) {
        // 支付成功回调,实现自定义的业务逻辑
        console.log('唤起支付组件成功:', res);
      },
      fail(err) {
        // 支付失败回调
        console.error('唤起支付组件失败:', err);
      }
    });
  },

另外,也可以通过云函数发起调用,通过小程序调用云函数、云函数调用工作流的方式,完成预付单的生成,然后再在小程序端唤起微信支付组件来进行支付。

如果需要从云函数中发起调用,可以参考如下代码:

// 2. 云函数中(服务端)调用

/**
 * 微信支付 - 下单
 */
const cloud = require('wx-server-sdk');
cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext();
  const res = await cloud.callFunction({
    // 固定参数
    name: 'cloudbase_module',
    data: {
      // 工作流ID, 需从工作流属性中获取
      name: 'xxxxxx',
      data: {
        /**
         * 注:appid 和 mchid 工作流已自动注入,无需传递
         * 本示例只传递了必要的参数,其他详细参数可参考微信支付文档:
         * https://pay.weixin.qq.com/docs/merchant/apis/mini-program-payment/mini-prepay.html
         */
        description: '商品描述',
        amount: {
          total: 1, // 订单金额
          currency: 'CNY',
        },
        // 商户订单号,业务自行生成,此处仅为示例
        out_trade_no: Math.round(Math.random() * 10 ** 13) + Date.now(),
        payer: {
          // 服务端调用需要手动传入payer.openid参数,可从云开发上下文中直接获取
          openid: wxContext.OPENID,
        },
      },
    },
  });
  return res.result;
};


// 云函数中调用下单工作流获取预付订单后,小程序中再调用云函数,完成支付流程

wx.cloud.callFunction({
  // 云函数名称
  name: 'xxxxx',
  success: (res) => {
    // 获取到预付订单信息
    const paymentData = res.result?.data;
    // 唤起微信支付组件,完成支付
    wx.requestPayment({
      timeStamp: paymentData?.timeStamp,
      nonceStr: paymentData?.nonceStr,
      package: paymentData?.packageVal,
      paySign: paymentData?.paySign,
      signType: 'RSA', // 该参数为固定值
      success(res) {
        // 支付成功回调,实现自定义的业务逻辑
        console.log('唤起支付组件成功:', res);
      },
      fail(err) {
        // 支付失败回调
        console.error('唤起支付组件失败:', err);
      },
    });
  },
});

可见,全程只有少量代码,即可完成生成预付单、完成付款、接收微信支付回调三大块逻辑,非常方便快捷。