アプリ内課金でのリジェクトを防ぐためのチェック事項2015


開発着手前、開発中、申請前で確認するためのメモです。


# そもそも

まず、ここが、はじまりです。
様々なドキュメントのポータルになってます。

* [In-App Purchase for Developer](https://developer.apple.com/in-app-purchase/)


# 実装方法に関して


Appleのドキュメント

* [In-App Purchaseプログラミングガイド](https://developer.apple.com/jp/documentation/StoreKitGuide.pdf)

Qiitaでの記事

* [アプリ内課金アイテムの情報(SKProduct)を取得する](http://qiita.com/sora/items/9116a12dcaed27ba27e1)

* [アプリ内課金(Delegateモデル)](http://qiita.com/sora/items/e65ed31493a2d9b8f1dd)

#チェック事項

(1)コンテンツが規約に違反していないか
(2)プロダクトのタイプが適切か
(3)復元(リストア)機能が実装されているか
(4)仮想通貨を実装する場合、期限をもうけていないか、他アプリに引き継いでないか。
(5)レシートレシートベリファイが含まれる場合、Sandboxレシートを扱えるようになっているか
(6)課金場所がわかりやすい場所にあるか
(7)iTunesConnectの登録情報に問題がないか
(8)iTunesConnectの”メモ”に説明があるか
(9)iTunesConnectのアプリ紹介文に説明があるか

## (1)コンテンツが規約に違反していないか

そもそもですw
アプリ内課金で販売可能なコンテンツである必要があります。
下記ドキュメントの条件を満たしている必要があります。

* [App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/#purchasing-currencies)
* [iTunes Connect In-App Purchase 設定ガイド](https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnectInAppPurchase_Guide_Jpn/Chapters/CreatingInAppPurchaseProducts.html)
* [In-App Purchaseプログラミングガイド](https://developer.apple.com/jp/documentation/StoreKitGuide.pdf)

必要箇所をピックアップし、かつ、肉付けしています。


#### **<販売可能なもの>**

* コンテンツ：雑誌、写真、アートワーク、仮想通貨などのデジタルコンテンツです。
* アプリケーションの機能：広告非表示、ゲームステージ解放などです。
* サービス：音声の転送などの1回限りのサービス、またはデータのコレクションへのアクセスなどの継続するサービス

#### **<販売不可のもの>**

* 実物の商品やサービス
* 不適切なコンテンツ：[App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/#purchasing-currencies)で許可されていないものはNGです。<br>例えば、<br>- アプリ外部で使用される物理的な商品、サービス<br>(これはクレジットカードなど、アプリ内課金以外のロジックで実装する必要があります)<br>- カメラやジャイロスコープなどの、iOSが提供する組み込みの機能<br>- 限られた時間後に期限が切れる”レンタル”のコンテンツやサービス<br>など

## (2)プロダクトのタイプが適切か
 [In-App Purchaseプログラミングガイド](https://developer.apple.com/jp/documentation/StoreKitGuide.pdf)から抜粋+肉付けです。


* **消耗型（Consumable）プロダクト**<br>何度でも課金できます。1度使ったら無効になったり減ったりするようなものに使います。<br>(例)<br>- アプリ内で使える仮想通貨<br>- 促進剤(アプリ内で進化時間を減少させるために使用)。栄養ドリンクとか<br>- 釣りアプリケーションの餌<br>- Voice over IPアプリケーションで通信できる残り分数<br>- 音声の転送など一度限りのサービス<br><br>
* **非消耗型（Non-consumable）プロダクト**<br>1度だけ課金できます。使っても無効になったり減ったりしないサービスに使用します。<br>(例)<br>- 書籍やゲームレベル解放<br>- アプリ内広告非表示　<br>- アプリケーションの追加機能<br>- カメラレンズやオーディオエフェクトなどのプロの機能へのアクセス<br>- ずっと提供される購読など<br><br>
* **自動更新購読（Auto-renewable subscriptions）**<br>所定の期間に、雑誌の購読など、動的なコンテンツを購入できます。購読はユーザがオプトアウトしない限り自動的に更新されます。<br>(例)<br>- 動的なデジタルコンテンツ<br>- 新聞や雑誌の定期的配信<br>- オーディオやビデオのストリーミングフィードの月間課金<br>- 出会い系サービスに毎週メンバーシップ(←英文を日本語訳ができない・・)<br>- ビジネスアプリでのクラウドストレージサービスの提供<br><br>
* **非更新購読（Non-renewable subscriptions）**<br>期間を限定した項目を販売します。時間ベースで静的コンテンツにアクセスできる製品に使用します。<br>(例)<br>- 歴史的な写真のデータベースに対するアクセス権<br>- フライトマップのコレクション<br>- 一定期間ナビゲーションアプリ内でのガイダンス機能の提供<br>- アーカイブされたビデオやオーディオのオンラインカタログへの年間サブスクリプション。<br><br>
* **無料購読（Free subscriptions）**<br>Newsstandに無料購読のコンテンツを置くための手段です。サイ
ンアップしたユーザは、Apple IDに関連付けられたどのデバイスからでも購読できます。期限切
れになることはありません。また、購読にはNewsstand対応アプリケーションが必要です。<br><br>

自動更新購読のコンテンツは、運用してる感を演出することが大事と思います。

消費型と非消費型の部分に関して、
一見すると消費型と思えるような課金アイテム名を非消費型にする場合注意が必要です。
例えば、「コンティニュー」という機能があったとします。
一見これは、消費型と思えるかもしれないですが、
一度買ったら何回でもコンティニューできるという機能という意味で非消費型に設定することもあると思います。
そういった場合、iTunesConnectの"メモ"欄に説明を記載することをオススメします。


## (3)復元(リストア)機能が実装されているか

リストアの定義は
「ユーザのApple IDに関連付けられているすべてのデバイスにコンテンツを提供する」
ってことです。

リストアは、プロダクトタイプに応じて実装が必須なものとそうでないものがあります。
詳しくは、下記にまとまってます。(英語ですが・・)
[Getting Started with In-App Purchase on iOS and OS X]
(https://developer.apple.com/in-app-purchase/In-App-Purchase-Guidelines.pdf)

なお、リストアが必要な場合、必ず**復元プロセスを開始するためのUIを提供する**必要があります。
「購入復元」「リストア」などのボタンです。なければリジェクトされてしまいます。

| プロダクトタイプ | リストアが必要か | リストア実装方法|
|:--------------|:--------------:|:-------------|
|消耗型(Consumable)　　　　　　　　|No|独自でサーバを用意して実装
|非消耗型(Non-Consumable) |YES|Store KitのrestoreCompletedTransactionsメソッドを利用※
|自動更新購読(Auto-Renewing)|YES|Store KitのrestoreCompletedTransactionsメソッドを利用※
|非更新購読(Non-Renewing)|YES|iCloudか独自サーバーで実装<br>(ユーザを一意に特定する必要あり。すごく面倒)
|無料購読(Free Subscriptions)|YES|Store KitのrestoreCompletedTransactionsメソッドを利用※

※別のドキュメントでは、
SKReceiptRefreshRequestクラスを使用してAppレシートを更新するか(iOS7からの方法)
SKPaymentQueueクラスのrestoreCompletedTransactionsメソッドを使用するか(従来からある方法)
と書かれています。リジェクトが怖いので、restoreCompletedTransactionsしか使ったことがありません・・・。


iCloudの復元機能実装はKey-Value Storeでがオススメです。
実装がシンプルでNSUserDefaultと同じ使い方ができます。
([iCloud設計ガイド](https://developer.apple.com/jp/documentation/iCloudDesignGuide.pdf))


非更新購読って、、リストア必須で、しかもその為のAPIをAppleが提供してくれないのですごく面倒です(汗


## (4)仮想通貨を実装する場合、期限をもうけていないか、他アプリに引き継いでないか。

よくありがちなのは、「仮想通貨の有効期限を設定している」とかです。
これは規約的にNGとなるため、有効期限を与えてはいけません。
（仮想通貨ではないですが、購読でもないのに、コンテンツの表示期間を設けるのはNGです。）

また、アプリ内課金で買ったものはそのアプリ内で使わなくてはなりません。
Andoridに引き継いだりするのは規約的にまずいはず、、、なんですが、
やっているアプリはあるので、グレーな感じ、、、、です。なんとも言えません。。
が、安全に過ごしたいなら、アプリ内だけに止めるのが良いと思います。


ちなみに、関係ありませんが、最近GooglePlayでも、
アプリ内仮想通貨をアプリ内以外で使ってはならないといった規約が追加されました。
この辺り、は両プラットフォームで今後厳しくなってくるのではと、個人的に思っております。

## (5)レシートベリファイが含まれる場合、Sandboxレシートを扱えるようになっているか

AppStoreのレシートベリファイのためのAPIを提供しています。
このAPIには本番APIとSandboxAPIの2種類あり、
Sandbox環境で発生したレシートは本番APIでベリファイするとエラー、
本番環境で発生したレシートはSandboxAPIでベリファイするとエラーになります。

なので、アプリ申請時に使用するAPIをSandboxAPI→本番APIに切り替えればいいかと思いますが、それは間違いです。

理由は、発行されるレシートが下記のようになるからです。

| 環境 | レシート種別 |
|:--------------|:--------------:|
| 開発時|　Sandbox　|
| 審査(In Review)時|　Sandbox　|
| 本番時|　本番　|

審査時はSandboxレシートがくるんです、、、、、。
なので、常にSandboxレシート、本番レシートどちらが来ても大丈夫なように実装しておく必要があります。
そのための方法として下記方法をAppleが提案しています。

[Adding In-App Purchase to your iOS and OS X Applications] (https://developer.apple.com/library/ios/technotes/tn2259/_index.html)より一部抜粋
> Always verify your receipt for auto-renewable subscriptions first with the production URL; proceed to verify with the sandbox URL if you receive a 21007 status code. Following this approach ensures that you do not have to switch between URLs while your application is being tested or reviewed in the sandbox or is live in the App Store.

>Note: The 21007 status code indicates that this receipt is a sandbox receipt, but it was sent to the production service for verification.

つまり、

1. 本番APIでベリファイ
2. ステータスコード”21007”が来たらSandBoxAPIでベリファイ

としておけば、Sandboxレシート、本番レシートどちらが来ても大丈夫です。

## (6)課金場所がわかりやすい場所にあるか

「課金する場所がわからない」というリジェクト対策です。

・・・・レビュワーも人間ですからね（汗

「ショップ」などわかりやすい表現のボタン、画面を設けることでリジェクトリスクを軽減できると思います。
加えて、iTunesConnectの”メモ”に課金画面への遷移方法を記載すれば、開発側の人間としてやれるべき最善を尽くしたことになると思いますw

## (7)iTunesConnectの登録情報に問題がないか

課金の設定部分です。
表示名、説明、審査用のスクリーンショットなどのメタデータがきちんとした内容のものかを確認します。

* [iTunes Connect In-App Purchase 設定ガイド - In-App Purchaseのメタデータのプロパティ]
(https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnectInAppPurchase_Guide_Jpn/Appendices/InAppPurchaseProperties.html)

特に私がいつも注意してみているのは、

* 表示名 ：　ユーザーに表示される名前です。ユーザー&Apple審査用
* 説明　：　プログラム方法次第ではユーザーに表示される部分です。ユーザー&Apple審査用
* 審査用のスクリーンショット　：ユーザには表示されません。Apple審査用

スクリーンショットは、適当なものでも通ることはあるんですが、念のため、ちゃんと課金画面のスクリーンショットを載せることをオススメします。

## (8)iTunesConnectの”メモ”に説明があるか

この”メモ”欄への記載は任意です。
が、個人的にかなりオススメの欄です。
リジェクト理由で多いのは「情報不足」です。
それは、この”メモ”欄である程度防げている・・・気がします。
最近Appleもやたら質問が多いように感じます、、、。
それだけで審査期間が延びるのは時間がもったいないですよね。

なお、記載する情報としては、

* どんなプロダクトタイプの課金アイテムが入っているか
* なぜそのプロダクトタイプに設定しているか(常識では想像できないようなタイプ設定の場合のみ)
* 独自のルールがある場合はその説明(◯◯の理由で購入の上限を設けている、など)
* 課金画面への導線(1タップ単位で)<br> 1. App Launced. <br> 2."購入"button tap. ・・・・

ですが、細かすぎるので、最低限「課金画面への導線」があれば心強いです。

## (9)iTunesConnectのアプリ紹介文に説明があるか

> 3.13 – Apps with screenshots, previews, and marketing text that do not clearly identify supplemental content or items that must be purchased separately (e.g. using IAP) will be rejected

これの対策です、アプリ内課金があるなら、説明文に記載が必要です。

# 最後に

これだけ見ても、
課金処理後にコンテンツが提供されなかったら、、、、リジェクトです。
デバッグはしっかりするべきですね＾＾

こちらにデバッグ時のポイントも書いてくれてます。

* [In-App Purchaseプログラミングガイド](https://developer.apple.com/jp/documentation/StoreKitGuide.pdf)




長くまとまりがなくてすみません、、
ちょくちょく、見直して追加したり修正したり、、整形していきたいと思います。

*6/28 早速ですが、(9)を追加しました。