How do you add an in-app purchase to an iOS application? Ask Question

How do you add an in-app purchase to an iOS application? Ask Question

How do you add an in-app purchase to an iOS app? What are all the details and is there any sample code?

これは、iOSアプリにアプリ内購入を追加する方法の包括的なものであることを意図しています。

ベストアンサー1

Swift ユーザー

Swift ユーザーは、この質問に対する My Swift Answerを確認できます。
または、この Objective-C コードを Swift に翻訳したYedidya Reiss の Answerを確認してください。

Objective-C ユーザー

この回答の残りはObjective-Cで書かれています

App Storeコネクト

  1. appstoreconnect.apple.comにアクセスしてログインします
  2. クリックしMy Appsて購入を追加したいアプリをクリックします
  3. ヘッダーをクリックしFeaturesIn-App Purchases左側の
  4. +中央のアイコンをクリックします
  5. このチュートリアルでは、広告を削除するアプリ内購入を追加するので、 を選択しますnon-consumable。ユーザーに物理的なアイテムを送信する場合、または複数回購入できるものを提供する場合は、 を選択しますconsumable
  6. 参照名には、好きな名前を入力してください(ただし、それが何であるかを確認してください)。
  7. 製品IDにはtld.websitename.appname.referencenameこれが最適です。たとえば、次のように使用できます。com.jojodmo.blix.removeads
  8. を選択しcleared for sale、価格帯を 1 (99 セント) にします。価格帯 2 は 1.99 ドル、価格帯 3 は 2.99 ドルになります。[view pricing matrix価格帯 1 を使用することをお勧めします] をクリックすると、完全なリストが表示されます。広告を削除するために支払う金額は通常これが最大であるためです。
  9. 青いadd languageボタンをクリックして情報を入力してください。これはすべて顧客に表示されるので、顧客に見せたくないものは入力しないでください。
  10. いいえhosting content with Apple選択
  11. 今のところ、レビューメモは空白のままにしておくことができます。
  12. screenshot for review 「今は」をスキップしてください。スキップしたものはすべて後で戻ってきます。
  13. 「保存」をクリック

製品 ID が に登録されるまでに数時間かかる場合がありますのでApp Store Connect、しばらくお待ちください。

プロジェクトの設定

App Store Connect でアプリ内購入情報を設定したら、Xcode プロジェクトに移動し、アプリケーション マネージャー (メソッドとヘッダー ファイルがある場所の上部にある青いページのようなアイコン) に移動し、ターゲットの下のアプリ (最初のものになるはずです) をクリックして、全般に移動します。下部に、linked frameworks and libraries小さなプラス記号をクリックしてフレームワークを追加すると表示されます。StoreKit.frameworkこれを行わないと、アプリ内購入は機能しませ

アプリの言語として Objective-C を使用している場合は、これらの 5 つの手順をスキップしてください。そうでない場合、Swift を使用している場合は、この質問に対する My Swift Answer をこちらで参照できます。または、アプリ内購入コードに Objective-C を使用するが、アプリでは Swift を使用している場合は、次の操作を実行できます。

  1. > > ( + ).hに移動して、新しい (ヘッダー) ファイルを作成します。このファイルは、チュートリアルの残りの部分では「Your file」と呼ばれます。FileNewFile...Command ⌘N.h

  2. プロンプトが表示されたら、「ブリッジング ヘッダーの作成」をクリックします。これがブリッジング ヘッダー ファイルになります。プロンプトが表示されない場合は、手順 3 に進みます。プロンプトが表示され場合は、手順 3 をスキップして、直接手順 4 に進みます。

  3. メインプロジェクトフォルダに という名前の別の.hファイルを作成しBridge.h、アプリケーションマネージャ(青いページのようなアイコン)に移動し、セクションでアプリを選択してTargetsをクリックします。Swiftコンパイラ - コード生成Build Settingsというオプションを見つけて、Objective-CブリッジングヘッダーオプションをBridge.h

  4. ブリッジ ヘッダー ファイルに、行 を追加します。#import "MyObjectiveCHeaderFile.h"ここMyObjectiveCHeaderFileで、 は手順 1 で作成したヘッダー ファイルの名前です。たとえば、ヘッダー ファイルにInAppPurchase.h という名前を付けた場合は、ブリッジ ヘッダー ファイルに行 を追加します#import "InAppPurchase.h"

  5. > > ( + ).mに移動して、新しい Objective-C メソッド ( ) ファイルを作成します。手順 1 で作成したヘッダー ファイルと同じ名前を付けます。たとえば、手順 1 でファイルをInAppPurchase.hと呼んだ場合は、この新しいファイルをInAppPurchase.mと呼びましょう。このファイルは、チュートリアルの残りの部分では「Your file」と呼ばれます。FileNewFile...Command ⌘N.m

コーディング

では、実際のコーディングに入ります。ファイルに次のコードを追加します.h

BOOL areAdsRemoved;

- (IBAction)restore;
- (IBAction)tapsRemoveAds;

StoreKit次に、フレームワークをファイルにインポートし、宣言の後にと を.m追加する必要があります。SKProductsRequestDelegateSKPaymentTransactionObserver@interface

#import <StoreKit/StoreKit.h>

//put the name of your view controller in place of MyViewController
@interface MyViewController() <SKProductsRequestDelegate, SKPaymentTransactionObserver>

@end

@implementation MyViewController //the name of your view controller (same as above)
  //the code below will be added here
@end

次に、.mファイルに次のコードを追加します。この部分は複雑になるので、コード内のコメントを読むことをお勧めします。

//If you have more than one in-app purchase, you can define both of
//of them here. So, for example, you could define both kRemoveAdsProductIdentifier
//and kBuyCurrencyProductIdentifier with their respective product ids
//
//for this example, we will only use one product

#define kRemoveAdsProductIdentifier @"put your product id (the one that we just made in App Store Connect) in here"

- (IBAction)tapsRemoveAds{
    NSLog(@"User requests to remove ads");

    if([SKPaymentQueue canMakePayments]){
        NSLog(@"User can make payments");
    
        //If you have more than one in-app purchase, and would like
        //to have the user purchase a different product, simply define 
        //another function and replace kRemoveAdsProductIdentifier with 
        //the identifier for the other product

        SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:kRemoveAdsProductIdentifier]];
        productsRequest.delegate = self;
        [productsRequest start];
    
    }
    else{
        NSLog(@"User cannot make payments due to parental controls");
        //this is called the user cannot make payments, most likely due to parental controls
    }
}

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    SKProduct *validProduct = nil;
    int count = [response.products count];
    if(count > 0){
        validProduct = [response.products objectAtIndex:0];
        NSLog(@"Products Available!");
        [self purchase:validProduct];
    }
    else if(!validProduct){
        NSLog(@"No products available");
        //this is called if your product id is not valid, this shouldn't be called unless that happens.
    }
}

- (void)purchase:(SKProduct *)product{
    SKPayment *payment = [SKPayment paymentWithProduct:product];

    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

- (IBAction) restore{
    //this is called when the user restores purchases, you should hook this up to a button
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}

- (void) paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
    NSLog(@"received restored transactions: %i", queue.transactions.count);
    for(SKPaymentTransaction *transaction in queue.transactions){
        if(transaction.transactionState == SKPaymentTransactionStateRestored){
            //called when the user successfully restores a purchase
            NSLog(@"Transaction state -> Restored");

            //if you have more than one in-app purchase product,
            //you restore the correct product for the identifier.
            //For example, you could use
            //if(productID == kRemoveAdsProductIdentifier)
            //to get the product identifier for the
            //restored purchases, you can use
            //
            //NSString *productID = transaction.payment.productIdentifier;
            [self doRemoveAds];
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            break;
        }
    }   
}

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions{
    for(SKPaymentTransaction *transaction in transactions){
        //if you have multiple in app purchases in your app,
        //you can get the product identifier of this transaction
        //by using transaction.payment.productIdentifier
        //
        //then, check the identifier against the product IDs
        //that you have defined to check which product the user
        //just purchased            

        switch(transaction.transactionState){
            case SKPaymentTransactionStatePurchasing: NSLog(@"Transaction state -> Purchasing");
                //called when the user is in the process of purchasing, do not add any of your own code here.
                break;
            case SKPaymentTransactionStatePurchased:
            //this is called when the user has successfully purchased the package (Cha-Ching!)
                [self doRemoveAds]; //you can add your code for what you want to happen when the user buys the purchase here, for this tutorial we use removing ads
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                NSLog(@"Transaction state -> Purchased");
                break;
            case SKPaymentTransactionStateRestored:
                NSLog(@"Transaction state -> Restored");
                //add the same code as you did from SKPaymentTransactionStatePurchased here
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
            case SKPaymentTransactionStateFailed:
                //called when the transaction does not finish
                if(transaction.error.code == SKErrorPaymentCancelled){
                    NSLog(@"Transaction state -> Cancelled");
                    //the user cancelled the payment ;(
                }
                [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
                break;
        }
    }
}

ここで、ユーザーがトランザクションを完了したときに何が起こるかを指定するコードを追加します。このチュートリアルでは、広告を削除する方法を使用しますが、バナー ビューが読み込まれたときに何が起こるかを指定する独自のコードを追加する必要があります。

- (void)doRemoveAds{
    ADBannerView *banner;
    [banner setAlpha:0];
    areAdsRemoved = YES;
    removeAdsButton.hidden = YES;
    removeAdsButton.enabled = NO;
    [[NSUserDefaults standardUserDefaults] setBool:areAdsRemoved forKey:@"areAdsRemoved"];
    //use NSUserDefaults so that you can load whether or not they bought it
    //it would be better to use KeyChain access, or something more secure
    //to store the user data, because NSUserDefaults can be changed.
    //You're average downloader won't be able to change it very easily, but
    //it's still best to use something more secure than NSUserDefaults.
    //For the purpose of this tutorial, though, we're going to use NSUserDefaults
    [[NSUserDefaults standardUserDefaults] synchronize];
}

アプリケーションに広告がない場合は、他の任意のものを使用できます。たとえば、背景色を青にすることができます。これを行うには、次のコードを使用します。

- (void)doRemoveAds{
    [self.view setBackgroundColor:[UIColor blueColor]];
    areAdsRemoved = YES
    //set the bool for whether or not they purchased it to YES, you could use your own boolean here, but you would have to declare it in your .h file

    [[NSUserDefaults standardUserDefaults] setBool:areAdsRemoved forKey:@"areAdsRemoved"];
    //use NSUserDefaults so that you can load wether or not they bought it
    [[NSUserDefaults standardUserDefaults] synchronize];
}

ここで、viewDidLoadメソッドのどこかに次のコードを追加します。

areAdsRemoved = [[NSUserDefaults standardUserDefaults] boolForKey:@"areAdsRemoved"];
[[NSUserDefaults standardUserDefaults] synchronize];
//this will load wether or not they bought the in-app purchase

if(areAdsRemoved){
    [self.view setBackgroundColor:[UIColor blueColor]];
    //if they did buy it, set the background to blue, if your using the code above to set the background to blue, if your removing ads, your going to have to make your own code here
}

これですべてのコードを追加したので、 または ファイルに移動して.xibstoryboard購入ボタンと復元ボタンの 2 つのボタンを追加します。 をtapsRemoveAds IBAction先ほど作成した購入ボタンに接続し、 をrestore IBAction復元ボタンに接続します。 このrestoreアクションは、ユーザーが以前にアプリ内購入を購入したかどうかを確認し、まだ購入していない場合はアプリ内購入を無料で提供します。

レビューのために提出する

Next, go into App Store Connect, and click Users and Access then click the Sandbox Testers header, and then click the + symbol on the left where it says Testers. You can just put in random things for the first and last name, and the e-mail does not have to be real - you just have to be able to remember it. Put in a password (which you will have to remember) and fill in the rest of the info. I would recommend that you make the Date of Birth a date that would make the user 18 or older. App Store Territory HAS to be in the correct country. Next, log out of your existing iTunes account (you can log back in after this tutorial).

Now, run your application on your iOS device, if you try running it on the simulator, the purchase will always error, you HAVE TO run it on your iOS device. Once the app is running, tap the purchase button. When you are prompted to log into your iTunes account, log in as the test user that we just created. Next,when it asks you to confirm the purchase of 99¢ or whatever you set the price tier too, TAKE A SCREEN SNAPSHOT OF IT this is what your going to use for your screenshot for review on App Store Connect. Now cancel the payment.

Now, go to App Store Connect, then go to My Apps > the app you have the In-app purchase on > In-App Purchases. Then click your in-app purchase and click edit under the in-app purchase details. Once you've done that, import the photo that you just took on your iPhone into your computer, and upload that as the screenshot for review, then, in review notes, put your TEST USER e-mail and password. This will help apple in the review process.

After you have done this, go back onto the application on your iOS device, still logged in as the test user account, and click the purchase button. This time, confirm the payment Don't worry, this will NOT charge your account ANY money, test user accounts get all in-app purchases for free After you have confirmed the payment, make sure that what happens when the user buys your product actually happens. If it doesn't, then thats going to be an error with your doRemoveAds method. Again, I recommend using changing the background to blue for testing the in-app purchase, this should not be your actual in-app purchase though. If everything works and you're good to go! Just make sure to include the in-app purchase in your new binary when you upload it to App Store Connect!


Here are some common errors:

Logged: No Products Available

This could mean four things:

  • You didn't put the correct in-app purchase ID in your code (for the identifier kRemoveAdsProductIdentifier in the above code
  • You didn't clear your in-app purchase for sale on App Store Connect
  • アプリ内購入 ID がApp Store Connectに登録されるまで待っていません。ID を作成してから数時間待つと、問題は解決するはずです。
  • 契約、税金、銀行情報の入力が完了していません。

最初はうまくいかなくても、イライラしないでください。あきらめないでください。これが機能するまでに約 5 時間かかり、正しいコードを探すのに約 10 時間かかりました。上記のコードを正確に使用すれば、問題なく動作するはずです。ご質問があれば、お気軽にコメントしてください

おすすめ記事