はじめに
最近になって、決済周りの実装をstripeなどを使用して任されるようになりました。そこで、冪等性という言葉が頻繁出てくるようになり、自分なりにまとめてみました。
冪等性とは
冪等性は、何回実行しても1回目と同じ結果になることです。
今回は決済だと、同じ決済リクエストが複数回来ても、実際の請求は1回だけになります。
たとえばユーザーが「1,000円購入」を押したとします。
ユーザー
↓
「1,000円購入」
↓
決済APIにリクエスト
↓
1,000円の決済成功
もし、通信の遅さでもう一度ボタンを押したりなどすると、
1回目 → 1,000円決済
2回目 → 1,000円決済
二重決済になる可能性があります。
そこで、決済ごとに一意な「冪等性キー」を付けます。
idempotency_key = order_12345
1回目のリクエスト:
order_12345
↓
1,000円決済
↓
成功
同じキーでもう一度リクエストが来た場合:
order_12345
↓
「このキーはすでに処理済み」
↓
新たに決済しない
結果として、同じリクエストが複数回来ても、処理が重複して実行されることを防げます。
Stripeでの冪等性
Stripe公式ドキュメントでも、冪等性キーを利用することで、接続エラーなどによってリクエストを再試行した場合に、同じ処理が誤って2回実行されることを防げると説明されています。
Stripeでは、ある冪等性キーに対する最初のリクエスト結果のステータスコードとレスポンスを保存します。
その後、同じ冪等性キーでリクエストされた場合は、最初に保存した結果を返す仕組みになっています。
Node.jsでPaymentIntentを作成する場合は、たとえば以下のように冪等性キーを指定できます。
const paymentIntent = await stripe.paymentIntents.create(
{
amount: 1000,
currency: "jpy",
},
{
idempotencyKey: "order_12345",
}
);
paymentIntents.create()ではPaymentIntentを作成でき、StripeのPOSTリクエストでは冪等性キーを指定できます。
idempotencyKey: "order_12345"
の部分が冪等性キーです。
Stripeでは、冪等性キーはクライアント側で生成します。公式ドキュメントでは、キーの重複を避けるためにUUID v4などのランダムな値を使用する方法が推奨されています。
まとめ
決済処理では、同じリクエストが複数回来ても二重決済にならないように気をつけることと、冪等性キーを使うことで、同じ処理が重複して実行されるのを防げることが分かりました。
参考文献
