From dcd883c58f17b55b7e708208ca038e0397ca781b Mon Sep 17 00:00:00 2001
From: "artem.semenov" <artem.semenov@freeconferencecall.com>
Date: Sun, 9 Apr 2023 18:28:02 +0300
Subject: [PATCH 1/2] Fixed consumable product purchase on Android

---
 .../AndroidInappPurchasePlugin.kt             | 23 +++++++++++--------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/android/src/main/kotlin/com/dooboolab/flutterinapppurchase/AndroidInappPurchasePlugin.kt b/android/src/main/kotlin/com/dooboolab/flutterinapppurchase/AndroidInappPurchasePlugin.kt
index bdd71936..b4918dd6 100644
--- a/android/src/main/kotlin/com/dooboolab/flutterinapppurchase/AndroidInappPurchasePlugin.kt
+++ b/android/src/main/kotlin/com/dooboolab/flutterinapppurchase/AndroidInappPurchasePlugin.kt
@@ -507,19 +507,22 @@ class AndroidInappPurchasePlugin internal constructor() : MethodCallHandler,
 
             // Get the selected offerToken from the product, or first one if this is a migrated from 4.0 product
             // or if the offerTokenIndex was not provided
+            val productDetailsParamsBuilder = ProductDetailsParams.newBuilder().setProductDetails(selectedProductDetails)
             var offerToken : String? = null
-            if (offerTokenIndex != null) {
-                offerToken = selectedProductDetails.subscriptionOfferDetails?.get(offerTokenIndex)?.offerToken
-            }
-            if (offerToken == null) {
-                offerToken = selectedProductDetails.subscriptionOfferDetails!![0].offerToken
+
+            if (type == BillingClient.ProductType.SUBS) {
+                if (offerTokenIndex != null) {
+                    offerToken = selectedProductDetails.subscriptionOfferDetails?.get(offerTokenIndex)?.offerToken
+                }
+                if (offerToken == null) {
+                    offerToken = selectedProductDetails.subscriptionOfferDetails!![0].offerToken
+                }
+
+                productDetailsParamsBuilder.setOfferToken(offerToken)
             }
 
-            val productDetailsParamsList =
-            listOf(ProductDetailsParams.newBuilder()
-                .setProductDetails(selectedProductDetails)
-                .setOfferToken(offerToken)
-                .build())
+            val productDetailsParamsList = listOf(productDetailsParamsBuilder.build())
+
             builder.setProductDetailsParamsList(productDetailsParamsList)
 
             val params = SubscriptionUpdateParams.newBuilder()

From fe3834467d5cbabb849c75838ae68d8db30dc1ab Mon Sep 17 00:00:00 2001
From: "artem.semenov" <artem.semenov@freeconferencecall.com>
Date: Sun, 18 Jun 2023 18:40:59 +0300
Subject: [PATCH 2/2] Fixed 'java.lang.IllegalStateException: Reply already
 submitted' exception in MethodResultWrapper

---
 .../MethodResultWrapper.kt                    | 20 +++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/android/src/main/kotlin/com/dooboolab/flutterinapppurchase/MethodResultWrapper.kt b/android/src/main/kotlin/com/dooboolab/flutterinapppurchase/MethodResultWrapper.kt
index a5abd8db..a10a5747 100644
--- a/android/src/main/kotlin/com/dooboolab/flutterinapppurchase/MethodResultWrapper.kt
+++ b/android/src/main/kotlin/com/dooboolab/flutterinapppurchase/MethodResultWrapper.kt
@@ -2,7 +2,6 @@ package com.dooboolab.flutterinapppurchase
 
 import android.os.Handler
 import io.flutter.plugin.common.MethodChannel
-import java.lang.Runnable
 import android.os.Looper
 
 // MethodChannel.Result wrapper that responds on the platform thread.
@@ -11,16 +10,29 @@ class MethodResultWrapper internal constructor(
     private val safeChannel: MethodChannel
 ) : MethodChannel.Result {
     private val handler: Handler = Handler(Looper.getMainLooper())
+    private var exhausted: Boolean = false
     override fun success(result: Any?) {
-        handler.post { safeResult.success(result) }
+        if (!exhausted) {
+            exhausted = true
+
+            handler.post { safeResult.success(result) }
+        }
     }
 
     override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {
-        handler.post { safeResult.error(errorCode, errorMessage, errorDetails) }
+        if (!exhausted) {
+            exhausted = true
+
+            handler.post { safeResult.error(errorCode, errorMessage, errorDetails) }
+        }
     }
 
     override fun notImplemented() {
-        handler.post { safeResult.notImplemented() }
+        if (!exhausted) {
+            exhausted = true
+
+            handler.post { safeResult.notImplemented() }
+        }
     }
 
     fun invokeMethod(method: String?, arguments: Any?) {