更新记录

1.0.2(2026-10-11)

  • 修复 Android 云端打包 Kotlin 编译失败(Unresolved reference 'DyPay'/'HashMap'/'IDyPayResultCallback'):Java/Kotlin 类改用默认导入,命名导入全限定类路径会生成双重包名的错误 import
  • 支付回调改由 ZDypayKt.kt 混编文件实现 IDyPayResultCallback(该接口为 Kotlin 接口,onResult(Map<String, String>)),避免 uts 与原生接口类型映射问题
  • 支付调起增加 try-catch 兜底,异常时按失败回调

1.0.1(2026-10-11)

  • 修复 uni-app Vue2 项目编译时 uts_transforms 编译器 panic(overload error initDypay != canOpenDypay)
  • 按官方规范重构:interface.uts 仅导出类型(含函数类型别名),平台实现统一为 export const
  • package.json 平台声明切换为 uni-app Vue2 schema
  • Android minSdkVersion 对齐为 21;HBuilderX 要求 ^4.61

1.0.0(2026-10-11)

初始测试版本

查看更多

平台兼容性

uni-app(5.31)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
√ - - - - - 5.0 - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(5.31)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - - - -

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
× × × √

z-dypay 抖音支付插件使用说明

抖音支付 UTS 插件,基于抖音支付官方 OpenSDK 封装,支持三端:

平台 支付方式 实现依据
Android App 调起抖音 App 支付 com.bytedance.caijing:dy-pay-sdk-tob:1.1.0.9(火山 maven 源)
iOS App 调起抖音 App 支付 DypaySDK 1.1.0.4(CocoaPods 火山 specs 源)
H5(浏览器) 跳转抖音 H5 收银台 服务端 H5 下单返回 h5_url,前端直接跳转

核心原则:客户端只透传服务端返回的支付参数,不参与签名。签名由商户服务端完成(SHA256withRSA,待签串 appId\ntimestamp\nnoncestr\nprepayid\n)。


一、接入前必做配置

1. iOS 回调 Scheme 替换(必须)

打开 utssdk/app-ios/Info.plist,将 REPLACE_WITH_DOUYIN_APPID 替换为抖音开放平台分配的真实 AppID:

<key>CFBundleURLSchemes</key>
<array>
  <string>你的抖音AppID</string>
</array>

该 Scheme 是支付完成后抖音 App 回跳本 App 的入口,必须与 initDypay({ appId }) 传入值一致(SDK 注册的回调 Scheme 固定为 ${appId}://dypay)。

2. 打自定义基座 / 云打包(必须)

UTS 插件包含三端原生代码(Kotlin/Swift),标准基座不包含,真机运行前必须重新打自定义基座或云打包,否则调用无反应。

3. 环境版本要求

  • HBuilderX 4.61+(iOS dependencies-pods 单库 source 字段要求)
  • Android minSdkVersion 21(插件 config.json 已配置)
  • iOS deploymentTarget 12.0(插件 config.json 已配置)
  • Mac 本机真机运行需安装 CocoaPods(打包时自动拉取火山源 DypaySDK)

4. 商户平台配置

  • H5 支付:需在抖音商户平台预先配置 H5 支付域名
  • App 支付:需在抖音开放平台配置应用包名 / Bundle ID / iOS Universal Link

二、API 说明

JS 侧通过 import * as zDypay from '@/uni_modules/z-dypay' 引入,共 4 个函数。

initDypay(options) — 初始化(App 启动时调用一次)

参数 类型 必填 说明
options.appId string 是 抖音开放平台 AppID,与支付参数中的 appid 一致
options.universalLink string | null iOS 建议 已在抖音开放平台配置的 Universal Link;Android 忽略

平台行为:Android 调用 DyPay.setAppId;iOS 注册 appId / Universal Link / 回调 Scheme;H5 空实现。

canOpenDypay() — 检测抖音是否可用

返回 boolean。Android 调用 DyPay.isDypayAppUsable;iOS 调用 DypayAPI.canOpenDypay(依赖 Info.plist 中已配置的 LSApplicationQueriesSchemes);H5 固定返回 false。

payDypay(payInfo) — 调起抖音 App 支付

Promise<DypayResult>,payInfo 为服务端 App 下单接口返回的支付参数,字段大小写敏感、全部为字符串:

字段 说明
appid 抖音开放平台 AppID
partnerid 商户号(mchid)
prepayid App 下单返回的预支付单号
package 固定值 Sign=DYPay
noncestr 随机字符串
timestamp 秒级时间戳(字符串)
sign 服务端生成的支付签名

平台行为:iOS 在 App 内拉起抖音;Android 在 App 内拉起抖音;H5 返回 {code: 2}(H5 请用 openDypayH5)。

内部已做保护:未安装抖音 / 版本过低时直接 resolve {code: 100},不会无效调起。

openDypayH5(h5Url) — H5 支付跳转

  • H5:当前页 location.href 跳转至抖音 H5 收银台(h5_url 有效期 5 分钟,需即时使用)
  • iOS:使用系统 Safari 打开
  • Android:空实现(App 内统一走 payDypay)

三、支付结果码(DypayResult)

与抖音 SDK resultCode 对齐:

code 含义 建议处理
0 支付成功 仍需调用服务端查单确认,不能只信客户端回调
1 用户取消 静默处理或提示
2 其他错误 提示失败(message 含错误信息)
3 支付结果不明 必须调用服务端查单确认
100 未安装抖音 / 版本过低 / iOS 未配置 Scheme 引导用户安装抖音
103 重复支付拦截 提示已有进行中的订单
其他非 0 失败 按 2 处理

四、前端接入示例

1. App.vue 初始化(onLaunch,一次即可)

import * as zDypay from '@/uni_modules/z-dypay'

export default {
  onLaunch() {
    // #ifdef APP-PLUS
    zDypay.initDypay({
      appId: '你的抖音AppID',
      universalLink: 'https://你的域名/ul/' // iOS 用
    })
    // #endif
  }
}

H5 端 initDypay 为空实现,不包条件编译也不会报错。

2. 支付页按平台分支(Vue2 Options API)

import * as zDypay from '@/uni_modules/z-dypay'

export default {
  methods: {
    // 后端统一下单接口返回后调用
    async payByDouyin(orderData) {
      // #ifdef APP-PLUS
      // orderData.payInfo 为服务端 App 下单接口返回的 7 字段参数,原样透传
      const res = await zDypay.payDypay(orderData.payInfo)
      if (res.code === 0 || res.code === 3) {
        // 不能只信 SDK 回调,必须调后端查单接口确认真实支付状态
        await this.queryOrderStatus(orderData.orderId)
      } else if (res.code === 100) {
        uni.showToast({ title: '未安装抖音或版本过低', icon: 'none' })
      } else if (res.code === 1) {
        // 用户取消,静默或提示
      } else {
        uni.showToast({ title: res.message || '支付失败', icon: 'none' })
      }
      // #endif

      // #ifdef H5
      // orderData.h5Url 为服务端 H5 下单接口返回的 h5_url(5 分钟有效)
      zDypay.openDypayH5(orderData.h5Url)
      // #endif
    }
  }
}

3. 可选:支付前检测

if (!zDypay.canOpenDypay()) {
  uni.showToast({ title: '请先安装抖音 App', icon: 'none' })
  return
}

五、服务端配合说明(插件不参与)

客户端仅消费以下两类数据,均由商户服务端生成:

1. App 支付

服务端调用抖音 App 下单接口:

POST https://api.douyinpay.com/v1/trade/transactions/app

将响应中的支付参数(appid / partnerid / prepayid / package / noncestr / timestamp / sign)原样返回给前端,前端透传给 payDypay。

签名规则(服务端):SHA256withRSA + Base64,待签串为:

appId\ntimestamp\nnoncestr\nprepayid\n

2. H5 支付

服务端调用抖音 H5 下单接口:

POST https://api.douyinpay.com/v1/trade/transactions/h5
  • 请求体 scene_info 必填,含 h5_info: { type: "iOS"|"Android", app_name, app_url, bundle_id }
  • 响应返回 h5_url(有效期 5 分钟),前端通过 openDypayH5 跳转
  • H5 支付域名需提前在商户平台配置

3. 查单

payDypay 返回 code = 0 或 3 时,前端必须调用服务端查单接口,以服务端订单状态作为最终支付结果,再进行发货/跳转。


六、平台差异与常见问题

问题 说明
真机无反应 未打自定义基座/云打包,标准基座不含 UTS 原生代码
iOS 支付后不回跳 检查 Info.plist 的 CFBundleURLSchemes 是否已替换为真实 AppID;Universal Link 是否在抖音开放平台与 apple-app-site-association 双侧配置
iOS canOpenDypay 恒为 false LSApplicationQueriesSchemes(dypay1128 / dypay2329 / dypay8663)必须位于列表前 50 项内
iOS 云打包找不到 DypaySDK 确认 HBuilderX ≥ 4.61,且 pod 走火山源 volcengine-specs(config.json 已锁定,勿删)
Android 打包失败 火山 maven 源 artifact.bytedance.com 可能被公司网络拦截,检查 utssdk/app-android/config.json 的 project.repositories
Android 未安装抖音 payDypay 内部已预检,直接返回 code=100,无需自行处理
H5 端调 payDypay 返回 {code: 2},H5 必须走 openDypayH5
修改支付参数字段 需同步修改 utssdk/interface.uts 类型声明,以及 Android index.uts 中的透传字段列表
编译报 uts overload panic interface.uts 只允许导出类型(含函数类型别名),不能写无函数体的抽象函数声明;平台实现统一用 export const fn: 类型 = function(){}
Android 报 Unresolved reference 引用 Java/Kotlin 类必须用默认导入 import X from 'a.b.c.X';命名导入全限定类路径会生成双重包名的错误 import
混淆 Android 侧 SDK 已要求 keep com.ss.android.dypay.api.**,打包时勿移除

七、目录结构

uni_modules/z-dypay/
├── package.json                    # 插件声明(vue2 / Android minSdk 21 / iOS 12 / H5)
├── readme.md                       # 本文档
├── changelog.md
└── utssdk/
    ├── interface.uts               # 对外 API 与类型声明
    ├── app-android/
    │   ├── config.json             # 火山 maven 源 + dy-pay-sdk-tob:1.1.0.9
    │   ├── ZDypayKt.kt             # Kotlin 混编封装(IDyPayResultCallback 回调接口实现)
    │   └── index.uts               # 初始化 / 能力检测 / 调起支付入口
    ├── app-ios/
    │   ├── config.json             # DypaySDK 1.1.0.4(火山 specs 源)+ 系统库
    │   ├── Info.plist              # dypay 查询 scheme + 支付回跳 URL Types(AppID 待替换)
    │   ├── ZDypayManager.swift     # OC SDK 的 Swift 包装层(注册/支付/回跳归一)
    │   └── index.uts               # UTS 入口 + UTSiOSHookProxy 回跳监听
    └── web/
        └── index.uts               # h5_url 跳转(类型与 interface.uts 保持同步)

版本记录

详见 changelog.md。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android:网络/相机(SDK 自带);iOS:无额外隐私权限

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据,支付参数由商户服务端生成并透传

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。