In-App Purchaseプログラミングガイド

In-App Purchase
プログラミングガイド
目次
In-App Purchaseについて 5
はじめに 6
iTunes Connectでプロダクトを作成し、設定する 6
App Storeでアプリケーションによってプロダクトを販売する 6
購読に必要なアプリケーションロジックを追加する 7
ユーザが購入したプロダクトを復元する 7
アプリケーションとプロダクトを審査用に登録する 7
関連項目 7
アプリケーション内プロダクトのデザイン 8
In-App Purchaseを使用して販売可能なもの 8
iTunes Connectでのプロダクトの作成 9
プロダクトのタイプ 9
プロダクトのタイプによる違い 10
プロダクト情報の取得 12
プロダクトIDのリストの取得 12
アプリケーションバンドル内へのプロダクトIDの埋め込み 13
サーバからのプロダクトIDのフェッチ 13
プロダクト情報の取得 15
アプリケーションのストアUIの表示 16
推奨されるテスト手順 18
テスト用アカウントによるApp Storeへのサインイン 18
プロダクトIDリストのフェッチテスト 18
無効なプロダクトIDの処理のテスト 19
プロダクト要求のテスト 19
支払いの要求 20
支払い要求の作成 20
異常アクティビティの検知 21
支払い要求の送信 22
プロダクトの配信 23
App Storeがトランザクションを処理するのを待機する 23
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
2
目次
購入の持続 26
Appレシートを使用した持続 27
User DefaultsまたはiCloudを使用した値の持続 27
User DefaultsまたはiCloudを使用したレシートの持続 27
独自のサーバを使用した持続 28
アプリケーションの機能のアンロック 28
関連コンテンツの配信 29
ローカルコンテンツのロード 30
ホストしたコンテンツのAppleのサーバからのダウンロード 30
独自サーバからのコンテンツのダウンロード 32
トランザクションの終了 32
推奨されるテスト手順 33
支払い要求のテスト 33
オブザーバコードの検証 34
成功したトランザクションのテスト 34
中断したトランザクションのテスト 34
トランザクションが終了したことの確認 34
購読の取り扱い 35
購読の有効期間の計算 35
期限切れと更新 37
キャンセル 37
プラットフォームをまたがる場合の考慮事項 38
ユーザーによる購読管理 38
テスト環境 38
購入したプロダクトの復元 40
Appレシートの更新 41
完了したトランザクションの復元 41
アプリケーション審査の準備 43
プロダクトを審査用に登録する 43
テスト環境のレシート 43
実装におけるチェックリスト 44
書類の改訂履歴 46
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
3
図、表、リスト
In-App Purchaseについて 5
図 I-1
購入プロセスの各段階 6
アプリケーション内プロダクトのデザイン 8
表 1-1
表 1-2
プロダクトのタイプによる比較 10
購読のタイプによる比較 11
プロダクト情報の取得 12
図 2-1
表 2-1
リスト 2-1
リスト 2-2
リスト 2-3
購入プロセスの各段階—ストアUIの表示 12
プロダクトIDを取得する方法の比較 12
サーバからのプロダクトIDのフェッチ 14
プロダクト情報の取得 15
プロダクト価格のフォーマット 17
支払いの要求 20
図 3-1
リスト 3-1
リスト 3-2
購入プロセスの各段階—支払いの要求 20
支払い要求の作成 20
アプリケーションのユーザ名の提供 21
プロダクトの配信 23
図 4-1
表 4-1
リスト 4-1
リスト 4-2
リスト 4-3
購入プロセスの各段階—プロダクトの配信 23
トランザクションの状態と対応するアクション 24
トランザクションキューのオブザーバの登録 24
トランザクションの状態への応答 25
ダウンロード済みコンテンツのバックアップからの除外 31
購読の取り扱い 35
図 5-1
表 5-1
購読タイムラインの例 35
購読例のタイムライン 35
アプリケーション審査の準備 43
図 7-1
開発、審査、本番の各環境 43
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
4
In-App Purchaseについて
In-App Purchaseを使用すると、Store Kitフレームワークを使用してアプリケーション内にストアを組
み込むことができます。このフレームワークはアプリケーションの代理としてApp Storeに接続して、
ユーザによる支払いを安全に処理することで、ユーザに対して支払いの承認を促すものです。フレー
ムワークは次にアプリケーションに通知を行い、これにより購入した項目がユーザに提供されます。
In-App Purchaseは、追加の機能やコンテンツの支払いの回収に使用します。
たとえば、In-App Purchaseを使用すると、次のようなシナリオを実行することができます。
●
追加のプレミアム機能が備わったアプリケーションの基本バージョン
●
ユーザが新しい記事を購入してダウンロードできる雑誌アプリケーション
●
探索する新しい階層を提供するゲーム
●
プレーヤーが仮想の不動産を購入できるオンラインゲーム
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
5
In-App Purchaseについて
はじめに
はじめに
図 I-1で説明するように、In-App Purchaseプロセスでのユーザ、アプリケーション、App Storeの相互処
理には3つの段階があります。まず、ユーザがアプリケーションのストアに移動すると、アプリケー
ションのプロダクトが表示されます。次に、ユーザが購入するプロダクトを選択し、アプリケーショ
ンがApp Storeに支払いを要求します。App Storeは支払いを処理し、アプリケーションが購入済みプ
ロダクトを配信します。
図 I-1
購入プロセスの各段階
iTunes Connectでプロダクトを作成し、設定する
In-App Purchaseでサポートされるプロダクトの種類と動作を理解することで、このテクノロジーを使
用したアプリケーションとアプリケーション内ストアを最大限に活用できます。
関連する章: “アプリケーション内プロダクトのデザイン” (8 ページ)
App Storeでアプリケーションによってプロダクトを販売する
ユーザが購入し、購入済みプロダクトを配信できるよう、In-App Purchaseを使用するすべてのアプリ
ケーションに、3つの章で説明するコア機能を実装する必要があります。
これらの開発タスクを順番に実行する必要があります。関連する章で、実行するタスクを順番に説明
しています(全一覧については“実装におけるチェックリスト” (44 ページ)を参照)。開発をスムーズ
に行うために、開始前にチェックリスト全体に目を通すとよいでしょう。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
6
In-App Purchaseについて
関連項目
関連する章: “プロダクト情報の取得” (12 ページ)、“支払いの要求” (20 ページ)、“プ
ロダクトの配信” (23 ページ)
購読に必要なアプリケーションロジックを追加する
購読を提供するアプリケーションでは、ユーザの購読が有効な場合に追跡を行い、購読期限の終了や
更新に対応し、ユーザがアクセスできるコンテンツを決定する必要があります。
関連する章: “購読の取り扱い” (35 ページ)
ユーザが購入したプロダクトを復元する
ユーザが以前に購入したプロダクト(支払い済みのコンテンツなど)を新しい携帯電話に復元できます。
関連する章: “購入したプロダクトの復元” (40 ページ)
アプリケーションとプロダクトを審査用に登録する
アプリケーションの開発とテストが終了したら、アプリケーションとIn-App Purchaseプロダクトを審
査用に登録します。
関連する章: “アプリケーション審査の準備” (43 ページ)
関連項目
●
●
●
『In-App Purchase Configuration Guide for iTunes Connect 』では、iTunes Connectでのアプリケーショ
ンのプロダクトの作成および設定方法が説明されています。
『App Distribution Quick Start 』では、アプリケーションにIn-App Purchaseを組み込んで使えるよう
にする手順を解説しています。
『Receipt Validation Programming Guide 』では、レシート、特にアプリケーション内での購入に成
功した記録について説明されています。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
7
アプリケーション内プロダクトのデザイン
ここでプロダクトとは、アプリケーション内ストアで販売するものを指しています。iTunes Connect
でプロダクトを作成して設定し、SKProductクラスとSKProductsRequestクラスを使用してアプリ
ケーションとプロダクトを連携します。
In-App Purchaseを使用して販売可能なもの
In-App Purchaseでは、コンテンツ、アプリケーションの機能、およびサービスを販売できます。
●
●
●
コンテンツ。雑誌、写真、アートワークなどのデジタルコンテンツまたはデジタルアセットを配
信します。コンテンツはアプリケーション自身によっても使用できます。たとえば、ゲーム内の
追加のキャラクターやレベル、カメラアプリケーションのフィルタ、ワードプロセッサ用の文房
具などです。
アプリケーションの機能。既に配信済みのアプリケーションでロックされている動作の解除や機
能の拡張を行います。たとえば、アプリケーション内の購入でマルチプレイヤーモードを提供す
る無料ゲームや、一度購入すると広告が表示されなくなる無料の天気予報アプリケーションなど
があります。
サービス。音声の転送などの1回限りのサービス、またはデータのコレクションへのアクセスな
どの継続するサービスに対して、ユーザに支払いを求めます。
In-App Purchaseを使用して、実物の商品やサービス、あるいは不適切なコンテンツを販売することは
できません 。
●
●
実物の商品やサービス。In-App Purchaseを使用する場合は、デジタルの商品またはサービスをア
プリケーション内に配信する必要があります。アプリケーション内でユーザに実物の商品やサー
ビスを購入してもらうには、クレジットカードや支払いサービスなどの別の支払いメカニズムを
使用してください。
不適切なコンテンツ。In-App Purchaseを使用してApp Review Guidelineで許可されないコンテンツ
を販売しないでください。たとえばポルノグラフィやヘイトスピーチ、または誹謗中傷などで
す。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
8
アプリケーション内プロダクトのデザイン
iTunes Connectでのプロダクトの作成
In-App Purchaseを使用して提供できるものの詳細については、ライセンス契約およびApp Review
Guidelineを参照してください。コーディングを始める前にこのガイドラインを注意深く検討しておく
と、審査期間中の遅れや拒否を回避できることがあります。特定のケースにおいてガイドラインの説
明が不十分である場合は、オンライン連絡フォームを使用して、App Reviewチームに具体的な質問を
行うことができます。
アプリケーションで販売するプロダクトにどのような物があるのかを知ったうえで、In-App Purchase
でそのプロダクトを販売するのが適切であると判断した場合は、iTunes Connectでプロダクトを作成
する必要があります。
iTunes Connectでのプロダクトの作成
コーディングを始める前に、アプリケーションと連携するプロダクトについて、iTunes Connectで設
定する必要があります。アプリケーションの開発状況に応じて、プロダクトを追加したり削除したり
することができ、また既存のプロダクトの改善や再設定を行うことができます。
各プロダクトは特定のアプリケーションに関連づけられています。あるアプリケーションのために開
発されたプロダクトを、他のアプリケーションから使うことはできません。別のプラットフォームで
動作するコンパニオンアプリケーションは、独立した(別個の)アプリケーションと考えます。した
がって、Macアプリケーション用のプロダクトをiOSアプリケーションから使う(あるいはその逆)、
といったこともできません。
プロダクトはアプリケーションを登録するときに、アプリケーションの審査プロセスの一部として審
査されます。ユーザがプロダクトを購入できるようになるには、プロダクトがあらかじめ審査者に
よって承認されている必要があり、またiTunes Connectでプロダクトを“cleared for sale”(購入可能)
としてマークしておく必要があります。
iTunes Connectでプロダクトを取り扱う具体的な手順については、『In-AppPurchaseConfigurationGuide
for iTunes Connect 』を参照してください。
プロダクトのタイプ
プロダクトタイプごとに異なるプロダクト動作を提供することで、アプリケーションの範囲でIn-App
Purchaseを使用できます。iTunes Connectでは、次のプロダクトのタイプから1つを選択します。
●
消耗型(Consumable)プロダクト。アプリケーションの実行に伴って消費されていく項目です。
Voice over IPアプリケーションで通信できる残り分数や、音声の転送など一度限りのサービスが例
として挙げられます。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
9
アプリケーション内プロダクトのデザイン
プロダクトのタイプによる違い
●
●
●
●
非消耗型(Non-consumable)プロダクト。ユーザのすべてのデバイス上で無制限に使用できる項
目です。ユーザのすべてのデバイスで使用可能になります。例としては、書籍やゲームレベルな
どのコンテンツ、およびアプリケーションの追加機能などがあります。
自動更新購読(Auto-renewable subscriptions)。エピソードで構成されるコンテンツです。消耗
型プロダクトと同様に、自動更新購読は、ユーザのすべてのデバイスで無制限に利用可能になり
ます。非消耗型プロダクトと異なるのは、自動更新購読には期限があるという点です。新しいコ
ンテンツは定期的に配信され、ユーザは購読が有効な期間中、発行されたコンテンツに対してア
クセスできます。自動更新購読の期限が近づいてくると、ユーザに代わってシステムにより購読
が自動的に更新されます。
非更新購読(Non-renewable subscriptions)。エピソードで構成されるコンテンツを含まない購
読です。たとえば、歴史的な写真のデータベースに対するアクセス権や、フライトマップのコレ
クションなどがあります。ユーザのすべてのデバイスで購読を使用可能にし、ユーザの購入を復
元するのは、アプリケーション側で対応することになります。このプロダクトタイプは、ユーザ
のアカウントが既にサーバ上に存在し、このアカウントを使用してコンテンツの復元時にユーザ
を識別できる場合によく使用されます。購読の期限と期間もアプリケーション(またはサーバ)
で実装し、実行することになります。
無料購読(Free subscriptions)。Newsstandに無料購読のコンテンツを置くための手段です。サイ
ンアップしたユーザは、Apple IDに関連付けられたどのデバイスからでも購読できます。期限切
れになることはありません。また、購読にはNewsstand対応アプリケーションが必要です。
プロダクトのタイプによる違い
プロダクトの各タイプは、特定の用途に合わせてデザインされています。次の表 1-1および表 1-2にま
とめているように、プロダクトタイプの動作はそれぞれ異なります。
表 1-1
プロダクトのタイプによる比較
プロダクトのタイプ
非消耗型
消耗型
購入できる回数
1回
複数回
レシートへの表示
常に
1回
デバイス間での同期
システムにより同期
同期なし
復元
システムにより同期
復元されない
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
10
アプリケーション内プロダクトのデザイン
プロダクトのタイプによる違い
表 1-2
購読のタイプによる比較
購読のタイプ
自動更新
非更新
無料
購入できる回数
複数回
複数回
1回
レシートへの表示
常に
1回
常に
デバイス間での同期
システムにより復元
アプリケーションによ
り復元
システムにより同
期
復元
システムにより復元
アプリケーションによ
り復元
システムにより復
元
期限のあるプロダクトまたは使用すると消耗するプロダクト(消耗型プロダクト、自動更新購読、非
更新購読)は、消耗される項目を再度手に入れるため、または購読期間を延長するために、複数回購
入することができます。非消耗型プロダクトと無料購読は、コンテンツに対するロックを解除して
ユーザが無制限に使用できるようになるため、購入できるのは1回限りになります。
消耗型プロダクトと非更新購読は、購入後レシートに表示されますが、“Appレシートを使用した持
続” (27 ページ)で詳しく説明されているように、レシートが次に更新されると削除されます。これ
以外のタイプのプロダクトには、レシートに削除されないエントリがあります。
消耗型プロダクトは、その性質上、同期されたり復元されたりすることはありません。たとえば、
iPhoneでバブル(bubble)を10個購入しても、iPadのバブルが10個増えるわけではないことをユーザは理
解しています。これ以外のタイプのプロダクトでは、ユーザのすべてのデバイスで使用できるように
なります。これらのタイプのプロダクトについては復元も行われるので、デバイスを新しく購入した
後でも、以前に購入したコンテンツに引き続きアクセスできます。Store Kitでは、自動更新購読と無
料購読、および非消耗型プロダクトについて、同期と復元の処理を行います。
非更新購読は、自動更新購読とは次のいくつかの重要な点で異なります。この違いにより、次のよう
にアプリケーションに必要な正しい動作を実装する柔軟性が実現されています。
●
●
●
購読が有効である期間の計算と、ユーザが使用できるようになる必要があるコンテンツの決定は
アプリケーション側で対応します。
購読の期限が近づいてきていることを検出して、プロダクトを再び購入することで購読を更新す
ることをユーザに促すのはアプリケーション側で対応します。
プロダクトの購入後にユーザのすべてのデバイスでこれを使用可能にするかどうか、また過去の
購入の復元をユーザに行わせるかどうかは、アプリケーション側での対応になります。たとえ
ば、ほとんどの定期購読はサーバから提供されます。サーバではユーザを識別して、定期購読と
これを購入しているユーザとを関連付けるメカニズムが必要になります。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
11
プロダクト情報の取得
購入プロセスの最初の段階では、アプリケーションがApp Storeからプロダクトに関する情報を取得
し、ユーザに対してストアUIを表示した後、ユーザがプロダクトを選択します(図 2-1を参照)。
図 2-1
購入プロセスの各段階—ストアUIの表示
プロダクトIDのリストの取得
アプリケーションで販売するすべてのプロダクトには、一意のプロダクトIDがあります。アプリケー
ションではこのプロダクトIDを使用して、価格などのプロダクトに関する情報をApp Storeから取得
し、ユーザがプロダクトを購入すると支払い要求を送信します。アプリケーションはプロダクトIDの
リストをアプリケーションにバンドルされるファイルから読み込むか、またはサーバからフェッチし
ます。表 2-1に、2つのやり方についての相違点をまとめてあります。
表 2-1
プロダクトIDを取得する方法の比較
アプリケーションバンドルに埋め込み
サーバからフェッチ
購入目的
機能のアンロック
コンテンツ配信
プロダクトのリストの変更
アプリケーションの更新時に可能
いつでも可能
サーバの必要性
不可
可
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
12
プロダクト情報の取得
プロダクトIDのリストの取得
アプリケーションのプロダクトリストが、広告の削除や機能の有効化など固定されている場合は、ア
プリケーションバンドルにリストを埋め込みます。追加のレベルやキャラクターをサポートするゲー
ムのように、プロダクトIDのリストがアプリケーションの更新しなくても変更できるようにするに
は、サーバからリストをフェッチするようにします。
特定のアプリケーションに対してiTunes Connectで設定されているすべてのプロダクトのリストを
フェッチする実行時のメカニズムはありません。アプリケーションは、プロダクトリストの管理と、
この情報のアプリケーションへの提示に対応します。多数のプロダクトを管理する必要がある場合
は、iTunes ConnectのXMLの一括アップロード/ダウンロード機能を使用することを検討します。
アプリケーションバンドル内へのプロダクトIDの埋め込み
アプリケーションバンドルに次のようなプロダクトIDの配列を含んだプロパティリストのファイルを
含めます。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<string>com.example.level1</string>
<string>com.example.level2</string>
<string>com.example.rocket_car</string>
</array>
</plist>
プロパティリストからプロダクションIDを取得するには、アプリケーションバンドルでファイルを探
して、これを読み込みます。
NSURL *url = [[NSBundle mainBundle] URLForResource:@"product_ids"
withExtension:@"plist"];
NSArray *productIdentifiers = [NSArray arrayWithContentsOfURL:url];
サーバからのプロダクトIDのフェッチ
プロダクトIDを含んだJSONファイルをサーバ上でホストします。以下に例を挙げます。
[
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
13
プロダクト情報の取得
プロダクトIDのリストの取得
"com.example.level1",
"com.example.level2",
"com.example.rocket_car"
]
サーバからプロダクトIDを取得するには、リスト 2-1に示すように、JSONファイルをフェッチして読
み込みます。旧版を破壊することなく、アプリケーションの将来の版の構造を変更できるよう、JSON
ファイルのバージョン管理を考慮してください。たとえば、古い構造を使用するファイルに
products_v1.json、新しい構造を使用するファイルにproducts_v2.jsonという名前を付けます。
これは、使用するJSONファイルが例の単純な配列よりも複雑な場合に特に有益です。
リスト 2-1
サーバからのプロダクトIDのフェッチ
- (void)fetchProductIdentifiersFromURL:(NSURL *)url delegate:(id)delegate
{
dispatch_queue_t global_queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(global_queue, ^{
NSError *err;
NSData *jsonData = [NSData dataWithContentsOfURL:url
options:NULL
error:&err];
if (!jsonData) { /* エラーを処理する */ }
NSArray *productIdentifiers = [NSJSONSerialization
JSONObjectWithData:jsonData options:NULL error:&err];
if (!productIdentifiers) { /* エラーを処理する */ }
dispatch_queue_t main_queue = dispatch_get_main_queue();
dispatch_async(main_queue, ^{
[delegate displayProducts:productIdentifiers]; // Custom method
});
});
}
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
14
プロダクト情報の取得
プロダクト情報の取得
NSURLConnectionを使用したファイルのダウンロードの詳細については、『URL Loading System
Programming Guide 』の“Using NSURLConnection”を参照してください。
アプリケーションが反応し続けるためには、JSONファイルのダウンロードとプロダクトIDリストの抽
出にバックグラウンドスレッドを使用します。データの転送量を最小化するには、Last-Modified
ヘッダやIf-Modified-Sinceヘッダなど、HTTPの標準キャッシュメカニズムを使用します。
プロダクト情報の取得
ユーザが実際に購入できるプロダクトのみが表示されることを確認するには、アプリケーションのス
トアUIを表示する前にApp Storeに問い合わせます。
App Storeに問い合わせるには、プロダクト要求オブジェクトを使用します。最初に、
SKProductsRequestのインスタンスを作成し、プロダクトIDのリストで初期化します。要求オブジェ
クトへの強い参照を保持してください。そうしないと、要求が完了しないうちに、システムが割り当
て解除してしまうおそれがあります
プロダクト要求により無効なプロダクトIDのリストとともに有効なプロダクトについての情報が取得
されます。次にオブジェクトのデリゲートを呼び出して結果を処理します。App Storeからの応答を処
理するために、デリゲートではSKProductsRequestDelegateプロトコルを実装している必要があり
ます。リスト 2-2に、両方のコードの一部の簡単な実装を示します。
リスト 2-2
プロダクト情報の取得
// Custom method
- (void)validateProductIdentifiers:(NSArray *)productIdentifiers
{
SKProductsRequest *productsRequest = [[SKProductsRequest alloc]
initWithProductIdentifiers:[NSSet
setWithArray:productIdentifiers]];
// Keep a strong reference to the request.
self.request = productsRequest;
productsRequest.delegate = self;
[productsRequest start];
}
// SKProductsRequestDelegate protocol method
- (void)productsRequest:(SKProductsRequest *)request
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
15
プロダクト情報の取得
アプリケーションのストアUIの表示
didReceiveResponse:(SKProductsResponse *)response
{
self.products = response.products;
for (NSString *invalidIdentifier in response.invalidProductIdentifiers) {
// Handle any invalid product identifiers.
}
[self displayStoreUI]; // Custom method
}
ユーザがプロダクトを購入すると、デリゲートに返されるプロダクトオブジェクトの配列に対する参
照を維持するために、支払い要求の作成に対応するプロダクトオブジェクトが必要になります。アプ
リケーションで販売するプロダクトのリストを変更できる場合は、サーバからフェッチする画像や説
明のテキストなどの他の情報とともに、プロダクトオブジェクトへの参照をカプセル化したカスタム
クラスを作成する場合があります。支払い要求については、“支払いの要求” (20 ページ)で説明さ
れています。
無効として返されたプロダクトIDは、アプリケーションのプロダクトIDのリストにエラーがあること
を表している場合がほとんどですが、iTunes Connectでプロダクトが適切に設定されていないことを
意味している場合もあります。この種の問題をより容易に解決するには、適切なログ記録と適切なUI
が重要になります。本番用のビルドでは、アプリケーションはエラーに「賢く」対処する必要があり
ます。このことは通常、アプリケーションの残りのストアUIを表示しながら、無効なプロダクトを省
略することを意味しています。開発用のビルドでは、問題に対する注意を喚起するために、エラーを
表示します。本番用ビルド、開発用ビルドの両方に対して、無効なIDについて記録を残すために、
NSLogを使用してコンソールにメッセージを書き込みます。アプリケーションがサーバからリストを
フェッチしてくる場合は、無効なIDのリストをアプリケーションからサーバに送信するためにログを
記録するメカニズムを定義することもできます。
アプリケーションのストアUIの表示
アプリケーションのストアのデザインはアプリケーション内での販売に大きく影響するため、これを
適切に行うために時間と労力を割くことには意義があります。アプリケーションのほかの部分と統合
されるように、ストアのUIをデザインします。Store KitではストアUIを提供することはできません。
プロダクトを最高の条件で展示し、アプリケーションのほかの部分とシームレスに連携するストアUI
をデザインできるのは、アプリケーションとそのコンテンツを熟知しているアプリケーションの作成
者だけです。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
16
プロダクト情報の取得
アプリケーションのストアUIの表示
アプリケーションのストアUIをデザインするときには、次のガイドラインを考慮してください。
ユーザが支払いを行える場合にのみストアを表示します。ユーザが支払いを行えるかどうかを判断す
るには、SKPaymentQueueクラスのcanMakePaymentsメソッドを呼び出します。ユーザが(たとえば保
護者による制限のために)支払いを行えない場合は、ストアは使用できないことを示すUIを表示する
か、UIのストア部分全体を省略します。
アプリケーションのフローの中で自然にプロダクトを表示します。アプリケーションのストアUIを表
示するのに最適な場所をUIの中で見つけます。ユーザが使用できるコンテキストでプロダクトを表示
します。たとえば、ユーザがプレミアム機能を使用しようとしたときに機能をアンロックできるよう
にします。ユーザがアプリケーションに初めて触れるときの体験に注意を払ってください。
楽しく簡単に体験ができるようにプロダクトを構成します。アプリケーションのプロダクトが多すぎ
なければ、すべての1つの画面に表示して構いません。そうでない場合、プロダクトをグループやカ
テゴリに分け、ナビゲートしやすくします。号数の多いコミック本リーダーや雑誌など、多数のプロ
ダクトがあるアプリケーションでは、ユーザが購入する新規アイテムを見つけやすいインタフェース
が特に有用です。プロダクト間の違いを明記するため、それぞれに異なる名前や外観を設定します。
必要な場合、明示的な比較を記載します。
ユーザにとってのプロダクトの価値を伝えます。ユーザは購入しようとしているものについて正確に
知りたいと考えています。プロダクトの価格や説明といったApp Storeからの情報を、プロダクトの画
像やデモといったサーバまたはアプリケーションバンドルからの情報と組み合わせます。購入前はプ
ロダクトでの体験を制限します。たとえば、ユーザに新しいレースカーを購入してもらうゲームで
は、新しいレースカーで1周テストできるようにします。同様に、追加のブラシを購入してもらうお
絵描きアプリケーションでは、小さな画面で新しいブラシで試し描きして違いを確認できるようにし
ます。この種のデザインにより、ユーザはプロダクトを体験する機会を得て、確信を持って購入でき
るようになります。
App Storeによって返されるロケールと通貨を使用して価格を明示します。プロダクトを見つけやす
く、説明を読みやすくします。ユーザのロケールと価格と価格のロケールが異なっている場合であっ
ても、異なる通貨間の変換をUI内で行わないようにしてください。たとえば、米国にいるユーザが(長
さの単位と英国式の日付の形式を使用するために)United Kingdomのロケールを設定する場合を考慮し
ます。アプリケーションは、United Kingdomのロケールに従ってUIを表示しますが、プロダクトの情
報はApp Storeで指定されたロケールで表示する必要があります。インタフェースのほかの部分に合わ
せてUnited Kingdomのロケールに合わせて価格を英国ポンドに変換すると、不正確になることがあり
ます。ユーザは米国でApp Storeアカウントを持ち、米ドルで支払うため、アプリケーションでは価格
が米ドルで表示されます。同様に、アプリケーションでも米ドルで価格が表示されます。リスト 2-3
に、プロダクトのロケール情報を使用して価格を正しくフォーマットする方法を示します。
リスト 2-3
プロダクト価格のフォーマット
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
17
プロダクト情報の取得
推奨されるテスト手順
[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setLocale:product.priceLocale];
NSString *formattedPrice = [numberFormatter stringFromNumber:product.price];
ユーザによる購入するプロダクトの選択後、アプリケーションはプロダクトの支払いを要求するため
にApp Storeに接続します。
推奨されるテスト手順
正しく実装されていることを検証するために、コードの各部分をテストします。
テスト用アカウントによるApp Storeへのサインイン
「テスト用ユーザアカウントの生成iniTunesConnectDeveloperGuide 」の説明に従って、iTunes Connect
でテスト用ユーザアカウントを設定します。
開発用のiOSデバイスの「設定(Settings)」で、App Storeからサインアウトします。次にXcodeでアプリ
ケーションをビルドして実行します。
開発用のOS Xデバイスで、Mac App Storeからサインアウトします。次にXcodeでアプリケーションを
ビルドして、Finderから起動します。
アプリケーションを使用して、アプリケーション内で購入を行います。App Storeにサインインする
メッセージが表示されたら、テスト用アカウントを使用します。このメッセージの一部に“[Environment:
Sandbox]”というテキストが表示されるのは、テスト環境に接続されていることを示しています。
“[Environment: Sandbox]”というテキストが表示されない場合は、本番用の環境を使用していることを
示しています。アプリケーションの開発用に署名されたビルドを実行していることを確認してくださ
い。本番用に署名されたビルドは本番用の環境を使用します。
Important: 本番用の環境にログインする場合、テスト用のユーザアカウントは使わないでくださ
い。使用した場合、テスト用ユーザアカウントは無効になり、使用できなくなります。
プロダクトIDリストのフェッチテスト
プロダクトIDがアプリケーションに埋め込まれている場合は、コードにブレークポイントを設定した
後でコードをロードし、NSArrayのインスタンスにプロダクトIDのリストが予想通りに格納されてい
ることを確認します。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
18
プロダクト情報の取得
推奨されるテスト手順
プロダクトIDがサーバからフェッチされる場合は、JSONファイルを手動で(SafariなどのWebブラウ
ザ、またはcurlなどのコマンドラインユーティリティを使用して)フェッチして、サーバから返され
るデータにプロダクトIDのリストが予想通りに格納されていることを確認します。また、サーバに
HTTPの標準キャッシュメカニズムが正しく実装されていることを検証します。
無効なプロダクトIDの処理のテスト
アプリケーションのプロダクションIDのリストに意図的に無効なIDを設定します(テスト後に削除す
るのを忘れないようにしてください)。
本番用のビルドで、アプリケーションにストアUIの無効なID以外の部分が表示され、ユーザがプロダ
クトを購入できることを確認します。開発用ビルドで、アプリケーションの問題について注意が喚起
されることを確認します。
コンソールログをチェックして、無効なプロダクトIDが正しく識別されていることを確認します。
プロダクト要求のテスト
テストするプロダクトIDのリストを使用して、SKProductsRequestのインスタンスを作成して送信し
ます。コードにブレークポイントを設定し、プロダクトIDが有効なリストと無効なリストを検査しま
す。無効なプロダクトIDがあった場合は、iTunes Connectでプロダクトを確認して、JSONファイルま
たはプロパティリストを修正します。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
19
支払いの要求
購入プロセスの第2段階では、図 3-1に示すように、ユーザが特定のプロダクトを購入することを選択
した後、アプリケーションがApp Storeに支払い要求を送信します。
図 3-1
購入プロセスの各段階—支払いの要求
支払い要求の作成
ユーザがプロダクトを購入することを選択した場合は、リスト 3-1に示すように、プロダクトオブジェ
クトを使用して支払い要求を作成し、必要に応じて数量を設定します。プロダクトオブジェクトは、
“プロダクト情報の取得” (15 ページ)に示すように、アプリケーションのプロダクト要求によって
返されるプロダクトの配列に由来します。
リスト 3-1
支払い要求の作成
SKProduct *product = <# Product returned by a products request #>;
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
payment.quantity = 2;
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
20
支払いの要求
異常アクティビティの検知
異常アクティビティの検知
App Storeは異常アクティビティ検知エンジンを使用して不正に対応します。追加情報を提供すること
で、エンジンの異常トランザクション検知能力を向上するアプリケーションもあります。ユーザが
App Storeアカウントに加えてアプリケーションのアカウントを持っている場合、支払い要求の際にこ
の追加情報を提供してください。
たとえば、次の2つの例を考えてみましょう。通常、サーバ上の多くのユーザがそれぞれゲームを使
用するためにコインを購入し、各ユーザが別のApp Storeアカウントから購入のため支払いを行いま
す。対照的に、サーバ上の1人のユーザがコインが何回も購入し、別のApp Storeアカウントから購入
のための支払いを行うことは異常なことです。App Storeがこの種の異常アクティビティを単独で検知
することはできません。サーバ上のどのアカウントがトランザクションと関連付けられているかにつ
いて、アプリケーションからの情報が必要です。
この情報を提供するためには、支払いオブジェクトのapplicationUsernameプロパティにサーバ上
のユーザアカウント名の一方向ハッシュを入力します。リスト 3-2に例を示します。
リスト 3-2
アプリケーションのユーザ名の提供
#import <CommonCrypto/CommonCrypto.h>
// Custom method to calculate the SHA-256 hash using Common Crypto
- (NSString *)hashedValueForAccountName:(NSString*)userAccountName
{
const int HASH_SIZE = 32;
unsigned char hashedChars[HASH_SIZE];
const char *accountName = [userAccountName UTF8String];
size_t accountNameLen = strlen(accountName);
// Confirm that the length of the user name is small enough
// to be recast when calling the hash function.
if (accountNameLen > UINT32_MAX) {
NSLog(@"Account name too long to hash: %@", userAccountName);
return nil;
}
CC_SHA256(accountName, (CC_LONG)accountNameLen, hashedChars);
// Convert the array of bytes into a string showing its hex representation.
NSMutableString *userAccountHash = [[NSMutableString alloc] init];
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
21
支払いの要求
支払い要求の送信
for (int i = 0; i < HASH_SIZE; i++) {
// Add a dash every four bytes, for readability.
if (i != 0 && i%4 == 0) {
[userAccountHash appendString:@"-"];
}
[userAccountHash appendFormat:@"%02x", hashedChars[i]];
}
return userAccountHash;
}
このプロパティの入力に別の方法を使用する場合、入力する値がサーバ上のユーザアカウントに一意
に関連付けられた不透明な識別子であるようにします。デベロッパアカウントのApple ID、ユーザの
Apple ID、サーバ上のユーザのハッシュなしのアカウント名は使用しないでください。
支払い要求の送信
トランザクションキューに支払い要求を追加すると、App Storeに送信されます。キューに支払いオブ
ジェクトを複数回追加すると、オブジェクトは複数回送信されます。そのためユーザは複数回課金さ
れ、アプリケーションはプロダクトを複数回配信されます。
[[SKPaymentQueue defaultQueue] addPayment:payment];
アプリケーションが支払い要求を送信するたびに、対応するトランザクションが発生し、処理が必要
になります。トランザクションとトランザクションキューについては、“App Storeがトランザクショ
ンを処理するのを待機する” (23 ページ)で説明します。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
22
プロダクトの配信
購入プロセスの最後の段階では、App Storeによる支払い要求の処理後、アプリケーションは今後の起
動に備えて情報を保存し、購入したコンテンツをダウンロードして、トランザクションに終了のマー
クを付けます(図 4-1を参照)。
図 4-1
購入プロセスの各段階—プロダクトの配信
App Storeがトランザクションを処理するのを待機する
トランザクションキューは、Store Kitフレームワークを介してアプリケーションとApp Storeが通信す
るときに中心的な役割を演じます。処理する必要がある支払い要求など、App Storeによる処理が必要
な作業をこのキューに追加します。トランザクションの状態が、たとえば、支払い要求に成功して変
化した場合、Store Kitはアプリケーションのトランザクションキューのオブザーバを呼び出します。
オブザーバとして振る舞うクラスは開発者が決めます。非常に小規模なアプリケーションであれば、
トランザクションキューの監視その他、Store Kitに関係する処理をすべてアプリケーションデリゲー
トで扱っても構いません。しかし多くの場合、オブザーバとしての挙動をはじめ、ストアに関係する
処理をおこなう独立したクラスを用意する方がよいでしょう。オブザーバには
SKPaymentTransactionObserverプロトコルを実装する必要があります。
オブザーバを使用する場合、アプリケーションではアクティブなトランザクションを常時ポーリング
しているわけではありません。アプリケーションでは、支払い要求のほか、Appleによってホストさ
れたコンテンツのダウンロードと購読の更新の検出にもトランザクションキューを使用します。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
23
プロダクトの配信
App Storeがトランザクションを処理するのを待機する
アプリケーションの起動時に、トランザクションキューのオブザーバを登録します(リスト 4-1を参
照)。オブザーバは、キューにトランザクションを追加した直後だけでなく、いつでもトランザクショ
ンを処理できることを確認します。たとえば、トンネルに入る直前にユーザがアプリケーションで何
かを購入する場合について考慮します。ネットワーク接続がないため、アプリケーションは購入され
たコンテンツを配信できません。アプリケーションが次回起動されたときに、Store Kitはトランザク
ションキューのオブザーバを再度呼び出して、購入された項目をその時点で配信します。同様に、ア
プリケーションがトランザクションに終了のマークを付けられなかった場合、トランザクションが終
了したと適切にマークされるまで、Store Kitはアプリケーションが起動されるたびに毎回オブザーバ
を呼び出します。
リスト 4-1
トランザクションキューのオブザーバの登録
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
/* ... */
[[SKPaymentQueue defaultQueue] addTransactionObserver:observer];
}
トランザクションキューのオブザーバにpaymentQueue:updatedTransactions:を実装します。トラ
ンザクションの状態が、たとえば支払い要求が処理されたために変化すると、Store Kitはこのメソッ
ドを呼び出します。トランザクションの状態は、表 4-1およびリスト 4-2に示すように、アプリケー
ションで実行する必要があるアクションがどれであるのかを通知します。キューに入っているトラン
ザクションの状態が変わる順序は不定です。アプリケーションはいつでもアクティブなトランザク
ションを処理できるようにしておかなければなりません。
表 4-1
トランザクションの状態と対応するアクション
状態
アプリケーションで実行するアクション
SKPaymentTransactionStatePurchasing
進捗している状態を反映するようにUIを更新し、再び呼び
出されるのを待機します。
SKPaymentTransactionStateDeferred
遅延している状態を反映するようにUIを更新し、再び呼び
出されるのを待機します。
SKPaymentTransactionStateFailed
errorプロパティの値を使用して、ユーザーにメッセージを
表示します。エラーを表す定数については、『Store Kit
Constants Reference 』のSKErrorDomainに関する項に一覧が
載っています。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
24
プロダクトの配信
App Storeがトランザクションを処理するのを待機する
状態
アプリケーションで実行するアクション
SKPaymentTransactionStatePurchased
購入した機能を提供します。
SKPaymentTransactionStateRestored
以前に購入した機能を復元します。
リスト 4-2
トランザクションの状態への応答
- (void)paymentQueue:(SKPaymentQueue *)queue
updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
// Call the appropriate custom method for the transaction state.
case SKPaymentTransactionStatePurchasing:
[self showTransactionAsInProgress:transaction deferred:NO];
break;
case SKPaymentTransactionStateDeferred:
[self showTransactionAsInProgress:transaction deferred:YES];
break;
case SKPaymentTransactionStateFailed:
[self failedTransaction:transaction];
break;
case SKPaymentTransactionStatePurchased:
[self completeTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
[self restoreTransaction:transaction];
break;
default:
// For debugging
NSLog(@"Unexpected transaction state %@",
@(transaction.transactionState));
break;
}
}
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
25
プロダクトの配信
購入の持続
}
待機中にユーザインターフェイスを最新の状態に保つには、トランザクションキューのオブザーバは
SKPaymentTransactionObserverプロトコルから次のようにオプションメソッドを実装できます。
paymentQueue:removedTransactions:メソッドは、トランザクションがキューから削除されると呼
び出されます。このメソッドの実装では、対応する項目をアプリケーションのUIから削除します。
paymentQueueRestoreCompletedTransactionsFinished:メソッドまたは
paymentQueue:restoreCompletedTransactionsFailedWithError:メソッドは、Store Kitがトラン
ザクションの復元を終了するとエラーの有無に応じて呼び出されます。これらのメソッドの実装で
は、アプリケーションのUIが処理の成功またはエラーを反映するように更新します。
購入の持続
プロダクトの提供を開始した後、アプリケーションは購入の持続的な記録を作成する必要がありま
す。アプリケーションは起動時にその持続的な記録を使用して、プロダクトの提供を継続します。ま
た、購入の復元にも記録を使用します(“購入したプロダクトの復元” (40 ページ)を参照)。アプリ
ケーションを持続させる方法は、販売するプロダクトの種類とiOSのバージョンによって異なります。
●
iOS 7以降の非消耗型プロダクトと自動更新購読では、アプリケーションのレシートを持続的な記
録として使用します。
●
iOS 7より前のバージョンの非消耗型プロダクトと自動更新購読では、User Defaultsシステムまた
はiCloudを使用して持続的な記録を管理します。
●
●
非更新購読では、iCloudまたは独自のサーバを使用して持続的な記録を管理します。
消耗型プロダクトの場合は、購入を反映するようにアプリケーションの内部状態をアプリケー
ションで更新しますが、消耗型プロダクトは復元やデバイス間での同期を行わないため、持続的
な記録を保持する必要はありません。更新された状態が、状態の保存をサポートするオブジェク
ト(iOS)、またはアプリケーションの起動時にわたって手動で状態を保存するオブジェクトの一部
である(iOSまたはOS X)ことを確認します。状態の保存の詳細については、“State Preservation and
Restoration” in iOS App Programming Guide を参照してください。
User DefaultsシステムまたはiCloudを使用している場合、アプリケーションは数値やブール値などの
値、またはトランザクションレシートのコピーを格納できます。OS Xでは、defaultsコマンドを使
用してUser Defaultsシステムを編集できます。レシートを格納するには追加のアプリケーションロジッ
クが必要ですが、持続的な記録の改ざんを防止できます。
iCloudを使用して持続する場合、アプリケーションの持続的な記録はデバイス間で同期されますが、
ほかのデバイスに関連コンテンツをダウンロードするのはアプリケーションです。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
26
プロダクトの配信
購入の持続
Appレシートを使用した持続
Appレシートには、ユーザの購入記録とAppleによって暗号化された署名が含まれています。詳細につ
いては、『Receipt Validation Programming Guide 』を参照してください。
消耗型プロダクトと非更新購読の情報は、支払いが行われるとシートに追加され、トランザクション
を終了するまでレシート上に残ります。トランザクションの終了後、この情報はレシートが次に更新
されるとき、たとえばユーザが次に購入を行ったときに削除されます。
これ以外の種類のプロダクト購入の情報は、支払いが行われるとレシートに追加され、レシートに残
り続けます。
User DefaultsまたはiCloudを使用した値の持続
User DefaultsまたはiCloudに情報を保存するには、キーの値を設定します。
#if USE_ICLOUD_STORAGE
NSUbiquitousKeyValueStore *storage = [NSUbiquitousKeyValueStore defaultStore];
#else
NSUserDefaults *storage = [NSUserDefaults standardUserDefaults];
#endif
[storage setBool:YES forKey:@"enable_rocket_car"];
[storage setObject:@15 forKey:@"highest_unlocked_level"];
[storage synchronize];
User DefaultsまたはiCloudを使用したレシートの持続
User DefaultsまたはiCloudにトランザクションのレシートを保存するには、レシートのデータのキーの
値を設定します。
#if USE_ICLOUD_STORAGE
NSUbiquitousKeyValueStore *storage = [NSUbiquitousKeyValueStore defaultStore];
#else
NSUserDefaults *storage = [NSUserDefaults standardUserDefaults];
#endif
NSData *newReceipt = transaction.transactionReceipt;
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
27
プロダクトの配信
アプリケーションの機能のアンロック
NSArray *savedReceipts = [storage arrayForKey:@"receipts"];
if (!savedReceipts) {
// Storing the first receipt
[storage setObject:@[newReceipt] forKey:@"receipts"];
} else {
// Adding another receipt
NSArray *updatedReceipts = [savedReceipts arrayByAddingObject:newReceipt];
[storage setObject:updatedReceipts forKey:@"receipts"];
}
[storage synchronize];
独自のサーバを使用した持続
どのレシートがどのユーザに属しているのかを追跡できるように、ある種の証明書またはIDとともに
レシートのコピーをサーバに送信します。たとえば、電子メールまたはユーザ名とパスワードを使っ
て、サーバに対してユーザが本人であることを証明します。UIDeviceのidentifierForVendorプロ
パティは使用しないでください。デバイスが異なると、このプロパティの値も異なるため、同じユー
ザの別のデバイスで行われた購入の識別と復元ができないので、このプロパティを使用することはで
きません。
アプリケーションの機能のアンロック
プロダクトによってアプリケーションの機能を有効にする場合、コードパスを有効にするためのブー
ル値を設定し、必要に応じてユーザインタフェースを更新します。案ロックする機能を決定するに
は、トランザクション発生時にアプリケーションによって作成された持続的な記録を確認してくださ
い。購入の完了時とアプリケーションの起動時、アプリケーションはこのブール値を更新する必要が
あります。
たとえば、アプリケーションのレシートを使用する場合、コードは次のようになります。
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
// Custom method to work with receipts
BOOL rocketCarEnabled = [self receipt:receiptData
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
28
プロダクトの配信
関連コンテンツの配信
includesProductID:@"com.example.rocketCar"];
また、User Defaultsシステムを使用する場合は次のようになります。
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL rocketCarEnabled = [defaults boolForKey:@"enable_rocket_car"];
その後、その情報を使用して、アプリケーションで適切なコードパスを有効にします。
if (rocketCarEnabled) {
// Use the rocket car.
} else {
// Use the regular car.
}
関連コンテンツの配信
プロダクトに関連付けられたコンテンツがある場合は、そのコンテンツもアプリケーションでユーザ
に配信する必要があります。たとえば、ゲームのレベルを購入するときにレベルを定義したファイル
を配信する必要がある場合、また音楽アプリケーションで追加の楽器を購入するときに、ユーザがそ
の楽器を演奏するために必要なサウンドファイルを配信する必要がある場合があります。
そのコンテンツをアプリケーションバンドルに埋め込むか、必要に応じてダウンロードできます。い
ずれの方法にもそれぞれの利点と欠点があります。アプリケーションバンドルに含めるコンテンツが
少なすぎると、購入したものが小さなものであってもダウンロードされる間待つ必要があります。ア
プリケーションバンドルに多くを詰め込み過ぎると、アプリケーションの初期ダウンロード時間が長
くなり、関連プロダクトの購入を望まないユーザの空き容量を無駄にすることになります。また、ア
プリケーションのサイズが大きすぎると、携帯電話のネットワークではアプリケーションをダウン
ロードできなくなります。
特に、ユーザの大半がプロダクトを購入することが予想される場合は、アプリケーションにはサイズ
の小さいファイル(数メガバイト程度まで)を埋め込みます。アプリケーションバンドルのコンテンツ
は、ユーザが購入した時点ですぐに使用できます。ただし、アプリケーションバンドルのコンテンツ
の更新や追加を行う場合は、更新されたバージョンのアプリケーションを登録する必要があります。
必要に応じて、サイズの大きいファイルをダウンロードしてください。アプリケーションバンドルと
コンテンツを分離しておくと、アプリケーションの初期ダウンロードが小さくて済みます。たとえ
ば、ゲームの最初のレベルはアプリケーションにバンドルしておいて、残りのレベルはユーザに購入
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
29
プロダクトの配信
関連コンテンツの配信
してもらうことができます。アプリケーションバンドルにハードコーディングされているのではな
く、アプリケーションが独自のサーバからプロダクトリストを取得する場合、コンテンツの追加やア
プリケーションによってダウンロードされたコンテンツの更新のためにアプリケーションを再登録す
る必要はありません。
iOS 6以降では、ほとんどのアプリケーションにおいて、ダウンロード済みファイルにAppleによって
ホストされたコンテンツを使用する必要があります。Appleによってホストされたコンテンツバンド
ルを作成するには、XcodeでIn-App Purchase Contentターゲットを使用してiTunes Connectに登録しま
す。Appleのサーバでコンテンツをホストする場合、サーバを提供する必要はありません。アプリケー
ションのコンテンツは、App Storeなどの大規模運用を支えているAppleのインフラストラクチャに保
存されます。また、Appleによってホストされたコンテンツは、アプリケーションが実行されていな
い場合であっても、バックグラウンドで自動的にダウンロードされます。
独自のサーバインフラストラクチャがあり、旧バージョンのiOSをサポートする必要がある場合や、
複数のプラットフォームでサーバインフラストラクチャを共有する場合、独自のコンテンツをホスト
することも可能です。
注意: アプリケーションのバイナリにパッチを当てたり、実行コードをダウンロードしたり
することはできません。アプリケーションの登録時には、アプリケーションのすべての機能
をサポートするために必要なすべての実行コードが含まれている必要があります。新しいプ
ロダクトによりコードの変更が必要になった場合は、アプリケーションの更新されたバー
ジョンを登録する必要があります。
ローカルコンテンツのロード
ロケットのロードには、アプリケーションバンドルから他のリソースをロードするときと同様に、
NSBundleクラスを使用します。
NSURL *url = [[NSBundle mainBundle] URLForResource:@"rocketCar"
withExtension:@"plist"];
[self loadVehicleAtURL:url];
ホストしたコンテンツのAppleのサーバからのダウンロード
Appleによってホストされたコンテンツと関連付けられたプロダクトをユーザが購入した場合、トラ
ンザクションキューのオブザーバに渡されたトランザクションにも関連コンテンツをダウンロードす
るSKDownloadのインスタンスが含まれます。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
30
プロダクトの配信
関連コンテンツの配信
そのコンテンツをダウンロードするには、downloadsのstartDownloads:メソッドを呼び出すことに
よって、ダウンロードオブジェクトをトランザクションのSKPaymentQueueプロパティからトランザ
クションキューに追加します。downloadsプロパティの値がnilの場合は、このトランザクションに
はAppleによってホストされたコンテンツがありません。アプリケーションのダウンロードとは異な
り、コンテンツのダウンロードでは一定のサイズよりも大きなコンテンツであってもWi-Fi接続を自動
的に要求しません。ユーザからの明示的なアクションがない限り、大きなファイルのダウンロードで
は携帯電話ネットワークの使用を避けてください。
進行状況をUIで更新するなど、ダウンロード状態の変更に応答するには、トランザクションキューの
オブザーバにpaymentQueue:updatedDownloads:メソッドを実装します。ダウンロードが失敗した
場合、errorプロパティの情報を使用してユーザにエラーを通知します。
アプリケーションでエラーが正常に処理されることを確認します。たとえば、ダウンロード中にディ
スク容量が不足した場合、不完全なダウンロードを破棄するか、素ペースを確保してからダウンロー
ドを再開するかをユーザが選択できるようにします。
コンテンツのダウンロード状況をユーザインターフェイスで更新するには、progressプロパティと
timeRemainingプロパティの値を使用します。ユーザにダウンロード進行状況をコントロールしても
らうには、SKPaymentQueueのpauseDownloads:メソッド、resumeDownloads:メソッド、および
cancelDownloads:メソッドを使用できます。ダウンロードが完了したかどうかを判別するには、
downloadStateプロパティを使用します。状態をチェックするために、ダウンロードオブジェクトの
progressまたはtimeRemainingプロパティを使用しないでください。これらのプロパティはUIの更
新用です。
注意: トランザクションが終了する前に、Appleによってホストされたすべてのコンテンツ
をダウンロードします。トランザクションの終了後は、トランザクションオブジェクトを使
用できなくなります。
iOSでは、ダウンロードしたファイルをアプリケーションで管理できます。Store Kitフレームワークに
よって保存されたファイルは、Caches辞書でバックアップフラグが設定されていない状態になって
います。ダウンロード完了後は、アプリケーションが適切な場所に移動します。デバイスのディスク
容量が不足した場合に削除可能なコンテンツ(後でアプリケーションによって再ダウンロード可能)に
ついては、ファイルをCachesディレクトリに残します。その他の場合、ファイルをDocumentsフォル
ダに移動、ユーザのバックアップから除外するフラグを設定します。
リスト 4-3
ダウンロード済みコンテンツのバックアップからの除外
NSError *error;
BOOL success = [URL setResourceValue:[NSNumber numberWithBool:YES]
forKey:NSURLIsExcludedFromBackupKey
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
31
プロダクトの配信
トランザクションの終了
error:&error];
if (!success) { /* エラーを処理... */ }
OS Xでは、ダウンロードされたコンテンツはシステムによって管理されます。アプリケーションで直
接これらのファイルを移動したり削除したりすることはできません。ダウンロード後にコンテンツの
ある位置を特定するには、ダウンロードオブジェクトのcontentURLプロパティを使用します。引き
続いて起こる起動中にファイルの位置を特定するには、SKDownloadのcontentURLForProductID:ク
ラスメソッドを使用します。ファイルを削除するには、deleteContentForProductID:クラスメソッ
ドを使用します。アプリケーションのレシートからプロダクトIDを読み込む方法の詳細については、
『Receipt Validation Programming Guide 』を参照してください。
独自サーバからのコンテンツのダウンロード
アプリケーションとサーバとの連携に関する詳細と、独自のサーバからコンテンツをダウンロードす
るプロセスの詳細およびメカニズムは、すべてユーザに委ねられています。最小限、通信は次の手順
を経ます。
1.
アプリケーションからサーバにレシートを送信し、コンテンツを要求します。
2.
『Receipt Validation Programming Guide 』の説明に従って、サーバはレシートを検証しプロダクト
が購入済みであることを確立します。
3.
レシートが有効である場合は、サーバはアプリケーションに対してコンテンツで応答します。
アプリケーションでエラーが正常に処理されることを確認します。たとえば、ダウンロード中にディ
スク容量が不足した場合、不完全なダウンロードを破棄するか、素ペースを確保してからダウンロー
ドを再開するかをユーザが選択できるようにします。
コンテンツをホストする方法、およびアプリケーションがサーバと通信する方法に関しては、セキュ
リティを実装することを検討してください。詳細については、『Security Overview 』を参照してくだ
さい。
トランザクションの終了
トランザクションが終了すると、購入で必要なすべての処理が完了したことがStore Kitに通知されま
す。終了していないトランザクションは終了するまではキューに残されたままになります。アプリ
ケーションが起動されるたびにアプリケーションによって未完のトランザクションを終了できるよう
に、トランザクションキューのオブザーバが呼び出されます。アプリケーションは、処理結果(成功
か否か)にかかわらず、トランザクションをすべて終了させる必要があります。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
32
プロダクトの配信
推奨されるテスト手順
トランザクションを終了する前には、次のアクションをすべて完了してください。
●
購入の持続
●
関連コンテンツのダウンロード
●
ユーザがプロダクトにアクセスできるためのアプリケーションUIの更新
トランザクションを終了するには、支払いキューでfinishTransaction:メソッドを呼び出します。
SKPaymentTransaction *transaction = <# The current payment #>;
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
トランザクションの終了後には、終了したトランザクションでアクションを実行したり、プロダクト
を配信したりする動作を一切行わないでください。未完了の動作がある場合は、トランザクションを
終了する準備がアプリケーションでできていないことになります。
注意: 終了していないトランザクションをアプリケーションで追跡するための他のメカニズ
ムを使用するため、トランザクションが実際に完了する前にfinishTransaction:メソッド
を呼び出そうとしないでください。Store Kitは、このような方法で使用されるようにはデザ
インされていません。これを行うと、Appleによってホストされたコンテンツがアプリケー
ションでダウンロードできなくなり、さらに他の問題にもつながることがあります。
推奨されるテスト手順
正しく実装されていることを検証するために、コードの各部分をテストします。
支払い要求のテスト
既にテスト済みの有効なプロダクトIDを使用してSKPaymentのインスタンスを作成します。ブレーク
ポイントを設定して、支払い要求を調査します。トランザクションキューに支払い要求を追加し、ブ
レークポイントを設定してオブザーバのpaymentQueue:updatedTransactions:メソッドが呼び出さ
れることを確認します。
テスト中は、コンテンツを提供せずに直ちにトランザクションを終了しても構いません。ただしテス
ト中であっても、終了していないトランザクションがキュー内に残っていると、後で行うテストと干
渉するため、トランザクションの終了に失敗すると問題が発生することがあります。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
33
プロダクトの配信
推奨されるテスト手順
オブザーバコードの検証
トランザクションオブザーバのSKPaymentTransactionObserverプロトコルの実装を確認します。
アプリケーションのストアUIが現在表示されておらず、また最近購入を行なっていない場合であって
も、オブザーバがトランザクションを処理できることを確認します。
コードでSKPaymentQueueのaddTransactionObserver:メソッドが呼び出されている場所を探しま
す。アプリケーションの起動時にこのメソッドが呼び出されていることを検証します。
成功したトランザクションのテスト
テスト用ユーザアカウントでApp Storeにサインインして、アプリケーションで購入を行います。トラ
ンザクションキューのオブザーバのpaymentQueue:updatedTransactions:メソッドの実装にブレー
クポイントを設定し、トランザクションを調査して、その状態が
SKPaymentTransactionStatePurchasedであることを確認します。
コードで購入を存続している場所にブレークポイントを設定し、購入が成功したときにこのコードが
呼び出されることを確認します。User DefaultsまたはiCloudキー値ストアを調査して、正しい情報が記
録されていることを確認します。
中断したトランザクションのテスト
トランザクションキューのオブザーバのpaymentQueue:updatedTransactions:メソッドにブレーク
ポイントを設定し、プロダクトを配信するかどうかを制御できるようにします。続いて、テスト環境
で通常どおり購入をし、ブレークポイントを使用してトランザクションを維一時的に無視します。た
とえば、LLDBのthread returnコマンドを使用して、メソッドから直ちに復帰します。
終了してアプリケーションを再起動します。起動後すぐに、Store Kitが
paymentQueue:updatedTransactions:メソッドを再び呼び出します。このときはアプリケーション
で正常に応答します。アプリケーションでプロダクトが正しく配信され、トランザクションが完了し
たことを確認します。
トランザクションが終了したことの確認
アプリケーションでfinishTransaction:メソッドが呼び出されている場所を特定します。このメ
ソッドが呼び出される前に、トランザクションに関係するすべての作業が完了していることを確認
し、成功か否かにかかわらず、このメソッドが呼び出されることを確認します。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
34
購読の取り扱い
購読を使用するアプリケーションについては、追加の動作と考慮事項があります。購読には時間の要
素が組み込まれているため、アプリケーションには購読が現在有効であるかどうかと、サブスクリプ
ションが有効だったのが過去のどの期間であったのかを判断する適切なロジックが備わっている必要
があります。アプリケーションは新規の購読と購読の更新にも対応し、また期限切れの購読も適切に
処理する必要があります。図 5-1に、アプリケーションで処理する必要のある複雑な部分も含めた、
購読のタイムラインの例を示します。
図 5-1
購読タイムラインの例
購読の有効期間の計算
アプリケーションでは、購読が有効な期間に基づいて、ユーザがアクセスできるコンテンツを決定す
る必要があります。たとえば、表 5-1に示すタイムラインに従い、毎月初日に最新号が出る雑誌を購
読する、という状況を考えてみましょう。
表 5-1
購読例のタイムライン
日付
イベント
2月1日
2月号発売。まだ購読を始めていないので提供しない(購読開始後に提供)。
2月20日
購読を開始(期間は1か月)。最新である2月号をすぐに提供する。
3月1日
3月号発売。購読中なのですぐに提供する。
3月20日
購読の自動更新(1か月)。
4月1日
4月号発売。購読中なのですぐに提供する。
4月20日
ユーザーが購読の更新を取りやめ、購読期間が終了。
5月1日
5月号発売。購読期間が終了しているので提供しない。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
35
購読の取り扱い
購読の有効期間の計算
日付
イベント
6月1日
6月号発売。購読期間が終了しているので、この時点では提供しない(再び購読を
開始した後に提供)。
6月17日
ユーザーが再び購読を開始。6月号をすぐに提供する。
7月1日
7月号発売。購読中なのですぐに提供する。
このロジックをアプリケーションに実装するには、各コンテンツが発行された日付を記録しておきま
す。各レシートエントリの「Original Purchase Date」および「Subscription Expiration Date」フィールド
を確認し、購読の開始日と終了日を特定します。(レシートについては『ReceiptValidationProgramming
Guide を参照)。ユーザーは、購読を購入した時点で最初にアンロックされたコンテンツに加えて、
購読期間の各開始日と各終了日の間に発行されたすべてのコンテンツにアクセスすることができま
す。購読が失効した場合、購読がアクティブな期間が複数あることになり、購読期間の開始時にコン
テンツがアンロックされます。
注意: 購入日に購読期間を加えて購読期間を計算しないでください。このやり方では、無料
トライアル期間、マーケティング目的の期間、およびユーザーが購読を購入した直後にコン
テンツが利用可能になる点が考慮されていません。
たとえば、購読を開始すればロックが解除されるので、月刊誌を1か月購読するだけで、2号
分を読めることになってしまいます。開始した時点で前月号のロックが解除され、続いて今
月号の発売時点でこちらも解除されるからです。
表 5-1に示した例を続けましょう。レシートには開始日と終了日が次のように記載されます。
2月20日~3月20日
3月20日~4月20日
(4月20日から6月17日についてはレシートに記載なし )
6月17日~7月17日
ユーザーは、購読を開始/再開した時点でロックが解除される、2月号と6月号を読めます。
さらに、3月号、4月号、7月号も読めます。それぞれの発売日時点で購読中だからです。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
36
購読の取り扱い
期限切れと更新
期限切れと更新
更新プロセスは、期限切れの10日前から開始される「事前」チェックから始まります。この10日の間
に、たとえば、顧客に有効な支払い方法があるかどうか、ユーザがこの購読を購入してからプロダク
トの価格が上昇していないかどうか、またはプロダクトが利用できなくなっていないかどうかなど、
購読の自動更新が遅れたり更新できなくなる可能性のある問題がApp Storeによってチェックされま
す。問題がある場合はApp Storeによってユーザに通知されるため、購読の更新が必要になる前に問題
を解決することができ、購読が中断されないようにします。
注意: 購読の価格が上昇しても、この10日以内に購読が期限切れとなる顧客を除いて、自
動更新が自動的に無効になることはありません。この価格の改定が間違いであった場合に、
元の価格に戻しても、影響を受けるユーザはいません。この変更が意図的なものであり、新
しいより高い価格が維持される場合は、残りのユーザが10日間の更新期間に入っていくにつ
れ、自動更新は順番に無効になっていきます。
購読が期限切れになる前の24時間の期間中に、App Storeは購読の自動更新を開始します。App Store
は一定期間、数回にわたって購読の自動更新を試みますが、失敗する回数が多いと最終的に更新を停
止します。
App Storeは購読期間に隙間が生じないように、期限切れになる少し前に更新を行います。ただし、こ
れでも隙間が生じる可能性があります。たとえば、ユーザの支払情報が有効でなかった場合、最初の
更新は失敗します。購読が期限切れになるまでにユーザが支払情報を更新しなかった場合は、購読が
期限切れになった日付と、これに続いて自動更新が成功した日付との間に短い隙間が生じます。ユー
ザは自動更新を無効にして、購読を意図的に期限切れにしてから、後日、購読を更新して、購読期間
に長い間隔を空けることができます。アプリケーションの購読ロジックでは、いろいろな長さの購読
期間の間隔を正しく扱えるようにしてください。
購読の更新に成功すると、Store Kitはトランザクションキューに更新用のトランザクションを追加し
ます。アプリケーションは起動時にトランザクションキューをチェックして、他のトランザクション
と同じ方法で更新の処理を行います。購読の更新時にアプリケーションが既に実行中であった場合
は、トランザクションのオブザーバは呼び出されません 。アプリケーションは次回起動されたときに
更新を認識します。
キャンセル
購読の購入時には全額が支払われ、Appleカスタマーサービスにご連絡されることによってのみ払い
戻されます。たとえば、ユーザが間違って違うプロダクトを購入した場合、カスタマーサポートはこ
の購読をキャンセルして払い戻しを行うことができます。購読期間の途中で気が変わって、残りの期
間について支払わないということはできません。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
37
購読の取り扱い
プラットフォームをまたがる場合の考慮事項
購入がキャンセルされたかどうかをチェックするには、レシートの「Cancellation Date」フィールド
を確認してください。フィールドに日付が入力されていた場合は、購読が期限切れになる日付にかか
わらず、購入はキャンセルされています。キャンセルされたレシートは、購入が行われなかったもの
として扱われます。
プロダクトのタイプに応じて、現在有効な購読のみをチェックできたり、過去のすべての購読をチェッ
クする必要があったりします。たとえば、雑誌のアプリケーションでは、ユーザがアクセスできたの
がどの号であったのかを判断するために、過去のすべての購読についてチェックする必要がありま
す。
プラットフォームをまたがる場合の考慮事項
プロダクトIDは、1つのアプリケーションに対して関連付けられています。アプリケーションにiOS
バージョンとOS Xバージョンの両方がある場合は、各プラットフォームに対して、独立したプロダク
トに独立したプロダクトIDを与えます。iOSバージョンのアプリケーションで購読を購入しているユー
ザがOS Xバージョンのアプリケーションから(またはこの逆から)コンテンツにアクセスできるように
する機能の実装は、アプリケーションの開発者に委ねられています。これには、非更新購読を使用す
るアプリケーションに実装されるものと同様の、ユーザを識別してユーザが購読したコンテンツの記
録を取るための何らかのシステムが必要になります。
ユーザーによる購読管理
アプリケーションに購読管理用のUIを実装せず、次のURLを開く形にしても構いません。
https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions
このURLを開くとiTunesまたはiTunes Storeが起動し、「Manage Subscription」ページが現れます。
テスト環境
テストに関しては、自動更新購読の本番環境とテスト環境の間には動作の点で多少の相違がありま
す。
更新が発生する頻度が速くなり、自動更新購読が1日で最大6回更新されます。これにより、購読の更
新、購読の失効、購読期間に間隔がある購読履歴がアプリケーションでどのように処理されるかをテ
ストできます。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
38
購読の取り扱い
テスト環境
更新と期限切れの頻度が増しているために、購読期間に短い間隔を残したまま、システムが購読の更
新を実行しようとする前に、購読が期限切れになる場合があります。本番環境でも、このような間隔
が生じるのには多くの理由があります。アプリケーションでこれらを正しく処理できることを確認し
てください。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
39
購入したプロダクトの復元
ユーザは購入済みのコンテンツに引き続きアクセスするためにトランザクションを復元します。たと
えば、新しい携帯電話にアップグレードする場合、古い携帯電話で購入したアイテムはいずれも失わ
れません。「Restore Purchases」ボタンなど、ユーザが購入を復元できる仕組みをアプリケーション
に組み込んでください。購入の復元では、ユーザのApp Storeクレデンシャルが求められ、アプリケー
ションのフローが中断されます。そのため、(特にアプリケーションが起動されるたびに)購入が自動
的に復元されるようにはしないでください。
ほとんどの場合、アプリケーションで必要な処理は、レシートの更新とレシートに含まれるプロダク
トの配信のみです。更新されたレシートには、このデバイスまたはほかのデバイス上においてユーザ
がこのアプリケーションで行った購入記録が含まれています。ただし、アプリケーションによって
は、次のような理由から別の方法を取る必要があります。
●
●
●
Appleによってホストされているコンテンツを使用している場合、完了したトランザクションを
復元すると、コンテンツをダウンロードするためのトランザクションオブジェクトがアプリケー
ションに与えられます。
アプリケーションのレシートが使用できない、iOS 7より前のiOSバージョンをサポートする必要
がある場合、完了したトランザクションを復元してください。
アプリケーションが非更新購読を使用する場合、アプリケーションで復元プロセスを処理しま
す。
レシートを更新すると、App Storeにレシートの最新コピーが要求されます。レシートを更新しても、
新しいトランザクションは作成されません。何度も続けて更新することは避けるべきですが、この操
作は1回だけ更新するのと同じ結果をもたらします。
完了したトランザクションを復元すると、ユーザが完了したトランザクションごとに新しいトランザ
クションが作成され、トランザクションキューのオブザーバの履歴が再現されます。トランザクショ
ン復元中、アプリケーションは完了したトランザクションを復元している理由と処理方法を把握する
ために状態を維持します。何度も復元すると、完了したトランザクションごとに復元したトランザク
ションが複数作成されます。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
40
購入したプロダクトの復元
Appレシートの更新
注意: ユーザーがアプリケーションの復元インタフェースを使用する代わりに購入済みのプ
ロダクトを購入しようとすると、App Storeによって復元トランザクションではなく正常な
トランザクションが作成されます。そのプロダクトについて、ユーザが二重請求されること
はありません。これらのトランザクションは、元のトランザクションとまったく同じように
扱ってください。
再ダウンロードできるコンテンツについて、適切なレベルのコントロールをユーザに提供します。た
とえば、日刊の新聞を3年分、数百メガバイト分のゲームレベルをまとめてダウンロードすることは
避けてください。
Appレシートの更新
レシート更新要求を作成し、デリゲートを設定して、要求を開始します。要求では、期限切れのレ
シートなど、テスト中のさまざまな状態のレシートの取得のためのオプションのプロパティがサポー
トされます。詳細については、SKReceiptRefreshRequestのinitWithReceiptProperties:メソッ
ドの値を参照してください。
request = [[SKReceiptRefreshRequest alloc] init];
request.delegate = self;
[request start];
レシートの更新後、そのレシートを確認し、追加されているプロダクトを配信します。
完了したトランザクションの復元
アプリケーションはSKPaymentQueueのrestoreCompletedTransactionsメソッドを呼び出すことで
プロセスを開始します。アプリケーションのすべての完了したトランザクションを復元するため、
App Storeに要求を送信します。アプリケーションが支払い要求のapplicationUsernameプロパティ
に値を設定している場合(“異常アクティビティの検知” (21 ページ)を参照)、
restoreCompletedTransactionsWithApplicationUsername:メソッドを使用してトランザクショ
ン復元時と同じ情報を提供します。
以前に完了したトランザクションごとに、App Storeが新しいトランザクションを生成します。復元さ
れたトランザクションには、元のトランザクションへの参照が含まれています。SKPaymentTransaction
のインスタンスにはoriginalTransactionプロパティがあり、レシートのエントリには「Original
Transaction Identifier」フィールドがあります。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
41
購入したプロダクトの復元
完了したトランザクションの復元
注意: 復元された購入では、日付フィールドの意味が多少異なります。詳細については、
『Receipt Validation Programming Guide 』の「Purchase Date」および「Original Purchase Date」
フィールドに関する項目を参照してください。
トランザクションキューのオブザーバは復元された各トランザクションの
SKPaymentTransactionStateRestored状態で呼び出されます。これについては、“App Storeがトラ
ンザクションを処理するのを待機する” (23 ページ)で説明します。この時点での対応は、アプリ
ケーションの設計によって異なります。
●
●
アプリケーションがアプリケーションレシートを使用し、Appleによってホストされたコンテン
ツがない場合、アプリケーションは完了したトランザクションを復元しないため、このコードは
不要です。復元されたトランザクションをすぐに終了してください。
アプリケーションがアプリケーションレシートを使用し、Appleによってホストされたコンテン
ツがある場合、復元プロセスを開始する前にユーザが復元するプロダクトを選択できるようにし
ます。復元中、ユーザが選択したコンテンツを再ダウンロードし、ほかのトランザクションはす
ぐに終了します。
NSMutableArray *productIDsToRestore = <# From the user #>;
SKPaymentTransaction *transaction = <# Current transaction #>;
if ([productIDsToRestore containsObject:transaction.transactionIdentifier])
{
// Re-download the Apple-hosted content, then finish the transaction
// and remove the product identifier from the array of product IDs.
} else {
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
●
アプリケーションがアプリケーションレシートを使用しない場合、復元時にすべての完了したト
ランザクションが調査されます。元の購入ロジックと同様のコードパスを使用してプロダクトを
使用可能な状態にし、トランザクションを終了します。
多数のプロダクト(特に関連付けられたコンテンツがあるプロダクト)があるアプリケーションで
は、すべてをまとめて復元するのではなく、ユーザが復元するプロダクトを選択できるようにし
ます。このようなアプリケーションは、復元時に処理が必要な完了したトランザクションと、す
ぐに終了して無視できるトランザクションを把握します。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
42
アプリケーション審査の準備
テストが終了すると、アプリケーションを審査のために登録する準備が整ったことになります。この
章では、審査プロセスについてのいくつかのヒントに焦点を当てます。
プロダクトを審査用に登録する
アプリケーションを初めて審査のために登録する場合は、同時に審査を受けるためにアプリケーショ
ン内プロダクトも登録する必要があります。最初の登録後は、審査のためのアプリケーションおよび
プロダクトに対する更新の登録をそれぞれ独自に行うことができます。詳細については、『In-App
Purchase Configuration Guide for iTunes Connect 』を参照してください。
テスト環境のレシート
図 7-1に示すように、アプリケーションは、開発、審査、および本番の各段階において異なる環境で
実行されます。
図 7-1
開発、審査、本番の各環境
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
43
アプリケーション審査の準備
実装におけるチェックリスト
開発の段階では、ユーザは開発用として署名されたバージョンのアプリケーションを実行します。こ
のアプリケーションはユーザのテスト用サーバとApp Storeのテスト用環境に接続します。本番では、
ユーザは本番用として署名されたバージョンのアプリケーションを実行します。このアプリケーショ
ンはユーザの本番用サーバと本番のApp Storeに接続されます。ただしアプリケーションの審査期間中
は、アプリケーションは本番用の環境とテスト用の環境が混ざった状態で実行されます。つまりアプ
リケーションは本番用として署名され、本番用のサーバに接続されますが、App Storeのテスト用の環
境に接続されます。
ユーザのサーバでレシートを検証する場合、サーバでは本番用として署名されたアプリケーションを
処理して、そのレシートをAppleのテスト用環境から受け取ることができる必要があります。本番用
のサーバでお勧めできるアプローチは、最初から本番のApp Storeで常にレシートの検証を開始すると
いうものです。検証が「Sandbox receipt used in production(サンドボック用のレシートが本番で使
用)」というエラーコードで失敗したら、本番用の代わりにテスト用の環境に対する検証を行いま
す。
実装におけるチェックリスト
審査を受けるためにアプリケーションを登録する前に、必要な動作がすべて実装されていることを確
認してください。アプリケーション内での購入のための次のコア動作(一般的な開発プロセスの順に
記載)が実装されていることを確認します。
●
iTunes Connectでプロダクトを作成し、設定します。
プロダクトの変更はプロセス全体で可能ですが、コードをテストするには1つ以上のプロダクト
が設定されている必要があります。
●
●
アプリケーションバンドルまたは独自のサーバからプロダクトIDのリストを取得します。
SKProductsRequestのインスタンスを使用して、そのリストをApp Storeに送信します。
App Storeから返されたSKProductのインスタンスを使用して、App Store向けのユーザインタフェー
スを実装します。最初はテーブルビューや少数のボタンなどの単純なインタフェースから開発を
始めましょう。
開発プロセスの適切な段階で、App Store向けの最終ユーザインタフェースを実装します。
●
SKPaymentQueueのaddPayment:メソッドを使用してSKPaymentのインスタンスをトランザクショ
ンキューに追加することで、支払いを要求します。
●
paymentQueue:updatedTransactions:メソッドからトランザクションキューのオブザーバを実
装します。
開発プロセスの適切な段階で、SKPaymentTransactionObserverプロトコルの他のメソッドを実
装します。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
44
アプリケーション審査の準備
実装におけるチェックリスト
●
購入したプロダクトを配信するには、アプリケーションの今後の起動に備えて購入記録を持続
し、関連するコンテンツをダウンロードした後、SKPaymentQueueのfinishTransaction:メソッ
ドを呼び出します。
開発では、最初にこのコードの簡易版(たとえば、画面に「プロダクト配信済み」と表示するも
の)を実装できます。その後、開発プロセスの適切な段階で実際のコードを実装します。
アプリケーションで非消耗型プロダクトや自動更新購読、非更新購読を販売する場合、次の復元ロ
ジックが実装されていることを確認してください。
●
復元プロセスを開始するためのUIを提供します。
●
SKReceiptRefreshRequestクラスを使用してAppレシートを更新するか、SKPaymentQueueクラ
スのrestoreCompletedTransactionsメソッドを使用して完了したトランザクションを復元する
ことで、過去の購入情報を取得します。
●
ユーザがコンテンツを再ダウンロードするようにします。
Appleによってホストされたコンテンツを使用している場合、完了したトランザクションを復元
し、トラン策ザクションのdownloadsプロパティを使用してSKDownloadのインスタンスを取得し
ます。
独自のコンテンツを使用している場合、独自のサーバに対して適切な呼び出しを実行します。
アプリケーションで自動更新購読または非更新購読を販売する場合、次の購読ロジックが実装されて
いることを確認してください。
●
最新の発行済みコンテンツ(雑誌の最新号など)を配信することで、新しく購入した購読を処理し
ます。
●
新規コンテンツが発行された場合、ユーザが参照できるようにします。
●
購読の有効期限が切れた場合、ユーザが更新するようにします。
アプリケーションで自動更新購読を販売する場合、App Storeがこのプロセスを処理します。アプ
リケーションで処理しないようにしてください。
アプリケーションで非更新購読を販売する場合、アプリケーションでこのプロセスを処理しま
す。
●
●
購読が無効になった時点で、新規コンテンツの提供を停止します。購読を再度有効にして購入す
るオプションがユーザに表示されるよう、インタフェースを更新します。
コンテンツが発行された場合に追跡するためのシステムを実装します。購入を復元する際には、
このシステムを使用して、購読がアクティブだった期間に基づき、ユーザが支払い済みのコンテ
ンツにアクセスできるようにします。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
45
書類の改訂履歴
この表は「In-App Purchaseプログラミングガイド 」の改訂履歴です。
日付
メモ
2015-10-21
SKProductRequestのインスタンスを保持することに関する情報を追
加しました。
2013-10-22
プロダクトの配信に関する説明を拡張しました。復元に関する章を
追加しました。全体を通して細かな変更を行いました。
“支払いの要求” (20 ページ) にapplicationUsername プロパティ
の説明を追加しました。“プロダクトの配信” (23 ページ) で、購
入の持続およびコンテンツのダウンロードに関する説明を拡張しま
した。“購入したプロダクトの復元” (40 ページ) の章を追加しま
した。“アプリケーション審査の準備” (43 ページ) に実装チェッ
クリストを追加しました。
2013-09-18
全体的に内容を拡張しわかりやすくしました。
レシートの検証に関する情報は、『Receipt Validation Programming
Guide 』に移動されました。
2012-09-19
expires_dateキーは復元されたトランザクションには存在しないと
いう注意が削除されました。
復元されたトランザクションのexpires_dateきーについては、自動
更新購読のベストプラクティスで簡単に触れられています。自動更
新行動の復元についてのセクションを削除しました。
2012-02-16
プラットフォームをまたがる使い方を反映するよう図版を作り直し
ました。コードから非推奨になったメソッドを削除しました。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
46
書類の改訂履歴
日付
メモ
「アプリケーションへのStoreの追加」で、非推奨になった
paymentWithProductIdentifier: メソッドを
paymentWithProduct: メソッドで置き換えました。
2012-01-09
OS Xにおけるこの技術の活用に関して細かな改訂を行いました。
2011-10-12
概要の項に新しいタイプの購入方法に関する情報を追加しました。
2011-06-06
本書の OS X向けの初版。
2011-05-26
自動更新購読に関して、最新のサーバの振る舞いに合わせて修正し
ました。
2011-03-08
更新可能な定期購読の章でキーのリストを訂正しました。
2011-02-15
アプリケーションは購入情報の提出前に、必ず製品情報を取得する
必要があり、これによって製品が販売状態にあることを確認できる
旨を追加しました。更新可能な定期購読についての情報を追加しま
した。
2010-09-01
細かな編集を行いました。
2010-06-14
SKRequestについての説明を分かりやすくしました。
2010-01-20
JSONレシートオブジェクトの誤字を訂正しました。
2009-11-12
レシートデータはbase64でエンコードしてから検証サーバに渡す必
要があることを追加しました。その他の細かな更新を行いました。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
47
書類の改訂履歴
日付
メモ
2009-09-09
「はじめに」の章を改訂しました。レシートデータの使い方を明確
にしました。プロダクトメタデータの作成について推奨する主要な
情報源として、『iTunes Connect Developer Guide』を記載しました。
ドキュメント名を『Store Kit Programming Guide』から『In App
Purchase Programming Guide』に変更しました。
2009-06-12
Apple App Storeからのプロダクトの価格情報の取得に関する説明、
およびStoreでのレシートの確認に関する説明を追加しました。
2009-03-13
アプリケーションにStoreを実装するためのStoreKit APIの使用方法に
ついて説明した新規ドキュメント。
2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.
48
Apple Inc.
Copyright © 2015 Apple Inc.
All rights reserved.
本書の一部あるいは全部を Apple Inc. から書
面による事前の許諾を得ることなく複写複製
(コピー)することを禁じます。また、製品
に付属のソフトウェアは同梱のソフトウェア
使用許諾契約書に記載の条件のもとでお使い
ください。書類を個人で使用する場合に限り
1 台のコンピュータに保管すること、またそ
の書類にアップルの著作権表示が含まれる限
り、個人的な利用を目的に書類を複製するこ
とを認めます。
Apple ロゴは、米国その他の国で登録された
Apple Inc. の商標です。
キーボードから入力可能な Apple ロゴについ
ても、これを Apple Inc. からの書面による事
前の許諾なしに商業的な目的で使用すると、
連邦および州の商標法および不正競争防止法
違反となる場合があります。
本書に記載されているテクノロジーに関して
は、明示または黙示を問わず、使用を許諾し
ません。 本書に記載されているテクノロジー
に関するすべての知的財産権は、Apple Inc.
が保有しています。 本書は、Apple ブランド
のコンピュータ用のアプリケーション開発に
使用を限定します。
本書には正確な情報を記載するように努めま
した。 ただし、誤植や制作上の誤記がないこ
とを保証するものではありません。
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
U.S.A.
Apple Japan
〒106-6140 東京都港区六本木 6
丁目10番1号 六本木ヒルズ
http://www.apple.com/jp
Offline copy. Trademarks go here.
Apple Inc. は本書の内容を確認しておりますが、本
書に関して、明示的であるか黙示的であるかを問わ
ず、その品質、正確さ、市場性、または特定の目的
に対する適合性に関して何らかの保証または表明を
行うものではありません。その結果、本書は「現状
有姿のまま」提供され、本書の品質または正確さに
関連して発生するすべての損害は、購入者であるお
客様が負うものとします。
いかなる場合も、Apple Inc. は、本書の内容に含ま
れる瑕疵または不正確さによって生じる直接的、間
接的、特殊的、偶発的、または結果的損害に対する
賠償請求には一切応じません。そのような損害の可
能性があらかじめ指摘されている場合においても同
様です。
上記の損害に対する保証および救済は、口頭や書面
によるか、または明示的や黙示的であるかを問わ
ず、唯一のものであり、その他一切の保証にかわる
ものです。 Apple Inc. の販売店、代理店、または従
業員には、この保証に関する規定に何らかの変更、
拡張、または追加を加える権限は与えられていませ
ん。
一部の国や地域では、黙示あるいは偶発的または結
果的損害に対する賠償の免責または制限が認められ
ていないため、上記の制限や免責がお客様に適用さ
れない場合があります。 この保証はお客様に特定
の法的権利を与え、地域によってはその他の権利が
お客様に与えられる場合もあります。