(新)領収書検証 + Notification V2 方式を使用するにはNHN Cloud SDK iOS v1.7.0以上を使用する必要があります。
NHN Cloud SDK iOS v1.8.0から(新)領収書検証 + Notification V2方式と(旧)領収書検証 + Notification V1方式の両方をサポートします。 SDKの検証方式は、IAPコンソールに設定された方式によって決定されます。- IAPコンソールガイド
1. NHN Cloud SDKをインストールします。 2. NHN CloudコンソールでMobile Service > IAPを有効化します。 3. IAPでAppKeyを確認します。
Service | Cocoapods Pod Name | Framework | Dependency | Build Settings |
---|---|---|---|---|
IAP | NHNCloudIAP | NHNCloudIAP.framework | * StoreKit.framework [Optional] * libsqlite3.tdb |
|
Mandatory | NHNCloudCore NHNCloudCommon |
NHNCloudCore.framework NHNCloudCommon.framework |
OTHER_LDFLAGS = ( "-ObjC", "-lc++" ); |
platform :ios, '11.0'
use_frameworks!
target '{YOUR PROJECT TARGET NAME}' do
pod 'NHNCloudIAP'
end
ユーザーIDが設定されていない状態では、購入、有効になっている商品照会、未消費履歴照会機能を使用できません。
// サービスログイン完了後、ユーザーID設定
[NHNCloudSDK setUserID:@"INPUT_USER_ID"];
// サービスログアウト完了後、ユーザーIDをnilに設定
[NHNCloudSDK setUserID:nil];
// 初期化
+ (void)initWithConfiguration:(NHNCloudIAPConfiguration *)configuration;
// Delegate設定
+ (void)setDelegate:(nullable id<NHNCloudInAppPurchaseDelegate>)delegate;
// 初期化およびDelegate設定
+ (void)initWithConfiguration:(NHNCloudIAPConfiguration *)configuration
delegate:(nullable id<NHNCloudInAppPurchaseDelegate>)delegate;
決済結果に対する通知を受けるためには、商品購入前にDelegateが設定されていなければなりません。
@protocol NHNCloudInAppPurchaseDelegate <NSObject>
// 購入成功
- (void)didReceivePurchaseResult:(NHNCloudPurchaseResult *)purchase;
// 購入失敗
- (void)didFailPurchaseProduct:(NSString *)productIdentifier withError:(NSError *)error;
@optional
// プロモーション決済進行方法の選択
- (BOOL)shouldAddStorePurchaseForProduct:(NHNCloudProduct *)product API_AVAILABLE(ios(11.0));
@end
#import <UIKit/UIKit.h>
#import <NHNCloudIAP/NHNCloudIAP.h>
@interface ViewController () <NHNCloudInAppPurchaseDelegate>
@end
@implementation ViewController
- (void)initializeNHNCloudIAP {
// 初期化およびDelegate設定
NHNCloudIAPConfiguration *configuration = [NHNCloudIAPConfiguration configurationWithAppKey:@"INPUT_YOUE_APPKEY"];
[NHNCloudIAP initWithConfiguration:configuration delegate:self];
}
// 購入成功
- (void)didReceivePurchaseResult:(NHNCloudPurchaseResult *)purchase {
NSLog(@"Successfully purchased");
}
// 購入失敗
- (void)didFailPurchaseProduct:(NSString *)productIdentifier withError:(NSError *)error {
NSLog(@"Failed to purchase: %@", error);
}
// プロモーション決済進行方法の選択
- (BOOL)shouldAddStorePurchaseForProduct:(NHNCloudProduct *)product {
/*
* return YES;
* リクエストしたプロモーション決済をSDKで行うようにします。
* 初期化およびログイン後に決済ウィンドウが表示されます。
*/
return YES;
/*
* return NO;
* プロモーション決済が終了します。
* productオブジェクトを保存した後、任意の時点で保存されたオブジェクトで決済を行うことができます。
*/
self.promotionProduct = product;
return NO;
}
@end
+ (void)requestProductsWithCompletionHandler:(nullable void (^)(NHNCloudProductsResponse * _Nullable response, NSError * _Nullable error))completionHandler;
[NHNCloudIAP requestProductsWithCompletionHandler:^(NHNCloudProductsResponse *response, NSError *error) {
if (error == nil) {
NSArray<NHNCloudProduct *> *products = response.products;
NSLog(@"Products : %@", products);
// ストアから商品情報を取得できない
NSArray<NHNCloudProduct *> *invalidProducts = response.invalidProducts;
NSLog(@"Invalid Products : %@", invalidProducts);
} else {
NSLog(@"Failed to request products: %@", error);
}
}
商品名 | 商品タイプ | 説明 |
---|---|---|
消費性商品 | NHNCloudProductTypeConsumable | 消費可能な1回限りの商品です。 ゲーム内通貨、コイン、繰り返し購入可能な商品などに使用できます。 |
自動更新型サブスクリプション商品 | NHNCloudProductTypeAutoRenewableSubscription | 指定された間隔と価格で決済が自動的に繰り返される商品です。 雑誌、音楽のストリーミングアクセス許可、広告の除去などに使用できます。 |
自動更新型消費性サブスクリプション商品 | NHNCloudProductTypeConsumableSubscription | 指定された間隔と価格で決済が自動的に繰り返される商品です。 指定された間隔と価格で消費性商品を支給したい時に使用できます。 |
自動更新型購読商品のアップグレード、ダウングレード、修正機能は、サポートしていません。
1つの購読グループに、1つの商品のみ登録する必要があります。
typedef NS_ENUM(NSInteger, NHNCloudProductType) {
// 商品種類取得失敗
NHNCloudProductTypeUnknown = 0,
// 消費性商品
NHNCloudProductTypeConsumable = 1,
// 自動更新型購読商品
NHNCloudProductTypeAutoRenewableSubscription = 2,
// 自動更新型消費性購読商品
NHNCloudProductTypeConsumableSubscription = 3
};
// 商品購入要請
+ (void)purchaseWithProduct:(NHNCloudProduct *)product;
// ユーザーデータを追加して商品購入
+ (void)purchaseWithProduct:(NHNCloudProduct *)product payload:(NSString *)payload;
// 商品IDを利用した購入要請
+ (void)purchaseWithProductIdentifier:(NSString *)productIdentifier;
// 商品IDで購入リクエストした時、ユーザーデータ追加
+ (void)purchaseWithProductIdentifier:(NSString *)productIdentifier payload:(NSString *)payload;
// 商品購入要請
[NHNCloudIAP purchaseWithProduct:self.products[0] payload:@"DEVELOPER_PAYLOAD"];
// or
// 商品IDを利用した購入要請
[NHNCloudIAP purchaseWithProductIdentifier:@"PRODUCT_IDENTIFIER" payload:@"DEVELOPER_PAYLOAD"];
// 有効になっているAppStore購読リストを照会する
+ (void)requestActiveSubscriptionsWithCompletionHandler:(nullable void (^)(NSArray<NHNCloudPurchaseResult *> * _Nullable purchases, NSError * _Nullable error))completionHandler;
// 有効になっているすべてのマーケット(AppStore、Googleプレイ、ONEstoreなど)購読リストを照会する
+ (void)requestAllMarketsActiveSubscriptionsWithCompletionHandler:(nullable void (^)(NSArray<NHNCloudPurchaseResult *> * _Nullable purchases, NSError * _Nullable error))completionHandler;
[NHNCloudIAP requestActiveSubscriptionsWithCompletionHandler:^(NSArray<NHNCloudPurchaseResult *> *purchases, NSError *error) {
if (error == nil) {
for (NHNCloudPurchaseResult *purchase in purchases) {
// 購読商品アクセス有効化
}
} else {
NSLog(@"Failed to request active purchases : %@", error);
}
}];
// 購入復元
+ (void)restoreWithCompletionHandler:(nullable void (^)(NSArray<NHNCloudPurchaseResult *> * _Nullable purchases, NSError * _Nullable error))completionHandler;
[NHNCloudIAP restoreWithCompletionHandler:^(NSArray<NHNCloudPurchaseResult *> *purchases, NSError *error) {
if (error == nil) {
for (NHNCloudPurchaseResult *purchase in purchases) {
NSLog(@"Restored purchase : %@", purchase);
}
} else {
NSLog(@"Failed to request restore : %@", error);
}
}];
// AppStore未消費購入履歴照会
+ (void)requestConsumablePurchasesWithCompletionHandler:(nullable void (^)(NSArray<NHNCloudPurchaseResult *> * _Nullable purchases, NSError * _Nullable error))completionHandler;
// すべてのマーケット(AppStore、Googleプレイ、ONEstoreなど)の未消費購入履歴の照会
+ (void)requestAllMarketsConsumablePurchasesWithCompletionHandler:(nullable void (^)(NSArray<NHNCloudPurchaseResult *> * _Nullable purchases, NSError * _Nullable error))completionHandler;
[NHNCloudIAP requestConsumablePurchasesWithCompletionHandler:^(NSArray<NHNCloudPurchaseResult *> *purchases, NSError *error) {
if (error == nil) {
NSLog(@"Consumable Purchases : %@", purchases);
} else {
NSLog(@"Failed to request consumable : %@", error);
}
}
+ (void)consumeWithPurchaseResult:(NHNCloudPurchaseResult *)result
completionHandler:(nullable void (^)(NSError * _Nullable error))completionHandler;
// 未消費購入履歴照会
[NHNCloudIAP requestConsumablePurchasesWithCompletionHandler:^(NSArray<NHNCloudPurchaseResult *> *purchases, NSError *error) {
if (error == nil) {
for (NHNCloudPurchaseResult *purchaseResult in purchases) {
// 商品支給処理
// ...
// 商品支給後に消費処理
[NHNCloudIAP consumeWithPurchaseResult:purchaseResult
completionHandler:^(NSError *error) {
if (error == nil) {
NSLog(@"Successfully consumed");
} else {
NSLog(@"Failed to consume : %@", error);
// 商品支給回数
// ...
}
}];
}
} else {
NSLog(@"Failed to request consumable : %@", error);
}
}
自動更新型サブスクリプション商品を使用する場合、ユーザーに購読管理ページを提供する必要があります。
別途のUIを構成せず、以下のURLを呼び出して購読管理ページを表示する必要があります。
https://apps.apple.com/account/subscriptions
itms-apps://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscription
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://apps.apple.com/account/subscriptions"] options: @{} completionHandler:nil];
または
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions"] options: @{} completionHandler:nil];
App Storeの購読管理ページに移動します。
iOS端末の左上の以前のアプリに戻ると
Service App
が表示されます。
sqlite3 Library(libsqlite3.tdb)
を追加で接続(link)する必要があります。
+ (void)processesIncompletePurchasesWithCompletionHandler:(nullable void (^)(NSArray <NHNCloudPurchaseResult *> * _Nullable results, NSError * _Nullable error))completionHandler;
// 未完了購入再処理要請
[NHNCloudIAP processesIncompletePurchasesWithCompletionHandler:^(NSArray<NHNCloudPurchaseResult *> *results, NSError *error) {
if (error == nil) {
for (NHNCloudPurchaseResult *purchaseResult in results) {
// 商品支給処理
// ...
// 商品支給後、消費処理
[NHNCloudIAP 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);
}
}];
NHN Cloud IAP初期化メソッドのパラメータとして使用されるアプリ内決済設定情報です。
@interface NHNCloudIAPConfiguration : NSObject <NSCoding, NSCopying>
// IAPサービスアプリキー
@property (nonatomic, copy, readonly) NSString *appKey;
// サービスゾーン
@property (nonatomic) NHNCloudServiceZone serviceZone;
+ (instancetype)configurationWithAppKey:(NSString *)appKey;
- (instancetype)initWithAppKey:(NSString *)appKey
NS_SWIFT_NAME(init(appKey:));
@end
決済結果の通知を受け取り、プロモーション決済の実行方式を設定できます。
@protocol NHNCloudInAppPurchaseDelegate <NSObject>
// 決済成功
- (void)didReceivePurchaseResult:(NHNCloudPurchaseResult *)purchase
NS_SWIFT_NAME(didReceivePurchase(purchase:));
// 決済失敗
- (void)didFailPurchaseProduct:(NSString *)productIdentifier withError:(NSError *)error
NS_SWIFT_NAME(didFailPurchase(productIdentifier:error:));
@optional
// プロモーション決済進行方法の選択
- (BOOL)shouldAddStorePurchaseForProduct:(NHNCloudProduct *)product API_AVAILABLE(ios(11.0));
@end
商品リスト情報を確認できます。
@interface NHNCloudProductsResponse : NSObject <NSCoding, NSCopying>
// IAPコンソールとストア(Apple)に登録されている決済に使用することができる商品リスト
@property (nonatomic, copy, readonly) NSArray<NHNCloudProduct *> *products;
// ストア(Apple)で商品情報を取得できなかった商品リスト
@property (nonatomic, copy, readonly) NSArray<NHNCloudProduct *> *invalidProducts;
@end
NHN Cloud IAPコンソールに登録された商品の情報を確認できます。
@interface NHNCloudProduct : 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) NHNCloudProductType 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
決済情報を確認できます。
@interface NHNCloudPurchaseResult : 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) NHNCloudProductType 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, getter=isSandboxPayment) BOOL sandboxPayment;
// ユーザーデータ
@property (nonatomic, readonly, copy, nullable) NSString *payload;
@end
// IAPエラーコード
static NSString *const NHNCloudIAPErrorDomain = @"com.nhncloud.iap";
typedef NS_ENUM(NSUInteger, NHNCloudIAPError) {
NHNCloudIAPErrorUnknown = 0, // 不明
NHNCloudIAPErrorNotInitialized = 1, // 初期化しない
NHNCloudIAPErrorStoreNotAvailable = 2, // ストア使用不可
NHNCloudIAPErrorProductNotAvailable = 3, // 商品情報取得に失敗
NHNCloudIAPErrorProductInvalid = 4, // 元決済の商品IDと現在の商品IDが不一致
NHNCloudIAPErrorAlreadyOwned = 5, // すでに所有している商品
NHNCloudIAPErrorAlreadyInProgress = 6, // すでに進行中の要請あり
NHNCloudIAPErrorUserInvalid = 7, // 現在のユーザーIDが決済ユーザーIDと不一致
NHNCloudIAPErrorPaymentInvalid = 8, // 決済追加情報(ApplicationUsername)取得失敗
NHNCloudIAPErrorPaymentCancelled = 9, // ストア決済キャンセル
NHNCloudIAPErrorPaymentFailed = 10, // ストア決済失敗
NHNCloudIAPErrorVerifyFailed = 11, // 領収書検証失敗
NHNCloudIAPErrorChangePurchaseStatusFailed = 12, // 購入状態変更失敗
NHNCloudIAPErrorPurchaseStatusInvalid = 13, // 購入進行不可状態
NHNCloudIAPErrorExpired = 14, // 購読満了
NHNCloudIAPErrorRenewalPaymentNotFound = 15, // 領収書内に更新決済と一致する決済情報がない
NHNCloudIAPErrorRestoreFailed = 16, // 復元に失敗しました
NHNCloudIAPErrorPaymentNotAvailable = 17, // 購入不可状態(e.g.アプリ内での購入制限設定)
NHNCloudIAPErrorPurchaseLimitExceeded = 18, // 月購入限度超過
};
// Networkエラーコード
static NSString *const NHNCloudHttpErrorDomain = @"com.nhncloud.http";
typedef NS_ENUM(NSUInteger, NHNCloudHttpError) {
NHNCloudHttpErrorNetworkNotAvailable = 100, // ネットワーク使用不可
NHNCloudHttpErrorRequestFailed = 101, // HTTPステータスコードが200でないか、要求を読み取れない
NHNCloudHttpErrorRequestTimeout = 102, // タイムアウト
NHNCloudHttpErrorRequestInvalid = 103, // 要請の誤り
NHNCloudHttpErrorURLInvalid = 104, // URLの誤り
NHNCloudHttpErrorResponseInvalid = 105, // 応答の誤り
NHNCloudHttpErrorAlreadyInprogress = 106, // 要請がすでに進行中
NHNCloudHttpErrorRequiresSecureConnection = 107, // Allow Arbitrary Loadsを設定しない
};