🦔

【Stripe】有効なCheckout URLを複数発行しないための施策【二重決済対策】

2022/12/19に公開約1,500字

この記事は、JP_Stripes Advent Calendar 2022 13 日目の記事です。

今回は紹介する施策は、実際に Stripe Checkout URL を使った決済サービスを運用する際に起こった不具合対策です。

起こった事象

二重決済による問い合わせが非常に多発した時期がありました。

これは本当にまれな事象ですが、以下のような手法を行ったユーザーがおられました。

  1. スマホブラウザから Checkout URL を生成するための決済ボタンを押す
  2. 生成した URL をコピーし、PC ブラウザに貼り付ける
  3. 再度スマホブラウザから Checkout URL を生成し、上記と同じように PC ブラウザで開く
  4. タブを開いたまま同時に決済を行う

と、かなりハックじみた行動をとったユーザーがおられました。

上記の流れはあくまで一例で他の方法で複数の URL から同時決済されたユーザーがおられました。

解決策

解決策として 2 つ思いつきました。

  1. Stripe Subscription Item が必ず 1 つになるようにトランザクション処理する
  2. 有効な Checkout URL が複数生成されないようにする

1 に関しては、採用している DB に応じてコードが異なると思われるので今回は 2 を紹介します。

早速ですが、答えを書きます。

// 1. 生成したCheckout URLを一覧で取得

const { data: sessionList } = await stripe.checkout.sessions.list({
  customer: stripeCustomerId,
});

// 2. 現在有効中のURLをフィルターする

const openSessionList = sessionList.filter(
  (sessionItem) => sessionItem.status === "open"
);

// 3. 有効中のURLを無効化する

await Promise.all(
  openSessionList.map((openSessionItem) =>
    stripe.checkout.sessions.expire(openSessionItem.id)
  )
);
  1. 生成した Checkout URL を一覧で取得する
  2. 現在有効中の URL をフィルターする
  3. 有効中の URL を無効化する

1 と 2 は Stripe Search でまとめることができますが、今回は処理の流れがわかりやすくするために上記の流れを記載しました。

この 3 つの処理を関数化し、stripe.checkout.sessions.createを実行する前に実行すれば、複数決済が行われることはなくなります。

まとめ

今回の処理を実装したことで、複数決済の問い合わせが一切こなくなりました。

決済周りはすごくセンシティブなので、この記事によって同じような問い合わせで困ってる方の手助けになれば幸いです。

今後も Stripe を活用したプチノウハウを発信していくので Twitter(@hyodoblog )の方フォローしてもらえると嬉しいです。

GitHubで編集を提案

Discussion

ログインするとコメントできます