Zalo Mini App 支付接入指南

247 阅读4分钟

坤哥!审核被拒了!!快看看咋回事。。。

啥?全越南文,我能看明白什么?!当然身为初级研发,这话我不能说,于是

经过超1200秒的研读审核意见,使用deepSeek,有道翻译等工具,历时7200秒,最终确认“Zalo创建订单功能审核不通过,原因是因为有下单要素但是却没有接入支付SDK。”

纳尼?我创建订单还要经过你的同意??这是什么霸王条款!!

心死,继续研读该死的越南文文档!!

想要接支付SDK,首先你得先去管理界面声明一个支付方式

小程序管理界面 支付方式的通用信息

doc_1-6ee2aa9e8e92d2f925ed3089d39165f7.png

  1. Callback URL: 用户付款成功扣款后,接收Checkout SDK Server回调的路径。
  2. Private Key: 用于从Checkout SDK Server生成回调认证信息。
  3. Security Method: 安全,默认为HmacSHA256。
  4. App Status: 应用程序的付款状态,默认为ACTIVE

配置付款方式(货到付款COD配置)

为什么要选COD配置呢?货到付款或者叫代收货款,实际是线下支付,所以Zalo是不参与支付流程的,那这样的话,我们可以通过COD的付款方式来绕过Zalo因支付审核。只需要告诉Zalo用户已经完成线下支付,请放行!

doc_2-54dd8ab9acd3091f294002825d4458c0.png

  1. 点击【Thêm thanh toán mới】(添加支付配置)按钮 doc_3-1e6ac631e7719e160577488548316b29.png
  2. Phương thức thanh toán(支付方式)选择 Thanh toán khi nhận hàng - Sandbox (货到付款-沙盒)
    • Notify URL Chi tiết 通知地址:用户选择货到付款时接收平台通知的路径。
    • Redirect path 跳转路径:支付成功后返回 Zalo Mini App 的路径(默认返回首页)。

到这里 支付方式就配好了

--------------------------------------------分割线---------------------------------------------

前端部分

需要使用Checkout SDK中的两个Api,createOrder 创建订单 checkTransaction 查询交易结果

业务流程

graph TD

Start --> 自己业务系统中创建预订单 --> 调用createOrder创建订单用于Zalo交互 --> 唤起订单信息弹窗 --> 确认支付 --> 拿到支付结果 --> 业务系统创建真实订单 --> 结束
确认支付 --> 支付失败 --> 取消预订单
唤起订单信息弹窗 --> 取消支付 --> 取消预订单 --> 结束

上代码

import { createOrder } from "zmp-sdk";

// 创建订单
createOrder({
  desc: "Thanh toán 50.000", // 支付交易说明 会展示在 订单信息弹窗
  item: [ // 付款项目信息 即 商品信息
    { id: "1", amount: 20000 },
    { id: "2", amount: 30000 },
  ],
  amount: 50000, // 付款金额
  // 附加信息 JSON格式 字符串
  extradata: "{
    storeName: "Cửa hàng A",
    storeId: "123"
  }",
// 付款方式 id 前面创建的支付方式  JSON格式 字符串  isCustom  false: 平台的支付方式, true: 自己的支付方式
  method: "{
    id: "COD",
    isCustom: true,
  }",
  mac: "YOUR MAC", // 订单数据的认证信息,使用私钥对数据进行哈希验证。
  success: (data) => {
    // 成功
    // 自动跳转  或 自定义处理逻辑
    const { orderId } = data;
    console.log(orderId);
  },
  fail: (err) => {
    // 失败
    console.log(err);
  },
});

参数名类型是否必填描述
amountnumber需要支付的金额
itemArray<Record<String, String>>支付项信息,例如商品 ID 和金额
descriptionstring支付交易的描述
extradataJSON String需要传递的额外信息,例如 storeNamestoreId
methodJSON String指定支付方法,包括支付方法代码和是否为自定义方法
macstring订单数据的认证信息,使用私钥对数据进行哈希验证
successfunction成功回调函数
failfunction失败回调函数

注意事项:

  • 要传递给 createOrder 的数据需要在商家服务器上进行排序和处理
  • 在商家系统创建订单时,合作伙伴必须在商家服务器上创建 Mac
  • 在创建 mac 和传递给 createOrder API 时,extradatamethod 数据必须是 JSON String 类型
  • 创建 mac 时,项目数据必须是 String 数据类型

OK 现在可以唤起支付信息弹窗了

image.png

下面是怎么拿到支付结果

服务器端处理支付结果

对于货到付款 (COD)和银行转账这两种 付款方式,应用程序需要实现 API 以便在用户选择这两种方式之一时接收通知。

Checkout SDK服务器会根据 notify 回调商户服务器。商家使用私钥**对结账SDK服务器发布的数据进行身份验证。

通过updateOrderStatus API主动将结果数据发送到 Checkout SDK

这里就不做过多介绍了

客户端处理支付结果

import { useEffect, useCallback } from "react";
import { events, EventName, CheckoutSDK, TransactionResult } from "zmp-sdk/apis";
import { useSnackbar, useNavigate } from "zmp-ui";
import yourService from '../service'

export function CheckoutPage() {
  const { openSnackbar } = useSnackbar();
  const navigate = useNavigate();

  function handleClickCheckout() {
    // 创建系统订单
    const order = await yourService.initOrder()
    // 初始订单 打开支付弹窗 Checkout SDK
    await CheckoutSDK.createOrder(order)
  }

  const handlePaymentDone = useCallback((data) => {
    try {
      // 使用付款事件的返回数据检查付款结果
      const result = await CheckoutSDK.checkTransaction({ data })
      switch (result.resultCode) {
        case 1:
          // 交易成功
          navigate("/result?status=success")
          break;
        case 0:
          // 交易正在进行中
          navigate("/result?status=pending")
          break;
        case -1:
          // 交易失败
          navigate("/result?status=fail")
          break;
        case -2:
          // 不选择支付和退出
          openSnackbar({
            type: "info",
            text: "Vui lòng chọn phương thức thanh toán",
          });
          break;
        default:
          openSnackbar({
            type: "error",
            text: result.msg || "Đã xảy ra lỗi, vui lòng thử lại sau",
          });
          // 无效交易,检查结果。结果不对 等
          console.error(result.msg);
          break;
        }
      } catch (error) {
        openSnackbar({
          type: "error",
          text: "Đã xảy ra lỗi, vui lòng thử lại sau",
        });
      }
  }, [openSnackbar, navigate]);

  useEffect(() => {
    events.on(EventName.PaymentDone, handlePaymentDone);
    return () => {
      events.off(EventName.PaymentDone, handlePaymentDone);
    };
  }, [handlePaymentDone]);

  return (
    <div>
      <Button onClick={handleClickCheckout}>Thanh toán</Button>
    </div>
  );
}

嗯,搞完了。提审试试~~

image.png

好的,审核通过,完美!! Zalo 牛逼!! Zalo万岁!! 呵~忒 ~~!