28.1 · Products, prices, the purchase call, verification and the update stream

The first sale is easy to demo and easy to get wrong: a missing product list, a price formatted by hand, a result that is not unwrapped, a delivery that happens twice.

Mental model. Treat every purchase as an event you may see more than once, from more than one place: ask the store for products, start the purchase, verify the signed result, deliver idempotently, then finish.

Products and the purchase call

What you can sell, how to show it, and what the purchase call can return or throw.

  1. Which product types does StoreKit 2 sell, why can Product.products(for:) come back empty, and why must prices come from the store? 28.1.1 · L2
    A Product has a type (.consumable, .nonConsumable, .autoRenewable, .nonRenewable), and the type decides who remembers the purchase. A consumable is gone from…
  2. What can product.purchase() return or throw, and how should each outcome behave in the UI? 28.1.2 · L2
    purchase(options:) returns a Product.PurchaseResult with three cases and can also throw. .success(VerificationResult<Transaction>) means the payment went…

Verification and delivery

What a verified result proves, and how to deliver once even if it arrives twice.

  1. What does a .verified StoreKit result prove, what does it not prove, and when would you read unsafePayloadValue? 28.1.3 · L3
    Every Transaction, RenewalInfo and AppTransaction arrives wrapped in a VerificationResult: .verified(value) or .unverified(value, error). .verified means…
  2. Why start a Transaction.updates listener at launch, and what do finish() and idempotent delivery guarantee? 28.1.4 · L3
    A purchase can complete when your purchase call is not running: a renewal at 3 a.m., an Ask to Buy approval, a refund, a purchase made on the iPad, a…

More in Purchases & subscriptions