Created
February 7, 2022 13:34
-
-
Save yusufonderd/2cf6e360dff1fff9a8719bd04e88eb6b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PaymentViewModel : ObservableObject{ | |
@Published var isLoadingRetrieveProducts = false | |
@Published var yearlySubscriptionPrice = "" | |
@Published var monthlySubscriptionPrice = "" | |
@Published var lifetimeSubscriptionPrice = "" | |
@Published var isLoadingPayment = false | |
@Published var showAlert = false | |
@Published var title: String = "" | |
@Published var payments : [PaymentView] = [] | |
init(){ | |
payments.append(PaymentView.init(paymentId: PaymentId.monthly, title: "_monthly".localized, index: 0,price: "",extraInfo: "Free for 3 days".localized)) | |
payments.append(PaymentView.init(paymentId: PaymentId.yearly, title: "_annual".localized, index: 1,price: "",extraInfo: "Free for 3 days".localized)) | |
payments.append(PaymentView.init(paymentId: PaymentId.lifetime, title: "_lifetime".localized, index: 2,price : "",extraInfo: "")) | |
} | |
func retrieveProducts(){ | |
isLoadingRetrieveProducts = true | |
SwiftyStoreKit.retrieveProductsInfo([PaymentId.monthly,PaymentId.yearly,PaymentId.lifetime]) { result in | |
self.isLoadingRetrieveProducts = false | |
result.retrievedProducts.forEach { skProduct in | |
switch(skProduct.productIdentifier){ | |
case PaymentId.monthly: | |
self.payments[0].price = skProduct.localizedPrice ?? "\(skProduct.price)" | |
break; | |
case PaymentId.yearly: | |
self.payments[1].price = skProduct.localizedPrice ?? "\(skProduct.price)" | |
let monthlyPrice = String(format: "%.1f",Float(skProduct.price) / 12) | |
let currency = skProduct.priceLocale.currencySymbol ?? "" | |
self.payments[1].discount = "\(currency)\(monthlyPrice) / \("_mo".localized) " | |
break; | |
case PaymentId.lifetime: | |
self.payments[2].price = skProduct.localizedPrice ?? "\(skProduct.price)" | |
break; | |
default: | |
debugPrint("PaymentViewModel default") | |
break; | |
} | |
} | |
} | |
} | |
func startPayment(with paymentId: String, completion: @escaping (PaymentResult) -> Void){ | |
isLoadingPayment = true | |
SwiftyStoreKit.purchaseProduct(paymentId, quantity: 1, atomically: true) { result in | |
debugPrint("PaymentManager startPayment => \(paymentId)") | |
switch result { | |
case .success(let purchase): | |
debugPrint("PaymentManager success => \(purchase.productId)") | |
completion(PaymentResult(success: true,error: nil)) | |
case .error(let error): | |
if let _error = PaymentErrorHandler.map(from: error){ | |
debugPrint("PaymentManager error => \(_error)") | |
completion(PaymentResult(success: false,error: _error)) | |
}else { | |
completion(PaymentResult(success: false,error: nil)) | |
} | |
case .deferred(purchase: let purchase): | |
debugPrint("PaymentManager deferred => \(purchase.productId)") | |
completion(PaymentResult(success: false,error: nil)) | |
} | |
self.isLoadingPayment = false | |
} | |
} | |
private func showAlert(title : String){ | |
self.title = title | |
self.showAlert = true | |
} | |
func restorePurchases(completion: @escaping (PaymentResult) -> Void){ | |
debugPrint("PaymentManager restorePurchases") | |
isLoadingPayment = true | |
SwiftyStoreKit.restorePurchases(atomically: true) { results in | |
debugPrint("PaymentManager restorePurchases results => \(results)") | |
if results.restoreFailedPurchases.count > 0 { | |
self.showAlert(title: "No restored purchase") | |
completion(PaymentResult(success: false,error: nil)) | |
} | |
else if results.restoredPurchases.count > 0 { | |
if let purchase = results.restoredPurchases.first{ | |
self.startPayment(with: purchase.productId, completion: completion) | |
} | |
} | |
else { | |
self.showAlert(title: "No restored purchase") | |
completion(PaymentResult(success: false,error: nil)) | |
} | |
self.isLoadingPayment = false | |
} | |
} | |
} | |
struct PaymentResult { | |
var success: Bool | |
var error : String? | |
} | |
struct PaymentErrorHandler{ | |
static func map(from error: SKError) -> String? { | |
var errorDescription : String? = nil | |
switch error.code { | |
case .unknown: | |
errorDescription = "Unknown error. Please contact support" | |
case .clientInvalid: | |
errorDescription = "Not allowed to make the payment" | |
case .paymentCancelled: | |
errorDescription = "Payment cancelled" | |
case .paymentInvalid: | |
errorDescription = "The purchase identifier was invalid" | |
case .paymentNotAllowed: | |
errorDescription = "The device is not allowed to make the payment" | |
case .storeProductNotAvailable: | |
errorDescription = "The product is not available in the current storefront" | |
case .cloudServicePermissionDenied: | |
errorDescription = "Access to cloud service information is not allowed" | |
case .cloudServiceNetworkConnectionFailed: | |
errorDescription = "Could not connect to the network" | |
case .cloudServiceRevoked: | |
errorDescription = "User has revoked permission to use this cloud service" | |
default: | |
errorDescription = (error as NSError).localizedDescription | |
} | |
return errorDescription | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
gid:PEYNFhLLRVUeoSQeLbyy8d