更新记录
1.0.0(2025-08-15)
平台兼容性
云端兼容性
uni-app(4.63)
Vue2 |
Vue3 |
Vue2插件版本 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
iOS插件版本 |
鸿蒙 |
× |
√ |
1.0.0 |
× |
× |
× |
× |
× |
15 |
1.0.0 |
× |
微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
快应用-华为 |
快应用-联盟 |
× |
× |
× |
× |
× |
× |
× |
× |
× |
× |
× |
uni-app x(4.63)
Chrome |
Safari |
Android |
iOS |
鸿蒙 |
微信小程序 |
- |
- |
- |
- |
- |
- |
UTS环境兼容性
sn-uts-iap
一个基于 UTS 的 iOS 应用内购买 (IAP) 模块,封装了 StoreKit 2 的功能。
功能特性
基础连接管理
initConnection()
- 初始化与 App Store 的连接
endConnection()
- 结束连接
disable()
- 禁用模块
商店信息
getStorefront()
- 获取当前商店区域
getAppTransaction()
- 获取应用交易信息
产品管理
getItems(skus)
- 获取指定 SKU 的产品信息
getAvailableItems()
- 获取可用的购买项目
购买相关
buyProduct()
- 购买产品
finishTransaction()
- 完成交易
getPendingTransactions()
- 获取待处理的交易
clearTransaction()
- 清理交易
订阅相关
isEligibleForIntroOffer()
- 检查是否有资格获得介绍性优惠
subscriptionStatus()
- 获取订阅状态
currentEntitlement()
- 获取当前权益
latestTransaction()
- 获取最新交易
促销产品
getPromotedProduct()
- 获取促销产品
buyPromotedProduct()
- 购买促销产品
onPromotedProduct()
- 监听促销产品通知
其他功能
sync()
- 同步与 App Store
presentCodeRedemptionSheet()
- 显示兑换码输入界面
showManageSubscriptions()
- 显示订阅管理界面
beginRefundRequest()
- 开始退款请求
getReceiptData()
- 获取收据数据
isTransactionVerified()
- 检查交易是否已验证
getTransactionJws()
- 获取交易的 JWS 表示
validateReceiptIOS()
- 验证 iOS 收据
安装和配置
1. 安装模块
将 sn-uts-iap
模块复制到项目的 uni_modules
目录中。
2. iOS 配置
在 Info.plist
中添加必要的权限:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
3. 沙盒测试配置
- 在 Xcode 中配置沙盒测试账户
- 确保设备已登录测试账户
- 使用测试产品 ID 进行测试
使用方法
1. 初始化连接
import { initConnection, endConnection, disable } from '@/uni_modules/sn-uts-iap'
// 初始化连接
const isConnected = initConnection()
if (isConnected) {
console.log('成功连接到 App Store')
} else {
console.log('无法连接到 App Store')
}
// 应用退出时清理
onUnload(() => {
endConnection()
disable()
})
2. 获取产品信息
import { getItems, getAvailableItems } from '@/uni_modules/sn-uts-iap'
// 获取指定产品信息
getItems(['com.example.product1', 'com.example.subscription1'], (result) => {
if (result.code === 0) {
const products = result.data.products
console.log('产品信息:', products)
products.forEach(product => {
console.log(`产品ID: ${product.id}`)
console.log(`产品名称: ${product.displayName}`)
console.log(`产品价格: ${product.displayPrice}`)
console.log(`产品类型: ${product.type}`)
})
} else {
console.log('获取产品信息失败')
}
})
// 获取可用购买项目
getAvailableItems(true, true, (result) => {
if (result.code === 0) {
const items = result.data.items
console.log('可用购买项目:', items)
}
})
3. 购买产品
import { buyProduct, finishTransaction, getPendingTransactions } from '@/uni_modules/sn-uts-iap'
// 购买产品
buyProduct({
sku: 'com.example.product1', // 产品 SKU
andDangerouslyFinishTransactionAutomatically: false, // 是否自动完成交易
appAccountToken: "test", // 应用账户令牌(可选)
quantity: 1, // 购买数量(可选)
discountOffer: null // 折扣优惠(可选)
}, (result) => {
if (result.code === 0) {
console.log('购买成功:', result.data)
// 手动完成交易:(如果andDangerouslyFinishTransactionAutomatically=true,则不需要手动处理)
const transactionId = result.data.transactionId
const success = finishTransaction(transactionId)
if (success) {
console.log('交易完成')
}
} else {
console.log('购买失败,错误码:', result.code)
// 处理不同的错误状态
switch (result.code) {
case -1:
console.log('用户取消购买')
break
case -2:
console.log('购买待处理')
break
case -3:
console.log('未知状态')
break
case -4:
console.log('购买异常:', result.data.error)
break
case -10:
console.log('产品未找到')
break
default:
console.log('其他错误')
}
}
})
// 获取待处理交易
getPendingTransactions((result) => {
if (result.code === 0) {
const transactions = result.data.transactions
console.log('待处理交易:', transactions)
// 完成所有待处理交易
transactions.forEach(transaction => {
finishTransaction(transaction.transactionId)
})
}
})
4. 订阅管理
import {
isEligibleForIntroOffer,
subscriptionStatus,
currentEntitlement,
latestTransaction
} from '@/uni_modules/sn-uts-iap'
// 检查是否有资格获得介绍性优惠
isEligibleForIntroOffer('com.example.subscription1', (result) => {
if (result.code === 0) {
const isEligible = result.data.isEligible
console.log('是否有资格获得介绍性优惠:', isEligible)
}
})
// 获取订阅状态
subscriptionStatus('com.example.subscription1', (result) => {
if (result.code === 0) {
const status = result.data.status
console.log('订阅状态:', status)
status.forEach(s => {
console.log(`状态: ${s.state}`)
console.log(`平台: ${s.platform}`)
})
}
})
// 获取当前权益
currentEntitlement('com.example.subscription1', (result) => {
if (result.code === 0) {
const entitlement = result.data
console.log('当前权益:', entitlement)
}
})
// 获取最新交易
latestTransaction('com.example.subscription1', (result) => {
if (result.code === 0) {
const transaction = result.data
console.log('最新交易:', transaction)
}
})
5. 促销产品处理
import {
getPromotedProduct,
buyPromotedProduct,
onPromotedProduct
} from '@/uni_modules/sn-uts-iap'
// 监听促销产品通知
onPromotedProduct((product) => {
if (product) {
console.log('收到促销产品:', product)
// 显示促销产品信息
uni.showModal({
title: '促销产品',
content: `发现促销产品: ${product.localizedTitle}`,
confirmText: '立即购买',
cancelText: '稍后再说',
success: (res) => {
if (res.confirm) {
buyPromotedProduct((result) => {
if (result.code === 0) {
console.log('促销产品购买成功')
}
})
}
}
})
}
})
// 获取当前促销产品
getPromotedProduct((result) => {
if (result.code === 0) {
const product = result.data
if (product && Object.keys(product).length > 0) {
console.log('当前促销产品:', product)
} else {
console.log('当前没有促销产品')
}
}
})
6. 其他功能
import {
sync,
presentCodeRedemptionSheet,
showManageSubscriptions,
beginRefundRequest,
getReceiptData,
isTransactionVerified,
getTransactionJws,
validateReceiptIOS
} from '@/uni_modules/sn-uts-iap'
// 同步与 App Store
sync((result) => {
if (result.code === 0) {
const success = result.data.success
console.log('同步结果:', success)
}
})
// 显示兑换码输入界面
const redemptionResult = presentCodeRedemptionSheet()
console.log('兑换码界面显示结果:', redemptionResult)
// 显示订阅管理界面
showManageSubscriptions((result) => {
if (result.code === 0) {
const success = result.data.success
console.log('订阅管理界面显示结果:', success)
}
})
// 开始退款请求
beginRefundRequest('com.example.product1', (result) => {
if (result.code === 0) {
const refundStatus = result.data.refundStatus
console.log('退款状态:', refundStatus)
}
})
// 获取收据数据
getReceiptData((result) => {
if (result.code === 0) {
const receiptData = result.data.receiptData
console.log('收据数据:', receiptData)
}
})
// 验证交易
isTransactionVerified('com.example.product1', (result) => {
if (result.code === 0) {
const isVerified = result.data.isVerified
console.log('交易验证结果:', isVerified)
}
})
// 获取交易 JWS
getTransactionJws('com.example.product1', (result) => {
if (result.code === 0) {
const jws = result.data.jwsRepresentation
console.log('交易 JWS:', jws)
}
})
// 验证 iOS 收据
validateReceiptIOS('com.example.product1', (result) => {
if (result.code === 0) {
const validation = result.data
console.log('收据验证结果:', validation)
console.log('是否有效:', validation.isValid)
console.log('收据数据:', validation.receiptData)
console.log('JWS 表示:', validation.jwsRepresentation)
}
})
错误处理
1. 网络错误处理
getItems(['com.example.product1'], (result) => {
if (result.code === 0) {
// 成功处理
console.log('产品信息:', result.data)
} else {
// 错误处理
console.error('获取产品失败:', result)
// 根据错误类型进行不同处理
if (result.code === -1001) {
console.log('网络超时,请检查网络连接')
} else if (result.code === -1009) {
console.log('无网络连接')
}
}
})
2. 购买失败处理
buyProduct({
sku: 'com.example.product1',
andDangerouslyFinishTransactionAutomatically: false,
appAccountToken: "test"
}, (result) => {
if (result.code === 0) {
console.log('购买成功')
} else {
console.error('购买失败:', result)
// 处理特定错误
switch (result.code) {
case -1:
console.log('用户取消购买')
break
case -2:
console.log('购买待处理')
break
case -3:
console.log('未知状态')
break
case -4:
console.log('购买异常:', result.data.error)
break
case -10:
console.log('产品未找到')
break
default:
console.log('其他错误')
}
}
})
最佳实践
1. 生命周期管理
export default {
onLoad() {
// 页面加载时初始化连接
this.initIAP()
},
onUnload() {
// 页面卸载时清理连接
this.cleanupIAP()
},
methods: {
initIAP() {
const isConnected = initConnection()
if (isConnected) {
console.log('IAP 连接成功')
this.loadProducts()
}
},
cleanupIAP() {
endConnection()
disable()
},
loadProducts() {
getItems(['com.example.product1'], (result) => {
if (result.code === 0) {
this.products = result.data.products
}
})
}
}
}
2. 状态管理
export default {
data() {
return {
iapConnected: false,
products: [],
pendingTransactions: [],
currentSubscription: null
}
},
methods: {
async checkIAPStatus() {
// 检查连接状态
this.iapConnected = initConnection()
if (this.iapConnected) {
// 加载产品信息
this.loadProducts()
// 检查待处理交易
this.checkPendingTransactions()
// 检查当前订阅
this.checkCurrentSubscription()
}
},
loadProducts() {
getItems(['com.example.product1', 'com.example.subscription1'], (result) => {
if (result.code === 0) {
this.products = result.data.products
}
})
},
checkPendingTransactions() {
getPendingTransactions((result) => {
if (result.code === 0) {
this.pendingTransactions = result.data.transactions
}
})
},
checkCurrentSubscription() {
currentEntitlement('com.example.subscription1', (result) => {
if (result.code === 0) {
this.currentSubscription = result.data
}
})
}
}
}
3. 用户界面集成
export default {
methods: {
showProductList() {
if (this.products.length === 0) {
uni.showToast({
title: '正在加载产品信息...',
icon: 'loading'
})
return
}
const productList = this.products.map(product => ({
title: product.displayName,
price: product.displayPrice,
description: product.description
}))
uni.showActionSheet({
itemList: productList.map(p => `${p.title} - ${p.price}`),
success: (res) => {
const selectedProduct = this.products[res.tapIndex]
this.purchaseProduct(selectedProduct)
}
})
},
purchaseProduct(product) {
uni.showModal({
title: '确认购买',
content: `确定要购买 ${product.displayName} 吗?价格:${product.displayPrice}`,
success: (res) => {
if (res.confirm) {
this.startPurchase(product)
}
}
})
},
startPurchase(product) {
uni.showLoading({
title: '正在处理购买...'
})
buyProduct({
sku: product.id,
andDangerouslyFinishTransactionAutomatically: false,
appAccountToken: 'test'
}, (result) => {
uni.hideLoading()
if (result.code === 0) {
uni.showToast({
title: '购买成功!',
icon: 'success'
})
// 完成交易
finishTransaction(result.data.transactionId)
// 刷新状态
this.checkCurrentSubscription()
} else {
uni.showToast({
title: '购买失败',
icon: 'error'
})
// 处理错误
console.error('购买失败:', result.code, result.data)
}
})
}
}
}
注意事项
- iOS 版本要求: 需要 iOS 15.0 或更高版本
- 权限配置: 确保在
Info.plist
中配置了必要的权限
- 沙盒测试: 开发阶段建议使用沙盒环境进行测试
- 错误处理: 所有异步操作都应该包含适当的错误处理
- 生命周期管理: 在应用/页面卸载时正确清理 IAP 连接
- 网络状态: 确保在网络连接正常时进行 IAP 操作
- 产品 ID: 使用正确的产品 ID 进行测试和生产
- 收据验证: 在生产环境中验证收据的真实性