Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

IAP auto renewable in practice

2.323 Aufrufe

Veröffentlicht am

some problems we meet after implement IAP

Veröffentlicht in: Software
  • Login to see the comments

IAP auto renewable in practice

  1. 1. IAP auto-renewable in practice Cocoaheads Taipei ,2016.12
  2. 2. 2
  3. 3. 3 In App Purchase Users use their Apple ID purchase virtual product(s) Developer use receipt(s) to implement business logic Financial receive simple report
  4. 4. 4 step 1~7 get products user can purchase 

  5. 5. 5
  6. 6. 6 NSSet *productsIDSet = ["product_identifiers1","product_identifiers2"] self.productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productsIDSet]; productRequest.delegate = self; [productRequest start];
  7. 7. 7 SKProductsRequestDelegate - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { NSLog(@"receive products %@", response.products); NSLog(@"invalidProductIdentifiers %@", response.invalidProductIdentifiers); self.products = response.products; …… } [SKProduct] from productsIDSet
  8. 8. 8 step 8 user select product to buy 

  9. 9. 9 step 8 user select product to buy 
 - (void)purchaseProduct:(SKProduct *)inProduct { SKPayment *p = [SKPayment paymentWithProduct:inProduct]; [[SKPaymentQueue defaultQueue] addPayment:p]; }
  10. 10. 10 step 9 ~11 validate user AppleID/password 

  11. 11. 11 step 12 ~14 receive receipt

  12. 12. 12 SKPaymentTransactionObserver - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { NSMutableArray *purchasedTransactions = [NSMutableArray array]; for (SKPaymentTransaction *t in transactions) { switch (t.transactionState) { case SKPaymentTransactionStatePurchased: [purchasedTransactions addObject:t]; [[SKPaymentQueue defaultQueue] finishTransaction:t]; break; //ignore other case in sample code } } if ([purchasedTransactions count] > 0) { //handle receipts here,continue step 15 } }
  13. 13. 13 step 15~19 verify receipt with Apple server / Your server

  14. 14. 14 How server validate a receipt 1.Apple API receipt product_id receipt bid receipt duration(auto-renewable) https://sandbox.itunes.apple.com/verifyReceipt https://buy.itunes.apple.com/verifyReceipt 2.DB ensure receipt transaction_id not used
  15. 15. 15 step 20 Deliver purchased content

  16. 16. 16 Overview (bad side) 3.1.1 In-App Purchase, 3.1.2 Subscriptions: If you want to unlock features or functionality within your app,you must use in-app purchase only verify API, no webhook When user cancel on iTunes ,Server will not get cancel request. Can not know which Apple ID user use Can not know purchase condition until receive receipt
  17. 17. 17 A lot of problems we met
  18. 18. 18 Receive sandbox receipt on production environment production validate API -> receive 21007 status code -> try sandbox API Solution:
  19. 19. 18 Receive sandbox receipt on production environment production validate API -> receive 21007 status code -> try sandbox API Solution: Look like workaround,but it’s spec
  20. 20. 19 Critical:Network condition bad When Upload receipt to server
  21. 21. 19 Critical:Network condition bad When Upload receipt to server Business logic
 Purchase Manager Purchase Manager StoreKit Purchase ViewController SKProductsRequestDelegate SKPaymentTransactionObserverdelegatedelegate Solution: cache receipts , remove cache after ensure receipt is uploaded
  22. 22. 19 Critical:Network condition bad When Upload receipt to server Business logic
 Purchase Manager Purchase Manager StoreKit Purchase ViewController SKProductsRequestDelegate SKPaymentTransactionObserverdelegatedelegate cache receipts Solution: cache receipts , remove cache after ensure receipt is uploaded
  23. 23. 19 Critical:Network condition bad When Upload receipt to server Business logic
 Purchase Manager Purchase Manager StoreKit Purchase ViewController SKProductsRequestDelegate SKPaymentTransactionObserverdelegatedelegate cache receipts trigger API remove receipts Solution: cache receipts , remove cache after ensure receipt is uploaded
  24. 24. 19 Critical:Network condition bad When Upload receipt to server Business logic
 Purchase Manager Purchase Manager StoreKit Purchase ViewController SKProductsRequestDelegate SKPaymentTransactionObserverdelegatedelegate cache receipts trigger API remove receipts UI Solution: cache receipts , remove cache after ensure receipt is uploaded
  25. 25. 20 User purchase on iTunes instead of app case 1 1.touch purchase product on App 2.when validate AppleID, type wrong password more than 3 times 3.StoreKit ask user to change password 4.redirect to iTunes 5.type correct password and user can purchase on iTunes
  26. 26. 21 User purchase on iTunes instead of app touch this itms-apps://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptionscase 2
  27. 27. 22 User purchase on iTunes instead of app case 2 https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions touch this
  28. 28. 23 User purchase on iTunes instead of app Business logic
 Purchase Manager Purchase Manager StoreKit Purchase ViewController SKProductsRequestDelegate SKPaymentTransactionObserverdelegate delegate Solution: init purchase manager at app launch
  29. 29. 23 User purchase on iTunes instead of app Business logic
 Purchase Manager Purchase Manager StoreKit Purchase ViewController SKProductsRequestDelegate SKPaymentTransactionObserverdelegate delegate Solution: init purchase manager at app launch AppDelegate init at app launch
  30. 30. 24 What is receipt (app side) SKPaymentTransaction @property(nonatomic, readonly, nullable) NSData *transactionReceipt /* base64 encode string */ NSString *receiptString = [receipt base64EncodedStringWithOptions:0];
  31. 31. 24 What is receipt (app side) SKPaymentTransaction @property(nonatomic, readonly, nullable) NSData *transactionReceipt /* base64 encode string */ NSString *receiptString = [receipt base64EncodedStringWithOptions:0];
  32. 32. 25 What is receipt (server side)
  33. 33. 25 What is receipt (server side)
  34. 34. 25 What is receipt (server side)
  35. 35. 26 Critical: Auto-renew fail but user receive charge mail
  36. 36. 26 Critical: Auto-renew fail but user receive charge mail Solution: Trigger Verify API at Next day of expire_date Not the same day
  37. 37. 27 When switch from objC to swift
  38. 38. 28 When switch from objC to swift
  39. 39. 28 When switch from objC to swift transactionReceipt property missing can only use iOS 7 style receipt
  40. 40. 29 iOS 7 receipt
  41. 41. 29 iOS 7 receipt
  42. 42. 29 iOS 7 receipt
  43. 43. 30 iOS 7 receipt
  44. 44. 30 iOS 7 receipt
  45. 45. 31 iOS 6 vs iOS 7 style transaction receipts • each transaction has unique iOS 6 style receipt • iOS 7 style receipt get all receipt data in one query • base64 encode iOS 7 style receipt is much larger than iOS 6 style
  46. 46. 32 Will original_transaction_id change? purchase cancel purchase again A C renew a long time B
  47. 47. 32 Will original_transaction_id change? purchase cancel purchase again A C original_transaction_id in receipt A , B and C keep the same renew a long time B
  48. 48. 33 Can I manage auto-renewable subscription in Sandbox ? No. In addition,sandbox will auto-renew 5 times. in the end will get 6 receipt
  49. 49. 34 What will user see in iTune Connect If my app have multiple auto- renewable products( A & B)?
  50. 50. 34 What will user see in iTune Connect If my app have multiple auto- renewable products( A & B)? https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/ manageSubscriptions 
 This URL will only work for production accounts to display existing auto-renewing subscriptions for management
  51. 51. 35 purchase product A in app cancel auto-renew A in iTune purchase product B in app product A expire What will user see in iTune Connect If my app have multiple auto- renewable products( A & B)?
  52. 52. 35 purchase product A in app cancel auto-renew A in iTune purchase product B in app product A expire What will user see in iTune Connect If my app have multiple auto- renewable products( A & B)? iTune display product A product B
  53. 53. 36 You can not do anything If You have a auto renewable product,also set trial period(Eq:1 month) But Apple receipt trial period is more than your setting KKTV happen this few times
  54. 54. 37 if your service has account system + multiple platform + multiple payment
  55. 55. 37 if your service has account system + multiple platform + multiple payment email facebook phone number iOS Android Web PS4 … IAP credit card mobile payment POSA card redeem code convenient store code
  56. 56. 38 Example: User Apple ID KKTV iTunes KKTV Result: StoreKit
  57. 57. 39 Example: User Apple ID KKTV iTunes KKTV Result: receipt server KKTV Solution: receipt Alert
  58. 58. 39 Example: User Apple ID KKTV iTunes KKTV Result: receipt server KKTV Solution: receipt Alert
  59. 59. 40 Example: user IAP iTunes IAP
  60. 60. 40 Example: user IAP iTunes IAP Result IAP user
  61. 61. 40 Example: user IAP iTunes IAP Result IAP user Solution app/server side user iTunes
  62. 62. 41 Example: user IAP ..... KKTV KKTV IAP
  63. 63. 41 Example: user IAP Result AppleID user ..... KKTV KKTV IAP
  64. 64. 42 Financial • report daily • report user ID transactionID • user cancel / refund •
  65. 65. 43 Conclusion • IAP is unfriendly to Developer. But super easy for user. • Tracking IAP log help find unexpected problems • Raise IAP price could be an option
  66. 66. 44 Reference TN2387:In-App Purchase Best Practices TN2413: In-App Purchase FAQ In-App Purchase Programming Guide Receipt Validation Programming Guide WWDC 2016: Using StoreKit for In-App Purchases with Swift 3 WWDC 2014: Optimizing In-App Purchases WWDC 2012: Selling Products with Store Kit WWDC 2013: Using Store Kit for In-App Purchases WWDC 2012: Managing Subscriptions with In-App Purchase TN2259: Adding In-App Purchase to your iOS and macOS Applications https://forums.developer.apple.com/community/system-frameworks/in-app-purchase

×