ios – StoreKit 2: how to verify an active subscription?

0
156


Many the tutorials around StoreKit 2 and even Apple’s own Sample Code reference “StoreKit testing in Xcode so you can build and run the sample app without completing any setup in App Store Connect. The project defines in-app products for the StoreKit testing server in the Products.storekit file.” I have an app with auto renewing subscriptions already set up in App Store Connect (migrating to StoreKit 2 from SwiftyStoreKit)…how can I set up this StoreKitManager class to check for an active subscription without needing to make a separate Products.plist file? This code below, largely based on Apple’s sample code, results in Error Domain=ASDErrorDomain Code=509 "No active account" which is obvious as I can’t figure out how to connect my products to the StoreKit 2 logic? 🤔

import Foundation
import StoreKit

typealias Transaction = StoreKit.Transaction

public enum StoreError: Error {
    case failedVerification
}

@available(watchOSApplicationExtension 8.0, *)
class WatchStoreManager: ObservableObject {
    
    var updateListenerTask: Task<Void, Error>? = nil
    
    init() {
        print("Init called in WatchStoreManager")
        //Start a transaction listener as close to app launch as possible so you don't miss any transactions.
        updateListenerTask = listenForTransactions()
    }
    
    deinit {
        updateListenerTask?.cancel()
    }
    
    func listenForTransactions() -> Task<Void, Error> {
        return Task.detached {
            //Iterate through any transactions that don't come from a direct call to `purchase()`.
            for await result in Transaction.updates {
                do {
                    let transaction = try self.checkVerified(result)
                    
                    print("we have a verified transacction")

                    //Deliver products to the user.
                    //TODO:
                    //await self.updateCustomerProductStatus()

                    //Always finish a transaction.
                    await transaction.finish()
                } catch {
                    //StoreKit has a transaction that fails verification. Don't deliver content to the user.
                    print("Transaction failed verification")
                }
            }
        }
    }
    
    func checkVerified<T>(_ result: VerificationResult<T>) throws -> T {
        //Check whether the JWS passes StoreKit verification.
        switch result {
        case .unverified:
            //StoreKit parses the JWS, but it fails verification.
            throw StoreError.failedVerification
        case .verified(let safe):
            //The result is verified. Return the unwrapped value.
            return safe
        }
    }
    
}