
KMP-IAP 1.0.0 brings built-in purchase verification (aka receipt validation) powered by IAPKit. Now you can verify purchases with enterprise-grade backend validation using a single API call-no server setup required.
Why IAPKit?โ
Purchase verification is critical for any production IAP implementation. Without proper server-side validation, your app is vulnerable to receipt tampering, replay attacks, and fraudulent transactions. IAPKit solves this with a battle-tested backend infrastructure. Sign up at iapkit.com to get your API key and start verifying purchases in minutes.
Key Benefitsโ
| Benefit | Description | |
|---|---|---|
| ๐ | Security First | Server-side validation that prevents fraud, receipt tampering, and token reuse. Far more secure than client-only verification. |
| ๐ | Unified API | Single endpoint for both Apple App Store and Google Play. No separate validation logic needed. |
| โก | Zero Infrastructure | No server setup required. IAPKit handles Apple and Google API complexity for you. |
| ๐ญ | Production Ready | Enterprise-grade reliability with comprehensive error handling and detailed responses. |
Getting Startedโ
Use the new verifyPurchaseWithProvider API to verify purchases through IAPKit:
import io.github.hyochan.kmpiap.kmpIapInstance
import io.github.hyochan.kmpiap.openiap.*
val result = kmpIapInstance.verifyPurchaseWithProvider(
VerifyPurchaseWithProviderProps(
provider = PurchaseVerificationProvider.Iapkit,
iapkit = RequestVerifyPurchaseWithIapkitProps(
apiKey = "your-iapkit-api-key",
apple = RequestVerifyPurchaseWithIapkitAppleProps(jws = purchase.jws),
google = RequestVerifyPurchaseWithIapkitGoogleProps(
purchaseToken = purchase.purchaseToken
)
)
)
)
if (result.iapkit?.isValid == true) {
// Purchase verified - grant entitlement
println("Purchase state: ${result.iapkit?.state}")
println("Store: ${result.iapkit?.store}")
}
The API returns a unified VerifyPurchaseWithProviderResult with:
isValid- Whether the purchase passed verificationstate- Detailed purchase state (entitled, pending, expired, canceled, etc.)store- The store where the purchase was made (apple, google, horizon)
Highlightsโ
- IAPKit Integration - Built-in purchase verification (aka receipt validation) with enterprise-grade backend
- OpenIAP 1.3.0 - Updated to openiap-apple v1.3.0, openiap-google v1.3.10, and openiap-gql v1.3.0
- New
IapStoreType - Unified store identification:Unknown,Apple,Google,Horizon - Enhanced Purchase Types - New
storefield on Purchase (replaces deprecatedplatform)
Type System Updatesโ
This release brings important type refinements aligned with the OpenIAP 1.3.0 specification:
New IapStore Enumโ
enum class IapStore(val rawValue: String) {
Unknown("unknown"),
Apple("apple"),
Google("google"),
Horizon("horizon")
}
Updated Purchase Typesโ
All purchase types now include a store field for unified store identification:
val purchase = PurchaseIOS(
productId = "premium",
transactionId = "12345",
store = IapStore.Apple, // NEW - unified store identification
// ...other fields
)
Request Parametersโ
Request parameters now support apple/google keys alongside the legacy ios/android:
// New (recommended)
kmpIapInstance.requestPurchase(
RequestPurchaseProps(
apple = RequestPurchasePropsApple(sku = productId),
google = RequestPurchasePropsGoogle(skus = listOf(productId))
)
)
// Legacy (still supported but deprecated)
kmpIapInstance.requestPurchase(
RequestPurchaseProps(
ios = RequestPurchasePropsIos(sku = productId),
android = RequestPurchasePropsAndroid(skus = listOf(productId))
)
)
Migration from 1.0.0-rcโ
Store Fieldโ
If you're checking platform-specific purchases, consider using the new store field:
// Before (1.0.0-rc)
if (purchase.platform == IapPlatform.Ios) {
// Handle iOS purchase
}
// After (1.0.0)
if (purchase.store == IapStore.Apple) {
// Handle Apple purchase
}
Verification Integrationโ
Add purchase verification to your existing purchase flow:
import io.github.hyochan.kmpiap.kmpIapInstance
import io.github.hyochan.kmpiap.openiap.*
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
// After successful purchase
scope.launch {
kmpIapInstance.purchaseUpdatedListener.collect { purchase ->
// Verify the purchase
val verification = kmpIapInstance.verifyPurchaseWithProvider(
VerifyPurchaseWithProviderProps(
provider = PurchaseVerificationProvider.Iapkit,
iapkit = RequestVerifyPurchaseWithIapkitProps(
apiKey = "your-api-key",
apple = RequestVerifyPurchaseWithIapkitAppleProps(
jws = (purchase as? PurchaseIOS)?.jwsRepresentationIOS
),
google = RequestVerifyPurchaseWithIapkitGoogleProps(
purchaseToken = purchase.purchaseToken
)
)
)
)
if (verification.iapkit?.isValid == true) {
// Grant entitlement
grantPurchase(purchase.productId)
// Finish the transaction
kmpIapInstance.finishTransaction(
purchase = purchase,
isConsumable = true
)
}
}
}
IAPKit Purchase Statesโ
The IapkitPurchaseState enum provides detailed purchase status:
| State | Description |
|---|---|
Entitled | Purchase is valid and user has access |
PendingAcknowledgment | Purchase needs acknowledgment (Android) |
Pending | Purchase is being processed |
Canceled | Purchase was canceled |
Expired | Subscription has expired |
ReadyToConsume | Consumable ready to be consumed |
Consumed | Consumable has been consumed |
Inauthentic | Purchase failed verification (potential fraud) |
Unknown | Unknown state |
Installationโ
Gradle (Kotlin DSL)โ
// shared/build.gradle.kts
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.hyochan:kmp-iap:1.0.0")
}
}
}
Gradle (Groovy)โ
// shared/build.gradle
kotlin {
sourceSets {
commonMain {
dependencies {
implementation 'io.github.hyochan:kmp-iap:1.0.0'
}
}
}
}
Version Catalog (libs.versions.toml)โ
[versions]
kmp-iap = "1.0.0"
[libraries]
kmp-iap = { module = "io.github.hyochan:kmp-iap", version.ref = "kmp-iap" }
Then sync your Gradle project.
Referencesโ
- IAPKit
- verifyPurchaseWithProvider API
- OpenIAP Ecosystem
- Purchase Flow Example
- Subscription Flow Example
Questions or feedback? Reach out via GitHub Issues or join our Slack community.
