应用内购买正确实施

时间:2014-02-04 05:42:55

标签: ios in-app-purchase in-app

我在移动应用中实施应用内购买时遇到问题。

基本上,有时用户会收取两次费用。 并且当用户在应用程序中被打断时 - 比如他们被重定向回iTunes以完成付款然后回到应用程序,他们会看到错误“发生了错误......”

我是否正确实施了应用内购买?

这是我的代码:

我做错了什么?

- (void) myLeftAction {
    [self performSegueWithIdentifier: @"login" sender: self];
}

- (void)viewDidLoad {
    [super viewDidLoad];


    UISwipeGestureRecognizer * recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(myLeftAction)];
    [recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
    [self.view addGestureRecognizer:recognizer];


    done = NO;
    paymentProcessing = NO;

    shownProducts = [NSArray arrayWithObjects: @"com.example.a", @"com.example.b", @"com.example.c", @"com.example.d", nil];

    hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.labelText = @"Loading";

    [self fetchAvailableProducts];
}

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

-(void)fetchAvailableProducts {
    if ([SKPaymentQueue canMakePayments])
    {
        NSSet *productIdentifiers = [NSSet setWithObjects: @"com.example.a", @"com.example.b", @"com.example.c", @"com.example.d",nil];
        productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
        productsRequest.delegate = self;
        [productsRequest start];
    }
    else {
        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:
                                  @"Purchases are disabled in your device. Please enable in-app purchases before continuing." message:nil delegate:
                                  self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
        [alertView show];
    }
}

- (BOOL)canMakePurchases {
    return [SKPaymentQueue canMakePayments];
}

- (void)purchaseMyProduct:(SKProduct*)product {
    if ([self canMakePurchases]) {
        SKPayment *payment = [SKPayment paymentWithProduct:product];
        [[SKPaymentQueue defaultQueue] addTransactionObserver: self];
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    }
    else{
        paymentProcessing = NO;

        UIAlertView *alertView = [[UIAlertView alloc]initWithTitle: @"Purchases are disabled on your device. Please enable in-app purchases before continuing." message:nil delegate: self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
        [alertView show];
    }
}

-(IBAction)purchase:(id)sender
{
    if(done && !paymentProcessing) {
        paymentProcessing = YES;
        chosenProduct = [validProducts objectAtIndex: [sender tag]];
        [self purchaseMyProduct: chosenProduct];
    }
}

#pragma mark StoreKit Delegate

-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    for (SKPaymentTransaction *transaction in transactions) {
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchasing:
                [self occuringTransaction: transaction];
                break;
            case SKPaymentTransactionStatePurchased:
                [self completeTransaction: transaction];
                break;
            case SKPaymentTransactionStateRestored:
                [self restoreTransaction: transaction];
                break;
            case SKPaymentTransactionStateFailed:
                [self failedTransaction: transaction];
                break;
            default:
                break;
        }
    }
}

- (void) occuringTransaction:(SKPaymentTransaction *)transaction
{
    [hud show: YES];
    NSLog(@"Purchasing");
}

- (void) processPurchase: (SKPaymentTransaction *)transaction
{
    id<FBGraphUser> fb = [[Auth sharedInstance] user];

    NSString * firstName = fb.first_name;
    NSString * lastName = fb.last_name;
    NSString * email = [fb objectForKey: @"email"];
    NSString * facebook_id = fb.id;

    PFObject * result = [PFObject objectWithClassName:@"payments"];
    result[@"firstName"] = firstName;
    result[@"lastName"] = lastName;
    result[@"email"] = email;
    result[@"facebookId"] = facebook_id;
    result[@"package"] = transaction.payment.productIdentifier;
    result[@"transactionId"] = transaction.transactionIdentifier;
    result[@"transactionError"] = transaction.error.localizedDescription;

    NSString *dateString = [NSDateFormatter localizedStringFromDate: transaction.transactionDate
                                                          dateStyle:NSDateFormatterShortStyle
                                                          timeStyle:NSDateFormatterFullStyle];

    result[@"transactionDate"] = dateString;
    result[@"transactionState"] = [NSString stringWithFormat: @"%ld", transaction.transactionState];

    [result saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error)
     {
         [[SKPaymentQueue defaultQueue] finishTransaction:transaction];

         UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:
                                   @"Purchase is completed successfully. You can now choose the hashtags you want shown in your review on lulu." message:nil delegate:
                                   self cancelButtonTitle:@"Ok" otherButtonTitles: nil];
         [alertView show];

         NSString * category = @"";

         if(
            [transaction.payment.productIdentifier isEqualToString: @"com.fakemylulu.player_1"] ||
            [transaction.payment.productIdentifier isEqualToString: @"com.fakemylulu.player_3"]
            ) {
             category = @"a";
         }
         else {
             category = @"b";
         }

         paymentProcessing = NO;

         [hud hide:YES];

         //push view manually
         UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
         fmHashtagsViewController *ivc = [storyboard instantiateViewControllerWithIdentifier:@"hashtags"];
         ivc.category = transaction.payment.productIdentifier;
         [self.navigationController pushViewController:ivc animated:NO];
     }];

}

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

    if([transaction.payment.productIdentifier isEqualToString: chosenProduct.productIdentifier]) {
        [self processPurchase: transaction];
    }
}

-(void)restoreTransaction:(SKPaymentTransaction *)transaction {
    NSLog(@"Restored transaction");
    [self processPurchase: transaction];
}

-(void)failedTransaction:(SKPaymentTransaction *)transaction
{
    [hud hide: YES];
    paymentProcessing = NO;

    if(transaction.error.code != SKErrorPaymentCancelled)
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"An error occured! We could not process your payment. Please try again."
                                                        message:[transaction.error localizedDescription]
                                                       delegate:nil
                                              cancelButtonTitle:nil
                                              otherButtonTitles:@"OK", nil];
        [alert show];
    }

    [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    NSInteger count = [response.products count];

    if (count>0)
    {
        validProducts = response.products;

        NSUInteger index = 0;

        for (SKProduct * x in validProducts)
        {
            NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
            [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
            [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
            [numberFormatter setLocale: x.priceLocale];
            NSString *formattedPrice = [numberFormatter stringFromNumber: x.price];

            if([x.productIdentifier isEqualToString: @"com.fakemylulu.romantic_1"]) {
                [self.a setTitle: [NSString stringWithFormat: @"%@", formattedPrice] forState:UIControlStateNormal];
                self.a.tag = index;
            }
            else if([x.productIdentifier isEqualToString: @"com.fakemylulu.romantic_3"])
            {
                [self.b setTitle: [NSString stringWithFormat: @"%@", formattedPrice] forState:UIControlStateNormal];
                self.b.tag = index;
            }
            else if([x.productIdentifier isEqualToString: @"com.fakemylulu.player_1"])
            {
                [self.c setTitle: [NSString stringWithFormat: @"%@", formattedPrice] forState:UIControlStateNormal];
                self.c.tag = index;
            }
            else if([x.productIdentifier isEqualToString: @"com.fakemylulu.player_3"])
            {
                [self.d setTitle: [NSString stringWithFormat: @"%@", formattedPrice] forState:UIControlStateNormal];
                self.d.tag = index;
            }

            index += 1;
        }
        done = YES;
    } else {
        UIAlertView *tmp = [[UIAlertView alloc]
                            initWithTitle:@"Not Available"
                            message:@"No products available for purchase"
                            delegate:self
                            cancelButtonTitle:nil
                            otherButtonTitles:@"Ok", nil];
        [tmp show];
    }

    [hud hide:YES];
}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error
{
    NSLog(@"Failed to load list of products. %@", error);

    UIAlertView *tmp = [[UIAlertView alloc]
                        initWithTitle:@"Oops"
                        message:@"There was an error retrieving the list of products. Please try this app again later."
                        delegate:self
                        cancelButtonTitle:nil
                        otherButtonTitles:@"Ok", nil];
    [tmp show];
}

- (void)dealloc {
    if ([SKPaymentQueue canMakePayments]) {
        [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    }
}

1 个答案:

答案 0 :(得分:0)

首先您必须说明什么类型的订阅。 iOS中有三种主要的应用内购买类型: 1)非消耗品。 2)消耗品。 3)订阅。 在自动续订订阅中,它将每5分钟自动续订一次。 因为在sanbox帐户中使用1个月,需要5分钟。

如果是耗材:这些是用户可以多次购买的东西。通常它们会“用完”,因此用户可以再次购买

非消耗品:这些是用户购买的东西(只有一次),然后可以永久访问。