Implementing Non-Consumable IAP for iOS

Non-consumable IAP is a category where every mistake in purchase restoration logic turns into an App Store complaint and a chargeback. A user bought "unlimited mode" or "remove ads," reinstalled the app, and didn't get what they paid for. Apple Support won't help: restoring non-consumable purchases

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    894
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

Non-consumable IAP is a category where every mistake in purchase restoration logic turns into an App Store complaint and a chargeback. A user bought "unlimited mode" or "remove ads," reinstalled the app, and didn't get what they paid for. Apple Support won't help: restoring non-consumable purchases is the developer's responsibility. Our five years of experience and more than twenty IAP projects show that correct implementation from the first try saves up to 40% of time on bug fixes. According to the StoreKit documentation, proper restoration is critical.

What Most Often Goes Wrong

The most common mistake is calling SKPaymentQueue.default().restoreCompletedTransactions() only when the user taps the "Restore" button. Correct approach: at every launch, check originalTransaction via SKReceiptRefreshRequest or server-side validation. Without this, a user returning after six months with a new iPhone will lose access to paid content.

The second issue is incorrect handling of SKPaymentTransactionObserver. If updatedTransactions does not call finishTransaction(_:) for all states (.purchased, .restored, .failed), the transaction stays in the queue and triggers the observer again at next launch. We've seen projects where this caused double activation of paid content after a restart.

The third problem is the lack of server-side validation. Local receipt parsing via ASN.1 is complex and vulnerable: an attacker can replace the receipt file. Server verification through Apple's /verifyReceipt endpoint (or alternative) guarantees authenticity.

How a Correct Implementation Works

The architecture of non-consumable IAP centers around StoreKit 2 (iOS 15+) or StoreKit 1 with support for iOS 13–14. Compare the two approaches:

Aspect StoreKit 2 StoreKit 1 (Legacy)
Minimum iOS version 15.0 3.0
API style async/await Delegate + completion handlers
Purchase restoration Automatic via Transaction.currentEntitlements Manual restoreCompletedTransactions()
Signature verification Built-in VerificationResult Requires ReceiptValidator
Code complexity Low Medium

StoreKit 2 radically simplifies the code: it reduces the number of lines by 2 times compared to StoreKit 1.

// Request products let products = try await Product.products(for: ["com.app.premium_unlock"]) // Purchase let result = try await products.first?.purchase() switch result { case .success(let verification): switch verification { case .verified(let transaction): // unlock content await transaction.finish() case .unverified: // receipt is forged — do not unlock break } case .pending: // SCA or parental control — wait break case .userCancelled: break } 

Transaction.currentEntitlements is an async sequence that returns all active purchases at each app launch. Iterate it in @main or AppDelegate.applicationDidFinishLaunching and restore state without a "Restore" button.

For iOS 13–14, StoreKit 1 with SKPaymentTransactionObserver remains. That requires a separate ReceiptValidator — either local verification via openssl (complex but without network requests) or server-side through Apple's /verifyReceipt endpoint (deprecated but works). We recommend server-side: local requires embedding the Apple root certificate and correct ASN.1 parsing.

How to Avoid Purchase Restoration Problems?

Key point: perform restoration automatically at every launch, not only via a button. In StoreKit 2, this is achieved by subscribing to Transaction.updates. In StoreKit 1, call restoreCompletedTransactions() and save the originalTransaction.transactionIdentifier in UserDefaults or Keychain. Without automation, users with new devices will lose their content.

Why Is Server Verification Critical?

For apps with a backend: upon purchase, the client sends appStoreReceiptURL to the server; the server queries Apple Sandbox/Production and stores the original_transaction_id in the database. On restoration from a new device, the server verifies against the Apple ID. This is the only way to guarantee "one device purchase, access on another" under the same Apple ID. Average savings from correct implementation — up to $10,000 per year on support.

Step-by-Step Plan for Implementing StoreKit 2

  1. Configure products in App Store Connect (localizations, prices).
  2. Implement product request via Product.products(for:).
  3. Add purchase handling with VerificationResult check.
  4. Subscribe to Transaction.updates for automatic restoration.
  5. Integrate server verification via /verifyReceipt.
  6. Test in Sandbox on the scenario: purchase → delete → restore.
Typical restoration mistake
// WRONG: restoration only via button func restorePurchases() { SKPaymentQueue.default().restoreCompletedTransactions() } // CORRECT: automatic restoration at startup Task { for await result in Transaction.currentEntitlements { if case .verified(let transaction) = result { // unlock content } } } 

Work Process and What's Included

Our turnkey IAP implementation includes:

  • Setting up products in App Store Connect (creation, localizations, prices — specific amounts calculated individually).
  • Integrating StoreKit 2 with fallback to StoreKit 1 for maximum compatibility.
  • Server-side receipt verification with storage of original_transaction_id.
  • Testing in Sandbox and on real devices with a scenario checklist.
  • Documentation for support and access.
  • Guarantee of passing App Review (compliance with paragraph 3.1.1 of the App Store Review Guidelines).

Testing

In Xcode Simulator, StoreKit works via a local .storekit file — you can test without real products. For device testing, a Sandbox Account in App Store Connect is required. Crucial scenario to test: purchase → delete → reinstall → restore. This path fails most often. Get a consultation on your project — we will assess risks and propose the optimal solution.

Implementation timeline — from 2 to 3 days: configure products in App Store Connect, integrate StoreKit 2 with fallback to StoreKit 1, cover with Sandbox tests, pass review (App Review requires a "Restore Purchases" button in the interface). Order turnkey IAP integration — we guarantee correct operation on all devices and iOS versions.