TOAST > TOAST SDK使用ガイド > TOAST IAP > iOS

Prerequisites

1. TOAST SDKをインストールします。 2. TOASTコンソールMobile Service > IAPを有効化します。 3. IAPでAppKeyを確認します。

TOAST IAP構成

  • iOS用TOAST IAP SDKの構成は次のとおりです。
Service Cocoapods Pod Name Framework Dependency Build Settings
TOAST IAP ToastIAP ToastIAP.framework * StoreKit.framework

[Optional]
* libsqlite3.tdb
Mandatory ToastCore
ToastCommon
ToastCore.framework
ToastCommon.framework
OTHER_LDFLAGS = (
"-ObjC",
"-lc++"
);

TOAST IAP SDKをXcodeプロジェクトに適用

1. Cococapods適用

  • Podfileを作成して、TOAST SDKに対するPodを追加します。
platform :ios, '9.0'
use_frameworks!

target '{YOUR PROJECT TARGET NAME}' do
    pod 'ToastIAP'
end

2. バイナリをダウンロードしてTOAST SDKを適用

  • TOASTのDownloadsページで全体iOS SDKをダウンロードできます。
  • Xcode ProjectにToastIAP.framework, ToastCore.framework, ToastCommon.framework, StoreKit.frameworkを追加します。
  • StoreKit.frameworkは、下記の方法で追加できます。 linked_storekit_frameworks

linked_frameworks_iap

プロジェクト設定

  • Build SettingsOther Linker Flags-lc++-ObjC項目を追加します。
    • Project Target > Build Settings > Linking > Other Linker Flags other_linker_flags

Capabilities設定

  • TOAST IAPを使用するには、CapabilitiesでIn-App Purchase項目を有効にする必要があります。
    • Project Target > Capabilities > In-App Purchase capabilities_iap

サービスログイン

  • TOAST SDKで提供するすべてのサービス(IAP、Log & Crash、Pushなど)は、同じユーザーID1つのみ使用します。

ログイン

  • ユーザーIDが設定されていない状態では、購入、有効になっている商品照会、未消費履歴照会機能を使用できません。
// サービスログイン完了後、ユーザーID設定
[ToastSDK setUserID:@"INPUT_USER_ID"];

ログアウト

// サービスログアウト完了後、ユーザーIDをnilに設定
[ToastSDK setUserID:nil];

TOAST IAP SDK初期化

初期化API仕様

// 初期化
+ (void)initWithConfiguration:(ToastIAPConfiguration *)configuration;
// Delegate設定
+ (void)setDelegate:(nullable id<ToastInAppPurchaseDelegate>)delegate;
// 初期化およびDelegate設定
+ (void)initWithConfiguration:(ToastIAPConfiguration *)configuration
                     delegate:(nullable id<ToastInAppPurchaseDelegate>)delegate;

Delegate API仕様

  • ToastInAppPurchaseDelegateを登録すると、購入結果とプロモーション決済を進行するかどうかの決定についての通知を受信できます。
    • プロモーション決済をSDKで行うか、ユーザーが任意の時点で直接決済をリクエストするかを決定できます。
  • 再処理により決済が完了した購買件は、Delegatingされず、未消費商品リスト(消耗性商品)、活性化された購読リスト(購読商品)に反映されます。
  • 決済結果に対する通知を受けるためには、商品購入前にDelegateが設定されていなければなりません。
@protocol ToastInAppPurchaseDelegate <NSObject>

// 購入成功
- (void)didReceivePurchaseResult:(ToastPurchaseResult *)purchase;
// 購入失敗
- (void)didFailPurchaseProduct:(NSString *)productIdentifier withError:(NSError *)error;

@optional
// プロモーション決済進行方法の選択
- (BOOL)shouldAddStorePurchaseForProduct:(ToastProduct *)product API_AVAILABLE(ios(11.0));
@end

初期化プロセス例

#import <UIKit/UIKit.h>
#import <ToastIAP/ToastIAP.h>

@interface ViewController () <ToastInAppPurchaseDelegate>
@end

@implementation ViewController

- (void)initializeTosatIAP {
    // 初期化およびDelegate設定
    ToastIAPConfiguration *configuration = [ToastIAPConfiguration configurationWithAppKey:@"INPUT_YOUE_APPKEY"];

    [ToastIAP initWithConfiguration:configuration delegate:self];
}

// 購入成功
- (void)didReceivePurchaseResult:(ToastPurchaseResult *)purchase {
    NSLog(@"Successfully purchased");
}

// 購入失敗
- (void)didFailPurchaseProduct:(NSString *)productIdentifier withError:(NSError *)error {
    NSLog(@"Failed to purchase: %@", erorr);
}

// プロモーション決済進行方法の選択
- (BOOL)shouldAddStorePurchaseForProduct:(ToastProduct *)product {
    /*
    * return YES;
        * リクエストしたプロモーション決済をSDKで行うようにします。
        * 初期化およびログイン後に決済ウィンドウが表示されます。
    */
    return YES;

    /*
    * return NO;
        * プロモーション決済が終了します。
        * productオブジェクトを保存した後、任意の時点で保存されたオブジェクトで決済を行うことができます。
    */
    self.promotionProduct = product;
    return NO;
}

@end

商品リスト照会

  • IAPコンソールに登録された商品がToastProductResponseオブジェクトで返されます。
  • IAPコンソールに登録された商品のうち、購入可能な商品はproducts(ToastProduct)として返されます。
  • IAPコンソールに登録された商品のうち、ストア(Apple)で商品情報を取得できなかった商品は、invalidProducts(ToastProduct)として返されます。

商品リスト照会API仕様

+ (void)requestProductsWithCompletionHandler:(nullable void (^)(ToastProductsResponse * _Nullable response, NSError * _Nullable error))completionHandler;

商品リスト照会API使用例

[ToastIAP requestProductsWithCompletionHandler:^(ToastProductsResponse *response, NSError *error) {
    if (error == nil) {
        NSArray<ToastProduct *> *products = response.products;
        NSLog(@"Products : %@", products);

        // ストアから商品情報を取得できない
        NSArray<ToastProduct *> *invalidProducts = response.invalidProducts;
        NSLog(@"Invalid Products : %@", invalidProducts);

    } else {
        NSLog(@"Failed to request products: %@", error);
    }
}

商品の種類

商品名 商品タイプ 説明
消費性商品 ToastProductTypeConsumable 消費可能な1回限りの商品です。
ゲーム内通貨、コイン、繰り返し購入可能な商品などに使用できます。
自動更新型サブスクリプション商品 ToastProductTypeAutoRenewableSubscription 指定された間隔と価格で決済が自動的に繰り返される商品です。
雑誌、音楽のストリーミングアクセス許可、広告の除去などに使用できます。
自動更新型消費性サブスクリプション商品 ToastProductTypeConsumableSubscription 指定された間隔と価格で決済が自動的に繰り返される商品です。
指定された間隔と価格で消費性商品を支給したい時に使用できます。

自動更新型購読商品のアップグレード、ダウングレード、修正機能は、サポートしていません。 1つの購読グループに、1つの商品のみ登録する必要があります。

typedef NS_ENUM(NSInteger, ToastProductType) {
    // 商品種類取得失敗
    ToastProductTypeUnknown = 0,
    // 消費性商品
    ToastProductTypeConsumable = 1,
    // 自動更新型購読商品
    ToastProductTypeAutoRenewableSubscription = 2,
    // 自動更新型消費性購読商品
    ToastProductTypeConsumableSubscription = 3
};

商品購入

  • 購入結果は、設定されたToastInAppPurchaseDelegateを通して伝達されます。
  • 購買進行中にアプリが終了したり、ネットワークエラーなどで購買が中断された場合、次回のアプリ実行におけるIAP SDK初期化以後、再処理が進みます。
  • 購入リクエスト時にユーザーデータを追加できます。
  • ユーザーデータは決済結果(購入成功Delegate、未消費決済履歴、有効なサブスクリプション、購入復元)情報に含まれて返されます。
  • 購入できない商品の場合、ToastInAppPurchaseDelegateを通して購入不可商品であることを示すエラーが伝達されます。
    • 商品リスト照会結果のToastProductオブジェクトまたは商品IDを利用して購入をリクエストします。

商品オブジェクトを利用した購入API仕様

// 商品購入要請
+ (void)purchaseWithProduct:(ToastProduct *)product;
// ユーザーデータを追加して商品購入
+ (void)purchaseWithProduct:(ToastProduct *)product payload:(NSString *)payload;
// 商品IDを利用した購入要請
+ (void)purchaseWithProductIdentifier:(NSString *)productIdentifier;
// 商品IDで購入リクエストした時、ユーザーデータ追加
+ (void)purchaseWithProductIdentifier:(NSString *)productIdentifier payload:(NSString *)payload;

商品オブジェクトを利用した購入API使用例

// 商品購入要請
[ToastIAP purchaseWithProduct:self.products[0] payload:@"DEVELOPER_PAYLOAD"];
// or
// 商品IDを利用した購入要請
[ToastIAP purchaseWithProductIdentifier:@"PRODUCT_IDENTIFIER" payload:@"DEVELOPER_PAYLOAD"];

有効になっている購読リスト照会

  • 現在のユーザーIDで有効なサブスクリプションリストを照会します。
  • 決済が完了したサブスクリプション商品(自動更新型サブスクリプション、自動更新型消費性サブスクリプション商品)は有効期限が切れるまで照会できます。
  • 同じユーザーIDであれば、Androidで購入した購読商品も照会されます。

有効になっている購読リスト照会API仕様

// 有効になっている購読リストを照会する
+ (void)requestActivePurchasesWithCompletionHandler:(nullable void (^)(NSArray<ToastPurchaseResult *> * _Nullable purchases, NSError * _Nullable error))completionHandler;

有効になっている購読リスト照会API使用例

[ToastIAP requestActivePurchasesWithCompletionHandler:^(NSArray<ToastPurchaseResult *> *purchases, NSError *error) {
    if (error == nil) {
        for (ToastPurchaseResult *purchase in purchases) {
            // 購読商品アクセス有効化
        }
    } else {
        NSLog(@"Failed to request active purchases : %@", error);
    }
}];

購入復元

  • 使用者のAppStoreアカウントで購入した内訳を基準に購買内訳を復元し、IAPコンソールに反映します。
  • 購買した購読商品が照会されないか、活性化しない場合に使います。
  • 有効期限が切れた決済を含めて復元された決済がToastPurchaseResultオブジェクトで返されます。
  • 自動更新型消費性サブスクリプション商品の場合、反映されていない購入履歴が存在する場合は復元後に未消費購入履歴から照会が可能です。

購入復元API仕様

// 購入復元
+ (void)restoreWithCompletionHandler:(nullable void (^)(NSArray<ToastPurchaseResult *> * _Nullable purchases, NSError * _Nullable error))completionHandler;

購入復元API使用例

[ToastIAP restoreWithCompletionHandler:^(NSArray<ToastPurchaseResult *> *purchases, NSError *error) {
    if (error == nil) {
        for (ToastPurchaseResult *purchase in purchases) {
            NSLog(@"Restored purchase : %@", purchase);
        }
    } else {
        NSLog(@"Failed to request restore : %@", error);
    }
}];

未消費購入履歴照会

  • 消費性商品の場合、商品支給後に消費(consume)処理を行う必要があります。
  • 消費処理されていない購入履歴がToastPurchaseResultオブジェクトで返されます。
  • 自動更新型消費性サブスクリプション商品は、更新決済が発生するたびに未消費購入履歴から照会できます。

未消費購入履歴照会API仕様

// 未消費購入履歴照会
+ (void)requestConsumablePurchasesWithCompletionHandler:(nullable void (^)(NSArray<ToastPurchaseResult *> * _Nullable purchases, NSError * _Nullable error))completionHandler;

未消費購入履歴照会API使用例

[ToastIAP requestConsumablePurchasesWithCompletionHandler:^(NSArray<ToastPurchaseResult *> *purchases, NSError *error) {
    if (error == nil) {
        NSLog(@"Consumable Purchases : %@", purchases);
    } else {
        NSLog(@"Failed to request consumable : %@", error);
    }
}

消費性商品の消費

  • 消費性商品の場合、サービスに商品支給後にREST APIまたはSDKのConsume APIで消費処理を行う必要があります。

消費API仕様

+ (void)consumeWithPurchaseResult:(ToastPurchaseResult *)result
                completionHandler:(nullable void (^)(NSError * _Nullable error))completionHandler;

消費API使用例

// 未消費購入履歴照会
[ToastIAP requestConsumablePurchasesWithCompletionHandler:^(NSArray<ToastPurchaseResult *> *purchases, NSError *error) {
    if (error == nil) {
        for (ToastPurchaseResult *purchaseResult in purchases) {
            // 商品支給処理
            // ...

            // 商品支給後に消費処理
            [ToastIAP consumeWithPurchaseResult:purchaseResult
                              completionHandler:^(NSError *error) {
                                    if (error == nil) {
                                        NSLog(@"Successfully consumed");

                                    } else {
                                        NSLog(@"Failed to consume : %@", error);

                                        // 商品支給回数
                                        // ...
                                    }
                              }];
        }

    } else {
        NSLog(@"Failed to request consumable : %@", error);
    }
}

購読商品管理ページの提供方法

  • 自動更新型購読商品を使用する場合、ユーザーに購読管理ページを提供する必要があります。

    Apple Guide

  • 別途のUIを構成せず、下記URLを呼び出して購読管理ページを表示する必要があります。

Safariで購読管理ページに接続する方法

https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions"]];

Safariで管理ページを呼び出す時は、次のような順序で管理ページが表示されます。

  1. Safari Open
  2. Popup表示:itunse Storeで開きますか?
  3. iTunse Store Open
  4. Popupで購読管理ページに接続

iOS端末左上の、以前のアプリに戻るにSafariが表示されます。

Schemeから購読管理ページに接続する方法

itms-apps://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions"]];

Schemeから管理ページを呼び出す時は、次のような順序で管理ページが表示されます。

  1. App Storeの購読管理ページがApp To App呼び出しですぐに接続されます。

iOS端末左上の、以前のアプリに戻るにService Appが表示されます。

(旧)IAP SDK互換性維持

  • (旧)IAP SDKとの互換性を維持できるように、(旧)IAP SDKで作成された未完了購入の件の再処理機能を提供します。
  • (旧)IAP SDKとの互換性維持機能を使用するには、sqlite3 Library(libsqlite3.tdb)を追加で接続(link)する必要があります。 linked_sqlite3

未完了購入再処理API仕様

+ (void)processesIncompletePurchasesWithCompletionHandler:(nullable void (^)(NSArray <ToastPurchaseResult *> * _Nullable results, NSError * _Nullable error))completionHandler;

未完了購入再処理API使用例

// 未完了購入再処理要請
[ToastIAP processesIncompletePurchasesWithCompletionHandler:^(NSArray<ToastPurchaseResult *> *results, NSError *error) {
    if (error == nil) {
        for (ToastPurchaseResult *purchaseResult in results) {
            // 商品支給処理
            // ...

            // 商品支給後、消費処理
            [ToastIAP consumeWithPurchaseResult:purchaseResult
                              completionHandler:^(NSError *error) {
                                    if (error == nil) {
                                        NSLog(@"Successfully consumed");

                                    } else {
                                        NSLog(@"Failed to consume : %@", error);

                                        // 商品支給回数
                                        // ...
                                    }
                              }];
        }

    } else {
        NSLog(@"Failed to process incomplete purchases : %@", error);
    }
}];

TOAST IAP Class Reference

ToastIAPConfiguration

TOAST IAP初期化メソッドのパラメータとして使用されるアプリ内決済設定情報です。

@interface ToastIAPConfiguration : NSObject <NSCoding, NSCopying>

// IAPサービスアプリキー
@property (nonatomic, copy, readonly) NSString *appKey;
// サービスゾーン
@property (nonatomic) ToastServiceZone serviceZone;

+ (instancetype)configurationWithAppKey:(NSString *)appKey;

- (instancetype)initWithAppKey:(NSString *)appKey
NS_SWIFT_NAME(init(appKey:));

@end

ToastInAppPurchaseDelegate

決済結果の通知を受け取り、プロモーション決済の実行方式を設定できます。

@protocol ToastInAppPurchaseDelegate <NSObject>

// 決済成功
- (void)didReceivePurchaseResult:(ToastPurchaseResult *)purchase
NS_SWIFT_NAME(didReceivePurchase(purchase:));

// 決済失敗
- (void)didFailPurchaseProduct:(NSString *)productIdentifier withError:(NSError *)error
NS_SWIFT_NAME(didFailPurchase(productIdentifier:error:));

@optional
// プロモーション決済進行方法の選択
- (BOOL)shouldAddStorePurchaseForProduct:(ToastProduct *)product API_AVAILABLE(ios(11.0));

@end

ToastProductResponse

商品リスト情報を確認できます。

@interface ToastProductsResponse : NSObject <NSCoding, NSCopying>

// IAPコンソールとストア(Apple)に登録されている決済に使用することができる商品リスト
@property (nonatomic, copy, readonly) NSArray<ToastProduct *> *products;
// ストア(Apple)で商品情報を取得できなかった商品リスト
@property (nonatomic, copy, readonly) NSArray<ToastProduct *> *invalidProducts;

@end

ToastProduct

TOAST IAPコンソールに登録された商品の情報を確認できます。

@interface ToastProduct : NSObject <NSCoding, NSCopying>

// 商品のID
@property (nonatomic, copy, readonly) NSString *productIdentifier;
// 商品固有番号
@property (nonatomic, readonly) long productSeq;
// 商品名(IAP Console)
@property (nonatomic, copy, readonly, nullable) NSString *productName;
// 商品タイプ
@property (nonatomic, readonly) ToastProductType productType;
// 価格
@property (nonatomic, copy, readonly, nullable) NSDecimalNumber *price;
// 通貨
@property (nonatomic, copy, readonly, nullable) NSString *currency;
// 現地の商品名(AppStoreConnect)
@property (nonatomic, copy, readonly, nullable) NSString *localizedTitle;
// 現地の商品説明(AppStoreConnect)
@property (nonatomic, copy, readonly, nullable) NSString *localizedDescription;
// 現地価格
@property (nonatomic, copy, readonly, nullable) NSString *localizedPrice;
// 商品有効化状況
@property (nonatomic, readonly, getter=isActive) BOOL active;
// ストアコード"AS"
@property (nonatomic, copy, readonly) NSString *storeCode;

@end

ToastPurchaseResult

決済情報を確認できます。

@interface ToastPurchaseResult : NSObject <NSCoding, NSCopying>

// ユーザーID
@property (nonatomic, copy, readonly) NSString *userID;
// ストアコード"AS"
@property (nonatomic, copy, readonly) NSString *storeCode;
// 商品のID
@property (nonatomic, copy, readonly) NSString *productIdentifier;
// 商品固有番号
@property (nonatomic, readonly) long productSeq;
// 商品タイプ
@property (nonatomic, readonly) ToastProductType productType;
// 価格
@property (nonatomic, copy, readonly) NSDecimalNumber *price;
// 通貨
@property (nonatomic, copy, readonly) NSString *currency;
// 決済固有番号決済ID
@property (nonatomic, copy, readonly) NSString *paymentSeq;
// 消費に使用されるトークン
@property (nonatomic, copy, readonly) NSString *accessToken;
// 決済ID
@property (nonatomic, copy, readonly) NSString *transactionIdentifier;
// 原本決済ID
@property (nonatomic, copy, readonly, nullable) NSString *originalTransactionIdentifier;
// 商品購入時間
@property (nonatomic, readonly) NSTimeInterval purchaseTime;
// サブスクリプション商品の有効期限
@property (nonatomic, readonly) NSTimeInterval expiryTime;
// プロモーション決済状況
@property (nonatomic, readonly, getter=isStorePayment) BOOL storePayment;
// ユーザーデータ
@property (nonatomic, readonly, copy, nullable) NSString *payload;

@end

エラーコード

// IAPエラーコード
static NSString *const ToastIAPErrorDomain = @"com.toast.iap";

typedef NS_ENUM(NSUInteger, ToastIAPErrorCode) {
    ToastIAPErrorUnknown = 0,                       // 不明
    ToastIAPErrorNotInitialized = 1,                // 初期化しない
    ToastIAPErrorStoreNotAvailable = 2,             // ストア使用不可
    ToastIAPErrorProductNotAvailable = 3,           // 商品情報取得に失敗
    ToastIAPErrorProductInvalid = 4,                // 元決済の商品IDと現在の商品IDが不一致
    ToastIAPErrorAlreadyOwned = 5,                  // すでに所有している商品
    ToastIAPErrorAlreadyInProgress = 6,             // すでに進行中の要請あり
    ToastIAPErrorUserInvalid = 7,                   // 現在のユーザーIDが決済ユーザーIDと不一致
    ToastIAPErrorPaymentInvalid = 8,                // 決済追加情報(ApplicationUsername)取得失敗
    ToastIAPErrorPaymentCancelled = 9,              // ストア決済キャンセル
    ToastIAPErrorPaymentFailed = 10,                // ストア決済失敗
    ToastIAPErrorVerifyFailed = 11,                 // 領収書検証失敗
    ToastIAPErrorChangePurchaseStatusFailed = 12,   // 購入状態変更失敗
    ToastIAPErrorPurchaseStatusInvalid = 13,        // 購入進行不可状態
    ToastIAPErrorExpired = 14,                      // 購読満了
    ToastIAPErrorRenewalPaymentNotFound = 15,       // 領収書内に更新決済と一致する決済情報がない
    ToastIAPErrorRestoreFailed = 16,                // 復元に失敗しました
    ToastIAPErrorPaymentNotAvailable = 17,          // 購入不可状態(e.g.アプリ内での購入制限設定)
    ToastIAPErrorPurchaseLimitExceeded = 18,        // 月購入限度超過
};

// Networkエラーコード
static NSString *const ToastHttpErrorDomain = @"com.toast.http";

typedef NS_ENUM(NSUInteger, ToastHttpErrorCode) {
    ToastHttpErrorNetworkNotAvailable = 100,        // ネットワーク使用不可
    ToastHttpErrorRequestFailed = 101,              // HTTPステータスコードが200でないか、要求を読み取れない
    ToastHttpErrorRequestTimeout = 102,             // タイムアウト
    ToastHttpErrorRequestInvalid = 103,             // 要請の誤り
    ToastHttpErrorURLInvalid = 104,                 // URLの誤り
    ToastHttpErrorResponseInvalid = 105,            // 応答の誤り
    ToastHttpErrorAlreadyInprogress = 106,          // 要請がすでに進行中
    ToastHttpErrorRequiresSecureConnection = 107,   // Allow Arbitrary Loadsを設定しない
};
TOP