ios6 - iOS inapp payments - what is the right way to confirm to the user when they have made a purchase? -


i confused how , when tell user completed purchase successfully. got application rejected during app review process reason:

1. launch app 2. tap on learn benefits of subscription 3. tap on subscribe 4. tap on confirm , enter itunes password 5. no further action occurs 

and not sure when , how tell user entered info correctly since confirmed on itunes server.

i have iaphelper class looks this:

// //  iaphelper.m //  businessplan // //  created macoslion on 8/12/13. // //  // 1 #import "iaphelper.h" #import <storekit/storekit.h>  // 2 //@interface iaphelper () <skproductsrequestdelegate> @interface iaphelper () <skproductsrequestdelegate, skpaymenttransactionobserver> @end  @implementation iaphelper {     // 3     skproductsrequest * _productsrequest;      // 4     requestproductscompletionhandler _completionhandler;     nsset * _productidentifiers;     nsmutableset * _purchasedproductidentifiers; }      - (id)initwithproductidentifiers:(nsset *)productidentifiers     {                 if ((self = [super init]))         {             // store product identifiers             _productidentifiers = productidentifiers;              // check purchased products             _purchasedproductidentifiers = [nsmutableset set];             (nsstring * productidentifier in _productidentifiers)             {                 bool productpurchased = [[nsuserdefaults standarduserdefaults] boolforkey:productidentifier];                 if (productpurchased)                 {                     [_purchasedproductidentifiers addobject:productidentifier];                     nslog(@"previously purchased: %@", productidentifier);                      // set memory yes , use later.                     // user data.                     nsuserdefaults *standarduserdefaults = [nsuserdefaults standarduserdefaults];                      // first time on app, set user cookie.                     [standarduserdefaults setbool:yes forkey:@"subscriber"];                      // saving                     [[nsuserdefaults standarduserdefaults] synchronize];                 }                 else                 {                     nslog(@"not purchased: %@", productidentifier);                 }             }              [[skpaymentqueue defaultqueue] addtransactionobserver:self];         }         return self;     }       // retrieve product information itunes connect     - (void)requestproductswithcompletionhandler:(requestproductscompletionhandler)completionhandler     {             // 1         _completionhandler = [completionhandler copy];          // 2         _productsrequest = [[skproductsrequest alloc] initwithproductidentifiers:_productidentifiers];         _productsrequest.delegate = self;         [_productsrequest start];      }  #pragma mark - skproductsrequestdelegate  - (void)productsrequest:(skproductsrequest *)request didreceiveresponse:(skproductsresponse *)response {     nslog(@"loaded list of products...");     _productsrequest = nil;      nsarray * skproducts = response.products;     (skproduct * skproduct in skproducts)     {         nslog(@"found product: %@ %@ %0.2f",               skproduct.productidentifier,               skproduct.localizedtitle,               skproduct.price.floatvalue);     }      _completionhandler(yes, skproducts);     _completionhandler = nil;  }  - (void)request:(skrequest *)request didfailwitherror:(nserror *)error {      nslog(@"failed load list of products.");     _productsrequest = nil;      _completionhandler(no, nil);     _completionhandler = nil;  }  - (bool)productpurchased:(nsstring *)productidentifier {     return [_purchasedproductidentifiers containsobject:productidentifier]; }  - (void)buyproduct:(skproduct *)product {         nslog(@"buying %@...", product.productidentifier);      skpayment * payment = [skpayment paymentwithproduct:product];     [[skpaymentqueue defaultqueue] addpayment:payment];  }  - (void)paymentqueue:(skpaymentqueue *)queue updatedtransactions:(nsarray *)transactions {     (skpaymenttransaction * transaction in transactions)     {         switch (transaction.transactionstate)         {             case skpaymenttransactionstatepurchased:                 [self completetransaction:transaction];                 break;             case skpaymenttransactionstatefailed:                 [self failedtransaction:transaction];                 break;             case skpaymenttransactionstaterestored:                 [self restoretransaction:transaction];             default:                 break;         }     }; }  - (void)completetransaction:(skpaymenttransaction *)transaction {     nslog(@"completetransaction...");      [self providecontentforproductidentifier:transaction.payment.productidentifier];     [[skpaymentqueue defaultqueue] finishtransaction:transaction];      // set memory yes , use later.     // user data.     nsuserdefaults *standarduserdefaults = [nsuserdefaults standarduserdefaults];      // first time on app, set user cookie.     [standarduserdefaults setbool:yes forkey:@"subscriber"];      // saving     [[nsuserdefaults standarduserdefaults] synchronize];       // tell user things purchased.      // message person can't connect server //    uialertview *message = [[uialertview alloc] initwithtitle:@"success sending purchase request." //                                                      message:@"just press ok , wait few moments while itunes processes request." delegate:nil cancelbuttontitle:@"ok"  otherbuttontitles:nil]; //     //    [message show]; }  - (void)restoretransaction:(skpaymenttransaction *)transaction {     nslog(@"restoretransaction...");      [self providecontentforproductidentifier:transaction.originaltransaction.payment.productidentifier];     [[skpaymentqueue defaultqueue] finishtransaction:transaction]; }  - (void)failedtransaction:(skpaymenttransaction *)transaction {         nslog(@"failedtransaction...");     if (transaction.error.code != skerrorpaymentcancelled)     {         nslog(@"transaction error: %@", transaction.error.localizeddescription);          // message person can't connect server         uialertview *message = [[uialertview alloc] initwithtitle:@"could not complete transaction"         message:@"please try again. if error persists, please email support at: alex@problemio.com" delegate:nil cancelbuttontitle:@"ok"  otherbuttontitles:nil];          [message show];     }      [[skpaymentqueue defaultqueue] finishtransaction: transaction]; }  // add top of file nsstring *const iaphelperproductpurchasednotification = @"iaphelperproductpurchasednotification";  // add new method - (void)providecontentforproductidentifier:(nsstring *)productidentifier {     //nslog(@"provifing content subsciber: ");      // message person can't connect server     uialertview *message = [[uialertview alloc] initwithtitle:@"subscribed successfully!"                                                       message:@"now can ask questions right on app, , our monthly business content." delegate:nil cancelbuttontitle:@"ok"  otherbuttontitles:nil];      [message show];      [_purchasedproductidentifiers addobject:productidentifier];     [[nsuserdefaults standarduserdefaults] setbool:yes forkey:productidentifier];     [[nsuserdefaults standarduserdefaults] synchronize];     [[nsnotificationcenter defaultcenter] postnotificationname:iaphelperproductpurchasednotification object:productidentifier userinfo:nil];  }  @end 

and class start transaction process:

#import "subscriptioncontroller.h"  // 1 #import "rageiaphelper.h" #import <storekit/storekit.h>  // 2 @interface subscriptioncontroller () {     nsarray *_products;      // add new instance variable class extension     nsnumberformatter * _priceformatter; } @end  @implementation subscriptioncontroller  // 3 - (void)viewdidload {     [super viewdidload];      //self.refreshcontrol = [[uirefreshcontrol alloc] init];     //[self.refreshcontrol addtarget:self action:@selector(reload) forcontrolevents:uicontroleventvaluechanged];     [self reload];     //[self.refreshcontrol beginrefreshing];      // add end of viewdidload     _priceformatter = [[nsnumberformatter alloc] init];     [_priceformatter setformatterbehavior:nsnumberformatterbehavior10_4];     [_priceformatter setnumberstyle:nsnumberformattercurrencystyle];      self.view.backgroundcolor = [uicolor colorwithwhite:0.859 alpha:1.000];     }  // 4 - (void)reload {     _products = nil;     //[self.tableview reloaddata];     [[rageiaphelper sharedinstance] requestproductswithcompletionhandler:^(bool success, nsarray *products)     {         if (success)         {             _products = products;             //[self.tableview reloaddata];         }         //[self.refreshcontrol endrefreshing];     }]; }  #pragma mark - table view  - (nsinteger)numberofsectionsintableview:(uitableview *)tableview {     return 1; }  // 5 - (nsinteger)tableview:(uitableview *)tableview numberofrowsinsection:(nsinteger)section {     return _products.count; }  - (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath {     nslog(@"a");     uitableviewcell *cell = [tableview dequeuereusablecellwithidentifier:@"cell" forindexpath:indexpath];      skproduct * product = (skproduct *) _products[indexpath.row];     cell.textlabel.text = product.localizedtitle;       // add bottom of tableview:cellforrowatindexpath (before return cell)     [_priceformatter setlocale:product.pricelocale];     cell.detailtextlabel.text = [_priceformatter stringfromnumber:product.price];      if ([[rageiaphelper sharedinstance] productpurchased:product.productidentifier])     {         cell.accessorytype = uitableviewcellaccessorycheckmark;         cell.accessoryview = nil;     }     else     {         uibutton *buybutton = [uibutton buttonwithtype:uibuttontyperoundedrect];         buybutton.frame = cgrectmake(0, 0, 72, 37);         [buybutton settitle:@"buy" forstate:uicontrolstatenormal];         buybutton.tag = indexpath.row;         [buybutton addtarget:self action:@selector(buybuttontapped:) forcontrolevents:uicontroleventtouchupinside];         cell.accessorytype = uitableviewcellaccessorynone;         cell.accessoryview = buybutton;     }      return cell; }  //- (ibaction)subscribe:(id)sender //{ //    uibutton *buybutton = (uibutton *)sender; //    skproduct *product = _products[buybutton.tag]; //     //    nslog(@"buying %@...", product.productidentifier); //    [[rageiaphelper sharedinstance] buyproduct:product]; //}  - (void)viewwillappear:(bool)animated {     [[nsnotificationcenter defaultcenter] addobserver:self selector:@selector(productpurchased:) name:iaphelperproductpurchasednotification object:nil]; }  - (void)viewwilldisappear:(bool)animated {     [[nsnotificationcenter defaultcenter] removeobserver:self]; }  - (void)productpurchased:(nsnotification *)notification {     nslog(@"purchaseddddddddd");   //    nsstring * productidentifier = notification.object; //    [_products enumerateobjectsusingblock:^(skproduct * product, nsuinteger idx, bool *stop) //     { //         if ([product.productidentifier isequaltostring:productidentifier]) //         { //             // todo: //             // update how button appears. //              //              ////             [self.table reloadrowsatindexpaths:@[[nsindexpath indexpathforrow:idx insection:0]] withrowanimation:uitableviewrowanimationfade]; //             *stop = yes; //         } //     }];      // message person can't connect server     uialertview *message = [[uialertview alloc] initwithtitle:@"purchased successfully"                                                       message:@":)" delegate:nil cancelbuttontitle:@"ok"  otherbuttontitles:nil];      [message show];      // push confirmation  } //- (ibaction)subscribe:(id)sender //{ //     //} - (void)viewdidunload {     [super viewdidunload]; }   - (ibaction)createsub:(id)sender {         uibutton *buybutton = (uibutton *)sender;         skproduct *product = _products[buybutton.tag];       if ( product == nil)     {         // message person can't connect server         uialertview *message = [[uialertview alloc] initwithtitle:@"pulling product data itunes..."                                                           message:@"please try again in few moments." delegate:nil cancelbuttontitle:@"ok"  otherbuttontitles:nil];          [message show];     }     else     {         // message person can't connect server         uialertview *message = [[uialertview alloc] initwithtitle:@"success sending purchase request."         message:@"just press ok , wait few moments while itunes processes request." delegate:nil cancelbuttontitle:@"ok"  otherbuttontitles:nil];          [message show];          nslog(@"buying %@...", product.productidentifier);         [[rageiaphelper sharedinstance] buyproduct:product];     } } @end 

thank help!

you should have sort of ui update tell user payment successful , feature available/unlocked. typically, done either update in views correspond new content, or uialertview if there no visual changes made.


Comments

Popular posts from this blog

How to remove text and logo OR add Overflow on Android ActionBar using AppCompat on API 8? -

html - How to style widget with post count different than without post count -

url rewriting - How to redirect a http POST with urlrewritefilter -