疑难解答
本页介绍开发者在集成 AppCoins iOS SDK(Swift 与 Unity)时最常遇到的问题及其解决方法。每个条目均采用相同结构:现象、原因和解决方法。
isAvailable() 始终返回 false
现象: 即使在真机上,AppcSDK.isAvailable()(Swift)或 AppCoinsIAP.ConfigureStoreAsync 中的 Automatic 模式判定(Unity)也始终不会启用 AppCoins 计费。
原因:
- 测试环境未配置——应用未被识别为通过替代应用市场分发。
- 设备运行的 iOS 版本低于 17.4。
- 应用是从 Apple App Store 或 TestFlight 安装的。
完整的安装来源列表及其对可用性的影响,请参见运行时检测的原理。
解决方法:
- 在 Xcode 中打开目标的 Build Settings 并搜索 Marketplaces。在 Deployment 下将值设置为
com.aptoide.ios.store。 - 在您的 scheme 中进入 Run → Options,在 Distribution 下拉框中选择
com.aptoide.ios.store。 - 在运行 iOS 17.4 及以上版本的真机上运行。
或者,您也可以无需重新构建,在设备上打开 Safari 并访问以下地址来在运行时强制启用 AppCoins 模式:
{bundle_id}.iap://wallet.appcoins.io/default/mode?value=appcoins
请将 {bundle_id} 替换为您应用的 bundle identifier。使用 value=apple 可测试 Apple 计费回落,使用 value=automatic 可恢复正常检测。请注意,为防止滥用,模式覆盖对从 Apple App Store 安装的构建无效。
购买时出现 notEntitled 错误
现象: 调用 product.purchase()(Swift)或 controller.InitiatePurchase(Unity)后,未显示支付页面就立即抛出或返回 AppCoinsSDKError.notEntitled。
原因:
- 尚未为该 target 添加 Keychain Sharing 能力。
- 钥匙串分组设置为了错误的值(Xcode 有时会自动填入团队标识符或 bundle identifier)。
解决方法:
- 在 Xcode 中选择您的 target,打开 Signing & Capabilities 标签页。
- 点击 + 并添加 Keychain Sharing 能力。
- 在 Keychain Groups 列表中删除所有已有条目,并准确输入
com.aptoide.appcoins-wallet。 - 执行 Clean 后重新构建。
com.aptoide.appcoins-wallet——不能有前缀、后缀或 bundle ID。任何其他值都会在运行时导致 notEntitled。商品数组为空 / 出现 productUnavailable 错误
现象: Product.products(for:)(Swift)返回空数组,或 GetProducts(Unity)触发 OnProductsFetchFailed;也可能是 product.purchase() 抛出 productUnavailable。
原因:
- 应用尚未在 Aptoide Connect 中提交并通过审核。
- 代码中的 SKU 标识符与 Aptoide Connect 中定义的不完全一致(标识符区分大小写)。
解决方法:
- 打开 Aptoide Connect,确认应用条目已存在且已通过审核。
- 在应用条目中进入 Products,逐字符核对每个 SKU 标识符是否与您传入
Product.products(for:)(Swift)或 UnityProductCatalog的值完全一致。 - 只有在审核通过之后,商品才可被查询。
支付跳转未完成(购买一直挂起)
现象: 用户被跳转到支付方式页面,但应用始终未收到购买结果,购买一直处于待处理状态。
原因(Swift):
- 未在 URL context 处理方法中调用
AppcSDK.handle(redirectURL:)。 - Info → URL Types 中缺少角色为 Editor 的 URL scheme
$(PRODUCT_BUNDLE_IDENTIFIER).iap。
解决方法:
- 在 Xcode 中打开目标的 Info 标签页。在 URL Types 下确认存在如下条目:
- URL Schemes:
$(PRODUCT_BUNDLE_IDENTIFIER).iap - Role:
Editor
- URL Schemes:
- 在
SceneDelegate.swift中确认scene(_:openURLContexts:)调用了AppcSDK.handle(redirectURL:)。注意:AppcSDK.initialize()必须在应用启动时于willConnectTo中调用,而不能放在 URL 处理方法内:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
if AppcSDK.handle(redirectURL: URLContexts.first?.url) { return }
// your existing URL handling
}
对于 Unity,后处理构建脚本会自动添加该 URL scheme。如果购买仍然挂起,请从 Unity 重新构建 Xcode 工程,并确认 URL Type 已出现在 Xcode target 的 Info 标签页中。
应用崩溃或重启后用户丢失了购买
现象: 用户已付款,但由于应用在购买流程中崩溃或被强制退出而未收到商品;重新启动后商品仍然缺失。
原因: 应用未在启动时遍历 Transaction.unfinished(Swift)或调用 FetchPurchases(Unity),因而没有恢复已付款但未消耗的交易。
解决方法(Swift):
在应用的初始化流程中、isAvailable() 检查之后,加入未完成交易的处理:
func processUnfinishedTransactions() async {
guard await AppcSDK.isAvailable() else { return }
for await verificationResult in Transaction.unfinished {
switch verificationResult {
case .verified(let transaction):
giveItemToUser(productID: transaction.productID)
await transaction.finish()
case .unverified(_, let error):
print("Unverified unfinished transaction: \(error.description)")
}
}
}
解决方法(Unity):
在 Connect() 之前设置 ProcessPendingOrdersOnPurchasesFetched(true),随后调用 FetchPurchases()。未完成的购买会通过 OnPurchasePending 重新到达——与新购买使用同一个处理方法。
async void Start()
{
await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic);
controller = UnityIAPServices.StoreController();
controller.OnPurchasePending += OnPurchasePending;
// Must be set before Connect so FetchPurchases results come through OnPurchasePending
controller.ProcessPendingOrdersOnPurchasesFetched(true);
await controller.Connect();
controller.FetchPurchases(); // recovers unfinished transactions
}
transaction.id 类型不匹配(Swift)
现象: 在比较或存储 transaction.id 时出现编译错误或非预期行为——在 StoreKit 下可用的代码在 AppCoins SDK 下无法编译或产生错误结果。
原因: StoreKit 的 Transaction.id 为 UInt64,而 AppCoins SDK 的 Transaction.id 为 String。从 StoreKit 集成中直接复制的代码会失效。
解决方法:
将所有比较和存储逻辑更新为将 transaction.id 视为 String:
// Wrong (StoreKit pattern)
let id: UInt64 = transaction.id
// Correct (AppCoins SDK)
let id: String = transaction.id
如果您在同一代码库中同时对接 StoreKit 和 AppCoins 计费,请在需要时转换 StoreKit 的交易 ID:
let appCoinsCompatibleID = String(storeKitTransaction.id)
Unity:调用 Connect 之前未 await ConfigureStoreAsync
现象: Unity IAP 已连接,但使用了错误的计费提供方,或 OnProductsFetched 从不触发。即使在本应启用的设备上,AppCoins 计费也未生效。
原因: 在 ConfigureStoreAsync 完成之前就调用了 controller.Connect()。Unity IAP 初始化时,AppCoins 的商店提供方尚未注册。
解决方法:
在调用 Connect 之前,务必 await ConfigureStoreAsync:
async void Start()
{
var selectedStore = await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic);
Debug.Log("Selected store: " + selectedStore);
await controller.Connect();
}
Connect 之前 await ConfigureStoreAsync。否则,AppCoins 商店可能来不及注册,Unity IAP 会回落到 Apple 或静默失败。Unity:设备上 AppCoins 未启用(Automatic 模式)
现象: 在 iOS 17.4 及以上版本的真机上使用 Automatic 模式,但 AppCoinsIAP.SelectedStore 始终为 "AppleAppStore"。
原因: 缺少测试环境配置——与 Swift 中 isAvailable() 返回 false 的根本原因相同。
解决方法:
应用相同的 Xcode 与 scheme 设置:
- 在 Build Settings 中将 Marketplaces 设置为
com.aptoide.ios.store。 - 在 scheme 的 Run → Options → Distribution 中选择
com.aptoide.ios.store。
或在设备上通过 Safari 使用深度链接强制启用 AppCoins 模式:
{bundle_id}.iap://wallet.appcoins.io/default/mode?value=appcoins