SlideShare une entreprise Scribd logo
1  sur  57
Télécharger pour lire hors ligne
App Store Subscriptions
Condensed Edition
Mark Pavlidis

mark@pavlidis.ca 

mark@groksoftware.net

@mhp

TACOW Presentation 

2019-05-14
Agenda
Why: Choose a Subscription Business Model?

Who: Am I To Know?

What: You need to know to get started?

How: Do you avoid some pain points?

Where: Are we having beers?
Why Choose Subscriptions?
• Fastest growing business model
on the App Store

• Over a 80% of all apps are free,
up from 67% in 2014

• Generated $10B in revenue in
2017, estimated $75B in 2022
App Store Revenue (%)
0
20
40
60
80
100
2010 2012 2015 2018
Paid Free+IAP Free+Subscrption
Why Choose Subscriptions?
Why Choose Subscriptions?
Why Choose Subscriptions?
PAID SUBSCRIPTION
Periodic impulse in revenue
Slow build to the sum of
the impulses every 3-4
months recurring
Launch
Apple Design Award
App Store Feature
Why Choose Subscriptions?
• Recurring Revenue
• Higher price points and fewer customers

• “Build meaningful relationships” with good customers

• Don’t hold back big features for new major versions

• Apple said so

• Everybody is doing it
Why Choose Subscriptions?
Are subscriptions right for me?

• Offering ongoing value

• Is the model right for the potential customers

• Do you have ongoing infrastructure costs

Popular Categories:

• Content, Utilities, Dating, Productivity, Creative
Who Am I To Know?
• First implemented Non-Renewing Subscriptions in 2011















Who Am I To Know?
• First implemented Non-Renewable Subscriptions in 2011

• Auto-renewing plans for Flixel hosting service in 2014

• Included the app unlock in 2015 before it was “legal”

• Worked around a number of limitations that have since been
added to the App Store (i.e., price changes)

• Lucky for you there are still lots of limitations and workarounds
What Are The Basics
• Create your Auto-renewing plans in App Store Connect

• Initiate StoreKit at launch and fetch products

• Show localized plans in-app with the conspicuous disclaimer

• ALWAYS END YOUR TRANSACTIONS

• Provide a mechanism to restore subscription and non-
consumable IAPs
Create Auto-Renewing IAP
Create Auto-Renewing IAP
Create Subscription Group
Subscription Groups
• Made up of subscriptions of different levels and durations

• Helps ensure multiple subscriptions are not active

• Rank the subscriptions in descending order by most access

• Ranking defines rules for upgrade, crossgrade, downgrade
Subscription Groups
Initiate StoreKit
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?) -> Bool {
PurchaseController.shared.setup()
return true
}
Initiate StoreKit
class PurchaseController: NSObject {
func setup() {
// Register Observer
SKPaymentQueue.default().add(self)
}
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions
transactions: [SKPaymentTransaction]) {
//Handle transaction states here.
}
}
Fetch Products
func setup() {
// Register Observer
SKPaymentQueue.default().add(self)
// Register for product refresh
refreshObserver =
NotificationCenter.default.addObserver(forName:
UIApplication.didBecomeActiveNotification, object: nil,
queue: .main) { [weak self] note in
self?.fetchProducts()
}
}
Fetch Products
func fetchProducts() {
guard productsRequest == nil else { return }
//
productsRequest = SKProductsRequest(productIdentifiers:
productIdentifiers)
productsRequest?.delegate = self
productsRequest?.start()
}
}
extension PurchaseController: SKProductsRequestDelegate {
func productsRequest(_ request: SKProductsRequest, didReceive
response: SKProductsResponse) {
products = response.products
}
}
Localized Pricing
open class SKProduct : NSObject {
@available(iOS 3.0, *)
open var localizedDescription: String { get }
@available(iOS 3.0, *)
open var localizedTitle: String { get }
@available(iOS 3.0, *)
open var price: NSDecimalNumber { get }
@available(iOS 3.0, *)
open var priceLocale: Locale { get }
Localized Pricing
extension SKProduct {
/// - returns: The cost of the product formatted in the local
currency.
var regularPrice: String? {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = self.priceLocale
return formatter.string(from: self.price)
}
}
Display Localized Products
Conspicuous Disclaimer
Start Purchase
func purchase(_ product: SKProduct) {
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
}
Purchase Completes
• Once the transaction state changes to .purchased you can
store the subscription transaction to unlock
• What about if a renewal occurs?

• What if the user deletes the app?

• What if you have more than one app or a web service?

• Can use the receipt instead of restoring the transactions
Complete Transactions
• Once verified on-device or sent the receipt to your server call 



SKPaymentQueue.default().finishTransaction(_:)
• If you don’t StoreKit will keep posting the transaction

• Apple is more likely to refund the transaction if you don’t
let receiptURL = Bundle.main.appStoreReceiptURL
• Receipt is in PKCS Cryptographic Container & ASN.1 encoded 

• Need to build a static OpenSSL, asn1c, etc to verify it

• Bundle Apple Root CA Certificate 

• Not provided by Apple on purpose — no single point of failure
On-Device Receipt Validation
Server Side Receipt Validation
• If you can, have your server manage receipt verification 

• Send the BASE64 binary encoded receipt data and store it

• Server sends it to Apple server that responds with JSON
payload of the receipt and a latest version of receipt data

• JSON includes additional information about subscription state
Server Side Receipt Validation
• If you have multiple apps/platforms you must use this method

• App Transport Security is required

• Different endpoints for Production and Sandbox environments

https://buy.itunes.apple.com/verifyReceipt

https://sandbox.itunes.apple.com/verifyReceipt

• Don’t call from the device

• Status code to indicate if you should use the other environment
Additional Receipt Fields
• auto_renew_status indicates if the customer has cancelled

• auto_renew_product_id renewal product could be different

• price_consent_status when you change the price 

• is_in_billing_retry_period indicate past due to user 

• expiration_intent is voluntary, billing, price increase, etc.

• original_transaction_id your primary key to the subscription
JSON Receipt Demo
Managing Server-to-Server
• Your server can receive push subscription status updates

• General App Information > Subscription Status URL

• Only one endpoint, so you have to forward sandbox requests 

• Different data structure containing partial change data

• Delivery is not guaranteed 

• Poll all receipts daily to ensure auto-renewal and cancelations are
synchronized
Ways to Increase Conversions
• Promoted In-App Purchases

• Auto-renewing Subscription Offers

• Introductory Offers

• NEW: Promotional Offers

• Handling Past Due user experience
Promoted IAPs
• Can promote up to 20 IAPs

• Give customers browsing the App Store a one-tap buy button

• Needs unique images

• Shows up in search results (n.b., ASO marketers)

• Another reason you need to initialize StoreKit at launch
Promoted IAPs
func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment
payment: SKPayment, for product: SKProduct) -> Bool
• Always return false now or risk rejection

• Hold on to the SKPayment

• Display Product, PRICE, and Conspicuous Disclaimer 

• Have the user sign-in/up if necessary

• Then add the payment to the payment queue
Subscription Offers
Introductory Offers
• Free Trial, Pay as you go, Pay up front

• Unique by (Territory, Plan)

• Displayed on Promoted IAP on the App Store

• SKProduct.introductoryPrice
Subscription Offers
Subscription Offers
Promotional Offers
• Up to 10 offers per plan to existing or churned subscribers

• You decide which are shown

• Not displayed on the App Store — avoid IAP pollution 

• Requires a server to determine eligibility & generate signature 

• SKProduct.discounts
Past Due User Experience
• On-device or before last year you don’t know user is past due

• Apple used to cancel after 24 hours, now it is 60 days

• Up to you how to limit access

• Clearly inform the user that they are past due

• Show a button that opens 

https://apps.apple.com/account/billing
How Do You Avoid Some Pain
• Cancelled is not what you think it means

• Converting a Paid app to Free+Subscription

• New App Auto-Renewing Subscription Propagation

• Have I mentioned the Conspicuous Disclaimer?
What “Cancelled” Means
• Another reason to poll nightly is that a transaction in the receipt
can change

• cancellation_date_ms, cancellation_reason
• Means refunded and you should remove access immediately
REALLY ?
How To Know If Churned
• On-device: if the latest transaction in the receipt end date is in
the past now

• Server-side : check pending_renewal_info for
expiration_intent
Converting Paid to Subscription
Converting Paid to Subscription
Sandbox
Prod iOS
Prod macOS
REALLY ?
New App with Subscriptions
• Turns out that auto-renewing subscriptions aren’t added to the
production environment until the app is live

• Most of the time this propagates to all stores quickly

• But…
New App with Subscriptions
Activation of the In-App Purchase identifiers may lag up to 48
hours following the activation of the application
REALLY ?
Conspicuous Disclaimer
Summary
Why: Choose a Subscription Business Model?

Who: Am I To Know?

What: You need to know to get started?

How: Do you avoid some pain points?
Available for consulting after
WWDC
References
• Auto-renewable Subscriptions

• In-App Purchase and Subscriptions

• Implementing Introductory Offers in Your App

• Implementing Subscription Offers

• IAP Propagation Critical Bug “Tech Note”
App Store Subscriptions
Condensed Edition
Mark Pavlidis

mark@pavlidis.ca 

mark@groksoftware.net

@mhp

TACOW Presentation 

2019-05-14

Contenu connexe

Similaire à App Store Subscriptions - Condensed Edition

Subsription and Recurring Payments
Subsription and Recurring PaymentsSubsription and Recurring Payments
Subsription and Recurring Payments
Ali Memon
 

Similaire à App Store Subscriptions - Condensed Edition (20)

Fireworks mall buddy whitelabel v1.2
Fireworks mall buddy whitelabel v1.2Fireworks mall buddy whitelabel v1.2
Fireworks mall buddy whitelabel v1.2
 
GRO n GO
GRO n GO GRO n GO
GRO n GO
 
SAP Automatic Payment Program Process - Scale Down Your Work Load
SAP Automatic Payment Program Process - Scale Down Your Work LoadSAP Automatic Payment Program Process - Scale Down Your Work Load
SAP Automatic Payment Program Process - Scale Down Your Work Load
 
Shopify
ShopifyShopify
Shopify
 
In-App Purchase
In-App PurchaseIn-App Purchase
In-App Purchase
 
Proposal for Point of Sale and Inventory Management Systems
Proposal for Point of Sale and Inventory Management SystemsProposal for Point of Sale and Inventory Management Systems
Proposal for Point of Sale and Inventory Management Systems
 
New features in oracle fusion financial accounts receivables and account paya...
New features in oracle fusion financial accounts receivables and account paya...New features in oracle fusion financial accounts receivables and account paya...
New features in oracle fusion financial accounts receivables and account paya...
 
Frappé Open Day Presentations - April 2016
Frappé Open Day Presentations - April 2016Frappé Open Day Presentations - April 2016
Frappé Open Day Presentations - April 2016
 
How to Start a Grocery Delivery Business?
How to Start a Grocery Delivery Business?How to Start a Grocery Delivery Business?
How to Start a Grocery Delivery Business?
 
What's New in Acumatica 5.0
What's New in Acumatica 5.0What's New in Acumatica 5.0
What's New in Acumatica 5.0
 
KPIs & Metrics - Innlab RM 2013
KPIs & Metrics - Innlab RM 2013KPIs & Metrics - Innlab RM 2013
KPIs & Metrics - Innlab RM 2013
 
Different architecture topology for dynamics 365 retail
Different architecture topology for dynamics 365 retailDifferent architecture topology for dynamics 365 retail
Different architecture topology for dynamics 365 retail
 
AP and AR Positioning
AP and AR PositioningAP and AR Positioning
AP and AR Positioning
 
Maximizing QuickBooks
Maximizing QuickBooksMaximizing QuickBooks
Maximizing QuickBooks
 
NCET Tech Bite - March 2015 - QuickBooks - Marie Gibson
NCET Tech Bite - March 2015 - QuickBooks - Marie GibsonNCET Tech Bite - March 2015 - QuickBooks - Marie Gibson
NCET Tech Bite - March 2015 - QuickBooks - Marie Gibson
 
Subsription and Recurring Payments
Subsription and Recurring PaymentsSubsription and Recurring Payments
Subsription and Recurring Payments
 
Cool New Advances in PayPal Express Checkout
Cool New Advances in PayPal Express CheckoutCool New Advances in PayPal Express Checkout
Cool New Advances in PayPal Express Checkout
 
How to Maximize Quickbooks (Retired Version)
How to Maximize Quickbooks (Retired Version)How to Maximize Quickbooks (Retired Version)
How to Maximize Quickbooks (Retired Version)
 
Company preso
Company presoCompany preso
Company preso
 
Efficiently handling Applications of Customer Receipts in Oracle Receivables
Efficiently handling Applications of Customer Receipts in Oracle Receivables Efficiently handling Applications of Customer Receipts in Oracle Receivables
Efficiently handling Applications of Customer Receipts in Oracle Receivables
 

Dernier

CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 

Dernier (20)

ManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide Deck
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 

App Store Subscriptions - Condensed Edition

  • 1. App Store Subscriptions Condensed Edition Mark Pavlidis mark@pavlidis.ca mark@groksoftware.net @mhp TACOW Presentation 2019-05-14
  • 2. Agenda Why: Choose a Subscription Business Model? Who: Am I To Know? What: You need to know to get started? How: Do you avoid some pain points? Where: Are we having beers?
  • 3. Why Choose Subscriptions? • Fastest growing business model on the App Store • Over a 80% of all apps are free, up from 67% in 2014 • Generated $10B in revenue in 2017, estimated $75B in 2022 App Store Revenue (%) 0 20 40 60 80 100 2010 2012 2015 2018 Paid Free+IAP Free+Subscrption
  • 6. Why Choose Subscriptions? PAID SUBSCRIPTION Periodic impulse in revenue Slow build to the sum of the impulses every 3-4 months recurring Launch Apple Design Award App Store Feature
  • 7. Why Choose Subscriptions? • Recurring Revenue • Higher price points and fewer customers • “Build meaningful relationships” with good customers • Don’t hold back big features for new major versions • Apple said so • Everybody is doing it
  • 8. Why Choose Subscriptions? Are subscriptions right for me? • Offering ongoing value • Is the model right for the potential customers • Do you have ongoing infrastructure costs Popular Categories: • Content, Utilities, Dating, Productivity, Creative
  • 9. Who Am I To Know? • First implemented Non-Renewing Subscriptions in 2011
 
 
 
 
 
 
 

  • 10.
  • 11. Who Am I To Know? • First implemented Non-Renewable Subscriptions in 2011 • Auto-renewing plans for Flixel hosting service in 2014 • Included the app unlock in 2015 before it was “legal” • Worked around a number of limitations that have since been added to the App Store (i.e., price changes) • Lucky for you there are still lots of limitations and workarounds
  • 12. What Are The Basics • Create your Auto-renewing plans in App Store Connect • Initiate StoreKit at launch and fetch products • Show localized plans in-app with the conspicuous disclaimer • ALWAYS END YOUR TRANSACTIONS • Provide a mechanism to restore subscription and non- consumable IAPs
  • 16. Subscription Groups • Made up of subscriptions of different levels and durations • Helps ensure multiple subscriptions are not active • Rank the subscriptions in descending order by most access • Ranking defines rules for upgrade, crossgrade, downgrade
  • 18. Initiate StoreKit func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { PurchaseController.shared.setup() return true }
  • 19. Initiate StoreKit class PurchaseController: NSObject { func setup() { // Register Observer SKPaymentQueue.default().add(self) } func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { //Handle transaction states here. } }
  • 20. Fetch Products func setup() { // Register Observer SKPaymentQueue.default().add(self) // Register for product refresh refreshObserver = NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main) { [weak self] note in self?.fetchProducts() } }
  • 21. Fetch Products func fetchProducts() { guard productsRequest == nil else { return } // productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers) productsRequest?.delegate = self productsRequest?.start() } } extension PurchaseController: SKProductsRequestDelegate { func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { products = response.products } }
  • 22. Localized Pricing open class SKProduct : NSObject { @available(iOS 3.0, *) open var localizedDescription: String { get } @available(iOS 3.0, *) open var localizedTitle: String { get } @available(iOS 3.0, *) open var price: NSDecimalNumber { get } @available(iOS 3.0, *) open var priceLocale: Locale { get }
  • 23. Localized Pricing extension SKProduct { /// - returns: The cost of the product formatted in the local currency. var regularPrice: String? { let formatter = NumberFormatter() formatter.numberStyle = .currency formatter.locale = self.priceLocale return formatter.string(from: self.price) } }
  • 26. Start Purchase func purchase(_ product: SKProduct) { let payment = SKPayment(product: product) SKPaymentQueue.default().add(payment) }
  • 27. Purchase Completes • Once the transaction state changes to .purchased you can store the subscription transaction to unlock • What about if a renewal occurs? • What if the user deletes the app? • What if you have more than one app or a web service? • Can use the receipt instead of restoring the transactions
  • 28. Complete Transactions • Once verified on-device or sent the receipt to your server call 
 
 SKPaymentQueue.default().finishTransaction(_:) • If you don’t StoreKit will keep posting the transaction • Apple is more likely to refund the transaction if you don’t
  • 29. let receiptURL = Bundle.main.appStoreReceiptURL • Receipt is in PKCS Cryptographic Container & ASN.1 encoded • Need to build a static OpenSSL, asn1c, etc to verify it • Bundle Apple Root CA Certificate • Not provided by Apple on purpose — no single point of failure On-Device Receipt Validation
  • 30. Server Side Receipt Validation • If you can, have your server manage receipt verification • Send the BASE64 binary encoded receipt data and store it • Server sends it to Apple server that responds with JSON payload of the receipt and a latest version of receipt data • JSON includes additional information about subscription state
  • 31. Server Side Receipt Validation • If you have multiple apps/platforms you must use this method • App Transport Security is required • Different endpoints for Production and Sandbox environments https://buy.itunes.apple.com/verifyReceipt
 https://sandbox.itunes.apple.com/verifyReceipt • Don’t call from the device • Status code to indicate if you should use the other environment
  • 32. Additional Receipt Fields • auto_renew_status indicates if the customer has cancelled • auto_renew_product_id renewal product could be different • price_consent_status when you change the price • is_in_billing_retry_period indicate past due to user • expiration_intent is voluntary, billing, price increase, etc. • original_transaction_id your primary key to the subscription
  • 34. Managing Server-to-Server • Your server can receive push subscription status updates • General App Information > Subscription Status URL • Only one endpoint, so you have to forward sandbox requests • Different data structure containing partial change data • Delivery is not guaranteed • Poll all receipts daily to ensure auto-renewal and cancelations are synchronized
  • 35. Ways to Increase Conversions • Promoted In-App Purchases • Auto-renewing Subscription Offers • Introductory Offers • NEW: Promotional Offers • Handling Past Due user experience
  • 36. Promoted IAPs • Can promote up to 20 IAPs • Give customers browsing the App Store a one-tap buy button • Needs unique images • Shows up in search results (n.b., ASO marketers) • Another reason you need to initialize StoreKit at launch
  • 37. Promoted IAPs func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool • Always return false now or risk rejection • Hold on to the SKPayment • Display Product, PRICE, and Conspicuous Disclaimer • Have the user sign-in/up if necessary • Then add the payment to the payment queue
  • 38.
  • 39. Subscription Offers Introductory Offers • Free Trial, Pay as you go, Pay up front • Unique by (Territory, Plan) • Displayed on Promoted IAP on the App Store • SKProduct.introductoryPrice
  • 41. Subscription Offers Promotional Offers • Up to 10 offers per plan to existing or churned subscribers • You decide which are shown • Not displayed on the App Store — avoid IAP pollution • Requires a server to determine eligibility & generate signature • SKProduct.discounts
  • 42. Past Due User Experience • On-device or before last year you don’t know user is past due • Apple used to cancel after 24 hours, now it is 60 days • Up to you how to limit access • Clearly inform the user that they are past due • Show a button that opens 
 https://apps.apple.com/account/billing
  • 43. How Do You Avoid Some Pain • Cancelled is not what you think it means • Converting a Paid app to Free+Subscription • New App Auto-Renewing Subscription Propagation • Have I mentioned the Conspicuous Disclaimer?
  • 44. What “Cancelled” Means • Another reason to poll nightly is that a transaction in the receipt can change • cancellation_date_ms, cancellation_reason • Means refunded and you should remove access immediately
  • 46. How To Know If Churned • On-device: if the latest transaction in the receipt end date is in the past now • Server-side : check pending_renewal_info for expiration_intent
  • 47. Converting Paid to Subscription
  • 48. Converting Paid to Subscription Sandbox Prod iOS Prod macOS
  • 50. New App with Subscriptions • Turns out that auto-renewing subscriptions aren’t added to the production environment until the app is live • Most of the time this propagates to all stores quickly • But…
  • 51. New App with Subscriptions Activation of the In-App Purchase identifiers may lag up to 48 hours following the activation of the application
  • 54. Summary Why: Choose a Subscription Business Model? Who: Am I To Know? What: You need to know to get started? How: Do you avoid some pain points?
  • 56. References • Auto-renewable Subscriptions • In-App Purchase and Subscriptions • Implementing Introductory Offers in Your App • Implementing Subscription Offers • IAP Propagation Critical Bug “Tech Note”
  • 57. App Store Subscriptions Condensed Edition Mark Pavlidis mark@pavlidis.ca mark@groksoftware.net @mhp TACOW Presentation 2019-05-14