InAppify

SDK errors and test checklist

Structured errors, empty offerings, uncertain purchases, unsupported capabilities and a safe release checklist.

Keep successful operations, missing selections and network failures distinct. Do not translate a network failure into “invalid discount” or “no subscription.”

Read results

Flutter: inspect isSuccess, then data or failure; failures expose code, message, isRetryable, details. Kotlin uses InappifyResult.Success or Failure.error. Successful lookups can contain null. JavaScript rejects Promises; use isInAppifyError(error) to identify SDK failures.

Review diagnostic messages before showing them. Retryable does not mean blindly repeat a payment; retain the original attempt/context. Keep credentials, receipts, tickets and full payment URLs out of public logs/tickets.

Common signals

SignalCheck
configuration / notConfiguredCorrect public app key, package/bundle and awaited configure
unauthorizedMatching app/session; no invented tokens or another account fallback
network / timeoutTemporary state; reconcile purchases before another payment
purchaseCancelledNeutral cancellation feedback; no grant
UI_HOST_NOT_SUPPORTEDFlutterFragmentActivity or valid AndroidX Activity
PURCHASE_IN_PROGRESSPrevent concurrent starts and repeated taps
PRODUCT_TYPE_REQUIREDFresh catalog and valid product classification; don't guess
PURCHASE_PACKAGE_CONTEXT_REQUIREDComplete Package from an offering
RATE_LIMITED_NO_CACHERespect five-per-minute quota and retry timing
unsupportedOperationActual backend support, not facade signature alone
Web bridgeUnavailableBundle/load the JS provider before Flutter

Kotlin/Flutter enum names differ; native codes/reasons may be in details. Unknown state is not permission to assume payment success.

Empty offerings

Check key, catalog membership, SKU, current offering, placement, targeting and Web feature permissions. Use supported sync for attribute-based targeting. An unknown explicit offering ID must not silently become default.

Charged but outcome unknown

Do not automatically start another payment. Android reconciles the saved attempt through history/events and manual syncStorePurchases() when needed. iOS uses fresh CustomerInfo and supported Direct delivery; Web queries the same checkout ID. Dashboard customers and transactions help diagnosis. Consumables may await a host grant.

Before-release checklist

  • Guest/authenticated startup, restart, logout and account switch without predecessor data.
  • Current, placement, exact offering and missing selection; label returned currency units without guessed rial/toman conversion.
  • Attribute set/delete and quota-aware refresh, empty queue, network failure and five/60 limit.
  • Success, cancellation, repeated taps, post-payment network loss and process death.
  • Unknown lookup/unrelated event without cleared journals or duplicate payments.
  • Durable consumable grant, failed confirm and restart without double inventory.
  • Subscription expiry, inactive entitlement and failed reads without false certainty.
  • Web tickets/OTP, a non-default discounted offering and a forged return without a grant.

Routine tests use fakes, not real OTP/payment requests. Perform separately authorized live store checks with appropriate test accounts/products; examples don't guarantee free transactions. Build/unit success does not establish live payment or backend deployment.

API reference · Agent skill