はじめに
こんにちは。Product Unit SINIS for Instagram開発チーム在籍のヒロシマと申します。 先日Stripeの月末決済が一日後ろにズレてしまう現象が発生し、 その対策をしたのでお話します。
Stripeとは?
弊社の事業であるSINIS for Instagramでは決済インフラにStripeを用いています。 Stripeとはインターネット決済インフラで、 オンライン決済処理、サブスクリプション管理、インボイス作成などを Web上で完結することができるプラットフォームです。 https://stripe.com/jp
なお、このたびお話することはサブスクリプションの事例になります。
何が起こったのか?
主題の件です。 サポートチームから問い合わせで 「1日課金で決済履歴が同月に2回(1日と31日)決済履歴が作成されていることがあります」 と連絡が来ました。
Stripeのダッシュボードを確認すると、、、
なんと。11月30日に作成されてほしいサブスクリプションが12月1日で作成されているではありませんか。
なぜ決済が一日後ろにズレたのか?
Stripeのサポートに問い合わせました。
原因
サブスクリプションの作成が、UTCタイムゾーン(以下UTC)で処理されているのが原因でした。
例)
- 2023年8月31日00:00JSTにサブスクリプション作成
- 実際には内部ではUTCで処理されていて2023年8月30日15:00UTCにサブスクリプション作成のリクエストが送信されている。 (JSTはUTCより9時間進んでいます)
時系列の一例も下記に記載します。
・2023年08月31日00:00JST(2023年8月30日15:00UTC)にサブスクリプションが作成 ・2023年10月01日00:00JSTに請求(2023年10月01日UTC15:00UTC(9月には31日がないため翌月初に決済が繰越)) ・2023年10月31日00:00JSTに請求(2023年10月30日UTC15:00UTC) … ・2024年01月31日00:00JSTに請求(2024年1月30日15:00UTC) ・2024年03月01日00:00JSTに請求予定(2024年2月29日15:00UTC(2月は最大29日までしかないので翌月初に決済が繰越))
StripeはUTCの月末に課金をすると自動で月末判定をしてくれるのですが、 30日しかない月は翌月初にサブスクリプションが作成されるというわけです。
どのようにして対策したか
こちらもStripeのサポートの回答になるのですが、 月末のサブスクリプション開始時刻を9:00〜23:59に設定する必要があります。 プログラミングでそれを実現するには、 サブスクリプション開始日まで無料トライアルを設定することです。
無料トライアルが終了するタイミングで自動でサブスクリプションが作成されるので、 無料と課金が切り替わるタイミングで開発者がなにかする必要はありません。
下記は実装の一例になります。
<?php $subscribeCreateDate = CarbonImmutable::now(); if ($this->月末で月ズレ発生の判定メソッド($subscribeCreateDate)) { $params['trial_end'] = $this->generateTrialEnd($subscribeCreateDate); }
最後に
海外のサービスを利用する際は、処理が走る時刻のタイムゾーンも加味して実装しなければならない気付きになりました。
(日本でStripe使っている企業はどこもこれをやっているのか、、、)
テテマーチでは、一緒にサービスを作り上げてくれる仲間を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください! herp.careers
エンジニアチームガイドはこちら! tetemarche01.notion.site