π 2019.12.10 (TUE)
WWDC2017 | Session : 303 | Category : App Store
π What's New in StoreKit - WWDC 2017 - Videos - Apple Developer
- Promoting in-pp purchases
- Sever-to-server subscription notifications
- Detailed subscription status information
- Responding to reviews
- Asking for ratings and reviews
- Digital content or service bought in-app
- Not for physical goods
- Consumable products β that can be consumed and used up by a user. ex. gold coins in a game that user buys and maybe spends. It dosen't persist around subsequent restores or new devices.
- Non-consumable products β It does persist. ex. unlocking a pro feature in your application, downloading a level pack for a game
- Non-renewing subscriptions β It doesn't automatically charge user the end of the biling period. consumable product with an expiry date on it.
- Auto-renewing subscriptions
Related: Advanced StoreKit
Options for storing the list of product identifiers
After setting up product identifiers in iTunes Connect
Bakes into your app
let identifiers = ["com.myComany.myApp.product1,"com.myComany.myApp.product1]
Or fetch from your sever
let identifiers = remoteIdentifiers()
let request = SKProductsRequest(productIdentifiers: identifierSet)
request.delegate = self
request.start()
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
for product in reponse.products {
// Localized title and description
product.localizedTitle
product.localizedDescription
// Price and Locale
product.price
product.priceLocale
// Content size and version (hosted)
product.downloadContentLengths
product.downloadContentVersion
}
}
You shouldn't cache the SKProduct that comes back in this point. It's really important that you get up to date product information, by performing these requests regularly. Because things like currency can fluctuate.
- Up to the application
- Can have a large effect on sales
- https://developer.apple.com/in-app-purchase/
Formatting the product price
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = product.priceLocale // π«device locale
let formattedString = formatter.string(from: product.price)
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
Suspicious activity during payment process
Provide an account identifier
- For applications with their own account management
- Provide an opaque identifier for your user's account
- Don't send us the user's Apple ID
- Don't provide the actual account name
- Don't provide the password
- We suggest using a hash of the account name
let payment = SKPayment(product: product)
payment.applicationUsername = hash(yourCustomerAccountName)
SKPaymentQueue.defaults().add(payment)
- Unlock functionality in your app
- Download additional content
Downloading Content
- Apple-hosted content
- On-demand resources
- Hosted in-app purchase content
- Self-hosted content
- Use background downloads with NSURLSession
- Finish all transactions once content is unlocked
- If downloading hosted content, wail until after the download completes
- Includes all auto-renewable subscription transactions
- Otherwise, the payment will stay in the queue
- Subscription billing retry depends of up-to-date information about transaction
SKPaymentQueue.default().finishTransaction(transaction)
- You must have a Restore button
- Restore and Purchases must be separate buttons.
- Not just as a "backup" tool
- User with multiple devices
Restore Completed Transactions
-
Only restores transactions for
- Non-consumables
- Auto-renewable subscriptions
-
For consumables and-renewing subscriptions
- You must persist the state!
SKPaymentQueue.default().restoreCompltedTransactions()
Observe the queue //Additional callbacks in SKPaymentTransactionObserver func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {} func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsailedWithError error: NSError) {}
Inspect the receipt and unlock content and features accordingly
In-app purchases discoverable in the App Sotre.
- App Page
- Editorial features
- Search results
Start purchase on the App Store
- choose up the 20 purcahses to promote per app, and set them up in iTunes Connect with an accompanying image.
Required
- Set up in iTunes Connect
- Handle info from App Store Implement single delegate method in your app to handle to purchase info sent to you from the App Store. StoreKit will handle the rest of the transaction for you.
Optional
- Order and visibility
Related: Whatβs New in iTunes Connect
StoreKit will automatically open your app and send information about the transaction to you via delegate method on the SKPaymentTransactionObserver
protocol.
If your app isn't already installed, the App Store will download or prompt the user to buy it.
In this case, it can't be opened automatically, so instead, the user will receive a notification.
And when they tap on that, then your app will open and be sent the transaction info.
// Continuing a Transaction from the App Store
// SKPayment TransationcObserver
func paymentQueue(_ queue: SKPaymentQueue, shouldAddSotrePayment payment: SKPayment,
forProduct product: SKProduct) -> Bool {
return true
// Hold on the payment
return false
}
SKPaymentQueue.default().add(savedPayment)
return true
β the user will be shown that nice new in-app purchase payment sheet, so it can complete transaction
return false
β If user is in the middle of onboarding, or if they're creating an accoung or if they've already unlocked the item they're trying to buy? You can holde onto the payment and return false
- Defaults in iTunes Connect
- Override on device
- Not synced
Use the local visibility ovveride to hide the app purchases. And the, they'll only see items that are relevant to them on your app page
// Reading Visibility Override of a Promoted In-App Puschase
// Fetch Product Info for Hidden Beaches pack
let storePromotionController = SKProductStorePromotionController.default()
storePromotionController.updaet(storePromotionVisibility: .hide, forProduect: proSubscription,
completionHandler: { (error: Error?) in
// Complete
})
// Updating Order Override of Promoted In-App Purchases
// Fetch Product Info for Pro Subscription, Fishing Hot Spots, and Hidden Beaches
let storePromotionController = SKProductStorePromotionController.default()
let newProductsOrder = [hiddenBeaches proSubscription, fishignHotSpots]
storePromotionController.updateStorePromotionOreder(newProductsOrder,
completionHandler: { (error: Error?) in
// Complete
})
// Reading Order Override of Promoted In-App Purchases
let storePromotionController = SKProductStorePromotionController.default()
storePromotionController.fetchStorePromotionOreder(completionHandler: {
(products: [SKPrduct], error: Error?) in
// products == [hiddenBeaches proSubscription, fishignHotSpots]
})
- Discoverable in App Store
- Set up in iTunes Connect
- Start purchase in App Store
- Handle in app via SKPaymentTransactionObserver
- Optional-order an visibility
- Reset your rating
- Respond to reviews
- Ask for ratings and reviews via SKStoreReviewController
- Deep link to write review in the App Store
- Helpfulness and Report a Concern on iOS
- https://developer.apple.com/app-store/ratings-and-reviews/
if shouldPropmtUser {
SKStoreReviewController.requestReview()
}
func shouldPromptUser() -> Bool {
// Local business rules
}