iap auto renewable in practice

66
IAP auto-renewable in practice Cocoaheads Taipei ,2016.12

Upload: hokila-jan

Post on 16-Apr-2017

909 views

Category:

Software


0 download

TRANSCRIPT

Page 1: IAP auto renewable  in practice

IAP auto-renewable in practice

Cocoaheads Taipei ,2016.12

Page 2: IAP auto renewable  in practice

2

Page 3: IAP auto renewable  in practice

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

Page 4: IAP auto renewable  in practice

4

step 1~7 get products user can purchase

Page 5: IAP auto renewable  in practice

5

Page 6: IAP auto renewable  in practice

6

NSSet *productsIDSet = ["product_identifiers1","product_identifiers2"]

self.productRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productsIDSet];

productRequest.delegate = self;

[productRequest start];

Page 7: IAP auto renewable  in practice

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

Page 8: IAP auto renewable  in practice

8

step 8 user select product to buy

Page 9: IAP auto renewable  in practice

9

step 8 user select product to buy

- (void)purchaseProduct:(SKProduct *)inProduct { SKPayment *p = [SKPayment paymentWithProduct:inProduct]; [[SKPaymentQueue defaultQueue] addPayment:p]; }

Page 10: IAP auto renewable  in practice

10

step 9 ~11 validate user AppleID/password

Page 11: IAP auto renewable  in practice

11

step 12 ~14 receive receipt

Page 12: IAP auto renewable  in practice

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 } }

Page 13: IAP auto renewable  in practice

13

step 15~19 verify receipt with Apple server / Your server

Page 14: IAP auto renewable  in practice

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

Page 15: IAP auto renewable  in practice

15

step 20 Deliver purchased content

Page 16: IAP auto renewable  in practice

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

Page 17: IAP auto renewable  in practice

17

A lot of problems we met

Page 18: IAP auto renewable  in practice

18

Receive sandbox receipt on production environment

production validate API -> receive 21007 status code -> try sandbox API

Solution:

Page 19: IAP auto renewable  in practice

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

Page 20: IAP auto renewable  in practice

19

Critical:Network condition bad When Upload receipt to server

Page 21: IAP auto renewable  in practice

19

Critical:Network condition bad When Upload receipt to server

Business logicPurchase Manager

Purchase Manager StoreKitPurchase

ViewController

SKProductsRequestDelegateSKPaymentTransactionObserverdelegatedelegate

Solution: cache receipts , remove cache after ensure receipt is uploaded

Page 22: IAP auto renewable  in practice

19

Critical:Network condition bad When Upload receipt to server

Business logicPurchase Manager

Purchase Manager StoreKitPurchase

ViewController

SKProductsRequestDelegateSKPaymentTransactionObserverdelegatedelegate

cache receipts

Solution: cache receipts , remove cache after ensure receipt is uploaded

Page 23: IAP auto renewable  in practice

19

Critical:Network condition bad When Upload receipt to server

Business logicPurchase Manager

Purchase Manager StoreKitPurchase

ViewController

SKProductsRequestDelegateSKPaymentTransactionObserverdelegatedelegate

cache receiptstrigger API

remove receipts

Solution: cache receipts , remove cache after ensure receipt is uploaded

Page 24: IAP auto renewable  in practice

19

Critical:Network condition bad When Upload receipt to server

Business logicPurchase Manager

Purchase Manager StoreKitPurchase

ViewController

SKProductsRequestDelegateSKPaymentTransactionObserverdelegatedelegate

cache receiptstrigger API

remove receiptsUI

Solution: cache receipts , remove cache after ensure receipt is uploaded

Page 25: IAP auto renewable  in practice

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

Page 26: IAP auto renewable  in practice

21

User purchase on iTunes instead of app

touch this

itms-apps://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptionscase 2

Page 27: IAP auto renewable  in practice

22

User purchase on iTunes instead of appcase 2 https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions

touch this

Page 28: IAP auto renewable  in practice

23

User purchase on iTunes instead of app

Business logicPurchase Manager

Purchase Manager StoreKitPurchase

ViewController

SKProductsRequestDelegateSKPaymentTransactionObserverdelegate

delegate

Solution: init purchase manager at app launch

Page 29: IAP auto renewable  in practice

23

User purchase on iTunes instead of app

Business logicPurchase Manager

Purchase Manager StoreKit

Purchase ViewController

SKProductsRequestDelegateSKPaymentTransactionObserverdelegate

delegate

Solution: init purchase manager at app launch

AppDelegate init at app launch

Page 30: IAP auto renewable  in practice

24

What is receipt (app side)SKPaymentTransaction@property(nonatomic, readonly, nullable) NSData *transactionReceipt

/* base64 encode string */NSString *receiptString = [receipt base64EncodedStringWithOptions:0];

Page 31: IAP auto renewable  in practice

24

What is receipt (app side)SKPaymentTransaction@property(nonatomic, readonly, nullable) NSData *transactionReceipt

/* base64 encode string */NSString *receiptString = [receipt base64EncodedStringWithOptions:0];

Page 32: IAP auto renewable  in practice

25

What is receipt (server side)

Page 33: IAP auto renewable  in practice

25

What is receipt (server side)

Page 34: IAP auto renewable  in practice

25

What is receipt (server side)

Page 35: IAP auto renewable  in practice

26

Critical: Auto-renew fail but user receive charge mail

Page 36: IAP auto renewable  in practice

26

Critical: Auto-renew fail but user receive charge mailSolution: Trigger Verify API at Next day of expire_date

Not the same day

Page 37: IAP auto renewable  in practice

27

When switch from objC to swift

Page 38: IAP auto renewable  in practice

28

When switch from objC to swift

Page 39: IAP auto renewable  in practice

28

When switch from objC to swift

transactionReceipt property missing can only use iOS 7 style receipt

Page 40: IAP auto renewable  in practice

29

iOS 7 receipt

Page 41: IAP auto renewable  in practice

29

iOS 7 receipt

Page 42: IAP auto renewable  in practice

29

iOS 7 receipt

Page 43: IAP auto renewable  in practice

30

iOS 7 receipt

Page 44: IAP auto renewable  in practice

30

iOS 7 receipt

Page 45: IAP auto renewable  in practice

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

Page 46: IAP auto renewable  in practice

32

Will original_transaction_id change?

purchase cancel purchase again

A C

renew

a long time

B

Page 47: IAP auto renewable  in practice

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

Page 48: IAP auto renewable  in practice

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

Page 49: IAP auto renewable  in practice

34

What will user see in iTune Connect If my app have multiple auto-renewable products( A & B)?

Page 50: IAP auto renewable  in practice

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

Page 51: IAP auto renewable  in practice

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)?

Page 52: IAP auto renewable  in practice

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

Page 53: IAP auto renewable  in practice

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

Page 54: IAP auto renewable  in practice

37

if your service has

account system + multiple platform + multiple payment

Page 55: IAP auto renewable  in practice

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

Page 56: IAP auto renewable  in practice

38

Example:User Apple ID KKTV

iTunesKKTV

Result:StoreKit

Page 57: IAP auto renewable  in practice

39

Example:User Apple ID KKTV

iTunesKKTV

Result:receipt server

KKTV

Solution:receipt Alert

Page 58: IAP auto renewable  in practice

39

Example:User Apple ID KKTV

iTunesKKTV

Result:receipt server

KKTV

Solution:receipt Alert

Page 59: IAP auto renewable  in practice

40

Example: user IAP

iTunes IAP

Page 60: IAP auto renewable  in practice

40

Example: user IAP

iTunes IAP

Result IAP user

Page 61: IAP auto renewable  in practice

40

Example: user IAP

iTunes IAP

Result IAP user

Solutionapp/server side user iTunes

Page 62: IAP auto renewable  in practice

41

Example:user

IAP

..... KKTV KKTV IAP

Page 63: IAP auto renewable  in practice

41

Example:user

IAP

ResultAppleID user

..... KKTV KKTV IAP

Page 64: IAP auto renewable  in practice

42

Financial

• report daily

• report user ID transactionID

• user cancel / refund

Page 65: IAP auto renewable  in practice

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

Page 66: IAP auto renewable  in practice

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