Skip to main content
Supported on: iOS SDK 1.0.61+ · Android SDK 1.0.33+ · Flutter SDK 1.0.3+
The AppDNA Flutter SDK provides a billing module for managing in-app purchases, subscriptions, entitlement verification, and purchase restoration. All billing logic is handled by the native iOS and Android SDKs through the com.appdna.sdk/billing MethodChannel and the com.appdna.sdk/entitlements EventChannel.

Configuration

Set the billing provider when configuring the SDK:

AppDNABillingProvider Options

You must set the billingProvider in AppDNAOptions before accessing AppDNA.billing. If set to AppDNABillingProvider.none, billing module methods will throw errors.

Billing Module

Access the billing module through AppDNA.billing, which returns an AppDNABilling instance:

Get Products

Fetch product information for one or more product identifiers:
Returns List<ProductInfo>.

ProductInfo

Purchase a Product

Initiate a purchase for a product:
Returns a PurchaseResult.

PurchaseResult

Transaction Map Keys

The transaction payload delivered to onPurchaseCompleted (and AppDNAPaywallDelegate.onPaywallPurchaseCompleted) is a Map<String, dynamic> with the following store-verified keys:
The offerToken parameter on purchase(...) is optional. On Android, pass the offer token from ProductInfo.offerToken to select a specific subscription offer. On iOS, this parameter is ignored. For Apple promotional offers (iOS), the SDK auto-applies any offer associated with the product in App Store Connect.
Server-side receipt verification is performed automatically by the SDK. You do not need to send receipts to your own server for validation.

Restore Purchases

Restore previously purchased products (e.g., after reinstalling the app or switching devices):
Returns List<Entitlement>.
Apple requires that all apps with in-app purchases include a restore mechanism. Call restorePurchases() when the user taps a “Restore Purchases” button.

Check Active Subscription

Check whether the user has an active subscription:
Returns bool.

Get Entitlements

Retrieve all current entitlements for the user:
Returns List<Entitlement>.

Entitlement

Real-Time Entitlement Changes

Stream

Listen for entitlement changes in real time via the com.appdna.sdk/entitlements EventChannel:
Returns Stream<List<Entitlement>>.

Callback

Alternatively, register a callback for entitlement changes:

AppDNABillingDelegate

Implement the AppDNABillingDelegate abstract class for fine-grained billing lifecycle callbacks:
The 5 methods semantics:
  • onPurchaseCompleted(productId, transaction) — fires after the store completes a purchase (paywall, direct AppDNA.billing.purchase(...), or transaction queue retry). The transaction map shape is documented above.
  • onPurchaseFailed(productId, error) — fires on store-side failure (user cancel, payment declined, network). The error is a typed Object (usually Map<String, dynamic> from native with message + type keys, or a raw String).
  • onEntitlementsChanged(entitlements) — fires whenever the active entitlement set changes (purchase, restore, renewal, expiry, refund). Delivers a list of entitlement maps, each shaped like an Entitlement (productId / store / status / expiresAt / isTrial / offerType) — parse each with Entitlement.fromMap. For strongly-typed Entitlement objects you can also call AppDNA.billing.getEntitlements() from inside the callback, or subscribe to the AppDNA.billing.onEntitlementsChanged stream instead.
  • onRestoreCompleted(restoredProductIds) — fires when a direct AppDNA.billing.restorePurchases() call resolves. Empty list means no prior purchases on file.
  • onBillingUnavailable() — fires when billing is permanently unavailable (Play Services missing or broken). Android-only — it never fires on iOS. Hide paywalls / disable purchase UI when it fires.
Overlap with AppDNAPaywallDelegate. When a purchase originates from a paywall, the paywall delegate fires onPaywallPurchaseStarted / onPaywallPurchaseCompleted / onPaywallPurchaseFailed. The billing delegate ALSO fires onPurchaseCompleted / onPurchaseFailed for that same purchase — they’re independent observers. Register both if you want paywall-specific UI (banners, confetti) AND a global purchase log; register only the billing delegate if you only care about the eventual state.

Example Implementation

Full Example

Always test purchases using sandbox/test accounts. On iOS, use StoreKit Testing in Xcode or a Sandbox Apple ID. On Android, use license testing accounts configured in the Google Play Console.

Auto-Tracked Events

The SDK automatically tracks the following billing events. You don’t need to call AppDNA.track(...) for any of them. Android-only events (fired by Play Billing’s subscription lifecycle): These events flow into the AppDNA Console exactly like any custom event you track yourself, and feed retention / monetization dashboards out of the box.