我对如何以及何时告诉用户他们成功完成购买感到困惑。我的申请在应用审核过程中被拒绝,原因如下:
1. Launch app
2. Tap on learn about the benefits of subscription
3. Tap on Subscribe
4. Tap on Confirm and enter iTunes password
5. No further action occurs
而且我不确定何时以及如何告诉用户他们正确输入了他们的信息,因为这已在 iTunes 服务器上得到确认。
我有一个 IAPHelper 类,如下所示:
//
// IAPHelper.m
// BusinessPlan
//
// Created by 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 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);
// SET memory to yes and then use that later.
// Get user data.
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
// First time on the app, so set the user cookie.
[standardUserDefaults setBool:YES forKey:@"subscriber"];
// Saving
[[NSUserDefaults standardUserDefaults] synchronize];
}
else
{
NSLog(@"Not purchased: %@", productIdentifier);
}
}
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}
return self;
}
// retrieve the product information from 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;
for (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 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 %@...", product.productIdentifier);
SKPayment * payment = [SKPayment paymentWithProduct:product];
[[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;
}
};
}
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
NSLog(@"completeTransaction...");
[self provideContentForProductIdentifier:transaction.payment.productIdentifier];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
// SET memory to yes and then use that later.
// Get user data.
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
// First time on the app, so set the user cookie.
[standardUserDefaults setBool:YES forKey:@"subscriber"];
// Saving
[[NSUserDefaults standardUserDefaults] synchronize];
// Tell user that things are purchased.
// MESSAGE PERSON THAT CAN'T CONNECT TO SERVER
// UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Success sending purchase request."
// message:@"Just press OK and wait a few moments while iTunes processes the 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 THAT CAN'T CONNECT TO SERVER
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Could not complete your transaction"
message:@"Please try again. If the error persists, please email support at: alex@problemio.com" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[message show];
}
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}
// Add to top of file
NSString *const IAPHelperProductPurchasedNotification = @"IAPHelperProductPurchasedNotification";
// Add new method
- (void)provideContentForProductIdentifier:(NSString *)productIdentifier
{
//NSLog(@"Provifing content for subsciber: ");
// MESSAGE PERSON THAT CAN'T CONNECT TO SERVER
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Subscribed successfully!"
message:@"Now you can ask questions right on the app, and get 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
还有我开始交易过程的班级:
#import "SubscriptionController.h"
// 1
#import "RageIAPHelper.h"
#import <StoreKit/StoreKit.h>
// 2
@interface SubscriptionController ()
{
NSArray *_products;
// Add new instance variable to 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 to 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 to 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 the button appears.
//
//
//// [self.table reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:idx inSection:0]] withRowAnimation:UITableViewRowAnimationFade];
// *stop = YES;
// }
// }];
// MESSAGE PERSON THAT CAN'T CONNECT TO SERVER
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Purchased successfully"
message:@":)" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[message show];
// PUSH TO 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 THAT CAN'T CONNECT TO SERVER
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Pulling product data from iTunes..."
message:@"Please try again in a few moments." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[message show];
}
else
{
// MESSAGE PERSON THAT CAN'T CONNECT TO SERVER
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Success sending purchase request."
message:@"Just press OK and wait a few moments while iTunes processes the request." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[message show];
NSLog(@"Buying %@...", product.productIdentifier);
[[RageIAPHelper sharedInstance] buyProduct:product];
}
}
@end
谢谢您的帮助!