Skip to main content
Version: 1.2

Purchase Flow

IAPKit - In-App Purchase Made Simple

Key Concepts

  • Always call initConnection() before any IAP operations
  • Listen to purchaseUpdatedListener and purchaseErrorListener for purchase results
  • Always call finishTransaction() after processing a purchase
  • Verify purchases server-side in production

Initialize

kmpIapInstance.initConnection()

Fetch Products

val products = kmpIapInstance.fetchProducts {
skus = listOf("coins_100", "premium_upgrade")
type = ProductQueryType.InApp
}

Listen for Purchases

// Success
kmpIapInstance.purchaseUpdatedListener.collect { purchase ->
// 1. Verify on server
// 2. Deliver content
// 3. Finish transaction
kmpIapInstance.finishTransaction(
purchase = purchase.toPurchaseInput(),
isConsumable = true
)
}

// Errors
kmpIapInstance.purchaseErrorListener.collect { error ->
when (error.code) {
ErrorCode.UserCancelled -> { /* Silent */ }
ErrorCode.AlreadyOwned -> { /* Suggest restore */ }
else -> { /* Show error */ }
}
}

Request Purchase

kmpIapInstance.requestPurchase {
ios {
sku = "coins_100"
// Optional: Attribution tracking (v1.3.7+)
// advancedCommerceData = "campaign_id"
}
google { skus = listOf("coins_100") } // Recommended (v1.3.15+)
}

Restore Purchases

val purchases = kmpIapInstance.getAvailablePurchases()
purchases.forEach { purchase ->
// Re-deliver non-consumables
}

Cleanup

kmpIapInstance.endConnection()

IAPKit Server Verification

For production apps, always verify purchases server-side. IAPKit provides a simple unified API for both iOS and Android verification.

Setup

  1. Get your API key from iapkit.com
  2. Configure environment variables:

Android (.env or local.properties):

IAPKIT_API_KEY=your_api_key_here

iOS (Secrets.xcconfig):

IAPKIT_API_KEY = your_api_key_here

How It Works

// In your purchase listener
kmpIapInstance.purchaseUpdatedListener.collect { purchase ->
val purchaseToken = purchase.purchaseToken
if (purchaseToken.isNullOrEmpty()) {
showError("No purchase token available")
return@collect
}

try {
val result = kmpIapInstance.verifyPurchaseWithProvider(
VerifyPurchaseWithProviderProps(
provider = PurchaseVerificationProvider.Iapkit,
iapkit = RequestVerifyPurchaseWithIapkitProps(
apiKey = AppConfig.iapkitApiKey,
apple = RequestVerifyPurchaseWithIapkitAppleProps(jws = purchaseToken),
google = RequestVerifyPurchaseWithIapkitGoogleProps(purchaseToken = purchaseToken)
)
)
)

if (result.iapkit?.isValid == true) {
// Grant entitlement to user
deliverProduct(purchase.productId)

// Finish the transaction
kmpIapInstance.finishTransaction(
purchase = purchase.toPurchaseInput(),
isConsumable = isConsumable(purchase.productId)
)
} else {
showError("Purchase verification failed: ${result.iapkit?.state}")
}
} catch (e: Exception) {
showError("Verification error: ${e.message}")
}
}

Verification Response

{
"isValid": true,
"state": "ENTITLED",
"store": "APPLE"
}
// Access in code
val isValid = result.iapkit?.isValid // true
val state = result.iapkit?.state // IapkitPurchaseState.Entitled
val store = result.iapkit?.store // IapStore.Apple or IapStore.Google

Verification Methods

MethodUse CaseSecurity
NoneDevelopment onlyNone
LocalBasic validationLow
IAPKitProduction appsHigh

Benefits of IAPKit

  • Unified API for iOS and Android
  • Real-time fraud detection
  • Subscription status tracking
  • Sandbox/Production environment detection
  • No backend infrastructure needed

For more details, visit the IAPKit Documentation.

IAPKit Purchase States

StateDescription
EntitledValid access
ExpiredSubscription expired
CanceledPurchase canceled
ConsumedConsumable used
InauthenticFraudulent

Next Steps