最近気づいたんだけど、iOSで使われるアプリ内課金(In-App Purchase)では複数の課金をしてもそれぞれにレシートのバイナリができるわけではなく、複数まとめて1つのバイナリになっている。
もしかしたら同じような勘違いをしている人もいるかもしれない。そうするとサンプルコードが全然違って見えるよという話です。
Appleの公式リファレンスであるレシート検証プログラミングガイド PDFによるとレシートの構造はこんな感じらしい。
(ちなみにこの図のタイトルはレシートの構造のはずなのに後続と訳されていた)
iOS7より前ではtransactionReceiptがNSDataで取得できるので、アイテムごとにレシートが作られているのかと思っていた。コードとしては次のような感じ
//このメソッドはオリジナルで
- (void)finishTransaction:(SKPaymentTransaction *)transaction
{
//iOS6など
//NSData *receiptData = transaction.transactionDate; //非推奨になった
//iOS7から
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
//...ここでレシートの検証やコンテンツの適用などを行う...//
}
iOS7のやり方ではローカルの場所をURLとして取得するだけで、その場所はトランザクションごとに変わっているわけでもない。うちの実機だと下記のような場所がURLとなる。
file:///var/mobile/Applications/<何かのUUID>/StoreKit/receipt
おそらくiOS7からレシートのバイナリが一つになったわけではないんだろうけど、iOS6以前はtransactionに対してレシートデータが取得できるおかげで変な勘違いをしていた。
ただ、iOS7からレシートはappStoreReceiptURLメソッドで取得できるので、ローカル検証したいときなど特にSKPaymentTransaction経由で取得しなくて良くなったよってことなんだろう(おそらくローカル検証自体もiOS7より前でも出来る、はず)。
日本語に訳されたドキュメントを読んでもイマイチぴんとこなかったんだけど、プロパティを非推奨にしてくれたおかげで勘違いから解放された。