メインコンテンツまでスキップ

Stripe と Squid の Webhook

Squid の @webhook デコレーターを使って Stripe のイベントに応答する

Webhook は、イベントが発生したときにアプリやサービスから送信される HTTP リクエストです。リクエストのペイロードにはイベントに関する有用な情報が含まれており、これを使って自分のコード内でアクションを実行できます。通常、プロダクトのダッシュボードを通じて、サービスに HTTP エンドポイントを提供します。各プロダクトには Webhook を持てる独自のイベントがありますが、一般的なシナリオの例を以下に示します。

  • 新規ユーザーの作成
  • ユーザープロフィールの更新
  • データベースまたはストレージの変更
  • Analytics イベント

このチュートリアルでは、Stripe の customer の invoice ステータスが 'paid' に変わったときに実行される webhook を作成します。

作成するもの

  • Stripe webhook に応答して、ビルトインデータベースにデータを追加する Squid backend。

学ぶこと

  • Stripe イベントにフックする Squid Service の作成方法
  • データベースにセキュリティを追加する Squid Service の作成方法

必要なもの

環境セットアップ

  1. 以下のコマンドで Squid CLI をインストールします。
npm install -g @squidcloud/cli
  1. notes-app のコードサンプルをダウンロードします。
squid init-sample stripe-webhooks --template stripe-webhooks
  1. 任意の IDE でプロジェクトを開きます。

starter プロジェクトには frontendbackend の 2 つのフォルダーがあることに注意してください。今回書くコードは backend のみなので、現時点では frontend に変更は不要です。チュートリアルの最後で、ドキュメント更新をリアルタイムで確認できるように frontend を設定するオプションがあります。

Squid backend をセットアップする

There are two subfolders that make up the stripe-webhooks project: frontend and backend. The backend folder contains the Squid backend for the app.

  1. Navigate to the Squid Console and create a new application named stripe-webhooks.

  1. In the Squid Console, navigate to the application overview page and scroll to the Backend project section. Click Create .env file and copy the command.

Copy Env Command

  1. In the terminal, change to the backend directory:
cd backend
  1. Create the .env file using the command you copied from the console. The command has the following format:
squid init-env --appId YOUR_APP_ID --apiKey YOUR_API_KEY --environmentId dev --squidDeveloperId YOUR_SQUID_DEVELOPER_KEY --region us-east-1.aws
  1. Install the required dependencies:
npm install

The backend is now set up and ready to use with a frontend!

webhook service を作成する

このセクションで作成する webhook Squid Service は、新しい invoice をそのステータス付きで追加するか、既存の invoice をステータス 'paid' で更新するように設計されています。各フィールドの key は Stripe の invoice ID、value は 'paid' または 'unpaid' です。

ドキュメント ID はユーザーの認証 ID です。セキュリティルールは、ユーザーが自分の invoice のみを閲覧できるように設定されています。イメージしやすいように、構造は次のようになります。

userPayments:
squidUserId123: {
kaglautA235980A: 'paid'
Edg26GH697dk104: 'unpaid'
...
squidUserId456: {
SFHGhg995gja0435: 'unpaid'
...
  1. backend/src/service/ に移動し、stripe-webhook-service.ts ファイルを開きます。
  2. StripeWebhookService クラスに、以下の関数を追加します。
backend/src/service/stripe-webhook-service.ts
async addInvoiceToDatabase(stripeUserId: string, invoiceId: string, paid: boolean): Promise<string | any> {
const paidStatus = paid ? 'paid' : 'unpaid';

try {
// Find user in database
const userDocs = await this.squid.collection('userPayments').query().eq('stripeUserId', stripeUserId).snapshot();

if (userDocs.length === 0) {
console.log('new user found, adding to database');
const newInvoices = { [invoiceId]: paidStatus };
await this.squid
.collection('userPayments')
.doc('squidUserId123')
.insert({ stripeUserId: stripeUserId, invoices: newInvoices });
return 'new user, database update complete';
}

const newInvoices = { ...userDocs[0].data.invoices, [invoiceId]: paidStatus };
await userDocs[0].update({ invoices: newInvoices });
return 'database update complete';
} catch (error) {
console.error(error);
return error.message;
}
}

このヘルパー関数は 3 つのパラメーター(Stripe customer ID、Stripe invoice ID、invoice の 'paid' ステータス)を受け取ります。userPayments というコレクションをクエリして、指定された Stripe customer ID を持つユーザーに属するドキュメントを見つけ、その invoices を更新して新しい invoice を含めます。

ドキュメントが見つからない場合は、key が squidUserId123 の新しいドキュメントを追加します。これはデモ用で、各 Stripe customer には対応する Squid user ID が存在し、その user ID を key に持つドキュメントがあるはずだからです。実際のアプリでは、このシナリオは別の場所(データベース内)にログを残すエラーとして扱うことになるでしょう。

  1. addInvoiceToDatabase 関数の後に、以下のコードを追加します。
backend/src/service/stripe-webhook-service.ts
@webhook('handleStripePayment')
async handleStripePayment(request: WebhookRequest): Promise<WebhookResponse | any> {
const stripeUserId = request.body.data.object.customer;
const invoiceId = request.body.data.object.id;
const response = await this.addInvoiceToDatabase(stripeUserId, invoiceId, true);
return this.createWebhookResponse(response);
}

この関数は @webhook デコレーターを使用し、Squid webhook としてマークします。文字列 handleStripePayment はエンドポイント URL に使われるため、エンドポイントの目的が明確になる値を選ぶとよいでしょう。

customerid プロパティは、Stripe から送信されるリクエスト body 内で利用できます。利用可能なプロパティの詳細は、Stripe の webhooks ドキュメント を参照してください。

これらの属性は addInvoiceToDatabase 関数に渡されます。その後、Squid の createWebhookResponse 関数を使って Stripe にレスポンスが送信されます。

  1. backend フォルダーで、以下のコマンドを使って Squid backend をローカルで実行します。
squid start

ターミナルログには webhook 用の URL が含まれます。ログは次のようになります。

| Available webhooks:
| Webhook URL for handleStripePayment: https://YOUR_APP_ID-dev-YOUR_SQUID_DEVELOPER_ID.us-east-1.aws.squid.cloud/webhooks/SQUID_WEBHOOK_NAME

この URL は次のセクションで必要になるため、控えておいてください。

Stripe customer を追加する

このセクションでは、Stripe アカウント が必要です。

  1. テストモードで、Stripe ダッシュボードの Customers セクション に移動します。
  2. Add customer をクリックします。customer の名前を John Doe など任意の名前にします。
  3. Add customer をクリックして、新しい customer を保存します。

Stripe に webhook を追加する

  1. Stripe ダッシュボードで Developers をクリックします。
  2. Developers ページで Wehooks タブをクリックします。
  3. Add endpoint をクリックします。
  4. ターミナルログに表示されたエンドポイント URL を貼り付けます。念のため、Endpoint URL は次の形式になります。
https://YOUR_APP_ID-dev-YOUR_SQUID_DEVELOPER_ID.us-east-1.aws.squid.cloud/webhooks/handleStripePayment
注記

ここで使用している URL 形式は dev 環境用です。prod 環境のエンドポイント形式は https://YOUR_APP_IDYOUR_SQUID_DEVELOPER_ID.APP_REGION.squid.cloud/webhooks/SQUID_WEBHOOK_NAME です。

  1. Select events をクリックし、invoice.paid を選択します。検索バーを使うと便利です。

  2. Add endpoint をクリックします。

webhook をテストする

  1. 新しいターミナルウィンドウを開きます。これでターミナルウィンドウが 2 つ開いている状態になります。まだの場合は、Stripe CLI をインストールしてください。

  2. Stripe customer ID を保存するための環境変数を追加します。Stripe customer ID は、Stripe の Customers ダッシュボードで追加した customer の details セクションにあります。

export customer=YOUR_STRIPE_CUSTOMER_ID
  1. 次の Stripe コマンドを使用して、customer の新しい paid invoice を作成します。
stripe trigger invoice.paid --override invoiceitem:customer=$customer --override invoice:customer=$customer --override payment_method:customer=$customer

このチュートリアルの目的上、これらのフラグの意味を深く気にする必要はありません。Stripe CLI の詳細を知りたい場合は、Stripe の reference docs を参照してください。

注記

このコマンドは設定した一時的な環境変数を使用します。別のターミナルウィンドウでこのコマンドを実行する場合は、customer 変数を再度追加する必要があります。

  1. Stripe ダッシュボードで、webhooks タブから自分の endpoint を選択します。発生したイベント、Squid のレスポンス、リクエスト body を確認できます。

  2. Stripe ダッシュボードで Customers タブを選択し、customer プロフィールの Invoices セクションまでスクロールします。paid invoice が追加されていることが分かります。

また、customer のリストに名前のない新しい cusotmer も追加されています。Stripe CLI で invoice.paid イベントをテストすると、新しい user が作成されます。これは live events では発生しません。

できました!

おめでとうございます!Stripe でトリガーされたイベントに応答する Squid Service webhook を作成しました。目的を達成したのでここで終えても構いませんが、希望する場合はさらに追加できます。

ボーナスセクション: frontend app を追加する

backend 側で更新されたドキュメントデータを見るには、クエリを追加してドキュメントを取得し、その結果をログに出力することもできます。しかし、アプリでデータを使う方法により近づけるには、frontend で更新を表示するのがベストです。

次のボーナス手順では、Stripe イベントに応答してデータベースがリアルタイムに更新される様子を確認できる frontend を設定します。

Auth0 アカウントReact を使用する single-page application を設定済み)が必要です。

Auth0 integration を追加する

  1. まだ Auth0 app を作成していない場合は、Auth0 アカウント を作成し、React を使用する single-page application を設定 してください。 callback と logout URL を追加する際は http://localhost:5173 を使用します。
  2. dev 環境の Squid Console で Integrations タブを選択します。
  3. Available integrations タブをクリックして、すべての integrations を表示します。
  4. Auth0 integration までスクロールし、Add integration をクリックします。
  5. Integration ID に auth0 を入力します。
  6. Auth0 app の client ID と domain を入力します。これらは Auth0 console で確認できます。
  7. Add integration をクリックします。

frontend に Squid を追加する

The following steps add configuration parameters to connect the application to Squid.

  1. Open a new terminal window and navigate to the project's frontend. You should now have two open terminal windows: one for the app's backend and one for the frontend.
cd frontend
  1. Install the required dependencies:
npm install
  1. Run the following command to create a .env.local file with the Squid environment configuration needed to initialize Squid:
npm run setup-env
  1. frontend/src/main.tsx に移動します。Auth0Provider コンポーネントがあり、設定が必要なことに注意してください。
frontend/src/main.tsx
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<Auth0Provider
domain="AUTH0_DOMAIN"
clientId="AUTH0_CLIENT_ID"
authorizationParams={{
redirect_uri: window.location.origin,
audience: 'auth0-api-id',
}}
>
<SquidContextProvider
options={{
appId: import.meta.env.VITE_SQUID_APP_ID,
region: import.meta.env.VITE_SQUID_REGION,
environmentId: import.meta.env.VITE_SQUID_ENVIRONMENT_ID,
squidDeveloperId: import.meta.env.VITE_SQUID_DEVELOPER_ID,
}}
>
<App />
</SquidContextProvider>
</Auth0Provider>
);
  1. Auth0Provider コンポーネントのプレースホルダーを、Auth0 application の domain と client ID に置き換えます。

  2. frontend/src/App.tsx ファイルを開きます。stripeUserId 変数内のプレースホルダーを、作成した customer の Stripe Customer ID に置き換えます。この ID は Stripe ダッシュボードで確認できます。

frontend/src/App.tsx
...
function App() {
const stripeUserId = '[YOUR_STRIPE_CUSTOMER_ID]'
...
  1. frontend フォルダーで、以下のコマンドを実行します。
npm run dev
  1. frontend app を表示するには、ターミナルにログ出力される PORT を使って localhost:PORT に移動します。アドレスはおそらく http://localhost:5173 です。

  2. Log in ボタンでログインします。

  3. Add mock data をクリックして、架空の invoices を生成します。

  4. Stripe コマンド用のターミナルウィンドウで、customer に対して別の paid invoice を作成します。可能であれば、別画面でコマンドを実行するか、web app も見えるようにターミナルを縮小してください。

stripe trigger invoice.paid --override invoiceitem:customer=$customer --override invoice:customer=$customer --override payment_method:customer=$customer
  1. web app 上で新しい paid invoice が追加されていることを確認します。Awesome sauce!

おめでとうございます! 🦑

お疲れさまでした!Stripe のイベントに応答する webhook を作成しただけでなく、変更をリアルタイムに確認できる frontend も設定しました。

次のステップ

Squid にエンドポイントを作成したので、次のようなことを試してみてください。

  • Squid にさらにエンドポイントを追加し、他の Stripe イベントに接続する。
  • Squid のエンドポイントを、webhooks を使う他のプロダクトに接続する。
  • Squid Backend SDK で利用できる他の機能について学ぶために、ドキュメント を確認する。