試用期間が終わった翌日、ユーザーからLINEが来たとします。課金してくれているかどうか確認するためにStripeを開いて、スプレッドシートを開いて、手動でステータスを確認して、利用できる状態かどうかを判断する。1件ならまだいい。件数が増えると、毎回これをやる気にはなれません。
私が作っていたのは、LINEのチャットボットに無料の1週間お試しをつけて、その後サブスク登録した人だけ使い続けられる仕組みでした。最初は「期限が切れたらユーザーに通知すればいい」くらいに考えていたのですが、実際に設計してみると細かいところがいくつか詰まりました。
設計の骨格
やることを整理すると、3つだけです。
- ユーザーが初めて発言したとき、登録日を記録する
- 次の発言が来るたびに「登録日から7日以内か」を確認する
- 期限切れなら利用を止め、課金済みなら制限を解除する
書くとシンプルに見えますが、この「確認する」という部分をどこにどう置くかで、後の動きが変わります。
最初に詰まったところ
最初のバージョンはGASとスプレッドシートで作っていました。登録日をスプレッドシートの列に保存して、発言が来るたびに今日の日付と比較する構成です。AIへはこう頼みました。
試用期間のチェックを追加したい。ユーザーが初めて発言した日をスプレッドシートに記録して、7日を超えていたら「試用期間が終わりました」と返して処理を止めて。スプレッドシートの列名は日本語にして。
コードは動くものが返ってきたのですが、デプロイしてみるとスプレッドシートの初期化でエラーになりました。ログを見ると「スプレッドシートIDが無効、もしくはアクセス権限が不足している」という内容。IDは合っているはずなのに、です。
この手のエラーは、IDの打ち間違いと、スクリプトを動かしているアカウントからスプレッドシートにアクセスできていない(共有・権限の設定)の両方で出ます。どちらかを切り分けるために、設定したIDをログに出して確認し、スプレッドシートの共有設定を見直す、という地味な作業に時間を使いました。コードのロジックそのものより、こういう接続まわりで詰まることのほうが多い、というのが正直なところです。
日付の判定は、どこでやるか
このボットの会話部分はDify(チャットを生成する仕組み)に任せていました。最初は「期限が切れているかどうか」の判定も含めて全部チャット側に寄せようかと考えたのですが、結局、期限の計算はサーバー側(GAS)でやって、チャット側は判定済みの結果を受けて返答を変えるだけ、という分担に落ち着きました。
サーバー側で「登録日から7日を超えているか」「課金済みか」を判定し、利用できる・できないだけを決める。チャット側は、その結果に応じた文面を返す。役割を分けておくと、後から期限の長さを変えたり判定条件を足したりするときに、チャット側を触らずに済みます。
日付の計算や条件分岐のような「正解がひとつに決まる処理」は、できるだけサーバー側のコードに寄せておく。ここを曖昧にしておくと、後から動きを追いにくくなります。
課金済みかどうかの確認
期限切れのユーザーが課金したかどうかは、決済サービス(Stripe)に問い合わせて確認します。ユーザーのIDを渡して、そのIDで有効なサブスクがあるかを調べる流れです。
ここで一つ気をつけたのは、LINE IDをそのまま決済サービスに渡せるわけではない、という点です。LINE側のIDと決済側の顧客IDを紐づけるための設計が別途必要になります。メールアドレスで突合する方法と、決済時にLINEのIDをメタデータとして渡しておく方法があって、後者を選びました。AIへはこう頼みました。
決済が完了したとき、LINEのユーザーIDを決済サービスのメタデータに保存して。次回の発言が来たとき、そのIDで有効なサブスクがあるかを確認して、あれば制限を解除するようにして。
実際に頼んだ順番
整理すると、こういう順で作りました。
- 初回発言で登録日を記録する処理を既存コードに追加してもらう
- 発言のたびに期限チェックを入れてもらう
- Stripeの有効サブスク確認をつないでもらう
- 期限切れかつ未課金のときだけ制限をかける分岐を入れてもらう
各ステップをひとつずつ頼んでいます。全部を一度に頼むより、順番に繋いでいくほうがどこで動かなくなったかが分かりやすい。
気をつけたいこと
登録日の上書き問題。 すでに登録済みのユーザーに対して、初回登録の処理をもう一度走らせてしまうと、登録日が今日に書き換わって試用期間がリセットされます。「すでに値が入っていたら上書きしないで」と明示しないと、ここで詰まります。何かが入っていたらスキップする、という条件をひとつ入れるだけで防げます。
課金状態の確認タイミング。 毎回の発言で決済サービスへ問い合わせるとコストや待ち時間が積み上がります。サブスク状態は自分側のデータ(スプレッドシートやDB)に持っておいて、決済完了のWebhookを受けたときに更新するほうが現実的です。WebhookはStripeから「課金が成功した」「サブスクが更新された」のような通知を受け取る仕組みのことで、それをトリガーに自分側のデータを更新します。
退会処理も忘れない。 課金した人が解約した後も、制限を解除したままになります。解約のWebhookを受けてステータスを戻す処理も最初から設計に入れておくと、後で慌てません。
