From 7f06e08a9dce960e1de2e1b920c1620e1c947b24 Mon Sep 17 00:00:00 2001 From: Surik Date: Wed, 21 Aug 2024 22:54:12 +0400 Subject: [PATCH 1/3] Added purchase options --- QonversionSandwich.podspec | 2 +- android/sandwich/build.gradle | 2 +- .../qonversion/sandwich/QonversionSandwich.kt | 101 ++++++++++++++---- ios/Podfile | 2 +- ios/Podfile.lock | 18 ++-- ios/sandwich/QonversionSandwich.swift | 28 ++++- 6 files changed, 118 insertions(+), 35 deletions(-) diff --git a/QonversionSandwich.podspec b/QonversionSandwich.podspec index 89f50fc..92b3d5d 100644 --- a/QonversionSandwich.podspec +++ b/QonversionSandwich.podspec @@ -19,5 +19,5 @@ Pod::Spec.new do |s| s.source_files = 'ios/sandwich/**/*.{h,m,swift}' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } - s.dependency "Qonversion", "5.11.1" + s.dependency "Qonversion", "5.12.0" end diff --git a/android/sandwich/build.gradle b/android/sandwich/build.gradle index 3767e89..cc74df0 100644 --- a/android/sandwich/build.gradle +++ b/android/sandwich/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.qonversion_version = '8.0.2' + ext.qonversion_version = '8.1.0' } plugins { diff --git a/android/sandwich/src/main/kotlin/io/qonversion/sandwich/QonversionSandwich.kt b/android/sandwich/src/main/kotlin/io/qonversion/sandwich/QonversionSandwich.kt index 9881a76..d9abdc2 100644 --- a/android/sandwich/src/main/kotlin/io/qonversion/sandwich/QonversionSandwich.kt +++ b/android/sandwich/src/main/kotlin/io/qonversion/sandwich/QonversionSandwich.kt @@ -10,6 +10,7 @@ import com.qonversion.android.sdk.dto.QAttributionProvider import com.qonversion.android.sdk.dto.QEnvironment import com.qonversion.android.sdk.dto.QLaunchMode import com.qonversion.android.sdk.dto.QPurchaseModel +import com.qonversion.android.sdk.dto.QPurchaseOptions import com.qonversion.android.sdk.dto.QPurchaseUpdateModel import com.qonversion.android.sdk.dto.QPurchaseUpdatePolicy import com.qonversion.android.sdk.dto.QRemoteConfig @@ -92,6 +93,7 @@ class QonversionSandwich( productId: String, offerId: String?, applyOffer: Boolean?, + contextKeys: List?, resultListener: ResultListener ) { val currentActivity = activityProvider.currentActivity @@ -100,13 +102,24 @@ class QonversionSandwich( return } - val purchaseModel = QPurchaseModel(productId, offerId) - if (applyOffer == false) { - purchaseModel.removeOffer() - } - val purchaseCallback = getEntitlementsCallback(resultListener) - Qonversion.shared.purchase(currentActivity, purchaseModel, purchaseCallback) + + Qonversion.shared.products(object: QonversionProductsCallback { + override fun onSuccess(products: Map) { + val product = products[productId] + if (product != null) { + val purchaseOptions = configurePurchaseOptions(offerId, applyOffer, contextKeys = contextKeys) + + Qonversion.shared.purchase(currentActivity, product, purchaseOptions, purchaseCallback) + } else { + purchaseCallback.onError(QonversionError(QonversionErrorCode.ProductNotFound)) + } + } + + override fun onError(error: QonversionError) { + purchaseCallback.onError(error) + } + }) } fun updatePurchase( @@ -115,6 +128,7 @@ class QonversionSandwich( applyOffer: Boolean?, oldProductId: String, updatePolicyKey: String?, + contextKeys: List?, resultListener: ResultListener ) { val currentActivity = activityProvider.currentActivity @@ -123,24 +137,25 @@ class QonversionSandwich( return } - val updatePolicy = updatePolicyKey?.let { - try { - QPurchaseUpdatePolicy.valueOf(it) - } catch (e: IllegalArgumentException) { - null + val purchaseCallback = getEntitlementsCallback(resultListener) + + Qonversion.shared.products(object: QonversionProductsCallback { + override fun onSuccess(products: Map) { + val product = products[productId] + val oldProduct = products[oldProductId] + if (product != null && oldProduct != null) { + val purchaseOptions = configurePurchaseOptions(offerId, applyOffer, oldProduct, updatePolicyKey, contextKeys) + + Qonversion.shared.updatePurchase(currentActivity, product, purchaseOptions, purchaseCallback) + } else { + purchaseCallback.onError(QonversionError(QonversionErrorCode.ProductNotFound)) + } } - } - val purchaseUpdateModel = QPurchaseUpdateModel(productId, oldProductId, updatePolicy, offerId) - if (applyOffer == false) { - purchaseUpdateModel.removeOffer() - } - val purchaseCallback = getEntitlementsCallback(resultListener) - Qonversion.shared.updatePurchase( - currentActivity, - purchaseUpdateModel, - purchaseCallback - ) + override fun onError(error: QonversionError) { + purchaseCallback.onError(error) + } + }) } fun checkEntitlements(resultListener: ResultListener) { @@ -365,6 +380,48 @@ class QonversionSandwich( return mapOf("success" to success) } + private fun configurePurchaseOptions( + offerId: String? = null, + applyOffer: Boolean? = null, + oldProduct: QProduct? = null, + updatePolicyKey: String? = null, + contextKeys: List? = null, + ): QPurchaseOptions { + val builder = QPurchaseOptions.Builder() + + if (oldProduct != null) { + builder.setOldProduct(oldProduct) + } + + val updatePolicy = updatePolicyKey?.let { + try { + QPurchaseUpdatePolicy.valueOf(it) + } catch (e: IllegalArgumentException) { + null + } + } + + if (updatePolicy != null) { + builder.setUpdatePolicy(updatePolicy) + } + + if (offerId != null) { + builder.setOfferId(offerId) + } + + if (applyOffer == false) { + builder.removeOffer() + } + + if (contextKeys != null) { + builder.setContextKeys(contextKeys) + } + + val purchaseOptions = builder.build() + + return purchaseOptions + } + private interface ProductCallback { fun onProductLoaded(product: QProduct) diff --git a/ios/Podfile b/ios/Podfile index 523970a..cc04d16 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -6,7 +6,7 @@ platform :ios, '9.0' use_frameworks! target 'QonversionSandwich' do - pod 'Qonversion', '5.10.0' + pod 'Qonversion', '5.12.0' end target 'Sample' do diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 771df09..2996b33 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,12 +1,12 @@ PODS: - - Qonversion (5.10.0): - - Qonversion/Main (= 5.10.0) - - Qonversion/Main (5.10.0) - - QonversionSandwich (4.5.0): - - Qonversion (= 5.10.0) + - Qonversion (5.12.0): + - Qonversion/Main (= 5.12.0) + - Qonversion/Main (5.12.0) + - QonversionSandwich (5.0.3): + - Qonversion (= 5.12.0) DEPENDENCIES: - - Qonversion (= 5.10.0) + - Qonversion (= 5.12.0) - QonversionSandwich (from `../`) SPEC REPOS: @@ -18,9 +18,9 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - Qonversion: 879e542136f238e963d5488ef31983f28bd315ef - QonversionSandwich: 40d9bb9065d0cc693b959552ad053e3d4bfc1a33 + Qonversion: ac2da69e497cb1f01cea13d82513fde14f338ca3 + QonversionSandwich: 11c3c29fccb4c0d22127df6e00a43ffbe461ab96 -PODFILE CHECKSUM: 47571a17dacda3f48496b805e608b6699cf2c2a7 +PODFILE CHECKSUM: 270a709ed1c745b2fbcd44832cb6e9be9fbbafe3 COCOAPODS: 1.15.2 diff --git a/ios/sandwich/QonversionSandwich.swift b/ios/sandwich/QonversionSandwich.swift index 7705976..552acbd 100644 --- a/ios/sandwich/QonversionSandwich.swift +++ b/ios/sandwich/QonversionSandwich.swift @@ -75,6 +75,26 @@ public class QonversionSandwich : NSObject { Qonversion.shared().purchase(productId, completion: purchaseCompletion) } + @objc public func purchase( + _ productId: String, + quantity: Int, + contextKeys: [String], + completion: @escaping BridgeCompletion + ) { + let purchaseCompletion = getPurchaseCompletionHandler(for: completion) + let purchaseOptions = Qonversion.PurchaseOptions(quantity: quantity, contextKeys: contextKeys) + Qonversion.shared().products { [weak self] result, err in + guard let self = self else { return } + + guard let product: Qonversion.Product = result[productId] else { + let error = self.productNotFoundError() + return purchaseCompletion([:], error, false) + } + + Qonversion.shared().purchaseProduct(product, options: purchaseOptions, completion: purchaseCompletion) + } + } + @objc public func purchaseProduct(_ productId: String, offeringId: String?, completion: @escaping BridgeCompletion) { guard let offeringId = offeringId else { return purchase(productId, completion: completion) @@ -100,7 +120,7 @@ public class QonversionSandwich : NSObject { self?.handleEntitlementsResult(entitlements, error, completion: completion) } } else { - let error = NSError.init(domain: QonversionErrorDomain, code: Qonversion.Error.productNotFound.rawValue, userInfo: nil) + let error = productNotFoundError() completion(nil, error.toSandwichError()) } @@ -361,6 +381,12 @@ public class QonversionSandwich : NSObject { isSubscribedOnAsyncEvents = true } + + private func productNotFoundError() -> NSError { + let error = NSError.init(domain: QonversionErrorDomain, code: Qonversion.Error.productNotFound.rawValue, userInfo: nil) + + return error + } } // MARK: - PurchasesDelegate From 2793e53c8f1ee27d1eb5f9f8cc4f5335cc2f7e3d Mon Sep 17 00:00:00 2001 From: Surik Sarkisyan Date: Thu, 22 Aug 2024 15:08:14 +0400 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Kamo Spertsyan --- .../qonversion/sandwich/QonversionSandwich.kt | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/android/sandwich/src/main/kotlin/io/qonversion/sandwich/QonversionSandwich.kt b/android/sandwich/src/main/kotlin/io/qonversion/sandwich/QonversionSandwich.kt index d9abdc2..f39adb0 100644 --- a/android/sandwich/src/main/kotlin/io/qonversion/sandwich/QonversionSandwich.kt +++ b/android/sandwich/src/main/kotlin/io/qonversion/sandwich/QonversionSandwich.kt @@ -381,40 +381,38 @@ class QonversionSandwich( } private fun configurePurchaseOptions( - offerId: String? = null, - applyOffer: Boolean? = null, + offerId: String?, + applyOffer: Boolean?, oldProduct: QProduct? = null, updatePolicyKey: String? = null, contextKeys: List? = null, ): QPurchaseOptions { val builder = QPurchaseOptions.Builder() - if (oldProduct != null) { - builder.setOldProduct(oldProduct) + oldProduct?.let { + builder.setOldProduct(it) } - val updatePolicy = updatePolicyKey?.let { + updatePolicyKey?.let { try { QPurchaseUpdatePolicy.valueOf(it) } catch (e: IllegalArgumentException) { null } + }?.let { + builder.setUpdatePolicy(it) } - if (updatePolicy != null) { - builder.setUpdatePolicy(updatePolicy) - } - - if (offerId != null) { - builder.setOfferId(offerId) + offerId?.let { + builder.setOfferId(it) } if (applyOffer == false) { builder.removeOffer() } - if (contextKeys != null) { - builder.setContextKeys(contextKeys) + contextKeys?.let { + builder.setContextKeys(it) } val purchaseOptions = builder.build() From 17d575728a5fc9d26f4b6a62aa9ea3a1a45d9921 Mon Sep 17 00:00:00 2001 From: Surik Date: Thu, 22 Aug 2024 15:14:33 +0400 Subject: [PATCH 3/3] Added fixes after review --- ios/sandwich/QonversionSandwich.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ios/sandwich/QonversionSandwich.swift b/ios/sandwich/QonversionSandwich.swift index 552acbd..2af517c 100644 --- a/ios/sandwich/QonversionSandwich.swift +++ b/ios/sandwich/QonversionSandwich.swift @@ -81,10 +81,11 @@ public class QonversionSandwich : NSObject { contextKeys: [String], completion: @escaping BridgeCompletion ) { - let purchaseCompletion = getPurchaseCompletionHandler(for: completion) - let purchaseOptions = Qonversion.PurchaseOptions(quantity: quantity, contextKeys: contextKeys) Qonversion.shared().products { [weak self] result, err in guard let self = self else { return } + + let purchaseCompletion = getPurchaseCompletionHandler(for: completion) + let purchaseOptions = Qonversion.PurchaseOptions(quantity: quantity, contextKeys: contextKeys) guard let product: Qonversion.Product = result[productId] else { let error = self.productNotFoundError()