How to migration from Original StoreKit to StoreKit2

Hello.

I have a question about migrating from Original StoreKit to StoreKit2.

In my app, there are two in-app purchase products implemented using Original StoreKit: Product A and Product B.

For each product, there are separate backend servers, and due to certain reasons, we need to migrate one of those servers to use the AppStore Server API instead of the VerifyReceipt API.

During this migration, the iOS app needs to have code that combines both Original StoreKit and StoreKit2 for each product.

I heard that combining StoreKit2 with the VerifyReceipt API is not recommended. To avoid doing so, I believe the implementation would look like the below. Is this approach problematic? Is it not recommended by Apple?

If anyone has successfully implemented a similar migration and has insights, I would appreciate hearing about it.

Code implemented using Original StoreKit

SKPaymentQueue.default().add(payment)
    func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
        for transaction in transactions.filter({ $0.payment.productIdentifier.hasPrefix("...Original StoreKit product only...")}) {

            switch transaction.transactionState {
            case .purchasing: break

            case .deferred: print(Messages.deferred)

            case .purchased: handlePurchased(transaction) // send base64 encoded receipt file.
            case .failed: handleFailed(transaction)

            case .restored: handleRestored(transaction)
            
            @unknown default: fatalError(Messages.unknownPaymentTransaction)
            
            }
        }
    }

Code implemented using StoreKit2

let result: Product.PurchaseResult = try await product.purchase()
switch result {
case .success(let verification):
	let transaction = try checkVerified(verification)
	
	// send transaction id
	// ...
	
	await transaction.finish()
case .pending:
	break
case .userCancelled:
	break
@unknown default:
	break
}
func observeTransactions() -> Task<Void, Error> {
	return Task(priority: .background) {
		for await result in Transaction.unfinished {
			do {
				let transaction = try self.checkVerified(result)
				guard transaction.productID.hasPrefix("... StoreKit2 product only...") else {
					return
				}
				
				// send transaction id
				// ...
				
				await transaction.finish()
			} catch {
				// ...
			}
		}
	}
}

Replies

verifyReceipt is deprecated. For Original API for in-app purchase, follow the steps in Validating receipts on the device on your server, or extract Transaction ID from the receipt using App Store Server Library and validate the purchase with App Store Server API.

For In-App Purchases (StoreKit 2), you don't need to call App Store Server at all. Send the JWS from your client to your server and validate it on your server. The same App Store Server Library can help:

The App Store Server Library offers four key capabilities:

Thank you for your response.

I’m aware that the VerifyReceipt API is deprecated.
Unfortunately, due to server-side constraints, we cannot migrate both servers to use the AppStore Server API simultaneously.
Therefore, our plan is to initially migrate only My Server2 and subsequently have My Server1 utilize the AppStore Server API as well.
During this migration, the client app’s code will temporarily have a state where both Original StoreKit and StoreKit2 processes coexist.
I would like to know if this state causes any issues.