saturngod / IAPHelper

No more maintenance for this repo. Please use the https://github.com/bizz84/SwiftyStoreKit
MIT License
1.55k stars 280 forks source link

Is workflow correct? #10

Open moleksyuk opened 10 years ago

moleksyuk commented 10 years ago

Hi @saturngod

I have questions about your workflow to perform purchase and provide content of it.

Please find comments in code below.

if(![IAPShare sharedHelper].iap) {
      NSSet* dataSet = [[NSSet alloc] initWithObjects:@"com.comquas.iap.test", nil];

      [IAPShare sharedHelper].iap = [[IAPHelper alloc] initWithProductIdentifiers:dataSet];
  }

[IAPShare sharedHelper].iap.production = NO;

  [[IAPShare sharedHelper].iap requestProductsWithCompletion:^(SKProductsRequest* request,SKProductsResponse* response)
   {
       if(response > 0 ) {
       SKProduct* product =[[IAPShare sharedHelper].iap.products objectAtIndex:0];

       [[IAPShare sharedHelper].iap buyProduct:product
                                  onCompletion:^(SKPaymentTransaction* trans){

              if(trans.error)
              {
                  NSLog(@"Fail %@",[trans.error localizedDescription]);
              }
              else if(trans.transactionState == SKPaymentTransactionStatePurchased) {

              // @moleksyuk: According to Apple API SKPaymentTransactionStatePurchased means that transaction is in queue, user has been charged.  Client should complete the transaction.
// And this doc says: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/DeliverProduct.html#//apple_ref/doc/uid/TP40008267-CH5-SW3
// Transaction statuses and corresponding actions
// SKPaymentTransactionStatePurchased -> Provide the purchased functionality.
// BUT in this place isPurchased will be NO.

BOOL isPurchased = [[IAPShare sharedHelper].iap isPurchasedProductsIdentifier:kInAppPurchaseRemoveAdsProductId];

// @moleksyuk: And if in this place internet connection will fail before we check receipt user won't get purchased item but will be charged.

                  [[IAPShare sharedHelper].iap checkReceipt:trans.transactionReceipt AndSharedSecret:@"your sharesecret" onCompletion:^(NSString *response, NSError *error) {

                      //Convert JSON String to NSDictionary
                      NSDictionary* rec = [IAPShare toJSON:response];

                      if([rec[@"status"] integerValue]==0)
                      {
                      NSString *productIdentifier = trans.payment.productIdentifier;
                        [[IAPShare sharedHelper].iap provideContent:productIdentifier];

// @moleksyuk: Only here we will get isPurchased = YES. Right after provideContent is called.
BOOL isPurchased = [[IAPShare sharedHelper].iap isPurchasedProductsIdentifier:kInAppPurchaseRemoveAdsProductId];

                          NSLog(@"SUCCESS %@",response);
                          NSLog(@"Pruchases %@",[IAPShare sharedHelper].iap.purchasedProducts);
                      }
                      else {
                          NSLog(@"Fail");
                      }
                  }];
              }
              else if(trans.transactionState == SKPaymentTransactionStateFailed) {
                   NSLog(@"Fail");
              }
                                  }];//end of buy product
       }
}];

Question:

  1. Is it important to checkReceipt and provide content only after validation?
  2. What is the best way to fix issue when user is charged successfully for item but checkReceipt is failed due to internet connection error? In this case we should provide content.