Skip to main content
Version: v1.0.0-beta

Types

Comprehensive type definitions for kmp-iap v1.0.0-rc following OpenIAP specification. All types are fully documented with Kotlin data classes for complete type safety and cross-platform compatibility.

OpenIAP Base Interfaces

ProductCommon (OpenIAP Base)

Base interface following OpenIAP specification for all product types.

interface ProductCommon {
val id: String // Unified product identifier
val title: String // Product title
val description: String // Product description
val type: ProductType // "inapp" or "subs"
val displayName: String? // Optional display name
val displayPrice: String // Formatted price for display
val currency: String // ISO currency code
val price: Double? // Numeric price value
val debugDescription: String?
val platform: String? // Platform identifier
}

PurchaseCommon (OpenIAP Base)

Base interface following OpenIAP specification for all purchase types.

interface PurchaseCommon {
val id: String // Transaction identifier
val productId: String // Product that was purchased
val ids: List<String>? // Multiple product IDs (Android)
val transactionId: String? // @deprecated - use id instead
val transactionDate: Double // Unix timestamp
val transactionReceipt: String
val purchaseToken: String? // Unified token field
val platform: String?
}

Platform-Specific Implementations

ProductIOS

iOS product implementation with platform-specific fields.

data class ProductIOS(
// ProductCommon fields
override val id: String,
override val title: String,
override val description: String,
override val type: ProductType,
override val displayPrice: String,
override val currency: String,
override val price: Double?,
override val debugDescription: String?,
override val displayName: String?,
override val platform: String = "ios",

// iOS-specific fields
val displayNameIOS: String,
val isFamilyShareableIOS: Boolean,
val jsonRepresentationIOS: String,
val subscriptionInfoIOS: SubscriptionInfoIOS? = null
) : ProductCommon

ProductAndroid

Android product implementation with Google Play Billing fields.

data class ProductAndroid(
// ProductCommon fields
override val id: String,
override val title: String,
override val description: String,
override val type: ProductType,
override val displayPrice: String,
override val currency: String,
override val price: Double?,
override val debugDescription: String?,
override val displayName: String?,
override val platform: String = "android",

// Android-specific fields
val nameAndroid: String,
val oneTimePurchaseOfferDetailsAndroid: ProductAndroidOneTimePurchaseOfferDetail? = null,
val subscriptionOfferDetailsAndroid: List<ProductSubscriptionAndroidOfferDetail>? = null
) : ProductCommon

PurchaseIOS

iOS purchase implementation with StoreKit fields.

data class PurchaseIOS(
// PurchaseCommon fields
override val id: String,
override val productId: String,
override val ids: List<String>? = null,
override val transactionId: String? = null, // @deprecated
override val transactionDate: Double,
override val transactionReceipt: String,
override val purchaseToken: String? = null,
override val platform: String = "ios",

// iOS-specific fields
val jwsRepresentationIOS: String? = null,
val originalTransactionDateIOS: Double? = null,
val originalTransactionIdentifierIOS: String? = null,
val transactionState: TransactionStateIOS? = null
) : PurchaseCommon

PurchaseAndroid

Android purchase implementation with Google Play Billing fields.

data class PurchaseAndroid(
// PurchaseCommon fields
override val id: String,
override val productId: String,
override val ids: List<String>? = null,
override val transactionId: String? = null, // @deprecated
override val transactionDate: Double,
override val transactionReceipt: String,
override val purchaseToken: String? = null,
override val platform: String = "android",

// Android-specific fields
val purchaseStateAndroid: AndroidPurchaseState? = null,
val acknowledgedAndroid: Boolean? = null,
val autoRenewingAndroid: Boolean? = null,
val obfuscatedAccountIdAndroid: String? = null,
val obfuscatedProfileIdAndroid: String? = null,
val orderIdAndroid: String? = null,
val packageNameAndroid: String? = null,
val purchaseTimeAndroid: Double? = null,
val purchaseTokenAndroid: String? = null, // @deprecated
val signatureAndroid: String? = null
) : PurchaseCommon

Type Aliases for Convenience

OpenIAP-compliant type aliases for backward compatibility and ease of use.

// Union types
typealias Product = ProductCommon
typealias Purchase = PurchaseCommon
typealias SubscriptionProduct = ProductCommon
typealias ProductPurchase = PurchaseCommon
typealias SubscriptionPurchase = PurchaseCommon

Request Types (OpenIAP-Compliant)

RequestPurchaseProps

OpenIAP-compliant purchase request structure with platform-specific options.

data class RequestPurchaseProps(
val ios: RequestPurchaseIosProps? = null,
val android: RequestPurchaseAndroidProps? = null
)

RequestPurchaseIosProps

iOS-specific purchase request parameters.

data class RequestPurchaseIosProps(
val sku: String,
val andDangerouslyFinishTransactionAutomatically: Boolean? = null,
val appAccountToken: String? = null,
val quantity: Int? = null,
val withOffer: PaymentDiscountIOS? = null
)

RequestPurchaseAndroidProps

Android-specific purchase request parameters.

data class RequestPurchaseAndroidProps(
val skus: List<String>,
val obfuscatedAccountIdAndroid: String? = null,
val obfuscatedProfileIdAndroid: String? = null,
val isOfferPersonalized: Boolean? = null
)

RequestSubscriptionProps

OpenIAP-compliant subscription request structure.

data class RequestSubscriptionProps(
val ios: RequestPurchaseIosProps? = null,
val android: RequestSubscriptionAndroidProps? = null
)

ActiveSubscription

Represents an active subscription with platform-specific details following OpenIAP specification.

data class ActiveSubscription(
val productId: String, // Product identifier
val isActive: Boolean, // Always true for active subscriptions

// iOS-specific fields
val expirationDateIOS: Long? = null, // Expiration timestamp (iOS only)
val environmentIOS: String? = null, // "Sandbox" | "Production" (iOS only)
val daysUntilExpirationIOS: Int? = null, // Days remaining until expiration (iOS only)

// Android-specific fields
val autoRenewingAndroid: Boolean? = null, // Auto-renewal status (Android only)

// Cross-platform fields
val willExpireSoon: Boolean? = null // True if expiring within 7 days
)

Platform-Specific Behavior:

  • iOS: Provides exact expiration dates, environment info, and calculated days until expiration
  • Android: Provides auto-renewal status. When false, the subscription will not renew
  • Cross-platform: willExpireSoon warns if subscription expires within 7 days

Use Cases:

  • Feature gating based on subscription status
  • Showing expiration warnings
  • Managing subscription renewals
  • Environment-specific testing (iOS Sandbox vs Production)

ProductRequest

Request parameters for loading products.

data class ProductRequest(
val skus: List<String>,
val type: ProductType
)

iOS-Specific Types

SubscriptionInfoIOS

iOS subscription information from StoreKit.

data class SubscriptionInfoIOS(
val subscriptionGroupId: String,
val subscriptionPeriod: SubscriptionOfferPeriod
)

SubscriptionOfferPeriod

iOS subscription period definition.

data class SubscriptionOfferPeriod(
val unit: String, // "DAY", "WEEK", "MONTH", "YEAR"
val value: Int // Number of units
)

PaymentDiscountIOS

iOS promotional offer payment discount.

data class PaymentDiscountIOS(
val identifier: String,
val keyIdentifier: String,
val nonce: String,
val signature: String,
val timestamp: Double
)

DiscountIOS

iOS product discount information.

data class DiscountIOS(
val identifier: String,
val type: String,
val numberOfPeriods: String,
val price: String,
val localizedPrice: String,
val paymentMode: String,
val subscriptionPeriod: String
)

Android-Specific Types

ProductAndroidOneTimePurchaseOfferDetail

Android one-time purchase offer details from Google Play Billing.

data class ProductAndroidOneTimePurchaseOfferDetail(
val formattedPrice: String,
val priceAmountMicros: String,
val priceCurrencyCode: String
)

ProductSubscriptionAndroidOfferDetail

Android subscription offer details.

data class ProductSubscriptionAndroidOfferDetail(
val basePlanId: String,
val offerId: String?,
val offerToken: String,
val pricingPhases: List<PricingPhaseAndroid>,
val offerTags: List<String>
)

PricingPhaseAndroid

Android subscription pricing phase.

data class PricingPhaseAndroid(
val formattedPrice: String,
val priceCurrencyCode: String,
val billingPeriod: String,
val billingCycleCount: Int,
val priceAmountMicros: String,
val recurrenceMode: Int
)

SubscriptionOfferAndroid

Android subscription offer for purchase requests.

data class SubscriptionOfferAndroid(
val basePlanId: String,
val offerId: String?,
val offerToken: String
)

RequestSubscriptionAndroidProps

Android-specific subscription request parameters.

data class RequestSubscriptionAndroidProps(
val skus: List<String>,
val obfuscatedAccountIdAndroid: String? = null,
val obfuscatedProfileIdAndroid: String? = null,
val isOfferPersonalized: Boolean? = null,
val purchaseTokenAndroid: String? = null,
val replacementModeAndroid: Int? = null,
val subscriptionOffers: List<SubscriptionOfferAndroid>
)

Enums

IapPlatform

Platform identifier for cross-platform compatibility.

enum class IapPlatform {
IOS,
ANDROID
}

Store

Store type identifier.

enum class Store {
NONE,
PLAY_STORE,
AMAZON,
APP_STORE
}

ProductType

Product type for queries.

enum class ProductType {
INAPP, // One-time purchases
SUBS // Subscriptions
}

TransactionStateIOS

iOS transaction states from StoreKit.

enum class TransactionStateIOS {
PURCHASING,
PURCHASED,
FAILED,
RESTORED,
DEFERRED
}

AndroidPurchaseState

Android purchase states from Google Play Billing.

enum class AndroidPurchaseState {
UNSPECIFIED_STATE, // 0 - Unspecified state
PURCHASED, // 1 - Purchase completed
PENDING // 2 - Purchase pending
}

SubscriptionPeriodUnitIOS

iOS subscription period units from StoreKit.

enum class SubscriptionPeriodUnitIOS {
DAY,
WEEK,
MONTH,
YEAR
}

DiscountPaymentModeIOS

iOS discount payment modes.

enum class DiscountPaymentModeIOS {
PAYASYOUGO,
PAYUPFRONT,
FREETRIAL
}

DiscountTypeIOS

iOS discount types.

enum class DiscountTypeIOS {
INTRODUCTORY,
SUBSCRIPTION
}

Error Types (OpenIAP-Compliant)

PurchaseError

Exception thrown for IAP errors following OpenIAP specification.

class PurchaseError(
val code: String, // ErrorCode enum value
override val message: String,
val responseCode: Int? = null,
val debugMessage: String? = null,
val purchaseToken: String? = null
) : Exception(message)

ErrorCode

OpenIAP-compliant error code enumeration.

enum class ErrorCode {
E_UNKNOWN,
E_USER_CANCELLED,
E_USER_ERROR,
E_ITEM_UNAVAILABLE,
E_REMOTE_ERROR,
E_NETWORK_ERROR,
E_SERVICE_ERROR,
E_RECEIPT_FAILED,
E_RECEIPT_FINISHED_FAILED,
E_NOT_PREPARED,
E_NOT_ENDED,
E_ALREADY_OWNED,
E_DEVELOPER_ERROR,
E_BILLING_RESPONSE_JSON_PARSE_ERROR,
E_DEFERRED_PAYMENT,
E_INTERRUPTED,
E_IAP_NOT_AVAILABLE,
E_PURCHASE_ERROR,
E_SYNC_ERROR,
E_TRANSACTION_VALIDATION_FAILED,
E_ACTIVITY_UNAVAILABLE,
E_ALREADY_PREPARED,
E_PENDING,
E_CONNECTION_CLOSED,
E_PRODUCT_NOT_AVAILABLE
}

Validation Types

ValidationOptions

Union type for platform-specific validation options.

sealed class ValidationOptions {
data class IOSValidation(
val receiptBody: IOSReceiptBody
) : ValidationOptions()

data class AndroidValidation(
val packageName: String,
val productId: String,
val productToken: String,
val accessToken: String,
val isSub: Boolean = false
) : ValidationOptions()
}

IOSReceiptBody

iOS receipt validation parameters.

data class IOSReceiptBody(
val receiptData: String,
val password: String? = null
)

ValidationResult

Receipt validation result.

data class ValidationResult(
val isValid: Boolean,
val status: Int,
val receipt: Map<String, Any>? = null
)

Utility Types

DeepLinkOptions

Options for deep linking to subscription management.

data class DeepLinkOptions(
val skuAndroid: String? = null,
val skuIOS: String? = null
)

PurchaseOptions

Options for querying purchases.

data class PurchaseOptions(
val productType: ProductType? = null,
val activeOnly: Boolean = false
)

ConnectionResult

Connection state result.

data class ConnectionResult(
val connected: Boolean,
val message: String
)

Subscription

Interface for event listeners.

interface Subscription {
fun remove()
}

Usage Examples

Cross-Platform Product Handling

// OpenIAP-compliant product handling
fun displayProduct(product: ProductCommon) {
// Use standardized fields
println("Product: ${product.title}")
println("Price: ${product.displayPrice}")
println("Type: ${product.type}")

// Platform-specific enhancements
when (product.platform) {
"ios" -> {
val iosProduct = product as ProductIOS
if (iosProduct.isFamilyShareableIOS) {
println("Available for family sharing")
}
}
"android" -> {
val androidProduct = product as ProductAndroid
androidProduct.oneTimePurchaseOfferDetailsAndroid?.let { offer ->
println("Detailed pricing: ${offer.formattedPrice}")
}
}
}
}

Standardized Purchase Processing

// OpenIAP-compliant purchase flow
kmpIapInstance.purchaseUpdatedListener.collect { purchase ->
// Use unified fields
val receiptData = PurchaseReceiptData(
transactionId = purchase.id,
productId = purchase.productId,
purchaseToken = purchase.purchaseToken,
transactionDate = purchase.transactionDate,
platform = purchase.platform
)

// Validate with your backend
val isValid = validateReceiptOnServer(receiptData)

if (isValid) {
// Grant entitlement
grantEntitlement(purchase.productId)

// Finish transaction
kmpIapInstance.finishTransaction(
purchase = purchase,
isConsumable = determineIfConsumable(purchase.productId)
)
}
}

Making Purchases with OpenIAP Request Structure

// OpenIAP-compliant purchase request
val purchase = kmpIapInstance.requestPurchase(
RequestPurchaseProps(
ios = RequestPurchaseIosProps(
sku = "premium",
quantity = 1
),
android = RequestPurchaseAndroidProps(
skus = listOf("premium")
)
)
)

Best Practices

  1. Use OpenIAP interfaces: Always work with ProductCommon and PurchaseCommon for maximum compatibility
  2. Platform-specific casting: Cast to platform-specific types only when needed for specific features
  3. Unified fields first: Use unified fields like purchaseToken instead of platform-specific deprecated fields
  4. Error handling: Always catch PurchaseError and check OpenIAP-compliant error codes
  5. Backward compatibility: Existing deprecated fields are still available for migration

Migration from Legacy Types

Type Aliases for Compatibility

// These work automatically with existing code
val products: List<Product> = kmpIapInstance.requestProducts(...)
val purchase: Purchase = kmpIapInstance.requestPurchase(...)

// But you can now access OpenIAP-compliant fields
products.forEach { product ->
val displayPrice = product.displayPrice // ✅ New unified field
val productType = product.type // ✅ New unified field
}

Deprecated Field Migration

// ❌ OLD: Platform-specific deprecated fields
val tokenOld = (purchase as? PurchaseAndroid)?.purchaseTokenAndroid
?: (purchase as? PurchaseIOS)?.jwsRepresentationIOS

// ✅ NEW: Unified purchaseToken field
val tokenNew = purchase.purchaseToken

// ❌ OLD: UnifiedPurchaseRequest (deprecated)
val oldRequest = UnifiedPurchaseRequest(sku = "premium")

// ✅ NEW: OpenIAP-compliant RequestPurchaseProps
val newRequest = RequestPurchaseProps(
ios = RequestPurchaseIosProps(sku = "premium"),
android = RequestPurchaseAndroidProps(skus = listOf("premium"))
)

See Also