Frequently Asked Questions
Common questions and answers about kmp-iap.
General Questions
Q: What platforms does kmp-iap support?
A: The library supports:
- iOS: 15.0+ with StoreKit 2
- Android: API 21+ (Android 5.0) with Google Play Billing Library v7+
- Desktop & Web: Planned for future releases
Windows, Linux, and Web support is on the roadmap as Kotlin Multiplatform expands to these platforms.
Q: How is kmp-iap different from flutter_inapp_purchase?
A: Key differences:
- Technology: kmp-iap uses Kotlin Multiplatform vs Flutter/Dart
- State Management: StateFlow vs Streams
- Integration: Works with Compose Multiplatform, native Android/iOS
- API Design: Coroutines-based vs Future/async-await
Q: Is this library free to use?
A: Yes, kmp-iap is open source and free to use under the MIT license. However, both Apple and Google charge fees for in-app purchases (typically 15-30%).
Setup & Configuration
Q: Do I need to configure anything in Xcode or Android Studio?
A: Yes, minimal setup is required:
iOS:
- Enable In-App Purchase capability in Xcode
- Configure products in App Store Connect
Android:
- Add
<uses-permission android:name="com.android.vending.BILLING" />to AndroidManifest.xml - Configure products in Google Play Console
See our setup guides for detailed instructions.
Q: Can I test purchases without publishing my app?
A: Yes:
iOS: Use sandbox testing with sandbox Apple IDs Android: Upload to Internal Testing track in Play Console
Both platforms require proper store setup but don't require public app release.
Q: How long does it take for products to appear after configuration?
A: Product availability varies:
- iOS: Usually within a few hours, up to 24 hours
- Android: Can take 24-48 hours after app upload
Products must be properly configured and approved in the respective stores.
Products & Subscriptions
Q: What's the difference between consumable and non-consumable products?
A:
- Consumable: Can be purchased multiple times (coins, gems, power-ups)
- Non-consumable: Purchased once, owned forever (remove ads, premium features)
- Subscriptions: Recurring purchases with auto-renewal
Q: How do I handle different product types?
A: Use the isConsumable parameter:
// For consumable products
val success = kmpIapInstance.finishTransaction(
purchase = purchase.toPurchaseInput(),
isConsumable = true
)
// For non-consumable products and subscriptions
val success = kmpIapInstance.finishTransaction(
purchase = purchase.toPurchaseInput(),
isConsumable = false
)
Q: Can I offer subscription trials?
A: Yes, but setup varies by platform:
- iOS: Configure introductory offers in App Store Connect
- Android: Configure free trials in Play Console
The library will return trial information in the product data.
Q: How do I handle subscription renewals?
A: Subscriptions auto-renew by default. To check status:
scope.launch {
val purchases = kmpIapInstance.getAvailablePurchases()
val activeSubscriptions = purchases.filter { purchase ->
subscriptionIds.contains(purchase.productId) &&
isActive(purchase)
}
}
}
Implement server-side receipt validation for accurate expiration checking.
Purchases & Transactions
Q: Why isn't my purchase completing?
A: Common causes:
- Not finishing transactions: Always call
finishTransaction() - No state observers: Set up StateFlow collectors before requesting purchases
- Network issues: Ensure device has internet connectivity
- Account issues: Verify store account is properly set up
Q: How do I restore purchases?
A: Purchases are automatically available via StateFlow:
suspend fun restorePurchases() {
try {
// Get available purchases
val purchases = kmpIapInstance.getAvailablePurchases()
purchases.forEach { purchase ->
// Re-deliver non-consumable products
if (isNonConsumable(purchase.productId)) {
deliverProduct(purchase)
}
}
} catch (e: PurchaseError) {
println("Restore failed: $e")
}
}
Q: Can users purchase the same product multiple times?
A: Depends on product type:
- Consumable: Yes, after finishing transaction as consumable
- Non-consumable: No, will get
PRODUCT_ALREADY_OWNEDerror - Subscription: Can upgrade/downgrade, but not duplicate
Q: How do I handle pending purchases on Android?
A: Monitor purchase state:
private fun handlePurchase(purchase: Purchase) {
when (purchase.purchaseState) {
PurchaseState.PURCHASED -> {
// Purchase completed
deliverProduct(purchase)
}
PurchaseState.PENDING -> {
// Purchase pending - show pending UI
showPendingMessage()
}
}
}
Security & Validation
Q: Do I need to validate receipts?
A: Yes, for production apps you should always validate receipts server-side to prevent fraud. The library provides receipt data, but validation must be implemented separately.
