In-app Billing APIのPurchaseの形式を調べた話

## Play Billing Libraryが3.xに
Play Billing Libraryが3.xがリリースされました。
Play Billing Libraryを利用することでAIDLファイルとサービスクラスを作成する手間なくIn-app Billing APIを利用できるようになり、非常に便利になりました。

## ところで、In-app Billing APIで購入をした際のレシートの形式が知りたい
Androidでアプリ内課金の実装をする場合、サーバーにレシートを送るAPIが必要です。
APIの実装のためにレシートの形式を把握する必要があり、実際にコードを書いて調べたので備忘録的にまとめておきます。

## 確認用のコード
今回の確認用のコードですが、以下のように `BillingClient.launchBillingFlow()`を実行して

```kotlin
val params = BillingFlowParams.newBuilder()
                        .setSkuDetails(details)
                        .build()
billingClient.launchBillingFlow(activity, params)
```

 `onPurchasesUpdated` で受け取った `Purchase` の構造をログに出力しました。

```kotlin
    override fun onPurchasesUpdated(billingResult: BillingResult, purchases: MutableList<Purchase>?) {
        when {
            billingResult.responseCode == BillingClient.BillingResponseCode.OK && !purchases.isNullOrEmpty() -> {
                // ここでPurchaseをログに出力
            }
            billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED -> {
                // user cancelled purchase
            }
            else -> {
                // error
            }
        }
    }
```

## 予約済みのproductIdを使った静的なレスポンス
In-app Billing APIにはテスト用に予約済みのアイテムIDとそれに対応する静的なレスポンスが設定されています。
構造はプロダクションと同じですが、各パラメータの中身についてはリアルな感じではないです。

```json
{
    "packageName": "your.package.name",
    "acknowledged": false,
    "orderId": "transactionId.android.test.purchased",
    "productId": "android.test.purchased",
    "developerPayload": "",
    "purchaseTime": 0,
    "purchaseState": 0,
    "purchaseToken": "inapp:your.package.name:android.test.purchased"
}
```
予約済みのアイテムIDの詳細は[公式のドキュメント](https://developer.android.com/google/play/billing/billing_testing?hl=ja)を参照してください:pray:

完全に余談ですが、テスト用の購入は１つのproductIdにつき１度実行すると、それ以降は `ITEM_ALREADY_OWNED` というエラーが発生します。これが起きないようにするためには、以下のコマンドを使ってGoogle Play Storeのキャッシュを削除して再度実行することが出来ます。

```
$ adb shell pm clear com.android.vending
```



## 実際のproductIdを使ったレスポンス
静的なレスポンスの内容がリアルな感じではなかったので、実際のproductIdをGoogle Play Consoleから登録して試してみます。（元のデータに変更を加えて記載しています。）

### Consumableの場合
```json
{
    "orderId": "GPA.0000-1234-5678-90000",
    "packageName": "your.package.name",
    "productId": "consumable",
    "purchaseTime": 1593597175681,
    "purchaseState": 0,
    "purchaseToken": "ocbmpajaaiigkcbmhdkoabcg.BO-J1OxQL832hkKZFhEEasaY8uJMeI7HQg2XLV5BVFAZK5e3lcchnuw4749PMTsA6PeBX-2PN7Sq5gpyl7qJYY1B2Oixfxfrck1oxbRFzO3cwz1NKIbqGB6-SR83wyNO29xVprXpl5Yw",
    "acknowledged": false
}

```

静的なレスポンスに存在した `developerPayload` は `obfuscatedAccountId`/ `obfuscatedProfileId` に変更されたようです。 `launchBillingFlow` を呼び出す際に使用する `BillingFlowParams` に追加することで、同じものがレスポンスにも追加されます。詳しくは[こちら](https://developer.android.com/google/play/billing/developer-payload?hl=ja)を参照してください。

### Subscriptionの場合
subscriptionの場合は `autoRenewing` が追加されるようですね。

```json
{
    "orderId": "GPA.3321-2766-9706-73593",
    "packageName": "your.package.name",
    "productId": "subscription",
    "purchaseTime": 1593599361267,
    "purchaseState": 0,
    "purchaseToken": "hkihoaiukokbicfiahkdkidk.BO-J1OzeRClCsDLfCASQmrTLKUHKz09R70QdDOZoiOtb4gxrlzo-v1GHxzuFOvCMPAtFFJQjV6tWrbQRjDO-feiG_Ue8Z38U-F9UIB5wYFbDrFA4MCUm4A3SgjiT7jYgFS4xX7vrdCBK",
    "autoRenewing": true,
    "acknowledged": false
}
```
## おわりに
こちらに書いたものは、現時点でこうだったという記録でしかないので、変更される可能性があります。
内容の不備等ありましたら、コメントで教えていただけると幸いです:bow: