更新记录

1.0.1(2026-08-15)

  • 重写使用文档:用法介绍、快速上手、API 示例、错误码表、后端验签说明、常见问题

1.0.0(2026-08-15)

  • 首次发布为 UTS 插件(iOS StoreKit2)
  • Swift 核心 + UTS 桥 + JS 便捷封装
  • 支持消耗型、非消耗型、自动续期订阅、非续期订阅
  • 便捷用法:init / applyPrices / purchase
  • 遗留交易由 SDK 内部自动处理
  • 最低 iOS 15.0

平台兼容性

uni-app(4.0)

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

FZ-SK2-IAP · iOS StoreKit2 内购 UTS 插件

基于 Apple StoreKit 2 的 iOS 内购插件(UTS 实现),支持:

  • 消耗型 / 非消耗型 / 自动续期订阅 / 非续期订阅
  • 商品拉取与价格本地化展示
  • 购买、恢复购买、订阅状态查询
  • 交易 JWS 票据透传(配合后端 App Store Server API 验签)
  • 遗留交易自动监听与补发验签
  • Android / H5 / 小程序调用自动降级(返回"iOS only"错误,不崩溃)

环境要求

要求
系统 iOS 15.0+
HBuilderX 4.0+
打包方式 云打包 / 自定义基座(标准基座可用于真机调试)
商品配置 需先在 App Store Connect 创建内购商品,且已签署付费应用协议

快速上手

import { appleIap, isAppleIapCancelled, isAppleIapPending } from '@/uni_modules/fz-sk2-iap/js_sdk/index'

// 1. 初始化:注册验签回调(购买成功与遗留交易都会走 verify)
const ok = await appleIap.init({
  // 把票据交给自己的后端验签(推荐 App Store Server API 验 transactionJwsToken)
  verify: (tx) => yourBackendVerify({
    transactionId: tx.transactionId,
    transactionJwsToken: tx.transactionJwsToken,
  }),
  // 验签成功后刷新会员状态
  onVerified: () => refreshVip(),
})
if (!ok) {
  // 非 iOS 或系统低于 15.0,走其他支付渠道或隐藏订阅入口
}

// 2. 回填套餐价格(plans 里每项需有 externalProductId = App Store 商品ID)
await appleIap.applyPrices(plans)
plans.forEach(p => console.log(p.displayPrice)) // 本地化价格字符串,直接展示

// 3. 发起购买
try {
  const tx = await appleIap.purchase(productId)
  console.log('购买并验签成功', tx.transactionId)
} catch (err) {
  if (isAppleIapCancelled(err)) {
    // 用户取消,无需提示错误
  } else if (isAppleIapPending(err)) {
    // 家长同意等场景,交易 pending,等待 onVerified 补发
  } else {
    console.error(err.code, err.message)
  }
}

API

appleIap 对象

@/uni_modules/fz-sk2-iap/js_sdk/index 导入。

appleIap.init(options) → Promise\<boolean>

初始化并绑定原生事件监听。false 表示当前环境不可用(非 iOS 或系统 < 15.0)。

参数 说明
options.verify (tx: AppleVerifyPayload) => Promise 购买成功和遗留交易的验签回调;抛错会重置该笔的验签状态,下次会重试
options.onVerified 验签成功回调,用于刷新会员状态

appleIap.isSupported() → Promise\<boolean>

当前设备是否支持 StoreKit 2。

appleIap.fetchProducts(productIds) → Promise\<{ products, invalidIds }>

按商品 ID 拉取商品信息。invalidIds 是 App Store 未识别的 ID,可用来排查配置问题。

appleIap.applyPrices(plans) → Promise\<plans>

批量把 App Store 本地化价格回填到套餐对象(需套餐字段 externalProductId):

回填字段:displayPrice(带货币符号的展示价)、priceStrcurrencyiapProduct(完整商品对象)。

appleIap.purchase(productId, appAccountToken?) → Promise\<AppleVerifyPayload>

发起购买并自动验签,成功返回 { transactionId, transactionJwsToken, productId, ... }

  • 取消 / pending / 失败会 throw,用 isAppleIapCancelled / isAppleIapPending 判断
  • appAccountToken 可选,传合法 UUID 用于和自己的账号系统对账;不传自动生成随机 UUID 并在结果中返回

appleIap.purchaseProduct(productId, appAccountToken?) → Promise\<AppleIapPurchaseResult>

购买的原始结果(不走 verify 自动验签):resultsuccess(含 transaction)/ userCancelled / pending

appleIap.restorePurchases() → Promise\<{ transactions }>

恢复购买(会先 AppStore.sync()),返回当前所有有效交易。

appleIap.getCurrentSubscriptions() → Promise\<AppleIapTransaction[]>

当前有效的订阅列表(含每条的 subscriptionStatus)。

appleIap.getSubscriptionStatus(productId) → Promise\<AppleIapSubscriptionStatus>

查询单个订阅状态:state(active / expired / inGracePeriod / inBillingRetryPeriod / revoked)、willAutoRenewexpirationDate 等。

appleIap.getAppStoreReceiptBase64() → Promise\<AppleIapReceiptInfo>

获取收据(优先返回最新交易的 JWS),用于老式收据校验。新项目建议直接用购买结果里的 transactionJwsToken

属性

  • appleIap.available:是否 iOS 平台
  • appleIap.ready:init 后是否可用
  • appleIap.products / appleIap.invalidIds:最近一次 fetchProducts 的结果

工具函数

import { isAppleIapCancelled, isAppleIapPending, toVerifyPayload } from '@/uni_modules/fz-sk2-iap/js_sdk/index'

isAppleIapCancelled(err)  // 用户是否取消了购买
isAppleIapPending(err)    // 购买是否处于 pending(如家长批准)
toVerifyPayload(tx)       // 交易对象 → 后端验签入参(transactionId + transactionJwsToken)

底层 UTS 接口

也可直接从 @/uni_modules/fz-sk2-iap 导入与原生一一对应的 Promise 接口:isSupportStoreKit2 / fetchProducts / purchaseProduct / restorePurchases / getCurrentSubscriptions / getSubscriptionStatus / getAppStoreReceiptBase64。一般情况直接用 appleIap 即可。

错误码

code 含义
-1 系统不支持(需 iOS 15+)
-2 未知错误
-3 网络错误
-4 商品不存在(未在 App Store Connect 配置或 ID 写错)
-5 用户取消购买
-6 已有购买进行中 / 交易待确认
-7 购买失败(含交易验签未通过)
-8 参数错误(productId 为空、token 非 UUID 等)
-9 获取收据失败

后端验签(重要)

不要在客户端判断发货。 购买/恢复返回的交易都带 jwsRepresentation(JWS 格式的 StoreKit 2 交易票据),把它交给后端,用 App Store Server API 验签后再发放权益:

客户端 purchase() → transactionJwsToken → 你的后端 → App Store Server API 验证 → 发放权益

插件会在 App 启动后自动监听遗留交易(退款重购、跨设备等),走同一个 verify 回调,避免丢单。

常见问题

  • 拉不到商品:检查 App Store Connect 商品状态、付费应用协议是否签署、商品 ID 是否一致、真机登录的沙盒账号地区。
  • 价格展示:一律用 displayPrice(系统本地化字符串),不要自己拼 price 浮点数。
  • 模拟器:StoreKit 2 购买需真机 + 沙盒账号;模拟器仅能验证插件编译与接口调用。
  • 测试:Xcode 工程 配置 StoreKit Configuration 文件可在本地模拟购买流程(不产生真实扣费)。
  • Android/H5:调用返回 iOS only 错误,请在业务侧按 appleIap.available 分流。

隐私、权限声明

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

StoreKit 内购

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

插件不采集用户隐私数据,内购票据由业务方自行提交后端验签

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

暂无用户评论。