Stripe Connect の refund で reverse_transfer が false になる仕組みと検知方法
問題
Stripe Connect でプラットフォームがアプリケーションフィーを受け取る決済を行った後、返金(refund)を発行すると、reverse_transfer パラメータのデフォルトが false になります。この状態では、プラットフォーム側のフィーは返却されず、接続先アカウントへの転送(transfer)も元に戻されません。結果として、接続先アカウントは本来返金されるべき金額を受け取れず、プラットフォーム側が不当にフィーを保持する「フィーリーク」が発生します。
仕組み
Stripe Connect の決済フローは以下のようになります。
-
Charge 作成
プラットフォームはapplication_fee_amountを指定してChargeを作成し、Stripe が接続先アカウントへのTransferを自動生成します。このとき、transferのamountは charge 金額からフィーを差し引いた額になります。 -
Refund 作成
POST /v1/refundsにchargeID と、オプションでreverse_transferフラグを渡します。-
reverse_transfer: true(明示的に指定) → 返金額に応じてTransferが逆方向に調整され、プラットフォーム側のフィーも返金されます。 -
reverse_transfer: falseまたは未指定(デフォルト) →Transferは変更されず、プラットフォーム側のフィーは返金されません。
-
したがって、デフォルトの挙動では返金時にフィーが戻らず、接続先アカウントに不利益が生じます。
実装例(検知・修正)
以下は、既存の refund オブジェクトを取得し、reverse_transfer が false であるかを確認し、必要に応じて再度返金を発行してフィーを戻すサンプルコードです(Stripe Node.js ライブラリを使用)。
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
async function checkAndFixRefund(refundId) {
// 1. refund オブジェクトを取得
const refund = await stripe.refunds.retrieve(refundId, {
expand: ['charge.transfer']
});
// 2. reverse_transfer が false か確認
if (!refund.reverse_transfer) {
const charge = refund.charge;
const fee = charge.application_fee_amount; // フィー額(最小通貨単位)
// 3. フィー分だけ追加で返金を作成(reverse_transfer: true)
await stripe.refunds.create({
charge: charge.id,
amount: fee,
reverse_transfer: true, // フィーをプラットフォーム側に戻す
refund_application_fee: true
});
console.log(`Refunded fee ${fee} for charge ${charge.id}`);
} else {
console.log(`Refund ${refundId} already has reverse_transfer: true`);
}
}
// 使用例
checkAndFixRefund('re_1J2abc...');
このコードは以下の手順で動作します。
- 対象の
refundを取得し、chargeとそのtransferを展開。 -
reverse_transferフラグがfalseの場合、プラットフォーム側が保持しているapplication_fee_amount分だけ追加でrefundを作成。 -
reverse_transfer: trueとrefund_application_fee: trueを指定することで、フィーをプラットフォーム側から接続先アカウントへ戻す。
注意点(キャベット)
-
権限:
refunds:writeとapplication_fees:readのスコープが必要です。 -
冪等性:同じ
refundに対して複数回実行しないように、状態フラグやログで管理してください。 - 部分返金:複数回にわたる部分返金が発生している場合は、各返金ごとにフィーの割合を計算し、合計が元のフィーを超えないように調整が必要です。
- Instant Payouts:接続先アカウントが即時払いを利用している場合、転送のタイミングによっては追加返金が二重に処理されるリスクがあります。トランザクションログを確認し、必要に応じて手動で調整してください。
-
手動転送:プラットフォームが手動で
transferを作成しているケースでは、上記ロジックは適用されません。手動転送のロジック別にフィーの返却フローを実装してください。
以上のように、reverse_transfer のデフォルト挙動を理解し、API レベルで適切にフラグを制御または追加返金を行うことで、フィーリークを防止し、接続先アカウントへの正しい返金を保証できます。