Skip to content

Instantly share code, notes, and snippets.

@arbyruns
Created September 25, 2022 15:49
Show Gist options
  • Save arbyruns/1b74e58cde6bc6fe7611a860a75265e0 to your computer and use it in GitHub Desktop.
Save arbyruns/1b74e58cde6bc6fe7611a860a75265e0 to your computer and use it in GitHub Desktop.
storekit
import Foundation
import SwiftUI
import StoreKit
class StoreManager: NSObject, ObservableObject, SKProductsRequestDelegate, SKPaymentTransactionObserver {
// setup logging
@ObservedObject var logStore: LogStore = LogStore()
let viewName = URL(fileURLWithPath: #file).lastPathComponent
@Published var myProducts = [SKProduct]()
@Published var transactionState: SKPaymentTransactionState?
@Published var showStoreManagerError = false
@Published var storeManagerErrorMessage: Error?
var request: SKProductsRequest!
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
print("Did receive response")
if !response.products.isEmpty {
for fetchedProduct in response.products {
DispatchQueue.main.async {
self.myProducts.append(fetchedProduct)
}
}
}
// If for some reason our response contains product IDs that are invalid
for invalidIdentifier in response.invalidProductIdentifiers {
logStore.addLogging(viewName, "Invalid identifiers found: \(invalidIdentifier)", type: .warning)
}
}
func getProducts(productIDs: [String]) {
logStore.addLogging(viewName, "\(#function) Start requesting products...", type: .info)
let request = SKProductsRequest(productIdentifiers: Set(productIDs))
request.delegate = self
request.start()
}
func request(_ request: SKRequest, didFailWithError error: Error) {
logStore.addLogging(viewName, "\(#function) Request did fail: \(error)", type: .error)
showStoreManagerError = true
storeManagerErrorMessage = error
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
switch transaction.transactionState {
case .purchasing:
transactionState = .purchasing
case .purchased:
// set transaction process here because the purchase is complete
logStore.addLogging(viewName, "\(#function) purchase: \(transaction.payment.productIdentifier)", type: .info)
UserDefaults.standard.setValue(true, forKey: ConstantStrings.storeKitDefaultKeyValue)
queue.finishTransaction(transaction)
transactionState = .purchased
case .restored:
UserDefaults.standard.setValue(true, forKey: ConstantStrings.storeKitDefaultKeyValue)
queue.finishTransaction(transaction)
transactionState = .restored
case .failed, .deferred:
logStore.addLogging(viewName, "\(#function) payment failed \(String(describing: transaction.error?.localizedDescription))", type: .warning)
queue.finishTransaction(transaction)
transactionState = .failed
default:
queue.finishTransaction(transaction)
}
}
}
// make sure that the user can also make payments.
// This is not the case, for example, if parental control is set up.
func purchaseProduct(product: SKProduct) {
if SKPaymentQueue.canMakePayments() {
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
} else {
showStoreManagerError = true
storeManagerErrorMessage = "Unable to make payments" as? Error
logStore.addLogging(viewName, "\(#function) User can't make payment", type: .error)
}
}
func restoreProducts() {
logStore.addLogging(viewName, "\(#function) restoring products", type: .info)
SKPaymentQueue.default().restoreCompletedTransactions()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment