SKPayment错误,SKProduct继续返回nill

时间:2015-06-02 20:02:14

标签: objective-c debugging in-app-purchase skpaymenttransaction

我在Spritekit工作,我试图在我的游戏中启用SKPayments,一旦他们购买就给用户5个生命。但每次我运行应用程序并尝试购买时,我都会收到错误,我的SKProduct FiveLives是零。我不断得到错误的代码和行在下面。有人可以帮帮我吗?

self.product1ID = @"com.retrogames.5Lives";

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

[self getProduct1ID:self];

SKPayment *payment = [SKPayment paymentWithProduct:_FiveLives];
ERROR LINE  [[SKPaymentQueue defaultQueue] addPayment:payment];

}

我班上的其他人都在这里

StoreViewController.h

#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>    
@interface StoreViewController : UIViewController <SKPaymentTransactionObserver, SKProductsRequestDelegate>{
SKProductsRequest *productsRequest;
}



@property (strong, nonatomic) SKProduct *FiveLives;
@property (strong, nonatomic) NSString *product1ID;

- (IBAction)_5Lives:(id)sender;

-(void)getProduct1ID:(UIViewController *)viewcontroller;

@end

StoreViewController.M

  #import "StoreViewController.h"

 @interface StoreViewController ()

 @end

 @implementation StoreViewController

 - (void)viewDidLoad {
 [super viewDidLoad];

   // Do any additional setup after loading the view.
  }

  - (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
   // Dispose of any resources that can be recreated.
 }

 -(void)getProduct1ID:(UIViewController *)viewcontroller{

  if ([SKPaymentQueue canMakePayments]) {
    SKProductsRequest *request = [[SKProductsRequest alloc]initWithProductIdentifiers:[NSSet setWithObject:self.product1ID]];
    request.delegate = self;
    [request start];
    }
   else{
       UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Sorry purchase was unsuccessful" message:@"Please enable in app purchases in your settings" delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil];
    [alert show];

   }


  }

  #pragma mark _
  #pragma mark SKProductsRequestDelegate

  -(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {

   NSArray *Products = response.products;

   if (Products.count != 0) {

    _FiveLives = Products[0];

    }

   Products = response.invalidProductIdentifiers;

    for (SKProduct *FiveLives in Products) {
      NSLog(@"Product Not Found : %@", FiveLives);
    }

   }

 - (IBAction)_5Lives:(id)sender {
self.product1ID = @"com.retrogames.5Lives";

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];

[self getProduct1ID:self];

SKPayment *payment = [SKPayment paymentWithProduct:_FiveLives];
[[SKPaymentQueue defaultQueue] addPayment:payment];

 }

 - (IBAction)RestorePurchases:(id)sender{
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue]restoreCompletedTransactions];
 }

 -(void)add5Lives{
NSLog(@"BUY5LIVES");
GameLives = GameLives + 5;
    [[NSUserDefaults standardUserDefaults] setInteger:GameLives forKey:@"Key"];

   }

  -(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
for (SKPaymentTransaction *transaction in transactions) {

    switch (transaction.transactionState) {
        case SKPaymentTransactionStatePurchased:[self add5Lives];{

            NSLog(@"TRANSACTION SUCCESSFUL");
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            break;
        }
        case SKPaymentTransactionStateFailed:NSLog(@"TRANSACTION FAILED");{
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Payment was unsuccessful" message:@"Payment was unable to be processed." delegate:self cancelButtonTitle:nil otherButtonTitles:nil, nil];
            [alert show];
        }

            break;

            default:
            break;
    }
    }
}

我在使用指南后的新规范

PURCHASELIVES

PurchaseLives.m

+ (PurchaseLives *)sharedInstance {
static dispatch_once_t once;
static PurchaseLives * sharedInstance;
dispatch_once(&once, ^{
    NSSet * productIdentifiers = [NSSet setWithObjects:
                                  @"com.retrogames.5Lives",
nil];
    sharedInstance = [[self alloc] initWithProductIdentifiers:productIdentifiers];
});
return sharedInstance;
}

 @end

IAPHelper

IAPHelper.m
NSString *const IAPHelperProductPurchasedNotification = @"IAPHelperProductPurchasedNotification";
@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 for previously purchased products
    _purchasedProductIdentifiers = [NSMutableSet set];
    for (NSString * productIdentifier in _productIdentifiers) {
        BOOL productPurchased = [[NSUserDefaults standardUserDefaults] boolForKey:productIdentifier];
        if (productPurchased) {
            [_purchasedProductIdentifiers addObject:productIdentifier];
            NSLog(@"Previously purchased: %@", productIdentifier);
        } else {
            NSLog(@"Not purchased: %@", productIdentifier);
        }


    }
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
   }
return self;
}

- (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;
  for (SKProduct * skProduct in skProducts) {
      NSLog(@"Found product: %@ %@ %0.2f",
          skProduct.productIdentifier,
          skProduct.localizedTitle,
          skProduct.price.floatValue);

       FiveLives = skProducts[0];
       NSLog(@"Products = %@",skProducts);

     }

    _completionHandler(YES, skProducts);
    _completionHandler = nil;

  }

  - (void)request:(SKRequest *)request didFailWithError:(NSError *)error {

   NSLog(@"Failed to 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 %@...", FiveLives.productIdentifier);

 SKPayment * payment = [SKPayment paymentWithProduct:FiveLives];
  [[SKPaymentQueue defaultQueue] addPayment:payment];

 }



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



// Add new method
- (void)provideContentForProductIdentifier:(NSString *)productIdentifier {

[_purchasedProductIdentifiers addObject:productIdentifier];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:productIdentifier];
[[NSUserDefaults standardUserDefaults] synchronize];
[[NSNotificationCenter defaultCenter] postNotificationName:IAPHelperProductPurchasedNotification object:productIdentifier userInfo:nil];

 }

- (void)completeTransaction:(SKPaymentTransaction *)transaction {
NSLog(@"completeTransaction...");

    [self provideContentForProductIdentifier:transaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

- (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);
 }

     [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
 }


 @end

BUYLIVES

#import "BuyLivesViewController.h"
#import "PurchaseLives.h"
#import "IAP Helper.h"
@interface BuyLivesViewController (){
NSArray *_products;
}

@end

@implementation BuyLivesViewController

 - (void)viewDidLoad {
 [super viewDidLoad];
// Do any additional setup after loading the view.
 }

 - (void)didReceiveMemoryWarning {
 [super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewWillAppear:(BOOL)animated {
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productPurchased:) name:IAPHelperProductPurchasedNotification object:nil];
 }

- (void)viewWillDisappear:(BOOL)animated {
  [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 - (IBAction)Buy5Lives:(id)sender {



  [[PurchaseLives sharedInstance] buyProduct:FiveLives];
 }





 - (void)productPurchased:(NSNotification *)notification {

    NSString * productIdentifier = notification.object;
    [_products enumerateObjectsUsingBlock:^(SKProduct * product, NSUInteger idx, BOOL *stop) {
        if ([product.productIdentifier isEqualToString:productIdentifier]) {
        GameLives = GameLives + 5;

      }
   }];

  }
   @end

1 个答案:

答案 0 :(得分:0)

问题在于:

[self getProduct1ID:self];

SKPayment *payment = [SKPayment paymentWithProduct:_FiveLives];

getProduct1ID发出从商店接收所有商品的请求。但是这个请求是非阻塞的。意味着在请求完成时您已经在调用paymentWithProduct。在此时间_FiveLives尚未使用有效产品进行设置,它将为nil

我建议您做的是在应用程序的START处调用getProduct1ID(我在应用程序委托方法application:didFinishLaunchingWithOptions:中执行此操作)并将您的产品存储在成员变量中你以后可以用。

然后,当用户点击购买按钮时,只需使用产品实例进行购买。

我还建议您查看here,看看如何提交IAP流程。我遵循的伟大教程,它完美无缺。