
前回までのあらすじ
「半年・500万円」と言われて諦めていた予約システムを、お盆休みにClaudeと作り始めた話を書いています。
前回は料金設計でした。組めると言われたマトリックスをあえて組まず、料金の「区分」は増やさずに期間の「指定」だけを足した、という引き算の回です。
今回は、決済です。
このシリーズの中で、性格が最も変わる工程でした。
モックが通用しなくなる地点
ここまでの開発は、ほとんどモックアップで進めていました。
カレンダーを作り、顧客導線を組み、料金の設定を入れる。画面の上で動くものを作りながら、イメージと違えば直す。この進め方で、3日ほどでモックはほぼ完成しました。
ところが、予約プロセスの最終局面まで来たところで、性格が変わります。
支払い方法を選択して、決済に進む。
ここは最も重要なプロセスです。そして、モックでは済みません。本物のお金が動くからです。
そこで、ここからは本番環境と同じ言語で、同じサーバーに実装して動かしていくステージに入りました。
開発の空気が変わった瞬間でした。それまでは「こういう画面にしたい」という話でしたが、ここからは「間違えたら実害が出る」という話になります。
そもそも、決済を自分で作れるとは思っていませんでした
実装に入る前に、正直な話を書いておきます。
私は、決済機能をオリジナルで作れるとは思っていませんでした。
決済というのは、プラグインなり、何かしらのシステムのパッケージなりを持ってきて、それをはめ込まないと組み立てられないもの。そういうものだと思い込んでいました。
お金を扱う領域ですから、素人が触れる場所ではないだろう、と。
ところが実際には、オリジナルで、しかも柔軟に組み立てられることが分かりました。
これを知ったときは、かなり驚きました。
もちろん、Claudeはその裏でかなり高度なことをやってくれているのだと想像します。私がコードの中身を理解しているわけではありません。
ただ、「決済は借りてくるもの」という前提そのものが間違っていたことに気づけたのは、この工程の大きな収穫でした。
Stripeを選んだ理由
決済にはStripeを使いました。
理由のひとつは単純で、もともとBooklyでもStripeを使っていたからです。すでに口座もあり、勝手も分かっていました。
ただ、作っていく中で気づいたことがあります。
Stripeとオリジナルの予約システムは、非常に相性がいい。
StripeはさまざまなAPIを持っていて、支払いのプロセスを柔軟に組み立てられます。決まった形にはめ込むのではなく、自分たちの運用に合わせて組める。
これは既製のプラグインを使っていたときには、まったく見えていなかった部分でした。
足りなかったのはStripeではなく、その手前にいたものでした
ここが、この回で一番お伝えしたいことかもしれません。
Booklyを使っていたとき、決済手段はクレジットカードだけでした。
一方で私は、Stripe自体にはコンビニ決済や銀行振込の機能があることを知っていました。知っていたけれど、使えなかった。プラグインの仕様がそこまで対応していなかったからです。
Booklyは、よくできたプラグインです。ただ、海外製であることが大きかったのだと思います。海外ではコンビニ払いや銀行振込による支払いは、あまり主流ではありません。 開発側にとって優先度が低いのは当然でしょう。
つまり、機能はもともとStripeの中にありました。足りなかったのはStripeではなく、その手前にいたプラグインのほうだったのです。
今回、Claudeに「コンビニ決済や銀行振込決済の作り込みもできるか」と聞いてみました。
答えは、可能でした。
そこから実装に入りました。
PayPalも組み込みました
決済手段として、PayPalも組み込んでいます。
ただし、こちらは性格が違います。PayPalで対応しているのは、クレジットカードによる決済のみです。 先ほど書いたコンビニ払いや銀行振込は、Stripe側で処理しています。
それでも組み込んだのは、世の中にPayPalを使い慣れている方が一定数いらっしゃるからです。普段使っているアカウントでそのまま払えるほうが、当然ストレスは少ない。
そこで、クレジットカードでの支払いについては、StripeとPayPalのどちらでも対応できるようにしました。
決済手段は「増やせばいい」というものではありませんが、同じカード払いでも入口を選べるようにしておくことには意味があると考えました。
一番悩んだのは、銀行振込とコンビニ払い
支払いのプロセスで最も悩んだのが、この2つです。
理由は、お金が後から届くからです。
クレジットカードなら、その場で結果が出ます。通ったか通らなかったか、それだけです。ところが銀行振込やコンビニ払いは、申し込みと入金の間に時間が空きます。その「待っている状態」をどう扱うかが問題になります。
これまでは、全部手作業でした
銀行振込の支払いは、これまでも受けていました。ただし、すべてのプロセスを手作業でやっていました。
請求書を作る。お客様に送る。指定した日に入金があったかどうかを確認する。入金がなければ催促のメールを送る。それでも入らなければ電話をする。
書き出してみると、かなりの工程です。しかも予約が入るたびに発生します。
自動で入金が反映されたときは、驚きました
Stripeで銀行振込とコンビニ払いを実装できる。これだけでも画期的でした。
しかし、本当に驚いたのはその先です。
銀行振込やコンビニ払いが実際に完了すると、その報告がStripeに通知されます。そしてその情報が即座に予約システムに返ってきて、「未入金」だったステータスが自動で「入金完了」に変わるのです。
正直に書きますが、当初の私たちはこう思っていました。
「銀行振込やコンビニ払いができるようになったとしても、入金確認は結局自分たちでやらなければいけないだろう」と。
ところが、そこも自動でした。
これで、かなりの作業量が減りました。お客様にとっては支払い方法の選択肢が増え、私たちにとっては作業が減る。 どちらにとっても良い支払い環境ができたと思っています。
コンビニで実際に支払って、メールが届いた
テストは、本当に何度も繰り返しました。
回数は覚えていませんが、少なくとも100回はやっていると思います。
そして印象に残っているのが、実地でのテストです。
実際にコンビニに行ってお金を払う。実際に銀行で振り込みをする。
そうすると、自動で予約が完了して、メールが届く。
「入金が確認できご予約が完了しました」というメールが届いたときは、かなり嬉しかったです。
画面の中だけで完結する作業をずっと続けてきて、それが現実の世界とつながった瞬間でした。自分が作ったものが、コンビニのレジと銀行と、ちゃんと会話している。
人間と、Claudeと、両方がテストする
テストについて、もうひとつ書いておきたいことがあります。
私が100回テストしている間、Claudeも改修のたびに何百回もテストをしてくれていました。
これは心強かったです。
役割は、自然と分かれていきました。
Claudeが見ているのは、動作が正しいかどうか。 処理が意図したとおりに走っているか、エラーが出ていないか。
私が見ているのは、体験として大丈夫かどうか。 分かりにくくないか、不安にならないか、メールの文面はこれでいいか。
ノンプログラマーの私に、動作の正しさは検証できません。逆に、お客様がどこで不安になるかは、10年見てきた私にしか分かりません。
両方が必要でした。
一番気を使ったのは「予約が成立する瞬間」
テストを重ねる中で、技術的な不具合よりも神経を使ったことがあります。
お客様が予約をするとき、できるだけ不安にならないようにすること。
その中で、最も重要な判断がこれでした。
予約が成立する瞬間を、どこに置くか。
私たちの商売で一番怖いのは、ダブルブッキングです。
たとえば、同じ枠に対して2人のお客様が同時に予約プロセスを始めたとします。このとき、どの時点で「予約成立」とするかによって、トラブルが起きるかどうかが決まります。
カレンダーで日付を選んだ時点でしょうか。フォームを埋めた時点でしょうか。それとも決済が通った時点でしょうか。
私たちが決めたのは、こうです。
決済が完了した瞬間に、予約が成立する。
このシンプルなルールを決めて、作り込みました。
理由は、ここにしか曖昧さがないからです。 途中の段階はどれも離脱の可能性があります。しかし決済は、通ったか通っていないかしかありません。
そして、お客様から見ても納得しやすい。払った人が取れた、という結果は説明がつきます。
これは技術の問題ではありませんでした。運営者として、どこに線を引くかという判断です。10年間ダブルブッキングを恐れ続けてきたからこそ、ここに神経を使えたのだと思います。
出金のタイミングが自由、というありがたさ
最後に、運営面での話をひとつ。
Stripeの良いところとして、出金のタイミングを自由に決められるという点があります。しかも、自社の銀行口座に振り込まれるまでの期間が短い。
支払い条件そのものは、Booklyを使っていた頃から変わっていません。
ただ、意味合いは大きく変わりました。
以前はクレジットカードの売上だけがStripeに入っていました。今は、カードもPayPalもコンビニも銀行振込も、すべてStripeに集約されています。
予約と同時に受け取ったお金が一箇所にまとまり、そこから必要なタイミングで自社口座へ動かせる。レンタルスペースのように規模の小さい事業にとって、資金が早く手元に来ることの意味は小さくありません。
この回でわかったこと
決済編を振り返ると、気づいたことがあります。
できなかったことの多くは、「本当にできなかった」わけではありませんでした。
コンビニ払いも銀行振込も、Stripeは最初から持っていました。入金の自動反映も、仕組みとしては存在していました。ただ、私たちがそこに手を伸ばせる形になっていなかっただけです。
既存のサービスを使っていると、「できること」の範囲が固定されます。 そしていつの間にか、その範囲が世界のすべてだと思うようになる。
決済はまさにそれでした。私は最初から「これは借りてくるものだ」と決めつけていた。誰にそう言われたわけでもないのに、自分で枠を作っていたのです。
自分で作るというのは、その枠を自分で決め直すことなのだと、この工程で実感しました。
次回:#6 Googleカレンダー双方向同期
次回は、10年以上私たちを悩ませ続けてきた問題に取り組みます。
Googleカレンダーとの双方向同期です。
これが一方通行だったために、私たちは手作業での転記を続け、当日予約を受けられない時期が長く続きました。ここを解決できるかどうかが、今回の開発で最も切実なテーマでした。
シリーズ一覧(全12話)
- 連載まとめ・目次
- #1 きっかけ編|「作れます」の一言から始まった
- #2 準備編|Cloudflareが何かも分かっていなかった
- #3 予約カレンダーと顧客導線|なぜ日付から入らせるのか
- #4 料金設計という難所|AIは「やめたほうがいい」とは言わない
- #5 決済とStripe|「借りてくるもの」だという思い込み(この記事)
- #6 Googleカレンダー双方向同期|台帳は1つでいい
- #7 メールと通知の設計|10年間、諦めていたこと
- #8 思わぬ落とし穴|2回、巻き戻しました
- #9 ローンチ当日|「あっ、ヤバい」
- #10 ローンチ後に起きたこと|作った本人には見つけられない
- #11 予約システムが、画面の外に出た日(SwitchBot連携)
- #12 最終回|私でも、優秀なプログラマーを配下に置ける
運営ルールの記事