I’m trying to implement InApp purchase/subscription option in my app and for some reason once I subscribe, I can see that there is a standard icon animation and sound of ‘success’ which is native iOS behavior, but then once the sheet is gone it will immediately reappear to subscribe again… not sure why this is happening.
I tried ChatGPT 4o but no luck.
Here is the code for my StoreKitManager
import Foundation
import StoreKit
class StoreKitManager: NSObject, ObservableObject, SKProductsRequestDelegate, SKPaymentTransactionObserver {
static let shared = StoreKitManager()
@Published var products: [SKProduct] = []
@Published var purchasedProductIDs: Set<String> = []
@Published var purchaseStatus: PurchaseStatus?
@Published var isPremiumUser: Bool = false
private var productRequest: SKProductsRequest?
override init() {
super.init()
SKPaymentQueue.default().add(self)
fetchProducts()
checkPremiumStatus()
}
func checkPremiumStatus() {
// Retrieve purchased product IDs from UserDefaults
let purchasedProductIDs = UserDefaults.standard.stringArray(forKey: "purchasedProductIDs") ?? []
self.purchasedProductIDs = Set(purchasedProductIDs)
// Set isPremiumUser based on purchased products
isPremiumUser = !self.purchasedProductIDs.isEmpty
print("Premium Status Checked: (isPremiumUser)")
}
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
DispatchQueue.main.async {
self.products = response.products
print("Products Fetched: (self.products)")
for product in self.products {
print("Product: (product.localizedTitle) - (product.productIdentifier) - (product.price)")
}
}
}
func fetchProducts() {
let productIdentifiers: Set<String> = ["here's my product id", "here's my product id", "here's my product id"]
print("Fetching products with identifiers: (productIdentifiers)")
productRequest = SKProductsRequest(productIdentifiers: productIdentifiers)
productRequest?.delegate = self
productRequest?.start()
}
func buyProduct(_ product: SKProduct) {
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
print("Initiating purchase for (product.productIdentifier)")
}
// Once payment is received update premium status
private func handleTransaction(_ transaction: SKPaymentTransaction) {
switch transaction.transactionState {
case .purchased, .restored:
DispatchQueue.main.async {
self.purchasedProductIDs.insert(transaction.payment.productIdentifier)
UserDefaults.standard.setValue(Array(self.purchasedProductIDs), forKey: "purchasedProductIDs")
self.purchaseStatus = .success
self.checkPremiumStatus()
print("Transaction Successful: (transaction.payment.productIdentifier)")
SKPaymentQueue.default().finishTransaction(transaction)
}
case .failed:
if let error = transaction.error as? SKError {
print("Transaction failed with error: (error.localizedDescription)")
DispatchQueue.main.async {
self.purchaseStatus = .failure(error)
SKPaymentQueue.default().finishTransaction(transaction)
}
}
default:
break
}
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
for transaction in transactions {
print("Updated transaction: (transaction.transactionState.rawValue)")
handleTransaction(transaction)
}
}
// Update premium status after restore
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
for transaction in queue.transactions where transaction.transactionState == .restored {
purchasedProductIDs.insert(transaction.payment.productIdentifier)
}
UserDefaults.standard.setValue(Array(purchasedProductIDs), forKey: "purchasedProductIDs")
checkPremiumStatus()
print("Restored Purchase: (self.purchasedProductIDs)")
}
func restorePurchase() {
SKPaymentQueue.default().restoreCompletedTransactions()
print("Restoring purchase")
}
}
I tried ChatGPT 4o but it just gives me basically the same code so looks like nothing is wrong but it is as it’s not working properly.