In App Purchaseを実装するときにわかったこと

In App Purchaseにまつわることで気づいたこと

Test Account

テストするためには, Accountが必要ですが, 架空のメールアドレスでも問題なく作成, テストできます。
ほかの人とかぶらないようにMyドメインを使った方が無難そうです。

つまりアカウント作成には躊躇なく作成, 削除でいこう。

0円

Freeでもレシートを発行してもらえそうです。前にダメっていってた気がするんですけど, テストしてみたらうまくいった。
(2013/08/23)

購入処理を戻せない?

やっぱり戻せないっぽい。一回購入すると, もう購入したけどダウンロードする?という主旨のメッセージが来ます。

verifyReceiptに渡すデータ

レシートをverifyしてもらうときにリクエストを作る訳ですが。…
base64にエンコードした文字列を渡す, マニュアルにはbyteとありますが文字列です。jsonはbyteではなく文字列で渡します。

Restoreボタン

購入処理を戻す処理, ほかのデバイスで同じアカウントでコンテンツリストアをする場合, リストアが必要です。
プログラミングガイドによるとリストアボタンを別途用意しろとのこと。Backgroundで勝手にやるとか, 明示しないボタンだと
rejectされる模様。

Observer

SKPaymentTransactionObserver を実装したクラスを用意します。
AppDelegateの, application, つまりはじめに実装します。

self.pobserver = [[PurchaseObserver alloc] init];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self.pobserver];

アプリケーション終了時に, observerを止めておいた方が無難かも

- (void)applicationWillTerminate:(UIApplication *)application
{
    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self.pobserver];
}

アプリケーションライフサイクルに関わらず, SKPaymentさんは動作するようです。

Observerの実装

実装のフレームです

#pragma mark -
#pragma mark SKPaymentTransactionObserver
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
    
    // In case of restore, invokes multiple times
    for ( SKPaymentTransaction *transaction in transactions ) {
        switch ( transaction.transactionState ) {
            case SKPaymentTransactionStatePurchasing:
                // In process
                break;
            case SKPaymentTransactionStateFailed:
                // Fail and cancel
                break;
            case SKPaymentTransactionStateRestored:
                // Restore
                break;
            case SKPaymentTransactionStatePurchased:
                // Purchased
                break;
        }
    }
}

#pragma mark -
#pragma mark All Transaction done
-(void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions {
    // Done all transaction
}

#pragma mark -
#pragma mark All Restore done
-(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
    // Restore Complete
}

#pragma mark -
#pragma mark Failed restore
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
    // Failed Restore
}

処理がすべてのここのクラスにやってきますので, それぞれの処理に応じてコードを書いていけばよいです。
各処理の終了時には, 以下を呼び出します。呼び出さないと, 処理がSKPaymentQueueに溜まったままになってしまいます。

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

transactionは, (SKPaymentTransaction *)です。
処理をUIなどに伝達するには, NSNotificationCenter を使うのがよさそうです。

Reference
stackoverflow