in-app purchaseプログラミングガイド (tp40008267 0.0.0)

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

Upload: duongkhuong

Post on 02-Feb-2017

252 views

Category:

Documents


13 download

TRANSCRIPT

Page 1: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

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

Page 2: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

目次

In-App Purchaseについて 5はじめに 6

iTunes Connectでプロダクトを作成し、設定する 6App Storeでアプリケーションによってプロダクトを販売する 6購読に必要なアプリケーションロジックを追加する 7ユーザが購入したプロダクトを復元する 7アプリケーションとプロダクトを審査用に登録する 7

関連項目 7

アプリケーション内プロダクトのデザイン 8In-App Purchaseを使用して販売可能なもの 8iTunes 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

プロダクトの配信 23App Storeがトランザクションを処理するのを待機する 23

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

2

Page 3: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

購入の持続 26Appレシートを使用した持続 27User DefaultsまたはiCloudを使用した値の持続 27User DefaultsまたはiCloudを使用したレシートの持続 27独自のサーバを使用した持続 28

アプリケーションの機能のアンロック 28関連コンテンツの配信 29ローカルコンテンツのロード 30ホストしたコンテンツのAppleのサーバからのダウンロード 30独自サーバからのコンテンツのダウンロード 32

トランザクションの終了 32推奨されるテスト手順 33支払い要求のテスト 33オブザーバコードの検証 34成功したトランザクションのテスト 34中断したトランザクションのテスト 34トランザクションが終了したことの確認 34

購読の取り扱い 35購読の有効期間の計算 35期限切れと更新 37キャンセル 37プラットフォームをまたがる場合の考慮事項 38ユーザーによる購読管理 38テスト環境 38

購入したプロダクトの復元 40Appレシートの更新 41完了したトランザクションの復元 41

アプリケーション審査の準備 43プロダクトを審査用に登録する 43テスト環境のレシート 43実装におけるチェックリスト 44

書類の改訂履歴 46

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

3

目次

Page 4: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

図、表、リスト

In-App Purchaseについて 5図 I-1 購入プロセスの各段階 6

アプリケーション内プロダクトのデザイン 8表 1-1 プロダクトのタイプによる比較 10表 1-2 購読のタイプによる比較 11

プロダクト情報の取得 12図 2-1 購入プロセスの各段階—ストアUIの表示 12表 2-1 プロダクトIDを取得する方法の比較 12リスト 2-1 サーバからのプロダクトIDのフェッチ 14リスト 2-2 プロダクト情報の取得 15リスト 2-3 プロダクト価格のフォーマット 17

支払いの要求 20図 3-1 購入プロセスの各段階—支払いの要求 20リスト 3-1 支払い要求の作成 20リスト 3-2 アプリケーションのユーザ名の提供 21

プロダクトの配信 23図 4-1 購入プロセスの各段階—プロダクトの配信 23表 4-1 トランザクションの状態と対応するアクション 24リスト 4-1 トランザクションキューのオブザーバの登録 24リスト 4-2 トランザクションの状態への応答 25リスト 4-3 ダウンロード済みコンテンツのバックアップからの除外 31

購読の取り扱い 35図 5-1 購読タイムラインの例 35表 5-1 購読例のタイムライン 35

アプリケーション審査の準備 43図 7-1 開発、審査、本番の各環境 43

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

4

Page 5: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

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について

Page 6: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

はじめに図 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 ページ)を参照)。開発をスムーズに行うために、開始前にチェックリスト全体に目を通すとよいでしょう。

In-App Purchaseについてはじめに

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

6

Page 7: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

関連する章: “プロダクト情報の取得” (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』では、レシート、特にアプリケーション内での購入に成功した記録について説明されています。

In-App Purchaseについて関連項目

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

7

Page 8: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

ここでプロダクトとは、アプリケーション内ストアで販売するものを指しています。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

アプリケーション内プロダクトのデザイン

Page 9: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

In-App Purchaseを使用して提供できるものの詳細については、ライセンス契約およびApp ReviewGuidelineを参照してください。コーディングを始める前にこのガイドラインを注意深く検討しておくと、審査期間中の遅れや拒否を回避できることがあります。特定のケースにおいてガイドラインの説明が不十分である場合は、オンライン連絡フォームを使用して、App Reviewチームに具体的な質問を行うことができます。

アプリケーションで販売するプロダクトにどのような物があるのかを知ったうえで、In-App Purchaseでそのプロダクトを販売するのが適切であると判断した場合は、iTunes Connectでプロダクトを作成する必要があります。

iTunes Connectでのプロダクトの作成コーディングを始める前に、アプリケーションと連携するプロダクトについて、iTunes Connectで設定する必要があります。アプリケーションの開発状況に応じて、プロダクトを追加したり削除したりすることができ、また既存のプロダクトの改善や再設定を行うことができます。

各プロダクトは特定のアプリケーションに関連づけられています。あるアプリケーションのために開発されたプロダクトを、他のアプリケーションから使うことはできません。別のプラットフォームで動作するコンパニオンアプリケーションは、独立した(別個の)アプリケーションと考えます。したがって、Macアプリケーション用のプロダクトをiOSアプリケーションから使う(あるいはその逆)、といったこともできません。

プロダクトはアプリケーションを登録するときに、アプリケーションの審査プロセスの一部として審査されます。ユーザがプロダクトを購入できるようになるには、プロダクトがあらかじめ審査者によって承認されている必要があり、またiTunes Connectでプロダクトを“cleared for sale”(購入可能)としてマークしておく必要があります。

iTunes Connectでプロダクトを取り扱う具体的な手順については、『In-AppPurchaseConfigurationGuidefor iTunes Connect』を参照してください。

プロダクトのタイププロダクトタイプごとに異なるプロダクト動作を提供することで、アプリケーションの範囲でIn-AppPurchaseを使用できます。iTunes Connectでは、次のプロダクトのタイプから1つを選択します。

● 消耗型(Consumable)プロダクト。アプリケーションの実行に伴って消費されていく項目です。Voice over IPアプリケーションで通信できる残り分数や、音声の転送など一度限りのサービスが例として挙げられます。

アプリケーション内プロダクトのデザインiTunes Connectでのプロダクトの作成

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

9

Page 10: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

● 非消耗型(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

Page 11: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

表 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

Page 12: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

購入プロセスの最初の段階では、アプリケーションが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

プロダクト情報の取得

Page 13: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

アプリケーションのプロダクトリストが、広告の削除や機能の有効化など固定されている場合は、アプリケーションバンドルにリストを埋め込みます。追加のレベルやキャラクターをサポートするゲームのように、プロダクト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ファイルをサーバ上でホストします。以下に例を挙げます。

[

プロダクト情報の取得プロダクトIDのリストの取得

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

13

Page 14: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

"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

});

});

}

プロダクト情報の取得プロダクトIDのリストの取得

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

14

Page 15: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

NSURLConnectionを使用したファイルのダウンロードの詳細については、『URL Loading SystemProgramming 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:[NSSetsetWithArray: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

Page 16: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

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をデザインできるのは、アプリケーションとそのコンテンツを熟知しているアプリケーションの作成者だけです。

プロダクト情報の取得アプリケーションのストアUIの表示

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

16

Page 17: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

アプリケーションのストア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];

プロダクト情報の取得アプリケーションのストアUIの表示

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

17

Page 18: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

[numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];

[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];

[numberFormatter setLocale:product.priceLocale];

NSString *formattedPrice = [numberFormatter stringFromNumber:product.price];

ユーザによる購入するプロダクトの選択後、アプリケーションはプロダクトの支払いを要求するためにApp Storeに接続します。

推奨されるテスト手順正しく実装されていることを検証するために、コードの各部分をテストします。

テスト用アカウントによるApp Storeへのサインイン「テスト用ユーザアカウントの生成 in iTunesConnectDeveloperGuide」の説明に従って、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

Page 19: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

プロダクト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

Page 20: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

購入プロセスの第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

支払いの要求

Page 21: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

異常アクティビティの検知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

Page 22: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

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

Page 23: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

購入プロセスの最後の段階では、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

プロダクトの配信

Page 24: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

アプリケーションの起動時に、トランザクションキューのオブザーバを登録します(リスト 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 トランザクションの状態と対応するアクション

アプリケーションで実行するアクション状態

進捗している状態を反映するようにUIを更新し、再び呼び出されるのを待機します。

SKPaymentTransaction-StatePurchasing

遅延している状態を反映するようにUIを更新し、再び呼び出されるのを待機します。

SKPaymentTransaction-StateDeferred

errorプロパティの値を使用して、ユーザーにメッセージを表示します。エラーを表す定数については、『Store KitConstants Reference』のSKErrorDomainに関する項に一覧が載っています。

SKPaymentTransaction-StateFailed

プロダクトの配信App Storeがトランザクションを処理するのを待機する

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

24

Page 25: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

アプリケーションで実行するアクション状態

購入した機能を提供します。SKPaymentTransaction-StatePurchased

以前に購入した機能を復元します。SKPaymentTransaction-StateRestored

リスト 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;

}

}

プロダクトの配信App Storeがトランザクションを処理するのを待機する

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

25

Page 26: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

}

待機中にユーザインターフェイスを最新の状態に保つには、トランザクションキューのオブザーバは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 andRestoration” 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

Page 27: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

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

Page 28: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

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

Page 29: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

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

Page 30: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

してもらうことができます。アプリケーションバンドルにハードコーディングされているのではなく、アプリケーションが独自のサーバからプロダクトリストを取得する場合、コンテンツの追加やアプリケーションによってダウンロードされたコンテンツの更新のためにアプリケーションを再登録する必要はありません。

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

Page 31: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

そのコンテンツをダウンロードするには、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

Page 32: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

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

Page 33: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

トランザクションを終了する前には、次のアクションをすべて完了してください。

● 購入の持続

● 関連コンテンツのダウンロード

● ユーザがプロダクトにアクセスできるためのアプリケーション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

Page 34: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

オブザーバコードの検証トランザクションオブザーバの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

Page 35: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

購読を使用するアプリケーションについては、追加の動作と考慮事項があります。購読には時間の要素が組み込まれているため、アプリケーションには購読が現在有効であるかどうかと、サブスクリプションが有効だったのが過去のどの期間であったのかを判断する適切なロジックが備わっている必要があります。アプリケーションは新規の購読と購読の更新にも対応し、また期限切れの購読も適切に処理する必要があります。図 5-1に、アプリケーションで処理する必要のある複雑な部分も含めた、購読のタイムラインの例を示します。

図 5-1 購読タイムラインの例

購読の有効期間の計算アプリケーションでは、購読が有効な期間に基づいて、ユーザがアクセスできるコンテンツを決定する必要があります。たとえば、表 5-1に示すタイムラインに従い、毎月初日に最新号が出る雑誌を購読する、という状況を考えてみましょう。

表 5-1 購読例のタイムライン

イベント日付

2月号発売。まだ購読を始めていないので提供しない(購読開始後に提供)。2月1日

購読を開始(期間は1か月)。最新である2月号をすぐに提供する。2月20日

3月号発売。購読中なのですぐに提供する。3月1日

購読の自動更新(1か月)。3月20日

4月号発売。購読中なのですぐに提供する。4月1日

ユーザーが購読の更新を取りやめ、購読期間が終了。4月20日

5月号発売。購読期間が終了しているので提供しない。5月1日

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

35

購読の取り扱い

Page 36: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

イベント日付

6月号発売。購読期間が終了しているので、この時点では提供しない(再び購読を開始した後に提供)。

6月1日

ユーザーが再び購読を開始。6月号をすぐに提供する。6月17日

7月号発売。購読中なのですぐに提供する。7月1日

このロジックをアプリケーションに実装するには、各コンテンツが発行された日付を記録しておきます。各レシートエントリの「Original Purchase Date」および「Subscription Expiration Date」フィールドを確認し、購読の開始日と終了日を特定します。(レシートについては『ReceiptValidationProgrammingGuideを参照)。ユーザーは、購読を購入した時点で最初にアンロックされたコンテンツに加えて、購読期間の各開始日と各終了日の間に発行されたすべてのコンテンツにアクセスすることができます。購読が失効した場合、購読がアクティブな期間が複数あることになり、購読期間の開始時にコンテンツがアンロックされます。

注意: 購入日に購読期間を加えて購読期間を計算しないでください。このやり方では、無料トライアル期間、マーケティング目的の期間、およびユーザーが購読を購入した直後にコンテンツが利用可能になる点が考慮されていません。

たとえば、購読を開始すればロックが解除されるので、月刊誌を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

Page 37: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

期限切れと更新更新プロセスは、期限切れの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

Page 38: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

購入がキャンセルされたかどうかをチェックするには、レシートの「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

Page 39: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

更新と期限切れの頻度が増しているために、購読期間に短い間隔を残したまま、システムが購読の更新を実行しようとする前に、購読が期限切れになる場合があります。本番環境でも、このような間隔が生じるのには多くの理由があります。アプリケーションでこれらを正しく処理できることを確認してください。

購読の取り扱いテスト環境

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

39

Page 40: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

ユーザは購入済みのコンテンツに引き続きアクセスするためにトランザクションを復元します。たとえば、新しい携帯電話にアップグレードする場合、古い携帯電話で購入したアイテムはいずれも失われません。「Restore Purchases」ボタンなど、ユーザが購入を復元できる仕組みをアプリケーションに組み込んでください。購入の復元では、ユーザのApp Storeクレデンシャルが求められ、アプリケーションのフローが中断されます。そのため、(特にアプリケーションが起動されるたびに)購入が自動的に復元されるようにはしないでください。

ほとんどの場合、アプリケーションで必要な処理は、レシートの更新とレシートに含まれるプロダクトの配信のみです。更新されたレシートには、このデバイスまたはほかのデバイス上においてユーザがこのアプリケーションで行った購入記録が含まれています。ただし、アプリケーションによっては、次のような理由から別の方法を取る必要があります。

● Appleによってホストされているコンテンツを使用している場合、完了したトランザクションを復元すると、コンテンツをダウンロードするためのトランザクションオブジェクトがアプリケーションに与えられます。

● アプリケーションのレシートが使用できない、iOS 7より前のiOSバージョンをサポートする必要がある場合、完了したトランザクションを復元してください。

● アプリケーションが非更新購読を使用する場合、アプリケーションで復元プロセスを処理します。

レシートを更新すると、App Storeにレシートの最新コピーが要求されます。レシートを更新しても、新しいトランザクションは作成されません。何度も続けて更新することは避けるべきですが、この操作は1回だけ更新するのと同じ結果をもたらします。

完了したトランザクションを復元すると、ユーザが完了したトランザクションごとに新しいトランザクションが作成され、トランザクションキューのオブザーバの履歴が再現されます。トランザクション復元中、アプリケーションは完了したトランザクションを復元している理由と処理方法を把握するために状態を維持します。何度も復元すると、完了したトランザクションごとに復元したトランザクションが複数作成されます。

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

40

購入したプロダクトの復元

Page 41: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

注意: ユーザーがアプリケーションの復元インタフェースを使用する代わりに購入済みのプロダクトを購入しようとすると、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プロパティがあり、レシートのエントリには「OriginalTransaction Identifier」フィールドがあります。

購入したプロダクトの復元Appレシートの更新

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

41

Page 42: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

注意: 復元された購入では、日付フィールドの意味が多少異なります。詳細については、『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

Page 43: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

テストが終了すると、アプリケーションを審査のために登録する準備が整ったことになります。この章では、審査プロセスについてのいくつかのヒントに焦点を当てます。

プロダクトを審査用に登録するアプリケーションを初めて審査のために登録する場合は、同時に審査を受けるためにアプリケーション内プロダクトも登録する必要があります。最初の登録後は、審査のためのアプリケーションおよびプロダクトに対する更新の登録をそれぞれ独自に行うことができます。詳細については、『In-AppPurchase Configuration Guide for iTunes Connect』を参照してください。

テスト環境のレシート図 7-1に示すように、アプリケーションは、開発、審査、および本番の各段階において異なる環境で実行されます。

図 7-1 開発、審査、本番の各環境

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

43

アプリケーション審査の準備

Page 44: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

開発の段階では、ユーザは開発用として署名されたバージョンのアプリケーションを実行します。このアプリケーションはユーザのテスト用サーバと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

Page 45: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

● 購入したプロダクトを配信するには、アプリケーションの今後の起動に備えて購入記録を持続し、関連するコンテンツをダウンロードした後、SKPaymentQueueのfinishTransaction:メソッドを呼び出します。

開発では、最初にこのコードの簡易版(たとえば、画面に「プロダクト配信済み」と表示するもの)を実装できます。その後、開発プロセスの適切な段階で実際のコードを実装します。

アプリケーションで非消耗型プロダクトや自動更新購読、非更新購読を販売する場合、次の復元ロジックが実装されていることを確認してください。

● 復元プロセスを開始するためのUIを提供します。

● SKReceiptRefreshRequestクラスを使用してAppレシートを更新するか、SKPaymentQueueクラスのrestoreCompletedTransactionsメソッドを使用して完了したトランザクションを復元することで、過去の購入情報を取得します。

● ユーザがコンテンツを再ダウンロードするようにします。

Appleによってホストされたコンテンツを使用している場合、完了したトランザクションを復元し、トラン策ザクションのdownloadsプロパティを使用してSKDownloadのインスタンスを取得します。

独自のコンテンツを使用している場合、独自のサーバに対して適切な呼び出しを実行します。

アプリケーションで自動更新購読または非更新購読を販売する場合、次の購読ロジックが実装されていることを確認してください。

● 最新の発行済みコンテンツ(雑誌の最新号など)を配信することで、新しく購入した購読を処理します。

● 新規コンテンツが発行された場合、ユーザが参照できるようにします。

● 購読の有効期限が切れた場合、ユーザが更新するようにします。

アプリケーションで自動更新購読を販売する場合、App Storeがこのプロセスを処理します。アプリケーションで処理しないようにしてください。

アプリケーションで非更新購読を販売する場合、アプリケーションでこのプロセスを処理します。

● 購読が無効になった時点で、新規コンテンツの提供を停止します。購読を再度有効にして購入するオプションがユーザに表示されるよう、インタフェースを更新します。

● コンテンツが発行された場合に追跡するためのシステムを実装します。購入を復元する際には、このシステムを使用して、購読がアクティブだった期間に基づき、ユーザが支払い済みのコンテンツにアクセスできるようにします。

アプリケーション審査の準備実装におけるチェックリスト

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

45

Page 46: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

この表は「In-App Purchaseプログラミングガイド」の改訂履歴です。

メモ日付

SKProductRequestのインスタンスを保持することに関する情報を追加しました。

2015-10-21

プロダクトの配信に関する説明を拡張しました。復元に関する章を追加しました。全体を通して細かな変更を行いました。

2013-10-22

“支払いの要求” (20 ページ) にapplicationUsername プロパティの説明を追加しました。“プロダクトの配信” (23 ページ) で、購入の持続およびコンテンツのダウンロードに関する説明を拡張しました。“購入したプロダクトの復元” (40 ページ) の章を追加しました。“アプリケーション審査の準備” (43 ページ) に実装チェックリストを追加しました。

全体的に内容を拡張しわかりやすくしました。2013-09-18

レシートの検証に関する情報は、『Receipt Validation ProgrammingGuide 』に移動されました。

expires_dateキーは復元されたトランザクションには存在しないという注意が削除されました。

2012-09-19

復元されたトランザクションのexpires_dateきーについては、自動更新購読のベストプラクティスで簡単に触れられています。自動更新行動の復元についてのセクションを削除しました。

プラットフォームをまたがる使い方を反映するよう図版を作り直しました。コードから非推奨になったメソッドを削除しました。

2012-02-16

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

46

書類の改訂履歴

Page 47: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

メモ日付

「アプリケーションへのStoreの追加」で、非推奨になったpaymentWithProductIdentifier: メソッドをpaymentWithProduct: メソッドで置き換えました。

OS Xにおけるこの技術の活用に関して細かな改訂を行いました。2012-01-09

概要の項に新しいタイプの購入方法に関する情報を追加しました。2011-10-12

本書の OS X向けの初版。2011-06-06

自動更新購読に関して、最新のサーバの振る舞いに合わせて修正しました。

2011-05-26

更新可能な定期購読の章でキーのリストを訂正しました。2011-03-08

アプリケーションは購入情報の提出前に、必ず製品情報を取得する必要があり、これによって製品が販売状態にあることを確認できる旨を追加しました。更新可能な定期購読についての情報を追加しました。

2011-02-15

細かな編集を行いました。2010-09-01

SKRequestについての説明を分かりやすくしました。2010-06-14

JSONレシートオブジェクトの誤字を訂正しました。2010-01-20

レシートデータはbase64でエンコードしてから検証サーバに渡す必要があることを追加しました。その他の細かな更新を行いました。

2009-11-12

書類の改訂履歴

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

47

Page 48: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

メモ日付

「はじめに」の章を改訂しました。レシートデータの使い方を明確にしました。プロダクトメタデータの作成について推奨する主要な情報源として、『iTunes Connect Developer Guide』を記載しました。ドキュメント名を『Store Kit Programming Guide』から『In AppPurchase Programming Guide』に変更しました。

2009-09-09

Apple App Storeからのプロダクトの価格情報の取得に関する説明、およびStoreでのレシートの確認に関する説明を追加しました。

2009-06-12

アプリケーションにStoreを実装するためのStoreKit APIの使用方法について説明した新規ドキュメント。

2009-03-13

書類の改訂履歴

2015-10-21 | Copyright © 2015 Apple Inc. All Rights Reserved.

48

Page 49: In-App Purchaseプログラミングガイド (TP40008267 0.0.0)

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 LoopCupertino, CA 95014U.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. の販売店、代理店、または従業員には、この保証に関する規定に何らかの変更、拡張、または追加を加える権限は与えられていません。一部の国や地域では、黙示あるいは偶発的または結果的損害に対する賠償の免責または制限が認められていないため、上記の制限や免責がお客様に適用されない場合があります。 この保証はお客様に特定

の法的権利を与え、地域によってはその他の権利がお客様に与えられる場合もあります。