iOS定期購読課金 アップグレード/ダウングレード Part2

iOS定期購読課金のアップグレード/ダウングレードの仕様についてPart2です。
サーバ側でアップグレード/ダウングレードしたのかをどうやって判断するのかについてのまとめとなります。
Part1はこちら :arrow_right: [iOS定期購読課金 アップグレード/ダウングレード Part1](https://qiita.com/natty420/items/b7cc167406813e9a3c00)

# サーバ側での課金状態取得

レシート検証を行い、レシートからなにが行われたのかを見ます。
https://developer.apple.com/jp/documentation/General/ValidateAppStoreReceipt/Introduction.html#//apple_ref/doc/uid/TP40010573-CH105-SW1

レシート検証についてはこちらの記事がとてもわかりやすくて参考にしました。
[Apple月額課金について【Productionレシート】](https://qiita.com/econa77/items/1f653ff6e0ab151a6eae)

#### 前提知識
レシート検証した場合、取得できるレシートは<font color="Pink">指定アプリケーションで今まで購入したものすべてのレシート</font>です。つまり、Aを購読しBにアップグレードした場合などは両方のレシートが取得できます。また更新毎にレシートは発行されます。

結果取得できるレシートデータの一部は以下の通りです。
公式ドキュメントは[こちら](https://developer.apple.com/jp/documentation/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1)

注目すべきはlatest_receipt_infoとpending_renewal_infoです。
receipt-data(base64エンコードを施したレシートデータ)をつかってレシートを取得しますが、
latest_receipt_infoにはこれまで購入したすべてのレシートデータが入っています。in_appにはreceipt-dataに対するレシートのみ入っています。

##### latest_receipt_info
|Key       |詳細      |
|:-----------|:------------|
|product_id           |購入したアイテムのproductId     |
|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|purchase_date           |購入日もしくは更新された日。(GTM)     |
|expires_date           |有効期限が切れる日。(GTM)     |

##### pending_renewal_info
|Key       |詳細      |
|:-----------|:------------|
| auto_renew_product_id  |購入状態の優先されるproductId|
| product_id  |購入したアイテムのプロダクトID。有効期限切れの場合もある。最後に購入したproductId。|
| original_transaction_id  |Appleアカウントで一意となる購入ID|
| auto_renew_status  |自動更新型購読について現在の更新ステータス|“1” - 現購読期間の最終日に更新される。つまり自動更新はONになっている。<br>“0” - 顧客が購読の自動更新をオフにした。次は更新されない。|
| expiration_intent  |購読期限切れの理由<br><font color="red">※期限切れの場合のみ</font>|“1” - 顧客が購読をキャンセルした<br>“2” - 課金エラー; 顧客の支払い情報が有効でなくなったなど<br>“3” - 顧客が値上げに同意しなかった<br>“4” - 更新の時点でプロダクトが購入できる状態でなかった<br>“5” - 原因不明のエラー。
| is_in_billing_retry_period  |期限切れになった購読についてAppleがなお自動更新を試みているか否か<br><font color="red">※期限切れの場合のみ</font>|“1” - App Storeは購読更新を試みている<br>“0” - App Storeは購読更新の試みをしていない|


## アップグレード/ダウングレードかどうかを見極めるには

|レベル      |アイテム      |期間　　　　　　|
|:-----------|------------:|:------------:|
|1           |アイテムA     |1ヶ月 　　　　　|
|2           |アイテムB     |1ヶ月 　　　　　|

アイテムA→Bがダウングレード、B→Aがアップグレードです。
[iOS定期購読課金のレシートに追加された「pending_renewal_info」をみてみる](https://qiita.com/natty420/items/530de949455fdb41caf4) を使います。

### アップグレード(アイテムBからAに変更した場合)
:one: Bを4/1に登録すると、次の更新日は5/1となる。
このときレシート検証して得られるレシートは以下となる

##### latest_receipt_info
|レシート       |Key       |詳細      |
|:-----------|:-----------|:------------|
|1|product_id           |アイテムBのproductId     |
|1|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|1|purchase_date           |4/1     |
|1|expires_date           |5/1     |

##### pending_renewal_info
|Key       |詳細      |
|:-----------|:------------|
|auto_renew_product_id           |アイテムBのproductId     |
|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|product_id           |アイテムBのproductId     |
|auto_renew_status           |“1” - 自動更新ON状態     |

:two: 4/10にAに乗り換える。この時点でAに変更となる。次の更新日は5/20となる。
このときレシート検証して得られるレシートは以下となる

##### latest_receipt_info(2つのレシートとなります)
|レシート       |Key       |詳細      |
|:-----------|:-----------|:------------|
|1|product_id           |アイテムBのproductId     |
|1|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|1|purchase_date           |4/1     |
|1|expires_date           |5/1     |
|2|product_id           |アイテムAのproductId     |
|2|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|2|purchase_date           |4/10     |
|2|expires_date           |5/10     |

##### pending_renewal_info(変更あり)
|Key       |詳細      |
|:-----------|:------------|
|auto_renew_product_id           |<font color="Red">アイテムAのproductId</font>     |
|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|product_id           |<font color="Red">アイテムAのproductId</font>     |
|auto_renew_status           |“1” - 自動更新ON状態     |

現在購読中である商品を確認する場合はpending_renewal_info.product_idをみればよい。またその購読が有効かどうかはpending_renewal_info.expiration_intentがないことを確認すればよさそう。
またアップグレードしたかについては、レシートの状態(latest_receipt_info)を確認することとなる。
2つのレシートが存在しているが、これを購入日(purchase_date)でソートする。
次に有効期限内かどうかを確認する。ここで有効期限内なレシートは2つとなる。今現在有効な商品はpending_renewal_info.product_idのAとなるため、BからAに変更したことがわかる。アップグレードは即座、ダウングレードは現在購読中のものの有効期限がきれるときにきりかわる仕様なのでアップグレードとわかる。
また、サーバ側で保持しているデータと合わせてみてもよさそうです。
サーバ側で保持している現在購読中の商品はBである。
レシート検証を行うとAになっていた。AとBのランクをみてアップグレードと判断する。

### ダウングレード(アイテムAからBに変更した場合)
:one: Aを4/1に登録すると、次の更新日は5/1となる。
このときレシート検証して得られるレシートは以下となる
##### latest_receipt_info
|レシート       |Key       |詳細      |
|:-----------|:-----------|:------------|
|1|product_id           |アイテムAのproductId     |
|1|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|1|purchase_date           |4/1     |
|1|expires_date           |5/1     |

##### pending_renewal_info
|Key       |詳細      |
|:-----------|:------------|
|auto_renew_product_id           |アイテムAのproductId     |
|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|product_id           |アイテムAのproductId     |
|auto_renew_status           |“1” - 自動更新ON状態     |

:two: 4/10にBに乗り換える。この時点ではまだAのままとなる。Aの有効期限日(5/1)にBに変更となる。
このときレシート検証して得られるレシートは以下となる

##### latest_receipt_info(なにも変わらない)
|レシート       |Key       |詳細      |
|:-----------|:-----------|:------------|
|1|product_id           |アイテムAのproductId     |
|1|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|1|purchase_date           |4/1     |
|1|expires_date           |5/1     |

##### pending_renewal_info(変更あり)
|Key       |詳細      |
|:-----------|:------------|
|auto_renew_product_id           |<font color="Red">アイテムBのproductId</font>     |
|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|product_id           |アイテムAのproductId     |
|auto_renew_status           |“1” - 自動更新ON状態     |

アップグレード時同様、現在購読中である商品を確認する場合はpending_renewal_info.product_idをみればよい。またその購読が有効かどうかはpending_renewal_info.expiration_intentがないことを確認すればよさそう。
またダウングレードしたかについては、pending_renewal_info.auto_renew_product_idで確認ができる。
購読中商品はAだが、次に予定されている商品はBであることから判断ができそう。
しかしこれはあくまで予約されているだけなので、設定画面等で自動更新をOFFにするとBに変更されることはないので注意。

:three: 5/1にレシート検証してみる。Bに変更となる。

##### latest_receipt_info(2つのレシートとなります)
|レシート       |Key       |詳細      |
|:-----------|:-----------|:------------|
|1|product_id           |アイテムAのproductId     |
|1|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|1|purchase_date           |4/1     |
|1|expires_date           |5/1     |
|2|product_id           |アイテムBのproductId     |
|2|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|2|purchase_date           |5/1     |
|2|expires_date           |6/1     |

##### pending_renewal_info(変更あり)
|Key       |詳細      |
|:-----------|:------------|
|auto_renew_product_id           |アイテムBのproductId     |
|original_transaction_id           |Appleアカウントで一意となる購入ID   |
|product_id           |<font color="Red">アイテムBのproductId</font>     |
|auto_renew_status           |“1” - 自動更新ON状態     |

現在購読中なのは、pending_renewal_info.product_idをみるとBに変わっている。
この時点でダウングレードかどうかをレシートだけで判断するのはなかなかむずかしそう。
サーバ側で保持しているデータと合わせてダウングレードかを判断するしかなさそうです。

サーバ側で保持している現在購読中の商品はAである。
レシート検証を行うとBになっていた。AとBのランクをみてダウングレードと判断する。

## まとめ

手探り感はありますがなんとか判断はできそうですね:sparkles:
Auto-renewable Subscriptionの購読ステータスの状態変更をサーバで受け取る機能などもあるようですがアップグレードかダウングレードかを判断する用途としては使えなさそうです。(レシート検証と変わらない)