From 094c6c3a49eb4e91a850f1e6f1ca0970581f3e78 Mon Sep 17 00:00:00 2001 From: Hyo Date: Fri, 3 Oct 2025 06:02:34 +0900 Subject: [PATCH 1/3] chore(deps): openiap-gql v1.0.11 --- openiap-versions.json | 2 +- .../src/main/java/dev/hyo/openiap/Types.kt | 71 +++++++++---------- .../hyo/openiap/utils/BillingConverters.kt | 12 +--- 3 files changed, 34 insertions(+), 51 deletions(-) diff --git a/openiap-versions.json b/openiap-versions.json index 78d7c27..6de2395 100644 --- a/openiap-versions.json +++ b/openiap-versions.json @@ -1,4 +1,4 @@ { "google": "1.2.10", - "gql": "1.0.10" + "gql": "1.0.11" } diff --git a/openiap/src/main/java/dev/hyo/openiap/Types.kt b/openiap/src/main/java/dev/hyo/openiap/Types.kt index 0b54a16..681607e 100644 --- a/openiap/src/main/java/dev/hyo/openiap/Types.kt +++ b/openiap/src/main/java/dev/hyo/openiap/Types.kt @@ -368,6 +368,13 @@ public interface ProductCommon { } public interface PurchaseCommon { + /** + * The current plan identifier. This is: + * - On Android: the basePlanId (e.g., "premium", "premium-year") + * - On iOS: the productId (e.g., "com.example.premium_monthly", "com.example.premium_yearly") + * This provides a unified way to identify which specific plan/tier the user is subscribed to. + */ + val currentPlanId: String? val id: String val ids: List? val isAutoRenewing: Boolean @@ -386,12 +393,24 @@ public interface PurchaseCommon { public data class ActiveSubscription( val autoRenewingAndroid: Boolean? = null, + val basePlanIdAndroid: String? = null, + /** + * The current plan identifier. This is: + * - On Android: the basePlanId (e.g., "premium", "premium-year") + * - On iOS: the productId (e.g., "com.example.premium_monthly", "com.example.premium_yearly") + * This provides a unified way to identify which specific plan/tier the user is subscribed to. + */ + val currentPlanId: String? = null, val daysUntilExpirationIOS: Double? = null, val environmentIOS: String? = null, val expirationDateIOS: Double? = null, val isActive: Boolean, val productId: String, val purchaseToken: String? = null, + /** + * Required for subscription upgrade/downgrade on Android + */ + val purchaseTokenAndroid: String? = null, val transactionDate: Double, val transactionId: String, val willExpireSoon: Boolean? = null @@ -401,12 +420,15 @@ public data class ActiveSubscription( fun fromJson(json: Map): ActiveSubscription { return ActiveSubscription( autoRenewingAndroid = json["autoRenewingAndroid"] as Boolean?, + basePlanIdAndroid = json["basePlanIdAndroid"] as String?, + currentPlanId = json["currentPlanId"] as String?, daysUntilExpirationIOS = (json["daysUntilExpirationIOS"] as Number?)?.toDouble(), environmentIOS = json["environmentIOS"] as String?, expirationDateIOS = (json["expirationDateIOS"] as Number?)?.toDouble(), isActive = json["isActive"] as Boolean, productId = json["productId"] as String, purchaseToken = json["purchaseToken"] as String?, + purchaseTokenAndroid = json["purchaseTokenAndroid"] as String?, transactionDate = (json["transactionDate"] as Number).toDouble(), transactionId = json["transactionId"] as String, willExpireSoon = json["willExpireSoon"] as Boolean?, @@ -417,12 +439,15 @@ public data class ActiveSubscription( fun toJson(): Map = mapOf( "__typename" to "ActiveSubscription", "autoRenewingAndroid" to autoRenewingAndroid, + "basePlanIdAndroid" to basePlanIdAndroid, + "currentPlanId" to currentPlanId, "daysUntilExpirationIOS" to daysUntilExpirationIOS, "environmentIOS" to environmentIOS, "expirationDateIOS" to expirationDateIOS, "isActive" to isActive, "productId" to productId, "purchaseToken" to purchaseToken, + "purchaseTokenAndroid" to purchaseTokenAndroid, "transactionDate" to transactionDate, "transactionId" to transactionId, "willExpireSoon" to willExpireSoon, @@ -956,6 +981,7 @@ public data class ProductSubscriptionIOS( public data class PurchaseAndroid( val autoRenewingAndroid: Boolean? = null, + override val currentPlanId: String? = null, val dataAndroid: String? = null, val developerPayloadAndroid: String? = null, override val id: String, @@ -979,6 +1005,7 @@ public data class PurchaseAndroid( fun fromJson(json: Map): PurchaseAndroid { return PurchaseAndroid( autoRenewingAndroid = json["autoRenewingAndroid"] as Boolean?, + currentPlanId = json["currentPlanId"] as String?, dataAndroid = json["dataAndroid"] as String?, developerPayloadAndroid = json["developerPayloadAndroid"] as String?, id = json["id"] as String, @@ -1003,6 +1030,7 @@ public data class PurchaseAndroid( override fun toJson(): Map = mapOf( "__typename" to "PurchaseAndroid", "autoRenewingAndroid" to autoRenewingAndroid, + "currentPlanId" to currentPlanId, "dataAndroid" to dataAndroid, "developerPayloadAndroid" to developerPayloadAndroid, "id" to id, @@ -1053,6 +1081,7 @@ public data class PurchaseIOS( val countryCodeIOS: String? = null, val currencyCodeIOS: String? = null, val currencySymbolIOS: String? = null, + override val currentPlanId: String? = null, val environmentIOS: String? = null, val expirationDateIOS: Double? = null, override val id: String, @@ -1089,6 +1118,7 @@ public data class PurchaseIOS( countryCodeIOS = json["countryCodeIOS"] as String?, currencyCodeIOS = json["currencyCodeIOS"] as String?, currencySymbolIOS = json["currencySymbolIOS"] as String?, + currentPlanId = json["currentPlanId"] as String?, environmentIOS = json["environmentIOS"] as String?, expirationDateIOS = (json["expirationDateIOS"] as Number?)?.toDouble(), id = json["id"] as String, @@ -1126,6 +1156,7 @@ public data class PurchaseIOS( "countryCodeIOS" to countryCodeIOS, "currencyCodeIOS" to currencyCodeIOS, "currencySymbolIOS" to currencySymbolIOS, + "currentPlanId" to currentPlanId, "environmentIOS" to environmentIOS, "expirationDateIOS" to expirationDateIOS, "id" to id, @@ -1582,45 +1613,7 @@ public data class ProductRequest( ) } -public data class PurchaseInput( - val id: String, - val ids: List? = null, - val isAutoRenewing: Boolean, - val platform: IapPlatform, - val productId: String, - val purchaseState: PurchaseState, - val purchaseToken: String? = null, - val quantity: Int, - val transactionDate: Double -) { - companion object { - fun fromJson(json: Map): PurchaseInput { - return PurchaseInput( - id = json["id"] as String, - ids = (json["ids"] as List<*>?)?.map { it as String }, - isAutoRenewing = json["isAutoRenewing"] as Boolean, - platform = IapPlatform.fromJson(json["platform"] as String), - productId = json["productId"] as String, - purchaseState = PurchaseState.fromJson(json["purchaseState"] as String), - purchaseToken = json["purchaseToken"] as String?, - quantity = (json["quantity"] as Number).toInt(), - transactionDate = (json["transactionDate"] as Number).toDouble(), - ) - } - } - - fun toJson(): Map = mapOf( - "id" to id, - "ids" to ids?.map { it }, - "isAutoRenewing" to isAutoRenewing, - "platform" to platform.toJson(), - "productId" to productId, - "purchaseState" to purchaseState.toJson(), - "purchaseToken" to purchaseToken, - "quantity" to quantity, - "transactionDate" to transactionDate, - ) -} +public typealias PurchaseInput = Purchase public data class PurchaseOptions( /** diff --git a/openiap/src/main/java/dev/hyo/openiap/utils/BillingConverters.kt b/openiap/src/main/java/dev/hyo/openiap/utils/BillingConverters.kt index 32aa7d9..c9d81d9 100644 --- a/openiap/src/main/java/dev/hyo/openiap/utils/BillingConverters.kt +++ b/openiap/src/main/java/dev/hyo/openiap/utils/BillingConverters.kt @@ -155,14 +155,4 @@ fun ProductSubscriptionAndroid.toProduct(): Product = ProductAndroid( type = type ) -fun Purchase.toPurchaseInput(): PurchaseInput = PurchaseInput( - id = id, - ids = ids, - isAutoRenewing = isAutoRenewing, - platform = platform, - productId = productId, - purchaseState = purchaseState, - purchaseToken = purchaseToken, - quantity = quantity, - transactionDate = transactionDate -) +fun Purchase.toPurchaseInput(): PurchaseInput = this From a5bf89d1fc6e75c7d5c77cc6b33d5fefa5f496bb Mon Sep 17 00:00:00 2001 From: Hyo Date: Fri, 3 Oct 2025 06:06:07 +0900 Subject: [PATCH 2/3] fix: example codes --- .../hyo/martie/screens/AlternativeBillingScreen.kt | 13 +------------ .../hyo/martie/screens/AvailablePurchasesScreen.kt | 13 +------------ .../hyo/martie/screens/SubscriptionFlowScreen.kt | 13 +------------ 3 files changed, 3 insertions(+), 36 deletions(-) diff --git a/Example/src/main/java/dev/hyo/martie/screens/AlternativeBillingScreen.kt b/Example/src/main/java/dev/hyo/martie/screens/AlternativeBillingScreen.kt index fb58795..67c18a0 100644 --- a/Example/src/main/java/dev/hyo/martie/screens/AlternativeBillingScreen.kt +++ b/Example/src/main/java/dev/hyo/martie/screens/AlternativeBillingScreen.kt @@ -86,18 +86,7 @@ fun AlternativeBillingScreen(navController: NavController) { val purchaseAndroid = purchase as? PurchaseAndroid if (purchaseAndroid != null) { android.util.Log.d("AlternativeBilling", "Auto-finishing transaction for testing") - val purchaseInput = PurchaseInput( - id = purchaseAndroid.id, - ids = purchaseAndroid.ids, - isAutoRenewing = purchaseAndroid.isAutoRenewing ?: false, - platform = purchaseAndroid.platform, - productId = purchaseAndroid.productId, - purchaseState = purchaseAndroid.purchaseState, - purchaseToken = purchaseAndroid.purchaseToken, - quantity = purchaseAndroid.quantity ?: 1, - transactionDate = purchaseAndroid.transactionDate ?: 0.0 - ) - iapStore.finishTransaction(purchaseInput, true) + iapStore.finishTransaction(purchaseAndroid, true) } } catch (e: Exception) { android.util.Log.e("AlternativeBilling", "Auto-finish failed: ${e.message}") diff --git a/Example/src/main/java/dev/hyo/martie/screens/AvailablePurchasesScreen.kt b/Example/src/main/java/dev/hyo/martie/screens/AvailablePurchasesScreen.kt index fe4dbad..152e0c5 100644 --- a/Example/src/main/java/dev/hyo/martie/screens/AvailablePurchasesScreen.kt +++ b/Example/src/main/java/dev/hyo/martie/screens/AvailablePurchasesScreen.kt @@ -218,18 +218,7 @@ fun AvailablePurchasesScreen( onFinish = { isConsumable -> scope.launch { try { - val purchaseInput = dev.hyo.openiap.PurchaseInput( - id = purchase.id, - ids = purchase.ids, - isAutoRenewing = purchase.isAutoRenewing, - platform = purchase.platform, - productId = purchase.productId, - purchaseState = purchase.purchaseState, - purchaseToken = purchase.purchaseToken, - quantity = purchase.quantity, - transactionDate = purchase.transactionDate - ) - iapStore.finishTransaction(purchaseInput, isConsumable) + iapStore.finishTransaction(purchase, isConsumable) iapStore.postStatusMessage( message = "Transaction finished successfully", status = PurchaseResultStatus.Success, diff --git a/Example/src/main/java/dev/hyo/martie/screens/SubscriptionFlowScreen.kt b/Example/src/main/java/dev/hyo/martie/screens/SubscriptionFlowScreen.kt index e2c970a..fd19349 100644 --- a/Example/src/main/java/dev/hyo/martie/screens/SubscriptionFlowScreen.kt +++ b/Example/src/main/java/dev/hyo/martie/screens/SubscriptionFlowScreen.kt @@ -787,18 +787,7 @@ fun SubscriptionFlowScreen( // 4) Finish transaction try { - val purchaseInput = dev.hyo.openiap.PurchaseInput( - id = purchase.id, - ids = purchase.ids, - isAutoRenewing = purchase.isAutoRenewing, - platform = purchase.platform, - productId = purchase.productId, - purchaseState = purchase.purchaseState, - purchaseToken = purchase.purchaseToken, - quantity = purchase.quantity, - transactionDate = purchase.transactionDate - ) - iapStore.finishTransaction(purchaseInput, isConsumable) + iapStore.finishTransaction(purchase, isConsumable) iapStore.getAvailablePurchases(null) iapStore.postStatusMessage( message = "Transaction finished successfully", From 7327d79ffbbc85705d093063cdb46a6b7aab12a7 Mon Sep 17 00:00:00 2001 From: Hyo Date: Fri, 3 Oct 2025 06:11:53 +0900 Subject: [PATCH 3/3] fix: generate-types.sh --- scripts/generate-types.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/generate-types.sh b/scripts/generate-types.sh index 41d0f8c..abd2df3 100755 --- a/scripts/generate-types.sh +++ b/scripts/generate-types.sh @@ -161,6 +161,7 @@ product_props = { } purchase_props = { + "currentPlanId", "id", "ids", "isAutoRenewing",