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

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

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

javascript - storing input from prompt in array and displaying the array -