1

購入が正常に完了したことをユーザーに伝える方法とタイミングについて混乱しています。次の理由により、アプリの審査プロセス中に申請が却下されました。

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

ご協力ありがとうございました!

4

1 に答える 1