From 099f79c6d1f0d07f41cc5a6f83a26c2636c41b26 Mon Sep 17 00:00:00 2001
From: Vladislav Shabanov <vshabanov88@gmail.com>
Date: Sun, 10 Jun 2018 16:35:01 +0700
Subject: [PATCH 1/4] Android subscription upgrade/downgrade

---
 README.md                                          |  2 +-
 .../main/java/com/dooboolab/RNIap/RNIapModule.java | 14 ++++++++++----
 index.d.ts                                         |  3 ++-
 index.js                                           |  5 +++--
 4 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index ecf5b2bb4..2dcca25b8 100644
--- a/README.md
+++ b/README.md
@@ -163,7 +163,7 @@ Lastly, this module also supports types for typescript users from `0.2.5`.
 | getSubscriptions | `string[]` Subscription IDs/skus | `Promise<Subscription[]>` | Get a list of subscriptions. Note: On iOS  this method has the same output as `getProducts`. Because iOS does not differentiate between IAP products and subscriptions.  |
 | getPurchaseHistory | | `Promise<Purchase[]>` | Gets an invetory of purchases made by the user regardless of consumption status (where possible) |
 | getAvailablePurchases | | `Promise<Purchase[]>` | Get all purchases made by the user (either non-consumable, or haven't been consumed yet)
-| buySubscription | `string` Subscription ID/sku | `Promise<Purchase>` | Create (buy) a subscription to a sku |
+| buySubscription | `string` Subscription ID/sku, `string` Old Subscription ID/sku (on Android) | `Promise<Purchase>` | Create (buy) a subscription to a sku. For upgrading/downgrading subscription on Android pass second parameter with current subscription ID, on iOS this is handled automatically by store. |
 | buyProduct | `string` Product ID/sku | `Promise<Purchase>` | Buy a product |
 | buyProductWithoutFinishTransaction | `string` Product ID/sku | `Promise<Purchase>` | Buy a product without finish transaction call (iOS only) |
 | finishTransaction | `void` | `void` | Send finishTransaction call to Apple IAP server. Call this function after receipt validation process |
diff --git a/android/src/main/java/com/dooboolab/RNIap/RNIapModule.java b/android/src/main/java/com/dooboolab/RNIap/RNIapModule.java
index 1fedb2421..574155f5f 100644
--- a/android/src/main/java/com/dooboolab/RNIap/RNIapModule.java
+++ b/android/src/main/java/com/dooboolab/RNIap/RNIapModule.java
@@ -308,19 +308,25 @@ public void onPurchaseHistoryResponse(@BillingClient.BillingResponse int respons
   }
 
   @ReactMethod
-  public void buyItemByType(String type, String sku, Promise promise) {
+  public void buyItemByType(String type, String sku, String oldSku, Promise promise) {
     final Activity activity = getCurrentActivity();
     if (activity == null) {
       promise.reject(E_UNKNOWN, "getCurrentActivity returned null");
     } else {
       addPromiseForKey(PROMISE_BUY_ITEM, promise);
-      BillingFlowParams flowParams = BillingFlowParams.newBuilder()
-          .setSku(sku)
+      BillingFlowParams.Builder builder = BillingFlowParams.newBuilder();
+
+      if (type == BillingClient.SkuType.SUBS && oldSku != null && !oldSku.isEmpty()) {
+        // Subscription upgrade/downgrade
+        builder.addOldSku(oldSku);
+      }
+
+      BillingFlowParams flowParams = builder.setSku(sku)
           .setType(type)
           .build();
 
       int responseCode = mBillingClient.launchBillingFlow(activity,flowParams);
-      Log.d(TAG, "buyItemByType (type: " + type + ", sku: " + sku + ") responseCode: " + responseCode + "(" + getBillingResponseCodeName(responseCode) + ")");
+      Log.d(TAG, "buyItemByType (type: " + type + ", sku: " + sku + ", oldSku: " + oldSku + ") responseCode: " + responseCode + "(" + getBillingResponseCodeName(responseCode) + ")");
       if (responseCode != BillingClient.BillingResponse.OK) {
         rejectPromisesWithBillingError(PROMISE_BUY_ITEM,responseCode);
       }
diff --git a/index.d.ts b/index.d.ts
index 199929cad..6b53034da 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -84,9 +84,10 @@ export function getAvailablePurchases() : Promise<Purchase[]>;
 /**
  * Create a subscription to a sku
  * @param {string} sku The product's sku/ID
+ * @param {string} oldSku Optional old product's ID for upgrade/downgrade (Android only)
  * @returns {Promise<Purchase>}
  */
-export function buySubscription(sku: string) : Promise<SubscriptionPurchase>;
+export function buySubscription(sku: string, oldSku: string) : Promise<SubscriptionPurchase>;
 
 /**
  * Buy a product
diff --git a/index.js b/index.js
index 6869bf0ff..ec10a9a74 100644
--- a/index.js
+++ b/index.js
@@ -86,11 +86,12 @@ export const getAvailablePurchases = () => Platform.select({
 /**
  * Create a subscription to a sku
  * @param {string} sku The product's sku/ID
+ * @param {string} oldSku Optional old product's ID for upgrade/downgrade (Android only)
  * @returns {Promise<SubscriptionPurchase>}
  */
-export const buySubscription = (sku) => Platform.select({
+export const buySubscription = (sku, oldSku) => Platform.select({
   ios: () => RNIapIos.buyProduct(sku),
-  android: () => RNIapModule.buyItemByType(ANDROID_ITEM_TYPE_SUBSCRIPTION, sku)
+  android: () => RNIapModule.buyItemByType(ANDROID_ITEM_TYPE_SUBSCRIPTION, sku, oldSku)
 })();
 
 /**

From ed331e8b09746c9298dcb23c371810b56c833b38 Mon Sep 17 00:00:00 2001
From: Vladislav Shabanov <vshabanov88@gmail.com>
Date: Sun, 10 Jun 2018 17:40:44 +0700
Subject: [PATCH 2/4] Fix type comparation

---
 android/src/main/java/com/dooboolab/RNIap/RNIapModule.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/android/src/main/java/com/dooboolab/RNIap/RNIapModule.java b/android/src/main/java/com/dooboolab/RNIap/RNIapModule.java
index 574155f5f..56a92c0cb 100644
--- a/android/src/main/java/com/dooboolab/RNIap/RNIapModule.java
+++ b/android/src/main/java/com/dooboolab/RNIap/RNIapModule.java
@@ -316,7 +316,7 @@ public void buyItemByType(String type, String sku, String oldSku, Promise promis
       addPromiseForKey(PROMISE_BUY_ITEM, promise);
       BillingFlowParams.Builder builder = BillingFlowParams.newBuilder();
 
-      if (type == BillingClient.SkuType.SUBS && oldSku != null && !oldSku.isEmpty()) {
+      if (type.equals(BillingClient.SkuType.SUBS) && oldSku != null && !oldSku.isEmpty()) {
         // Subscription upgrade/downgrade
         builder.addOldSku(oldSku);
       }

From 11f68de8dbdfd966bd966616a4acee5a8519d91b Mon Sep 17 00:00:00 2001
From: Vladislav Shabanov <vshabanov88@gmail.com>
Date: Mon, 11 Jun 2018 15:08:07 +0700
Subject: [PATCH 3/4] Make oldSku optional in TS definition

---
 index.d.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/index.d.ts b/index.d.ts
index 6b53034da..3610005c1 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -87,7 +87,7 @@ export function getAvailablePurchases() : Promise<Purchase[]>;
  * @param {string} oldSku Optional old product's ID for upgrade/downgrade (Android only)
  * @returns {Promise<Purchase>}
  */
-export function buySubscription(sku: string, oldSku: string) : Promise<SubscriptionPurchase>;
+export function buySubscription(sku: string, oldSku?: string) : Promise<SubscriptionPurchase>;
 
 /**
  * Buy a product

From 11b989af2803e84df8a3406ad974a9bde31b39d4 Mon Sep 17 00:00:00 2001
From: Vladislav Shabanov <vshabanov88@gmail.com>
Date: Mon, 11 Jun 2018 15:08:54 +0700
Subject: [PATCH 4/4] Make oldSku optional in JSDoc

---
 index.d.ts | 2 +-
 index.js   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/index.d.ts b/index.d.ts
index 3610005c1..7226a4f35 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -84,7 +84,7 @@ export function getAvailablePurchases() : Promise<Purchase[]>;
 /**
  * Create a subscription to a sku
  * @param {string} sku The product's sku/ID
- * @param {string} oldSku Optional old product's ID for upgrade/downgrade (Android only)
+ * @param {string} [oldSku] Optional old product's ID for upgrade/downgrade (Android only)
  * @returns {Promise<Purchase>}
  */
 export function buySubscription(sku: string, oldSku?: string) : Promise<SubscriptionPurchase>;
diff --git a/index.js b/index.js
index ec10a9a74..4cc5ef667 100644
--- a/index.js
+++ b/index.js
@@ -86,7 +86,7 @@ export const getAvailablePurchases = () => Platform.select({
 /**
  * Create a subscription to a sku
  * @param {string} sku The product's sku/ID
- * @param {string} oldSku Optional old product's ID for upgrade/downgrade (Android only)
+ * @param {string} [oldSku] Optional old product's ID for upgrade/downgrade (Android only)
  * @returns {Promise<SubscriptionPurchase>}
  */
 export const buySubscription = (sku, oldSku) => Platform.select({