
UnityIAP subscription 対応時の備忘メモ
はじめに
リトルチャンピオンズ では、定期購読型(subscription)課金実装にUnityIAPを使用しました。
今回はその実装を行った際の知見を紹介したいと思います。
subscription以外の実装例については前回の記事 を参照ください。
また、サーバー側の実装についてはこちらの記事 を参照ください。
対象環境
- Unity 2017.2.1f1
- UnityIAP 1.15.0
ドキュメント
定期購読型課金 (Auto-Renewing subscription)とは
こうしたサービスやコンテンツは所定の期間で定期購読することができ、満期になると自動的に更新されます。購読期間は、週単位、月単位、四半期単位、年単位など、App によってさまざまです。定期購読によっては、トライアルを割引料金や無料で提供しているものがあります。
定期購読型の仕様
ストアで設定できる項目
iOS | Android | |
---|---|---|
価格 | 価格テーブルから選択(tierと異なる) | 税抜きで入力 |
期間 | 1週間/1ヶ月/2ヶ月/3ヶ月/6ヶ月/1年 | 1週間/1ヶ月/3ヶ月/6ヶ月/1年/”季節” |
お試し
(1度のみ無料や割引) |
期間
価格 都度払い/前払い/無料トライアル |
N日無料(3以上)
価格 |
グループ | 同グループ内の優先度設定
アップグレードやダウングレード、クロスグレードがある |
なし |
※ UnityIAPではお試しは未サポート
消費型と違うこと
- レシート
- 1度購入した商品はレシート内に残り続けます
- リストア
- 購入復元処理(リストア)
- 購入期間内であれば復元できなければならなりません(端末移行など)
- ゲーム内にリストアボタンを設置しなければなりません
- 購入復元処理(リストア)
- 自動更新
- 更新タイミングでプラットフォーム側が決済します
- アプリ起動中は購入トランザクションが通知されます
- 購入レシートからサーバからレシート検証すると更新分が含まれています
- アプリ起動待たずサーバから反映可能です
- 更新キャンセル
- ユーザがAppStore/GooglePlayからいつでも購読をキャンセル可能です
- キャンセルしても購読期間中は有効になります
- googleはcancelAPIからこちらからキャンセルできるっぽいです(未検証)
- レシート検証
- iOSはレシート検証に秘密鍵が必要になります
- 購入
- 同一プロダクトは購入中は購入できません
- 別グループのプロダクトは購入できます
- グループ内の優先度が高いプロダクトを購入する際はアップグレードになります
- 購入時、即時反映されます。以前購読中だったものは比例配分で返金されます
- 優先度が低いプロダクトを購入する際はダウングレードになります
- iOSは次回更新時に反映されます。それまでは購読中のものが引き続き有効になります
- Androidは即時反映されます
- 優先度が同じものの購入の場合はクロスグレードになります
- 同じ期間の場合、即時反映されます。期間が違う場合は次回更新時に反映されます
実装
購入
購入動線の制御
リトルチャンピオンズでは1つしか定期購読型のプロダクトが存在しなかったため
アップグレード等を考慮した実装まではしませんでしたが、
購入中は、購入動線があってもユーザが混乱するだけなので
アプリ側の購読中判定で購入動線を制御しました。
購入処理自体は消費型と変わりません。(参考:前回の記事)
更新
更新タイミング(決済後の反映)
- サーババッチ更新
- 1日1回、サーバで管理している購入時レシートを再度検証APIでプラットフォーム側に問い合わせ反映します
- 主にこの契機で反映を考えていたためゲーム内の有効期限は実際の期限より24時間ほどバッファを設けてました
- この契機で反映した場合、アプリ側から購入リクエストの際に反映済みのステータスコードを返却し裏でトランザクションを閉じています
- アプリ側からサーバに購入リクエスト
- 決済時にアプリ起動中などで1よりも先に反映する場合
- 通常の購入APIリクエストと同じくレシート情報付きでリクエスト
- ユーザがアプリ上から手動リストア
- 稀なケースだが1, 2にも引っかからなかった場合
以下呼び出すと未処理のトランザクションがIStoreListener経由で流れ始めます
すべてのトランザクションが流れ終った後、引数のActionが呼ばれます
_appleExtensions.RestoreTransactions(result =>
{
// リストア完了処理
});
検証環境(Sandbox)
Sandbox環境での自動購読型の注意点
- iOSは購読キャンセルができない
- 普段はAppStoreから購読のキャンセルを行いますが課金テストアカウントではAppStoreに入れないためキャンセルできません
- Androidは普通にGooglePlayからキャンセル可能
- 自動更新
- 6回の自動更新でその後キャンセルされます
- テストしていると購入後1回も更新されずキャンセルされているときがあります
- レシート内のauto_renew_statusで更新されるか確認できます
- 更新期間短縮
おまけ
レシート検証
レシート検証はよく使うので書いておきます
iOS
- ${Receipt} : base64エンコードを施したレシートデータ
- ${Secret} : App用共有シークレット(iTunesConnectから取得)
curl -H 'Content-Type:application/json' -i -X POST -d '{"receipt-data":"${Receipt}", "password":"${Secret}"}' https://sandbox.itunes.apple.com/verifyReceipt
Android
リフレッシュトークンを取得(1度のみ)
アクセストークンの取得
- ${RefreshToken} : 1で取得したもの
- ${ClientId} : Google API OAuth2のClientId
- ${ClientSecret} : Google API OAuth2のSecret
curl --data "refresh_token=${RefreshToken}" --data "client_id=${ClientId}" --data "client_secret=${ClientSecret}" --data "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token
------------------
{
"access_token": "xxxxxxxxxxxx",
"token_type": "Bearer",
"expires_in": 3600
}
レシート検証
- ${AppPackage} : アプリのパッケージ
- ${StoreProductId} : Google管理の商品ID
- ${Token} : base64化されたレシート文字列
- ${AccessToken} : 上で取得したアクセストークン
curl https://www.googleapis.com/androidpublisher/v2/applications/${AppPackage}/purchases/subscriptions/${StoreProductId}/tokens/${Token}?access_token=${AccessToken}
この記事へのコメントはありません。