メインコンテンツまでスキップ

错误参考

本页是 AppCoins iOS SDK 可能返回的所有错误码的完整参考,涵盖原生 Swift 接口以及 Unity IAP v5 集成。针对每个错误,您都可以找到其含义、最常见的原因以及推荐的解决方法。


Swift 错误(AppCoinsSDKError

Swift SDK 抛出的所有错误均为 AppCoinsSDKError 类型。该枚举包含六种情形。

networkError

SDK 发起的网络请求在收到响应之前失败。

常见原因:

  • 设备没有网络连接。
  • Aptoide 计费服务器暂时无法访问。
  • 请求超时。

解决方法:

  1. 在调用 SDK 方法之前检查网络连通性(例如使用 NWPathMonitor)。
  2. 针对瞬时故障实现带指数退避的重试机制。
  3. 向用户展示类似「请检查网络连接后重试」的提示。
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 计费服务器返回了非预期或格式错误的响应。

解决方法:

  1. 记录完整的错误描述以便诊断。
  2. 稍作延迟后重试该操作一次。
  3. 如果该错误跨会话持续出现,请附上已记录的描述向 Aptoide 支持团队报告。
if case .systemError(let description) = error {
print("System error: \(description)")
}

notEntitled

宿主应用缺少 SDK 存储钱包信息所需的 Keychain Sharing 授权。

常见原因:

  • 尚未为该 target 添加 Keychain Sharing 能力。
  • 钥匙串分组被设置为 com.aptoide.appcoins-wallet 以外的值(例如应用自身的 bundle identifier)。

解决方法:

  1. 在 Xcode 中选择您的 target,进入 Signing & Capabilities 标签页。
  2. 点击 + 并添加 Keychain Sharing 能力。
  3. Keychain Groups 列表中,将已有条目准确替换为 com.aptoide.appcoins-wallet
  4. 执行 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 中被停用。

解决方法:

  1. 打开 Aptoide Connect,逐字符核对 SKU 标识符是否完全一致(区分大小写)。
  2. 确认您的应用已在 Aptoide Connect 上提交并通过审核。在应用通过审核之前无法查询商品。
  3. 确认该商品处于启用状态且未被归档。
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

发生了不属于上述任何类别的错误。

解决方法:

  1. 记录该错误返回的描述以便诊断。
  2. 将其视为瞬时故障,允许用户重试。
  3. 如果该错误持续出现,请附上完整描述向 Aptoide 支持团队报告。
if case .unknown(let description) = error {
print("Unknown error: \(description)")
}

Unity 错误(AppCoinsSDKError 到 Unity IAP 的映射)

Unity IAP v5 集成会将 AppCoins 错误转换为标准的 Unity IAP 失败原因。下表列出完整映射关系。

AppCoins 错误Unity IAP 原因适用于
productUnavailableProductFetchFailureReason.ProductsUnavailableOnProductsFetchFailed
networkErrorProductFetchFailureReason.ProviderUnavailableOnProductsFetchFailed
productUnavailablePurchaseFailureReason.ProductUnavailableOnPurchaseFailed
purchaseNotAllowedPurchaseFailureReason.PaymentDeclinedOnPurchaseFailed
notEntitledPurchaseFailureReason.PaymentDeclinedOnPurchaseFailed
systemErrorPurchaseFailureReason.UnknownOnPurchaseFailed
unknownPurchaseFailureReason.UnknownOnPurchaseFailed

在 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 立即消耗该笔购买。


对于以运行时故障形式出现的安装与配置问题,请参见疑难解答指南