2012-02-08 18 views
5

Próbuję dokonać zakupu aplikacji w mojej aplikacji. Ale nie mam wyniku, gdy próbuję uruchomić go na urządzeniu.W zakupie aplikacji nie działa na urządzeniu

Mój kod jest następujący:

to przedmiot potrzebny uzyskać informacje na temat produktów i kupić go.

.h

#import <Foundation/Foundation.h> 
#import "StoreKit/StoreKit.h" 

#define kProductsLoadedNotification   @"ProductsLoaded" 
#define kProductPurchasedNotification  @"ProductPurchased" 
#define kProductPurchaseFailedNotification @"ProductPurchaseFailed" 

@interface StoreManager : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver> 

@property (strong, nonatomic) NSMutableSet * _purchasedProducts; 
@property (strong, nonatomic) NSArray *products; 
@property (strong, nonatomic) NSSet *_productIdentifiers; 
@property (strong, nonatomic) SKProductsRequest *request; 

- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers; 
- (void)requestProducts; 
- (void)buyProduct:(SKProduct *)product; 

- (void)completeTransaction:(SKPaymentTransaction *)transaction; 
- (void)restoreTransaction:(SKPaymentTransaction *)transaction; 
- (void)failedTransaction:(SKPaymentTransaction *)transaction; 
- (void)provideContent:(NSString *)productIdentifier; 
- (void)recordTransaction:(SKPaymentTransaction *)transaction; 

@end 

.m

Przedmiotem
#import "StoreManager.h" 

@implementation StoreManager 
@synthesize _purchasedProducts; 
@synthesize products; 
@synthesize _productIdentifiers; 
@synthesize request; 

// Initializes the request object with the set of product identifiers. 
- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers{ 
    self = [super init]; 
    if(self){ 
     self._productIdentifiers = productIdentifiers;   
     NSMutableSet *purchased = [NSMutableSet set]; 
     for(NSString * productId in self._productIdentifiers){ 
      BOOL flag = [[NSUserDefaults standardUserDefaults] boolForKey:productId]; 
      if(flag){ 
       [purchased addObject:productId]; 
       NSLog(@"Previously purchased: %@", productId); 
      } 
      NSLog(@"Not purchased: %@", productId); 
     } 
     self._purchasedProducts = purchased; 
    } 
    return self; 
} 

// Request info for the product. 
- (void)requestProducts{ 
    self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:self._productIdentifiers]; 
    self.request.delegate = self; 
    [self.request start]; 
} 

// Request fail. 
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error{ 
    NSLog(@"Fail request! Error: %@", error); 
} 

// Delegate method - did receive responce. 
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{ 
    self.products = response.products; 
    self.request = nil; 
    [[NSNotificationCenter defaultCenter] postNotificationName:kProductsLoadedNotification object:self.products]; 
} 

// Buy product. 
- (void)buyProduct:(SKProduct *)product{  
    SKPayment *payment = [SKPayment paymentWithProduct:product]; 
    [[SKPaymentQueue defaultQueue] addPayment:payment]; 
} 

// Payment transactions 
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{ 
    for (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)recordTransaction:(SKPaymentTransaction *)transaction {  
    // TODO: Record the transaction on the server side...  
} 

- (void)completeTransaction:(SKPaymentTransaction *)transaction{ 
    [self recordTransaction: transaction]; 
    [self provideContent: transaction.payment.productIdentifier]; 
    NSLog(@"completeTransaction..."); 
} 

- (void)provideContent:(NSString *)productIdentifier { 

    NSLog(@"Toggling flag for: %@", productIdentifier); 

    [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:productIdentifier]; 
    [[NSUserDefaults standardUserDefaults] synchronize]; 
    [self._purchasedProducts addObject:productIdentifier]; 

    [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchasedNotification object:productIdentifier]; 

} 

- (void)restoreTransaction:(SKPaymentTransaction *)transaction { 

    NSLog(@"restoreTransaction..."); 

    [self recordTransaction: transaction]; 
    [self provideContent: transaction.originalTransaction.payment.productIdentifier]; 
    [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; 

} 

- (void)failedTransaction:(SKPaymentTransaction *)transaction { 

    if (transaction.error.code != SKErrorPaymentCancelled) 
    { 
     NSLog(@"Transaction error: %@", transaction.error.localizedDescription); 
    } 

    [[NSNotificationCenter defaultCenter] postNotificationName:kProductPurchaseFailedNotification object:transaction]; 

    [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; 

} 

@end 

Singleton

.h

#import <Foundation/Foundation.h> 
#import "StoreManager.h" 

@interface StoreWrapper : StoreManager 

+ (StoreWrapper *)sharedInstance; 

@end 

.m

#import "StoreWrapper.h" 

@implementation StoreWrapper 
static StoreWrapper *gInstance = NULL; 

- (id)init{  
    NSSet *productId = [NSSet setWithObjects:@"com.company.sb.pack1", @"com.company.sb.pack5", nil]; 
    self = [super initWithProductIdentifiers:productId]; 
    if(self){ 

    } 
    return self; 
} 

+ (StoreWrapper *)sharedInstance{ 
    if(gInstance == NULL){ 
     gInstance = [[self alloc] init]; 
    } 
    return gInstance; 
} 

@end 

W moim zdaniem kontrolera i wywołać następny:

- (void)viewWillAppear:(BOOL)animated 
{ 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productsLoaded:) name:kProductsLoadedNotification object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productPurchased:) name:kProductPurchasedNotification object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(productPurchaseFailed:) name:kProductPurchaseFailedNotification object: nil];  
    Reachability *reach = [Reachability reachabilityForInternetConnection]; 
    NetworkStatus netStatus = [reach currentReachabilityStatus];  
    if (netStatus == NotReachable) {   
     NSLog(@"No internet connection!");   
    } else {   
     NSLog(@"Internet connection available!"); 
     // Request product 
     [[StoreWrapper sharedInstance] requestProducts];   
     [activIndicator startAnimating]; 
    }  
    [super viewWillAppear:animated]; 
} 

w tym momencie wysłania żądania do informacji o produkcie uzyskać z serwera z moim ID produktu

dalej, jeśli produkt załadowany moją klasę otrzyma powiadomienie o tym (i wywołaj następującą metodę).

- (void)productsLoaded:(NSNotification *)notification{  
    [activIndicator stopAnimating]; 
    [activIndicator setHidden:YES];  
    NSArray *arr = [notification object];  
    for(int i = 0; i < [arr count]; i++){ 
     SKProduct *product = [[StoreWrapper sharedInstance].products objectAtIndex:i]; 
     UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
     [btn setFrame:CGRectMake(0, i*55, 100, 50)]; 
     [btn setTitle:product.localizedTitle forState:UIControlStateNormal]; 
     [btn setTag:i]; 
     [btn addTarget:self action:@selector(buyProduct:) forControlEvents:UIControlEventTouchUpInside]; 
     [self.view addSubview:btn];   
    }  
} 

dla przycisku i dodać wyboru buyProduct (jak pokazano powyżej)

- (void)buyProduct:(id)sender{ 
    NSLog(@"sender tag %d", [sender tag]); 
    int tag = [sender tag]; 
    SKProduct *product = [[StoreWrapper sharedInstance].products objectAtIndex:tag];  
    [[StoreWrapper sharedInstance] buyProduct:product];  
} 

Dla iPhone Simulator to dzieło wspaniałe, ale na urządzeniu Ja nie mam żadnego przycisku, ponieważ response.products nie ściągnąć.

Wszystkie metody są nazywane, ale metoda delegat * - (void) productsRequest: (SKProductsRequest *) prośba didReceiveResponse: (SKProductsResponse ) odpowiedź nie powrócić response.products.

Dziękujemy za poświęcony czas i podziękowanie!

+0

Działa na symulatorze? Zakup InApp powinien zawsze być testowany na urządzeniu. I nawet tam należy wylogować się z konta iTunes i użyć konta testowego (specjalnie stworzonego do testowania w AppStore) w aplikacji. –

+0

tak, to prawda, ale do tego czasu muszę utworzyć przycisk tylko po otrzymaniu odpowiedzi od serwera i mam produkty. Jeśli otrzymam produkty, wysłałem powiadomienie z tym obiektem, a kiedy otrzymam wiadomość, utworzę przycisk z produktami zliczania odpowiedzi. To tylko przykład testowy. Ale działa tylko na symulatorze. –

+0

Chcę powiedzieć, że w zależności od urządzenia lub symulatora - metoda delegata - (void) productRequest: (SKProductsRequest *) request didReceiveResponse: (SKProductsResponse) odpowiedź lub zwrot produktów lub nie zwraca. To jest mój problem. –

Odpowiedz

5

Do rozwiązania tego problemu zresetowałem urządzenie i ponownie uruchomiłem aplikację.

To mi pomaga.

+0

Po twardym resetowaniu metoda delegująca productsRequest działa poprawnie. –

+0

po długim poszukiwaniu rozwiązań nie działa, ale to działa dobrze. Dzięki za to – Adel

+0

Jak "zresetować delegate method productsRequest"? – Jacky

Powiązane problemy