
Stripe+Auth0+kintoneをNext.jsで統合してVercelで公開してみる。
この記事は、「JP_Stripes Advent Calendar 2022」22日目参加の記事です。よろしくお願いします。
Stripeにkintoneを組み合わせられるか
僕は普段の業務でcybozu社のkintoneを利用した業務システムの提案、構築を行っています。
Stripeを業務で開発利用したことはないです。けど、kintoneのCRMをうまく統合できたら面白いんじゃないかと妄想していました。
だいたいこんな利点があると思うんです。
1)顧客情報を収集してメール送付やマーケティング活動。
2)クレーム管理や決済失敗のフォロー管理など、顧客ごとの問題管理に。
3)ECサイトの運用に関するバックオフィス業務の支援。
kintoneは複数の作業者が1つのデータをもとに協奏する業務が得意なので、Stripeとうまく組み合わせることで運用を潤滑にして、顧客の利用体験の改善にもつながるのではないかと、餅の絵をかいてみました。
認証。あるいはいかにして顧客を見つけられるようになるか。
さあ、お客様に対しての活動を行いたい場合、その「お客様」を特定する必要があります。そう、認証ですね! Webで活動し、商品購入を行ったユーザーと、支払い義務のある人物を紐づける必要があります。
こんな感じでできるのでは?


インフラには・・・Auth0を利用したい。
うわさはかねがね聞いていましたのでね。
それから僕はReact者なので、中間はNext.jsを利用したいと思います。
Auth0もStripeもユーザーを一意に識別できるキーを持っています。それをkintoneに紐づけ登録します。
正直StripeとAuth0だけであればStripe側にmetadataを持たせればいいのですが、kintone側に持ち出してユーザーへの支援を行いたい狙いがあります。例えば、「サインアップだけできたけど、顧客登録はまだ」というユーザーに対して、メールなどで支援することができますよね。
Nextを利用する場合、認証はサーバー側の戦略になるので、@auth0/nextjs-auth0パッケージが必要になります。UserProvidarで包んで・・・。

import { useUser } from '@auth0/nextjs-auth0/client';

サーバーサイドへの顧客情報の提出はWebAPIで受けます。Next.jsはWebAPIがフロントエンドのReactページと統合管理されているので、もはやAPIをおやつ感覚で書けますね。AWS-AmplifyやFirebaseでNextを使わずに書くときは、明確に別機構のソース管理を受けますからね。


*ソースコード、だいぶサボってます。命名とか型宣言とか許してね。

カスタマーポータルを提供する
せっかく顧客ごとに認証して識別できるようになったので、顧客にカスタマーポータルを提供したいと思いました。
カスタマーポータルは時間制限があるので、ポータルはアクセス前に作ってあげる必要がありますね。WebAPI側に一度リクエストし、URLを作って提供してみます。StripeSDKめっちゃ優秀ですね!


ボタンを押下したら、WebAPI経由でstripe.billingPortal.session.createでカスタマーポータルを作成し、URL先に飛んでいきます。
kintoneにもリンクを仕込みまくる
kintone側には、Stripe顧客を素早く見つけられるようにしてみます。
Stripeは下記のようなURLパス設計になっていますね
https://dashboard.stripe.com/{{test}}/customers/{{customer.id}}
これはkintoneで簡単に作れそうです!


さあ、これでStripeの顧客とkintoneのレコードがつながりました。
Stripeはパス設計が素晴らしいので、ProductやSubscriptionも同じやり方でkintoneでリンクできちゃうのがいいですね!
Vercelでの公開
さあ、Next.jsプロジェクトが完成したので、Vercelで公開してみます。
Githubでprivateリポジトリ(2020年から無料だって!)を作って、Pushしたら、Vercelから呼び出します。
結果は・・・うーん。なんだか簡単にできてしまって拍子抜け。でした。
いや、いいことなんですが。
公開以降はmasterブランチとの継続的デプロイが入るので、管理も楽々ですね。
ここからどうするか・・・。
構想としては、kintone側にデータを同期して、支払いに問題がある請求の管理や、顧客への販促メール対応など、kintoneが得意なバックヤード業務への支援を充実させたいですね。
Stripeとのデータ同期はNext.js+Vercelだけでは難しいので、データ連携用のバッチを置く必要があるかもしれません。
いろいろ妄想が広がりますが、今回はここまで。
感想をつらつらと
StripeSDKはとっても質感がいい!
PaymentLinksは細かい料金体系が対応していなかったり、数量設定に制限があったり、顧客がチェックアウトごとに作られたり、けっこう面倒くさい。
StripeにGraphQLなげたい。Subscription>Product>Pricingなど、IDつながりで紐づるで取得したいのに、クエリをばらばらにしなければならなかったから。
StripeのWebhookにSubscriptionの変更に対応するものがなくて、ちょっと不便だった。(定期のポーリングするしかなさそう・・・。)
Next.jsはAPIが簡単に書けるし、CORS対応もできる。ただし、バッチ処理やスケジュール実行はやっちゃいけない。
Vercelのログがめちゃくちゃフラッシュされるので、ログ機構は別で用意する必要がある。
(正直VercelよりAmplifyのほうが安くて環境のコピーもできて、良かったかなぁ・・・。cloudwatchあるし。)
Vercelのいいところもっと知りたい。
kintoneは相変わらずええな!
という結論でした。
おわり
この記事はStripe初心者がkintone連携妄想を実現する試みでした。
お楽しみいただけましたでしょうか?
お読みいただき、ありがとうございました。