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

Stripe と Squid の Webhook

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

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

  • 新しいユーザーの作成
  • ユーザーのプロフィール更新
  • データベースまたはストレージの変更
  • アナリティクス(analytics)イベント

このチュートリアルでは、Stripe の顧客の請求書(invoice)ステータスが「paid」に変わったときに実行される webhook を作成します。

作成するもの

  • Stripe webhook に応答して、組み込みデータベースにデータを追加する Squid バックエンド

学ぶこと

  • 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 に変更は不要です。チュートリアルの最後に、フロントエンドを設定してドキュメント更新をリアルタイムで確認できるようにするオプションがあります。

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 サービスの作成

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

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

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、請求書の「paid」ステータス)を受け取ります。userPayments というコレクションをクエリして、指定された Stripe customer ID を持つユーザーに紐づくドキュメントを見つけ、その invoices に新しい invoice を含めるように更新します。

ドキュメントが見つからない場合、キーが squidUserId123 の新しいドキュメントを追加します。これはデモ目的で、すべての Stripe customer は対応する Squid user ID を持ち、したがってユーザー ID をキーとするドキュメントが存在するはずだからです。実際のアプリでは、このケースは別の場所にログとして保存するなど、エラーとして扱うことが多いでしょう。

  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 の webhook ドキュメント を参照してください。

これらの属性は 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 を保存します。

webhook を Stripe に追加する

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

ここで使用している URL 形式は dev 環境用です。prod 環境の endpoint 形式は 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 セクションまでスクロールします。支払い済み invoice が追加されていることに注意してください。

また、customers の一覧に名前なしの新しい cusotmer も追加されています。Stripe CLI で invoice.paid イベントをテストすると新しいユーザーが作成されます。これはライブイベントでは発生しません。

できました!

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

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

backend 上の更新されたドキュメントデータを確認するには、クエリを追加してドキュメントを取得し、結果をログに出すこともできます。しかし、アプリでデータを使う方法をよりよく反映するには、フロントエンドで更新を表示するのが最適です。

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

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

Auth0 integration の追加

  1. まだ Auth0 アプリを作成していない場合は、Auth0 アカウント をセットアップし、React を使う single-page application を作成 します。 callback URL と logout URL を追加する際は http://localhost:5173 を使用してください。
  2. dev 環境の Squid Console で Integrations タブを選択します。
  3. Available integrations タブをクリックして、すべての integration を表示します。
  4. Auth0 integration までスクロールして Add integration をクリックします。
  5. Integration ID に auth0 を入力します。
  6. Auth0 アプリの 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 アプリケーションの 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 アプリを表示するには、ターミナルにログ出力されている PORT を使って localhost:PORT に移動します。アドレスはおそらく http://localhost:5173 です。

  2. Log in ボタンを使ってログインします。

  3. Add mock data をクリックして、架空の invoice をいくつか生成します。

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

stripe trigger invoice.paid --override invoiceitem:customer=$customer --override invoice:customer=$customer --override payment_method:customer=$customer
  1. web アプリで、新しい支払い済み invoice が追加されていることを確認します。Awesome sauce!

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

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

次のステップ

Squid に endpoint を作成したので、次のようなことを試してみましょう。

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