From ef92732e358256a69d93fb67d1a728f27d7c9dd9 Mon Sep 17 00:00:00 2001 From: Ramesh Gadagoju Date: Wed, 16 Aug 2023 19:19:25 +0530 Subject: [PATCH 1/5] Two Things handled in this commit 1. Passing customer_id for restore purchases 2. Handled customer_id in return handler for purchases. --- Chargebee/Classes/Purchase/CBPurchaseManager.swift | 14 ++++++++------ .../Restore/CBPurchaseManager+Extension.swift | 4 ++-- Example/Chargebee/CBSDKOptionsViewController.swift | 4 +++- .../CBSDKProductsTableViewController.swift | 2 ++ 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Chargebee/Classes/Purchase/CBPurchaseManager.swift b/Chargebee/Classes/Purchase/CBPurchaseManager.swift index 7260e3b..dfe5d8e 100644 --- a/Chargebee/Classes/Purchase/CBPurchaseManager.swift +++ b/Chargebee/Classes/Purchase/CBPurchaseManager.swift @@ -12,7 +12,7 @@ public class CBPurchase: NSObject { public static let shared = CBPurchase() private var productIDs: [String] = [] public var receiveProductsHandler: ((_ result: Result<[CBProduct], CBPurchaseError>) -> Void)? - public var buyProductHandler: ((Result<(status:Bool, subscriptionId:String?, planId:String?), Error>) -> Void)? + public var buyProductHandler: ((Result<(status:Bool, subscriptionId:String?, planId:String?,customerId:String?), Error>) -> Void)? private var buyNonSubscriptionProductHandler: ((Result) -> Void)? private var authenticationManager = CBAuthenticationManager() @@ -26,6 +26,7 @@ public class CBPurchase: NSObject { var refreshHandler: RestoreResultCompletion? var includeInActiveProducts = false private var productType: ProductType? + var restoreCustomer: CBCustomer? // MARK: - Init private override init() { @@ -121,24 +122,25 @@ public extension CBPurchase { //Buy the product @available(*, deprecated, message: "This will be removed in upcoming versions, Please use this API func purchaseProduct(product: CBProduct, customer : CBCustomer? = nil, completion)") - func purchaseProduct(product: CBProduct, customerId : String? = "",completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?), Error>) -> Void)) { + func purchaseProduct(product: CBProduct, customerId : String? = "",completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?,customerId:String?), Error>) -> Void)) { buyProductHandler = handler activeProduct = product self.customer = CBCustomer(customerID: customerId ?? "") self.purchaseProductHandler(product: product, completion: handler) } - func purchaseProduct(product: CBProduct, customer : CBCustomer? = nil, completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?), Error>) -> Void)) { + func purchaseProduct(product: CBProduct, customer : CBCustomer? = nil, completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?,customerId:String?), Error>) -> Void)) { buyProductHandler = handler activeProduct = product self.customer = customer self.purchaseProductHandler(product: product, completion: handler) } - func restorePurchases(includeInActiveProducts:Bool = false ,completion handler: @escaping ((_ result: Result<[InAppSubscription], RestoreError>) -> Void)) { + func restorePurchases(includeInActiveProducts:Bool = false ,customer: CBCustomer ,completion handler: @escaping ((_ result: Result<[InAppSubscription], RestoreError>) -> Void)) { self.restoreResponseHandler = handler self.includeInActiveProducts = includeInActiveProducts self.restoredPurchasesCount = 0 + self.restoreCustomer = customer SKPaymentQueue.default().restoreCompletedTransactions() } @@ -309,7 +311,7 @@ public extension CBPurchase { } } - func validateReceipt(_ product: CBProduct?,customer: CBCustomer? = nil,completion: ((Result<(status:Bool, subscriptionId:String?, planId:String?), Error>) -> Void)?) { + func validateReceipt(_ product: CBProduct?,customer: CBCustomer? = nil,completion: ((Result<(status:Bool, subscriptionId:String?, planId:String?, customerId:String?), Error>) -> Void)?) { guard let receipt = getReceipt(product: product?.product,customer: customer) else { debugPrint("Couldn't read receipt data with error") @@ -327,7 +329,7 @@ public extension CBPurchase { return } self.activeProduct = nil - completion?(.success((true, receipt.subscriptionId, receipt.planId))) + completion?(.success((true, receipt.subscriptionId, receipt.planId,receipt.customerId))) case .error(let error): debugPrint(" Chargebee - Receipt Upload - Failure") completion?(.failure(error)) diff --git a/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift b/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift index 626a515..c03dd9d 100644 --- a/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift +++ b/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift @@ -136,9 +136,9 @@ extension CBPurchase{ for product in products { operationQueue?.addOperation{ if let _ = product.product.subscriptionPeriod { - self.validateReceipt(product, completion: nil) + self.validateReceipt(product,customer: self.restoreCustomer, completion: nil) }else{ - self.validateReceiptForNonSubscriptions(product, .unknown, completion: nil) + self.validateReceiptForNonSubscriptions(product, .unknown, customer: self.restoreCustomer, completion: nil) } } } diff --git a/Example/Chargebee/CBSDKOptionsViewController.swift b/Example/Chargebee/CBSDKOptionsViewController.swift index a0c4d92..a8c5512 100644 --- a/Example/Chargebee/CBSDKOptionsViewController.swift +++ b/Example/Chargebee/CBSDKOptionsViewController.swift @@ -169,7 +169,9 @@ extension CBSDKOptionsViewController: UITableViewDelegate, UITableViewDataSource } case .restore: self.view.activityStartAnimating(activityColor: UIColor.white, backgroundColor: UIColor.black.withAlphaComponent(0.5)) - CBPurchase.shared.restorePurchases(includeInActiveProducts: true) { result in + //Ex: customer_id is mandatory field for restoring purchases so please pass customer object as shown example below + let customer = CBCustomer(customerID: "Test123",firstName: "CB",lastName: "Test",email: "cbTest@charebee.com") + CBPurchase.shared.restorePurchases(includeInActiveProducts: true, customer: customer) { result in switch result { case .success(let response): if response.count > 0 { diff --git a/Example/Chargebee/CBSDKProductsTableViewController.swift b/Example/Chargebee/CBSDKProductsTableViewController.swift index 0e202e4..bb5cb71 100644 --- a/Example/Chargebee/CBSDKProductsTableViewController.swift +++ b/Example/Chargebee/CBSDKProductsTableViewController.swift @@ -362,6 +362,8 @@ extension CBSDKProductsTableViewController: ProductTableViewCellDelegate { print(result.status) print(result.subscriptionId ?? "") print(result.planId ?? "") + print(result.customerId ?? "") + DispatchQueue.main.async { self.view.activityStopAnimating() let alertController = UIAlertController(title: "Chargebee", message: "success", preferredStyle: .alert) From 3d870ee0bcf65d6ba0c26040041c6640e66e477e Mon Sep 17 00:00:00 2001 From: Ramesh Gadagoju Date: Wed, 16 Aug 2023 19:26:01 +0530 Subject: [PATCH 2/5] Formatting the lines and removing spaces --- Chargebee/Classes/Purchase/CBPurchaseManager.swift | 10 +++++----- Example/Chargebee/CBSDKOptionsViewController.swift | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Chargebee/Classes/Purchase/CBPurchaseManager.swift b/Chargebee/Classes/Purchase/CBPurchaseManager.swift index dfe5d8e..693e3a7 100644 --- a/Chargebee/Classes/Purchase/CBPurchaseManager.swift +++ b/Chargebee/Classes/Purchase/CBPurchaseManager.swift @@ -12,7 +12,7 @@ public class CBPurchase: NSObject { public static let shared = CBPurchase() private var productIDs: [String] = [] public var receiveProductsHandler: ((_ result: Result<[CBProduct], CBPurchaseError>) -> Void)? - public var buyProductHandler: ((Result<(status:Bool, subscriptionId:String?, planId:String?,customerId:String?), Error>) -> Void)? + public var buyProductHandler: ((Result<(status:Bool, subscriptionId:String?, planId:String?, customerId:String?), Error>) -> Void)? private var buyNonSubscriptionProductHandler: ((Result) -> Void)? private var authenticationManager = CBAuthenticationManager() @@ -122,21 +122,21 @@ public extension CBPurchase { //Buy the product @available(*, deprecated, message: "This will be removed in upcoming versions, Please use this API func purchaseProduct(product: CBProduct, customer : CBCustomer? = nil, completion)") - func purchaseProduct(product: CBProduct, customerId : String? = "",completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?,customerId:String?), Error>) -> Void)) { + func purchaseProduct(product: CBProduct, customerId : String? = "",completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?, customerId:String?), Error>) -> Void)) { buyProductHandler = handler activeProduct = product self.customer = CBCustomer(customerID: customerId ?? "") self.purchaseProductHandler(product: product, completion: handler) } - func purchaseProduct(product: CBProduct, customer : CBCustomer? = nil, completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?,customerId:String?), Error>) -> Void)) { + func purchaseProduct(product: CBProduct, customer : CBCustomer? = nil, completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?, customerId:String?), Error>) -> Void)) { buyProductHandler = handler activeProduct = product self.customer = customer self.purchaseProductHandler(product: product, completion: handler) } - func restorePurchases(includeInActiveProducts:Bool = false ,customer: CBCustomer ,completion handler: @escaping ((_ result: Result<[InAppSubscription], RestoreError>) -> Void)) { + func restorePurchases(includeInActiveProducts:Bool = false, customer: CBCustomer, completion handler: @escaping ((_ result: Result<[InAppSubscription], RestoreError>) -> Void)) { self.restoreResponseHandler = handler self.includeInActiveProducts = includeInActiveProducts self.restoredPurchasesCount = 0 @@ -214,7 +214,7 @@ extension CBPurchase: SKPaymentTransactionObserver { SKPaymentQueue.default().finishTransaction(transaction) if let product = activeProduct { if let _ = product.product.subscriptionPeriod { - validateReceipt(product,customer: self.customer, completion: buyProductHandler) + validateReceipt(product, customer: self.customer, completion: buyProductHandler) }else{ validateReceiptForNonSubscriptions(product, self.productType,customer: self.customer, completion: buyNonSubscriptionProductHandler) } diff --git a/Example/Chargebee/CBSDKOptionsViewController.swift b/Example/Chargebee/CBSDKOptionsViewController.swift index a8c5512..2fb8ec0 100644 --- a/Example/Chargebee/CBSDKOptionsViewController.swift +++ b/Example/Chargebee/CBSDKOptionsViewController.swift @@ -170,7 +170,7 @@ extension CBSDKOptionsViewController: UITableViewDelegate, UITableViewDataSource case .restore: self.view.activityStartAnimating(activityColor: UIColor.white, backgroundColor: UIColor.black.withAlphaComponent(0.5)) //Ex: customer_id is mandatory field for restoring purchases so please pass customer object as shown example below - let customer = CBCustomer(customerID: "Test123",firstName: "CB",lastName: "Test",email: "cbTest@charebee.com") + let customer = CBCustomer(customerID: "Test123",firstName: "CB",lastName: "Test",email: "cbTest@chargebee.com") CBPurchase.shared.restorePurchases(includeInActiveProducts: true, customer: customer) { result in switch result { case .success(let response): From 7ccabe3352041d79c513e2ff92088d12db78816c Mon Sep 17 00:00:00 2001 From: Ramesh Gadagoju Date: Wed, 16 Aug 2023 19:40:16 +0530 Subject: [PATCH 3/5] Handling optional customer object while validating receipt after restore purchases --- .../Classes/Restore/CBPurchaseManager+Extension.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift b/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift index c03dd9d..6d0d8ef 100644 --- a/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift +++ b/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift @@ -136,9 +136,13 @@ extension CBPurchase{ for product in products { operationQueue?.addOperation{ if let _ = product.product.subscriptionPeriod { - self.validateReceipt(product,customer: self.restoreCustomer, completion: nil) + if let customer = self.restoreCustomer { + self.validateReceipt(product,customer: customer, completion: nil) + } }else{ - self.validateReceiptForNonSubscriptions(product, .unknown, customer: self.restoreCustomer, completion: nil) + if let customer = self.restoreCustomer { + self.validateReceiptForNonSubscriptions(product, .unknown, customer: customer, completion: nil) + } } } } From 2dc2fe00fba804a9594fa397564556ecf62270b9 Mon Sep 17 00:00:00 2001 From: Ramesh Gadagoju Date: Wed, 16 Aug 2023 21:37:51 +0530 Subject: [PATCH 4/5] 1. Reverted handling customerId on Purchase API it will be picked in separate PR 2. Passing 'restoreCustomer' as optional for validateReceipt() since its expecting a optional parameter --- Chargebee/Classes/Purchase/CBPurchaseManager.swift | 10 +++++----- .../Classes/Restore/CBPurchaseManager+Extension.swift | 8 ++------ .../Chargebee/CBSDKProductsTableViewController.swift | 1 - README.md | 7 ++++++- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Chargebee/Classes/Purchase/CBPurchaseManager.swift b/Chargebee/Classes/Purchase/CBPurchaseManager.swift index 693e3a7..0dd8b51 100644 --- a/Chargebee/Classes/Purchase/CBPurchaseManager.swift +++ b/Chargebee/Classes/Purchase/CBPurchaseManager.swift @@ -12,7 +12,7 @@ public class CBPurchase: NSObject { public static let shared = CBPurchase() private var productIDs: [String] = [] public var receiveProductsHandler: ((_ result: Result<[CBProduct], CBPurchaseError>) -> Void)? - public var buyProductHandler: ((Result<(status:Bool, subscriptionId:String?, planId:String?, customerId:String?), Error>) -> Void)? + public var buyProductHandler: ((Result<(status:Bool, subscriptionId:String?, planId:String?), Error>) -> Void)? private var buyNonSubscriptionProductHandler: ((Result) -> Void)? private var authenticationManager = CBAuthenticationManager() @@ -122,14 +122,14 @@ public extension CBPurchase { //Buy the product @available(*, deprecated, message: "This will be removed in upcoming versions, Please use this API func purchaseProduct(product: CBProduct, customer : CBCustomer? = nil, completion)") - func purchaseProduct(product: CBProduct, customerId : String? = "",completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?, customerId:String?), Error>) -> Void)) { + func purchaseProduct(product: CBProduct, customerId : String? = "",completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?), Error>) -> Void)) { buyProductHandler = handler activeProduct = product self.customer = CBCustomer(customerID: customerId ?? "") self.purchaseProductHandler(product: product, completion: handler) } - func purchaseProduct(product: CBProduct, customer : CBCustomer? = nil, completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?, customerId:String?), Error>) -> Void)) { + func purchaseProduct(product: CBProduct, customer : CBCustomer? = nil, completion handler: @escaping ((_ result: Result<(status:Bool, subscriptionId:String?, planId:String?), Error>) -> Void)) { buyProductHandler = handler activeProduct = product self.customer = customer @@ -311,7 +311,7 @@ public extension CBPurchase { } } - func validateReceipt(_ product: CBProduct?,customer: CBCustomer? = nil,completion: ((Result<(status:Bool, subscriptionId:String?, planId:String?, customerId:String?), Error>) -> Void)?) { + func validateReceipt(_ product: CBProduct?,customer: CBCustomer? = nil,completion: ((Result<(status:Bool, subscriptionId:String?, planId:String?), Error>) -> Void)?) { guard let receipt = getReceipt(product: product?.product,customer: customer) else { debugPrint("Couldn't read receipt data with error") @@ -329,7 +329,7 @@ public extension CBPurchase { return } self.activeProduct = nil - completion?(.success((true, receipt.subscriptionId, receipt.planId,receipt.customerId))) + completion?(.success((true, receipt.subscriptionId, receipt.planId))) case .error(let error): debugPrint(" Chargebee - Receipt Upload - Failure") completion?(.failure(error)) diff --git a/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift b/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift index 6d0d8ef..66e18ec 100644 --- a/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift +++ b/Chargebee/Classes/Restore/CBPurchaseManager+Extension.swift @@ -136,13 +136,9 @@ extension CBPurchase{ for product in products { operationQueue?.addOperation{ if let _ = product.product.subscriptionPeriod { - if let customer = self.restoreCustomer { - self.validateReceipt(product,customer: customer, completion: nil) - } + self.validateReceipt(product,customer: self.restoreCustomer, completion: nil) }else{ - if let customer = self.restoreCustomer { - self.validateReceiptForNonSubscriptions(product, .unknown, customer: customer, completion: nil) - } + self.validateReceiptForNonSubscriptions(product, .unknown, customer: self.restoreCustomer, completion: nil) } } } diff --git a/Example/Chargebee/CBSDKProductsTableViewController.swift b/Example/Chargebee/CBSDKProductsTableViewController.swift index bb5cb71..2af4a18 100644 --- a/Example/Chargebee/CBSDKProductsTableViewController.swift +++ b/Example/Chargebee/CBSDKProductsTableViewController.swift @@ -362,7 +362,6 @@ extension CBSDKProductsTableViewController: ProductTableViewCellDelegate { print(result.status) print(result.subscriptionId ?? "") print(result.planId ?? "") - print(result.customerId ?? "") DispatchQueue.main.async { self.view.activityStopAnimating() diff --git a/README.md b/README.md index 0e24df8..451c331 100644 --- a/README.md +++ b/README.md @@ -231,8 +231,13 @@ The `restorePurchases()` function helps to recover your app user's previous purc To retrieve **inactive** purchases along with the **active** purchases for your app user, you can call the `restorePurchases()` function with the `includeInActiveProducts` parameter set to `true`. If you only want to restore active subscriptions, set the parameter to `false`. Here is an example of how to use the `restorePurchases()` function in your code with the `includeInActiveProducts` parameter set to `true`. +To Restore Purchases please pass `CBCustomer` Object for `restorePurchases()` method as shown in below example. +Note: `customerId` is mandatory field to restore purchases. + ```swift -CBPurchase.shared.restorePurchases(includeInActiveProducts: true) { result in + +let customer = CBCustomer(customerID: "Test123",firstName: "CB",lastName: "Test",email: "cbTest@chargebee.com") +CBPurchase.shared.restorePurchases(includeInActiveProducts: true, customer: customer) { result in switch result { case .success(let response): for subscription in response { From a6f662dbeb795df8897ff545a276a14f761bd7e2 Mon Sep 17 00:00:00 2001 From: Ramesh Gadagoju Date: Thu, 17 Aug 2023 15:49:57 +0530 Subject: [PATCH 5/5] Updated Customer object as Optional param for restorePurchases and updated Version number in all places --- Chargebee.podspec | 2 +- Chargebee/Classes/Logger/CBLoggerResource.swift | 2 +- Chargebee/Classes/Purchase/CBPurchaseManager.swift | 2 +- README.md | 5 ++--- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Chargebee.podspec b/Chargebee.podspec index 0c3efd3..284f4be 100644 --- a/Chargebee.podspec +++ b/Chargebee.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'Chargebee' - s.version = '1.0.27' + s.version = '1.0.28' s.summary = 'Chargebee iOS SDK' # This description is used to generate tags and improve search results. diff --git a/Chargebee/Classes/Logger/CBLoggerResource.swift b/Chargebee/Classes/Logger/CBLoggerResource.swift index 19b1f28..384c9ce 100644 --- a/Chargebee/Classes/Logger/CBLoggerResource.swift +++ b/Chargebee/Classes/Logger/CBLoggerResource.swift @@ -24,7 +24,7 @@ var osVersion: String { } var sdkVersion: String { - return "1.0.27" + return "1.0.28" } class CBLoggerResource: CBAPIResource { diff --git a/Chargebee/Classes/Purchase/CBPurchaseManager.swift b/Chargebee/Classes/Purchase/CBPurchaseManager.swift index 0dd8b51..8c63fd8 100644 --- a/Chargebee/Classes/Purchase/CBPurchaseManager.swift +++ b/Chargebee/Classes/Purchase/CBPurchaseManager.swift @@ -136,7 +136,7 @@ public extension CBPurchase { self.purchaseProductHandler(product: product, completion: handler) } - func restorePurchases(includeInActiveProducts:Bool = false, customer: CBCustomer, completion handler: @escaping ((_ result: Result<[InAppSubscription], RestoreError>) -> Void)) { + func restorePurchases(includeInActiveProducts:Bool = false, customer: CBCustomer? = nil, completion handler: @escaping ((_ result: Result<[InAppSubscription], RestoreError>) -> Void)) { self.restoreResponseHandler = handler self.includeInActiveProducts = includeInActiveProducts self.restoredPurchasesCount = 0 diff --git a/README.md b/README.md index 451c331..e4a7bc9 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Choose from the following options to install Chargeee iOS SDK. Add the following snippet to the Podfile to install directly from Github. ```swift -pod 'Chargebee', :git => 'https://github.com/chargebee/chargebee-ios', :tag => '1.0.27' +pod 'Chargebee', :git => 'https://github.com/chargebee/chargebee-ios', :tag => '1.0.28' ``` ### CocoaPods @@ -231,8 +231,7 @@ The `restorePurchases()` function helps to recover your app user's previous purc To retrieve **inactive** purchases along with the **active** purchases for your app user, you can call the `restorePurchases()` function with the `includeInActiveProducts` parameter set to `true`. If you only want to restore active subscriptions, set the parameter to `false`. Here is an example of how to use the `restorePurchases()` function in your code with the `includeInActiveProducts` parameter set to `true`. -To Restore Purchases please pass `CBCustomer` Object for `restorePurchases()` method as shown in below example. -Note: `customerId` is mandatory field to restore purchases. +CBCustomer - Optional object. Although this is an optional object, we recommend passing the necessary customer details, such as customerId, firstName, lastName, and email if it is available before the user subscribes to your App. This ensures that the customer details in your database match the customer details in Chargebee. If the customerId is not passed in the customer’s details, then the value of customerId will be the same as the SubscriptionId created in Chargebee. Also, the restored subscriptions will not be associate with existing customerId. ```swift