Apple Hosted in-App-Purchaseについて
こんにちは、いちかわです。
前回のエントリで少し書いたサンプルをgithubに公開しました。
注)
最低限の目的を達成するだけのものなので、レシートの検証とか、大事なことが色々抜けています。
あくまで参考程度として見てもらえればと思います。
サンプルアプリは、
- プロダクトの一覧
- プロダクトの詳細
の2つの画面で構成されています。
1.プロダクト一覧
iTunes Connectに登録したプロダクトIDの一覧を取得するようなAPIが見当たらなかったので、プロダクトの情報をplistに登録してその内容を表示することで画面を作成しています。
随時プロダクトが追加されるようなアプリの場合、プロダクト一覧をサーバから配信するようにしないと、コンテンツが増えるたびにアプリのアップデートが必要になりそうですね。
2.プロダクト詳細
一覧で選択されたプロダクトの情報を、AppStoreから取得して表示します。
「購入」ボタンをタプすると、購入処理が行われ、プロダクトをダウンロードして、画面の下部に表示します。
購入〜ダウンロードの流れ
1.購入の実行
「購入」ボタンをタップすると、SKPaymentQueueのaddPaymentで購入の手続きが開始されます。
1 2 3 4 5 6 |
// オブザーバ登録
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
// 購入リクエスト
SKPayment *payment = [SKPayment paymentWithProduct:<SKProduct>];
[[SKPaymentQueue defaultQueue] addPayment:payment]; |
2.購入トランザクションを取得する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
// 購入処理オブザーバ
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
// 購入成功
case SKPaymentTransactionStatePurchased: {
[self successPayment:transaction.payment.productIdentifier receipt:transaction.transactionReceipt];
if (transaction.downloads && transaction.downloads.count > 0) {
// コンテンツのダウンロード有り
[[SKPaymentQueue defaultQueue] startDownloads:transaction.downloads];
}
else {
[queue finishTransaction:transaction];
}
break;
}
// 購入失敗(キャンセル含む)
case SKPaymentTransactionStateFailed: {
[self failedPayment:transaction];
[queue finishTransaction:transaction];
break;
}
// 購入履歴復元
case SKPaymentTransactionStateRestored: {
if (transaction.downloads && transaction.downloads.count > 0) {
// コンテンツのダウンロード有り
[self restoreItem:transaction.payment.productIdentifier receipt:transaction.transactionReceipt];
[[SKPaymentQueue defaultQueue] startDownloads:transaction.downloads];
}
else {
[queue finishTransaction:transaction];
}
break;
}
}
}
} |
transactionStateが SKPaymentTransactionStatePurchased(購入成功)となったら、トランザクションのdownloadプロパティにダウンロード可能なプロダクトの情報が含まれているので、13行目のSKPaymentQueueのstartDownloadsメソッドに情報を渡してダウンロードを実行します。
3.ダウンロードの状況を取得
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
- (void)paymentQueue:(SKPaymentQueue *)queue updatedDownloads:(NSArray *)downloads
{
for (SKDownload *downloadItem in downloads) {
switch (downloadItem.downloadState) {
case SKDownloadStateWaiting: {
NSLog(@"Download is inactive, waiting to be downloaded");
break;
}
case SKDownloadStateActive: {
NSLog(@"Download progress:%f", downloadItem.progress);
NSLog(@"Download timeRemaining:%f", downloadItem.timeRemaining);
break;
}
case SKDownloadStatePaused: {
NSLog(@"Download was paused by the user");
break;
}
case SKDownloadStateFinished: {
// ダウンロード完了を通知
[self downloadFinished:[downloadItem.contentURL path]];
[queue finishTransaction:downloadItem.transaction];
break;
}
case SKDownloadStateFailed: {
NSLog(@"error:%@", [downloadItem.error localizedDescription]);
break;
}
case SKDownloadStateCancelled: {
NSLog(@"Download was cancelled");
break;
}
}
}
} |
ダウンロード中はdownloadStateが SKDownloadStateActiveの状態ですので、進捗状況などをSKDownloadのprogressやtimeRemainingプロパティーから取得して、呼び出し元のデリゲートに渡してあげれば、プログレスバーの表示に使えます。
4.ダウンロードしたコンテンツを取得
ダウンロードが完了すると、downloadStateはSKDownloadStateFinishedとなり、SKDownloadのcontentURLにダウンロードされたプロダクトのパスが取得できます。
この時プロダクトがダウンロードされる先は「/Library/Caches」になります。
Cache直下に作成される上記の0E6966〜の部分は同じコンテンツをダウンロードしても毎回変わるようです。
また、ディレクトリ名が~.zipになっていて、最初はzip形式なのかと騙されてしまった。。実際は展開済みとなっています。
ちなみに、プロダクト用のプロジェクトを作成した際に、ファイルの格納先を変えていたのですが、ダウンロードされたパッケージはすべてContentsの中に含まれるようです。
(それらしいドキュメントは見当たらないですが、試してみた限りでは)
こんな感じで、Appleに預けたコンテンツは取得できます。
すごく簡単です。。。
- 2012年09月24日
- iPad, iPhone, Samurai Purchase, SamuraiSmartphoneServices