2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Stripe Webhookを使ってLINEとGASを連携、通知させる

Posted at

LINE Bot と ChatGPT を組み合わせた有料Botを開発している。
Stripeで課金を受け取ったり、解約・プラン変更をトリガーにしてLINEへ通知を送る仕組みを実装中だ。

Stripeから送られてくるWebhookを受け取る処理の中で、どういう分岐をしているかを整理しておく。

全体の流れ

Stripeでの決済やプラン変更が行われると、
Stripeは設定してある Webhook URL(GASのdoPost)にイベント情報を送ってくる。

そのイベントの種類ごとに処理を分けている。

Stripe → GAS(doPost)
         ├── checkout.session.completed  決済完了
         ├── customer.subscription.updated  プラン変更
         └── customer.subscription.deleted  解約

それぞれのイベントで、
スプレッドシートを更新したり、LINEでユーザーに通知を送ったりする。

Stripe Webhookのメイン処理

Webhookを受け取るエントリーポイントは doPost(e)。
ここで event.type に応じて分岐している。

function doPost(e) {
  const event = JSON.parse(e.postData.contents);

  if (event.type === 'checkout.session.completed') {
    // 決済完了イベント
  } else if (event.type === 'customer.subscription.updated') {
    // プラン変更イベント
  } else if (event.type === 'customer.subscription.deleted') {
    // 解約イベント
  }
}

1. checkout.session.completed

決済が完了した時に発火

Stripeの決済が完了すると、このイベントが送られる。
ここでは「ユーザーが有料プランに入った」ことを検知する。

if (event.type === 'checkout.session.completed') {
  const object = event.data.object;

  // 支払いステータスを確認
  if (object.payment_status !== 'paid') return;

  const userId = object.client_reference_id; // LINEユーザーID
  const customerId = object.customer;        // Stripeの顧客ID
  const email = object.customer_details.email;
  const subscriptionId = object.subscription;

  // LINEにメッセージ送信
  sendTextMessage(,)); //独自メソッド
}

処理の目的

  • 決済済みであることを確認
  • 顧客情報を「顧客シート」に登録
  • 有料プラン情報を「ユーザープランシート」に記録
  • LINEで「ご契約ありがとうございます」メッセージを送信

client_reference_idにLINEのIDを仕込むと

client_reference_id にLINEのuserIdを仕込んでおくことで、
Stripe→GAS→LINEの紐付けが自動でできる。

2. customer.subscription.updated

プラン変更時(アップグレード/ダウングレード)

ユーザーがStripeのカスタマーポータルなどでプランを変更した場合に発火する。

else if (event.type === 'customer.subscription.updated') {
  const subscription = event.data.object;
  const customerId = subscription.customer;

  // キャンセル予約があるか
  if (subscription.cancel_at_period_end === true) {
    // 期限までの解約予約
  }

  // schedule が存在する場合 → 次回請求日からの変更
  if (subscription.schedule) {
    // 予約変更(翌月反映)
  } else {
    // 即時変更(今すぐ切り替え)
  }
}

ケース別の動作

cancel_at_period_end === true

「今月末で解約予定」として、キャンセル予約メッセージを送信

subscription.schedule が存在

翌月からプラン変更 → ユーザープランシートに「pending」として予約情報を記録

上記どちらもなし

即時プラン変更 → プランタイプを即時更新、LINEで変更完了通知

具体的な例:翌月変更のスケジュール

if (subscription.schedule) {
  const billingCycleAnchor = subscription.billing_cycle_anchor;
  const effectiveDate = Utilities.formatDate(
    new Date(billingCycleAnchor * 1000), 'Asia/Tokyo', 'yyyy/MM/dd'
  );

処理の目的

  • 解約予約・変更予約を検知し、ユーザーにわかりやすく加工する

3. customer.subscription.deleted

解約完了時

ユーザーがプランを完全に解約したときに発火する。

else if (event.type === 'customer.subscription.deleted') {
  const object = event.data.object;
  const customerId = object.customer;

分岐はハマった。未来の自分が迷わないようにメモを残す。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?