目的

2021年1月13日時点での情報です。
AppleはサイトやツールのUIを頻繁に変更するので手順が異なる場合がありますので、ご注意ください。

SwiftyStoreKitは利用しません。

環境

  • Xcode Version 12.3
  • Swift 5
  • iOSアプリはiTunesConnectに登録済とする




参照サイト

課金アイテムについて

今回は一番最安値の120円の **消耗型(一度利用すると無くなるアイテム)*+ をアプリに実行していきたいと思います。





iTunes Connectでの対応

iTunes Connect(App Store Connect)
にアクセス後、マイAppを選択後、対象のアプリを選択。
アプリの詳細画面の左ペインより管理を選択。

画面内の+ボタンをクリックします。
一番最初の App 内課金は、App の新しいバージョンと一緒に提出する必要があります。

課金アイテムの種類を選択(今回は消耗型)後、作成をクリック

新しい App 内課金画面が表示されて、結構設定が必要なようです。
参照名はApp Store Connectおよび「売上とトレンド」のレポートで使用されます。App Storeには表示されません。名前は最大で64文字です。
レポートに使用される固有な英数字のID。ある製品に対して使用した製品IDは、その製品が削除されても再度使用することはできません。
承認後に App Store に App 内課金コンテンツを表示するには、チェックボックスを選択します。

価格の項目で価格を選択します。

残りの以下の設定も行います。

AppStore情報の項目
ローカライズも設定できます。
App Store に表示される App 内課金の名前です。
App 内課金の設定によっては、この説明はカスタマーにも表示される場合があります。

AppStoreプロモーションの項目
こちらはオプションということで設定しませんでした。
App StoreでこのApp内課金のプロモーションをする

審査に関する情報項目
スクショとメモを設定します。
後で変えられるので準備していない場合は適当に。
スクリーンショットは課金アイテムが表示されている画面とか。
メモは課金画面への遷移を記載しました。
スクリーンショットは審査の目的においてのみ使用します。App Store に表示されることはありません。 iOS では、少なくとも 640 x 920 ピクセルが必要です。 審査に役立つ App 内課金に関する追加情報。

設定後、画面右上の保存ボタンをクリックで以下のように、送信準備完了になりました。






Xcodeでの対応

次にXcodeでの作業です。
アプリのTARGETSを選択し、Signing & Capabilitiesを選択後、Capabilityボタンをクリック

ポップアップよりIn-App Purchaseを選択

プログラムについては、 Apple Developer Offering, Completing, and Restoring In-App Purchases
にサンプルがあるのでそれを利用しました。
サンプルのはMac用とかのも含まれているので注意。
StoreObserver.swiftStoreManager.swiftあと共通関数のとかメッセージの所を持ってくれば良いかなと。

SwiftyStoreKitという便利なライブラリもあるようだが、時間があるならライブラリに頼らず、課金の仕組みを知っておいたほうが良いと思いました。

課金処理が成功すると、レシートというものをアプリ内で受け取ります。
それを運営サーバに送って、今度はサーバからAppleサーバにレシートを送って整合性を確認します。
こうすることで課金購入の整合性ととって、偽装などに対応できるということ。
後述のレシートについても参照

SKProductのpriceLocaleは、テストユーザなどで支払画面に行くまでは、ずっと「USD」で返ってくる。
テストユーザがJPで支払画面にいくと「JPY」になる。

テストユーザの作成

App Store Connect
にアクセス後、ユーザとアクセスをクリック

ユーザとアクセス画面のSandbox項目よりテスターを選択。

画面上の+ボタンをクリックして、テストユーザを作成する。





レシートについて

課金処理をすると、Appleサーバとレシートの検証を行う。
Appleサーバにレシートを送る際のURLは、環境によって異なるので注意。

Appleサーバ
本番:https://buy.itunes.apple.com/verifyReceipt
開発:https://sandbox.itunes.apple.com/verifyReceipt

消費アイテムの場合は、receipt-dataを送るだけで良い。
passwordは不要。←は定期購読とかで必要のよう。

AppleサーバへのAPIだが、環境ごとに分けるのではなく、まず本番と通信するようにする。
テストユーザでの課金の場合、Appleサーバからの返り値でstatus21007となるので、
そこでさらに開発環境へAPIを投げる方式が良いらしい。(Appleドキュメントに記載されていた)

レシートが問題ない場合、status0で返ってくる。
それ以外の項目としては以下となる。
重要そうなところのみ抜粋

レシート
"receipt":{
    ...
    "bundle_id":"xxxx",
    ...
    "receipt_creation_date":"2021-01-17 03:58:27 Etc/GMT",
    "receipt_creation_date_ms":"1610855907000",
    ...
    "in_app":[{
        "quantity":"1",
        "product_id":"yyyy",
        "transaction_id":"9000000766037499",
        "original_transaction_id":"9000000766037499",
        "purchase_date":"2021-01-17 03:58:26 Etc/GMT",
        "purchase_date_ms":"1610855906000",
        ...
    }]},
    "environment":"Sandbox",
    "status":0
}

参照項目にあるApple Developer original_transaction_idページによると、
product_idriginal_transaction_idexpires_date_mspurchase_date_msは保存したほうが良いらしい。
個人的には今回の場合、
まずbundle_idstatusをチェックして整合性を確認。
DBには
product_idquantityoriginal_transaction_idpurchase_datepurchase_date_msenvironmentstatus を保存しようと思いました。
ドキュメントにある、expires_date_msの項目はありませんでした。

定期購読アイテムなどはあるのかもしれないが、
このアプリではそういうアイテムは今後も売らないので無視。

transaction_idoriginal_transaction_idは基本的には同じ値なのですが、 定期購読アイテムやリストアしたアイテムの場合は値が異なるとのこと
リストアされるのは、非消費アイテムということで(購入者だけの特別メニューとか。)、そのアイテムも今の所実装する目処ないので、不要かなと。

審査

iTunes Connect上で登録した課金アイテムが準備完了となっていること。
そして、XcodeよりアプリをArchiveする。
バイナリを送ったら、次にiTunes Connectにて、申請用のアプリバージョンを作成する。
作ったアプリを選択すると、ページ右ペインの中頃にApp内課金の項目が増えている。


Select In-App Purchasesを選択。

今回作成した課金アイテムを選択する。

App内課金の項目にアイテムが追加される。
Purchase用にバイナリを送るなんてことは無かった。

そして、アプリのバイナリも追加したり、その他もいつもの審査通りに設定後、
画面右上の審査へ提出ボタンをタップする。
そしてら、レビュー待ちとなる。
課金アイテムも審査待ち状態となっていることを確認。

審査開始はその2日後に行われ、審査時間はいつもどおり数時間でした
なにか指摘があると思ったのですが、特に何もなく審査通りましたね。
サーバのログも無く、Apple側ではテストはしていないように見受けられました。

以上です。