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

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

## 流程概览

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

![](https://qcloudimg.tencent-cloud.cn/raw/20e02b05fb965834d5d83ac536366f88.png)

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

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

![](https://qcloudimg.tencent-cloud.cn/raw/f5569866e90da20d33ca97cc81d5ccdf.png)

![](https://qcloudimg.tencent-cloud.cn/raw/52d82923a2c47b362b27be142b2d6abc.png)

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

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

在微信支付下单节点内，完成 API 的配置。
![](https://qcloudimg.tencent-cloud.cn/raw/22fd68a71dab637525bf3d84fa9c14d0.png)

方法选择：JSAPI 下单

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

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

另外，首次使用的用户如果没有可用的微信支付 API 实例，可以新建凭证+API 实例。
![](https://qcloudimg.tencent-cloud.cn/raw/16abbe5e57ddc19e1461e9f770be4e53.png)

支付通知回调的配置，可以配置成另一个工作流，或者已有 HTTP 服务的 URL：
![](https://qcloudimg.tencent-cloud.cn/raw/6a2c7346726c230ee785b77e00dc2b67.png)

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

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

![](https://qcloudimg.tencent-cloud.cn/raw/bc54a71b4a75f32c5b8514716fd8ce72.png)

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

```js
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并填写在代码中。
![](https://qcloudimg.tencent-cloud.cn/raw/c4eacfa7df765f37d6be06ac1373b79f.png)

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

```js
// 1. 小程序端调用
wx.cloud.callFunction({
  name: 'cloudbase_module',
  data: {
    // 工作流ID, 需从工作流属性中获取
    name: 'xxxxxxx',
    data: {
      /**
       * 注：appid 和 mchid 工作流已自动注入，无需传递
       * 本示例只传递了必要的参数，其他详细参数可参考微信支付文档：
       * https://pay.weixin.qq.com/doc/v3/merchant/4012791897
       */
      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);
      }
    });
  },
});
```

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

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

```js
// 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/doc/v3/merchant/4012791897
         */
        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);
      },
    });
  },
});
```

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