mixi engineer blog

*** 引っ越しました。最新の情報はこちら → https://medium.com/mixi-developers *** ミクシィ・グループで、実際に開発に携わっているエンジニア達が執筆している公式ブログです。様々なサービスの開発や運用を行っていく際に得た技術情報から採用情報まで、有益な情報を幅広く取り扱っています。

【CREウィーク水曜日】サブスクリプションのちょっと危険でディープなお話

※こちらの記事は過去のブログから転載したものです。

こんにちは。XFLAG スタジオ CRE チームの上埜です。

 

XFLAG スタジオでは、スマホアプリ「モンスターストライク」(以下モンスト)内で「モンパス」という月額課金制の会員サービスを昨年2017年9月13日より開始しました。
モンパスは App Store, Google Play Store, Amazon Appstore の3つのプラットフォームで提供しており、会員サービスの購入・継続の処理はそれぞれのプラットフォームのサブスクリプション機能を利用して実装しています。

 

この記事では、プラットフォーム側から提供される契約情報が当初の想定と異なっており困ったケースがありましたので紹介したいと思います。

モンパスについて

モンパスの購入・継続の仕組み

モンパスの購入・継続時の実装について簡単に説明します。

f:id:mixi_PR:20210129155653p:plain
図1 : 購入フロー

購入時はクライアントが各プラットフォームのサーバに購入リクエストを送ります。購入OKであればレシート情報がプラットフォームのサーバから送られてきますので、クライアントはこれをモンストのサーバへと転送します。モンストのサーバでは送られてきたレシート情報に従ってモンパス会員権の有効化処理を行います。これは全プラットフォーム共通です(図1)。

 

継続時の処理はプラットフォームごとに異なります。

f:id:mixi_PR:20210129155807p:plain

図2 : 2ヶ月目以降の継続購入フロー(App Storeの場合)


App Storeでは、継続確認はクライアントが行います。クライアントはApp Storeサーバへ確認依頼を投げ、App Storeサーバは継続が行われていれば継続購入分のレシートを返します。以降は購入時と同じで、クライアントはレシート情報をモンストのサーバに投げ、モンストのサーバは受け取ったレシート情報に従ってモンパス会員権の有効期限を延長します(図2)。

f:id:mixi_PR:20210129160338p:plain

図3:2ヶ月目以降の継続購入フロー(Google Play Store・Amazon Appstoreの場合)

一方、Google Play Store・Amazon Appstoreでは、継続確認はモンストのサーバが行います(図3)。プラットフォーム側の継続更新が完了した頃合いを見計らってレシート情報を問い合わせ、購入が継続がされている場合はモンパス会員権の有効期限を延長します。

では、プラットフォーム側の継続更新が完了するのはいつでしょうか?プラットフォームの公式ドキュメントにはいつまでに契約更新が完了するかは明記されていません。そのため、モンパスにおいては契約終了日から2〜3日間 (契約終了の時間帯により変わります) を会員更新期間とし、この間に継続更新を試みることにしました。それでも継続が行われないケースについては、お客様からのお問い合わせ起点で対応できるようCS (Customer Support : カスタマーサポート)の体制を整えています。

モンパス継続によるインセンティブ

モンパスでは会員サービスの継続によるインセンティブを設けています。
継続インセンティブは1ヶ月毎、3ヶ月毎にあり(2018年3月14日現在)、どちらも購入日から指定期間以上契約を続けることが条件となります。例えば最初の1ヶ月の継続インセンティブは、モンパスを2018年3月1日0時に購入した場合では1ヶ月後の2018年4月1日0時まで契約を続けると受け取ることができます。

お問い合わせによって判明する契約日時の謎

お客様からのお問い合わせを直接対応するのはCSスタッフです。CSスタッフで解決できなかった問題はCREへ調査依頼として届けられます。

モンパスをリリースしてから1ヶ月半経った11月のある日、契約終了日が想定と異なるお客様がいらっしゃるということで、調査依頼が来ました。
これらのアカウントに共通しているのは購入日が10月1日、契約終了日が10月31日になっていることでした。利用されているプラットフォームはApp Store, Google Play Storeと異なります。

CREによる問い合わせ調査

実際にお客様のアカウントの契約終了日時がいつになっているか確認してみます。

  プラットフォーム 購入日時 契約終了日時
アカウントA App Store 2017-10-01 00:00:47 2017-10-31 00:00:47
アカウントB Google Play Store 2017-10-01 00:03:14 2017-10-31 02:03:04

公式ドキュメントには契約終了日はいつになると記載されているのでしょうか?
App Storeの公式ドキュメントには明記されていませんが、 Working with Subscriptions の契約例が記載された Table 6-1 を見ると

February 20 : User subscribes to a monthly subscription plan. The February issue is the most recent, and is made available immediately. March 20 : The user’s subscription automatically renews for another month. April 20 : The user cancels their subscription, thus ending the subscription period.

と書かれているので、購入日の翌月同日が契約終了日となりそうです。10月1日に購入したのであれば契約終了日は11月1日になると予想できます。

App Storeを利用している他のアカウントの契約情報も見てみましょう。

  プラットフォーム 購入日時 契約終了日時
アカウントC App Store 2017-10-01 18:09:20 2017-11-01 18:09:20

購入日時が同じ10月1日でも、契約終了日時が想定通り11月1日となるケースと、そうでないケースがあるようです。

勘の良い方はここで気づいたかもしれませんが、続けていきます。
ここまで記載した日時はすべて日本時間(JST)です。試しにアカウントAの購入情報を太平洋時間(PT)で見てみます

  プラットフォーム 購入日時 契約終了日時
アカウントA App Store 2017-10-01 00:00:47 JST 2017-10-31 00:00:47 JST
2017-09-30 08:00:47 PT 2017-10-30 08:00:47 PT

太平洋時間で考えると購入日時は9月30日で、契約終了日時は丁度1ヶ月後の10月30日になるので、ドキュメントどおりです。つまり、プラットフォーム側で契約期間を計算する基準となるタイムゾーンはそれぞれ独自に定義されており、サブスクリプションの提供国 (モンパスの場合は日本) の標準時とは異なるということです。
他のアカウントの契約情報をさらに詳細に調査した結果、 App Storeは太平洋時間を、Google Play Store・Amazon Appstoreは世界協定時間を利用していそうだということがわかりました。太平洋時間については、もちろんサマータイムを考慮する必要があります。

モンパス継続によるインセンティブへの影響

契約終了日が日本時間基準ではないとなると、モンパスにおいては継続インセンティブの配布に影響がでます。

f:id:mixi_PR:20210129160531p:plain

図4 : アカウントAの契約状況

アカウントAの場合、購入日時が 2017-10-01 00:00:47 JST 、契約終了日時が2017-10-31 00:00:47 JSTでした(図4)。
1ヶ月毎の継続インセンティブの受取条件は、購入日の1ヶ月後(2018-11-01 00:00:47 JST)まで契約を続けていることです。これは図4の例でいうと赤い矢印の長さが青い矢印の長さ以上になることと同義ですが、ご覧の通り受取条件を満たしていません。つまり、プラットフォーム上は1ヶ月間契約をしているのに、モンパスの1ヶ月毎のインセンティブを受け取ることができないというおかしな状況になっています。

 

この事実が発覚した2017年11月時点では1ヶ月毎の継続インセンティブは未実装で、3ヶ月毎の継続インセンティブしかありませんでした。また、不幸中の幸いで、まだリリース日から3ヶ月経っていなかったため、事前にインセンティブの判定処理に修正を入れることができ、事なきを得ました。

最後に

各プラットフォームで基準としているタイムゾーンの違いについて紹介しました。

 

プラットフォームの仕様についてはドキュメントが豊富にあります。開発環境も用意されていますので、動作テストも可能です。 しかし、ドキュメントで網羅されていない挙動も多くあることと、開発環境と本番環境で挙動が一部異なるケースがあることから、実際に本番環境で運用してみないとわからない部分が多々あります。

 

本記事で紹介したプラットフォーム毎のタイムゾーンの違いについても、公式ドキュメントには記載されていないところでした。
実際にサブスクリプション機能を実装・運用して得られた知見は (公式ではないのであくまで参考ではありますが) 貴重な情報で、有志の開発者によってブログやコミュニティ等様々な場で共有されています。本記事もサブスクリプション機能を利用する開発者の皆様の一助となれば幸いです。

 

明日3/15(木)は、田村より「ChatOpsによる解析基盤の運用改善とAWSクロスアカウント環境における実装例」を紹介いたします!