错误参考
本页是 AppCoins iOS SDK 可能返回的所有错误码的完整参考,涵盖原生 Swift 接口以及 Unity IAP v5 集成。针对每个错误,您都可以找到其含义、最常见的原因以及推荐的解决方法。
Swift 错误(AppCoinsSDKError)
Swift SDK 抛出的所有错误均为 AppCoinsSDKError 类型。该枚举包含六种情形。
networkError
SDK 发起的网络请求在收到响应之前失败。
常见原因:
- 设备没有网络连接。
- Aptoide 计费服务器暂时无法访问。
- 请求超时。
解决方法:
- 在调用 SDK 方法之前检查网络连通性(例如使用
NWPathMonitor)。 - 针对瞬时故障实现带指数退避的重试机制。
- 向用户展示类似「请检查网络连接后重试」的提示。
do {
let products = try await Product.products()
} catch let error as AppCoinsSDKError {
if case .networkError(let description) = error {
print("Network error: \(description)")
// Show retry UI
}
}
systemError
发生了 AppCoins 内部系统错误,或服务器返回了非预期的响应。
常见原因:
- 与用户操作或网络连接无关的 SDK 内部故障。
- Aptoide 计费服务器返回了非预期或格式错误的响应。
解决方法:
- 记录完整的错误描述以便诊断。
- 稍作延迟后重试该操作一次。
- 如果该错误跨会话持续出现,请附上已记录的描述向 Aptoide 支持团队报告。
if case .systemError(let description) = error {
print("System error: \(description)")
}
notEntitled
宿主应用缺少 SDK 存储钱包信息所需的 Keychain Sharing 授权。
常见原因:
- 尚未为该 target 添加 Keychain Sharing 能力。
- 钥匙串分组被设置为
com.aptoide.appcoins-wallet以外的值(例如应用自身的 bundle identifier)。
解决方法:
- 在 Xcode 中选择您的 target,进入 Signing & Capabilities 标签页。
- 点击 + 并添加 Keychain Sharing 能力。
- 在 Keychain Groups 列表中,将已有条目准确替换为
com.aptoide.appcoins-wallet。 - 执行 Clean 后重新构建。
com.aptoide.appcoins-wallet,不能带任何前缀或后缀。Xcode 有时会自动填入您的 Team ID 或 bundle identifier——请删除该条目并手动输入上述值。if case .notEntitled = error {
// Configuration error — cannot be recovered at runtime.
// Fix in Xcode Signing & Capabilities.
print("Missing Keychain Sharing entitlement.")
}
productUnavailable
未找到所请求的 SKU,或该商品当前不可购买。
常见原因:
- 代码中的 SKU 标识符与 Aptoide Connect 中定义的不完全一致。
- 应用尚未在 Aptoide Connect 上通过审核。
- 该商品已在 Aptoide Connect 中被停用。
解决方法:
- 打开 Aptoide Connect,逐字符核对 SKU 标识符是否完全一致(区分大小写)。
- 确认您的应用已在 Aptoide Connect 上提交并通过审核。在应用通过审核之前无法查询商品。
- 确认该商品处于启用状态且未被归档。
if case .productUnavailable(let description) = error {
print("Product unavailable: \(description)")
}
purchaseNotAllowed
在当前情境下不允许该用户进行购买。
常见原因:
- 设备启用了家长控制并限制了购买。
- 用户账户存在区域限制,无法完成此次购买。
- 屏幕使用时间或其他限制配置阻止了应用内购买。
解决方法: 此错误无法由您的应用解决。请显示提示信息,说明当前情境下不允许购买,并建议用户检查其设备的限制设置。
if case .purchaseNotAllowed(let description) = error {
// Inform the user — nothing the app can do programmatically.
print("Purchase not allowed: \(description)")
}
unknown
发生了不属于上述任何类别的错误。
解决方法:
- 记录该错误返回的描述以便诊断。
- 将其视为瞬时故障,允许用户重试。
- 如果该错误持续出现,请附上完整描述向 Aptoide 支持团队报告。
if case .unknown(let description) = error {
print("Unknown error: \(description)")
}
Unity 错误(AppCoinsSDKError 到 Unity IAP 的映射)
Unity IAP v5 集成会将 AppCoins 错误转换为标准的 Unity IAP 失败原因。下表列出完整映射关系。
| AppCoins 错误 | Unity IAP 原因 | 适用于 |
|---|---|---|
productUnavailable | ProductFetchFailureReason.ProductsUnavailable | OnProductsFetchFailed |
networkError | ProductFetchFailureReason.ProviderUnavailable | OnProductsFetchFailed |
productUnavailable | PurchaseFailureReason.ProductUnavailable | OnPurchaseFailed |
purchaseNotAllowed | PurchaseFailureReason.PaymentDeclined | OnPurchaseFailed |
notEntitled | PurchaseFailureReason.PaymentDeclined | OnPurchaseFailed |
systemError | PurchaseFailureReason.Unknown | OnPurchaseFailed |
unknown | PurchaseFailureReason.Unknown | OnPurchaseFailed |
在 Unity IAP v5 中处理购买失败:
_controller.OnPurchaseFailed += OnPurchaseFailed;
private void OnPurchaseFailed(FailedOrder order)
{
switch (order.FailureReason)
{
case PurchaseFailureReason.UserCancelled:
// User dismissed the payment sheet — no action needed.
break;
case PurchaseFailureReason.ProductUnavailable:
// SKU not found in Aptoide Connect — check your product configuration.
Debug.LogError("Product unavailable: " + order.Details);
break;
case PurchaseFailureReason.PaymentDeclined:
// Parental controls, region restriction, or missing Keychain entitlement.
// Show the user a message; check Xcode entitlements if this is unexpected.
Debug.LogError("Payment declined: " + order.Details);
break;
default:
// Transient or unknown failure — allow retry.
Debug.LogError($"Purchase failed ({order.FailureReason}): {order.Details}");
break;
}
}
在 Unity IAP v5 中处理商品拉取失败:
_controller.OnProductsFetchFailed += OnProductsFetchFailed;
private void OnProductsFetchFailed(ProductFetchFailed failure)
{
Debug.LogError("Products fetch failed: " + failure.FailureReason);
foreach (var product in failure.FailedFetchProducts)
Debug.LogError("Failed to fetch product: " + product.id);
}
验证错误
Swift —— VerificationResult.unverified
购买成功后,SDK 会执行本地签名校验。如果签名无法验证,结果将是 .unverified(transaction, error)。
case .success(let verificationResult):
switch verificationResult {
case .verified(let purchase):
// Signature check passed — safe to grant the item.
try await purchase.finish()
case .unverified(let purchase, let verificationError):
// Signature check failed. Decide based on your business logic:
// Option A (lenient): grant the item anyway and finish.
// try await purchase.finish()
// Option B (strict): do NOT finish — Aptoide will refund after 24 hours.
print("Unverified purchase: \(verificationError)")
}
purchase.finish(),该笔购买将在 24 小时后自动退款。请在发布前在您的业务逻辑中考虑这一点。Unity —— 收据中的 verificationResult 字段
每个 PendingOrder 附带的收据是一个 JSON 字符串。解析 Payload 字段即可找到 verificationResult,其值为 "verified" 或 "unverified"。
private void OnPurchasePending(PendingOrder order)
{
// The receipt is a JSON string: { "Store": "...", "TransactionID": "...", "Payload": "..." }
// Parse Payload to inspect verificationResult.
string receipt = order.Info.Receipt;
// Forward the receipt to your backend for Remote Check validation (optional).
// Then decide whether to grant and confirm:
GiveItemToUser(order);
_controller.ConfirmPurchase(order); // Consumes the purchase.
}
如果您通过 Remote Check 进行服务端验证且服务器返回 unverified,您可以选择不发放商品并让该笔购买超时(用户将获得退款)。如果您选择发放商品,请调用 ConfirmPurchase 立即消耗该笔购买。
对于以运行时故障形式出现的安装与配置问题,请参见疑难解答指南。