stripe-dispute について
stripe-disputeは、Stripeを使うSaaSチーム向けの異議申し立て評価・証拠作成スキルです。費用と過去の結果を確認し、承認後に証拠をまとめて提出します。
主な機能
- 01異議申し立ての費用と期待値の評価
- 02紛争と決済履歴の確認
- 03読み取り専用でのユーザー活動照会
- 04活動ログとポリシーのPDF作成
- 05承認後の証拠提出
活用シーン
- 01Stripeのチャージバックに異議を申し立てるか評価
- 02紛争用のログイン・利用記録を収集
- 03請求書やポリシー資料を作成・提出
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ openclaudia/ openclaudia-skills --skill stripe-disputeインストール後、Claude Code で/stripe-disputeを入力して読み込まれたか確認します。
詳細
Stripe の異議申し立ての評価と証拠
まず採算性を評価します。異議申し立てを行う妥当性があり、承認された場合は、証拠一式を作成して Stripe に提出します。Stripe と、ログインまたは利用状況のログを持つユーザーデータベースを使用するあらゆる SaaS に対応しています。
このスキルを使用する場面
ユーザーが次のような場合に、このスキルを使用します。
- Stripe からチャージバックの通知を受け取り、異議を申し立てたい
- 異議申し立て ID(
du_*)を提示し、「反論」/「反証」/「争う」方法を尋ねる fraudulent、product_not_received、product_unacceptable、またはsubscription_canceledとしてマークされた異議申し立てについて、証拠の集め方を尋ねる- 顧客が製品を利用したことを示すアクティビティログの PDF を作成したい
必須の環境変数
STRIPE_SECRET_KEY=sk_live_... # Stripe restricted/secret key with disputes:write scope
DATABASE_URL=postgres://... # READ-ONLY connection to your app's user database (optional but recommended)
TERMS_URL=https://yoursite.com/terms # URL to your published cancellation/refund policy
EVIDENCE_DIR=~/disputes # Where to save the per-customer evidence folders
**データベースの安全性:**すべてのクエリは SELECT のみです。このスキルで UPDATE/DELETE/INSERT を実行してはなりません。
入力
ユーザーが次のいずれかを提供します。
- Stripe の異議申し立て ID(
du_xxxxx)— 推奨 - 顧客のメールアドレス — スキルが異議申し立てを検索します
- チャージ ID(
ch_xxxxxまたはpy_xxxxx)
まず異議を申し立てるかどうかを判断する
異議申し立てを受け入れることが適切な場合もあります。事案が存在するというだけで、証拠を提出してはなりません。
- Stripe の最新の料金を確認します。現在の米国標準料金では、Stripe は異議申し立ての受領時に 15 ドルの手数料を自動的に請求し、証拠を提出すると、さらに 15 ドルの異議申し立て手数料を請求します。受領手数料は埋没費用です。異議申し立て手数料は勝訴した場合に限り返金されます。金額が変更された場合は、最新の料金を使用してください。
- 販売者の Stripe における最新の異議申し立て履歴を照会します。防御した場合の勝率は、
evidence_details.submission_count > 0のクローズ済み異議申し立てのみを集計します。初回購入と更新を分け、サンプル数が許す場合は同じ理由に絞り込みます。勝訴、敗訴、対応中の事案、サンプル数を報告します。完全に一致する前例がない場合は、その旨を明記します。 - 異議申し立て手数料と証拠作成の人件費を考慮して、損益分岐点となる勝訴確率と期待値を計算します。事案の強さだけを根拠に、確率を捏造してはなりません。
- ユーザーが別の基準を提示しない限り、保守的な最低勝訴確率として 30% を使用します。比較可能なデータでその基準を裏付けられない場合は、異議申し立てに回答しないことを推奨します。これにより異議申し立て手数料は回避できますが、係争額と受領手数料は引き続き失われます。
- ファイルの作成、証拠のアップロード、または提出を行う前に、ユーザーから明示的な承認を得ます。提出は最終的なものであり、手数料が発生します。
手順
1. Stripe から異議申し立てを取得する
curl -s -u "$STRIPE_SECRET_KEY:" \
"https://api.stripe.com/v1/disputes/$DISPUTE_ID" | python3 -m json.tool
amount、reason、charge、evidence_details.due_by、evidence_details.submission_count、status を抽出します。
submission_count > 0 の場合、異議申し立てはすでに行われています — 停止してユーザーに警告してください。
2. 関連する周辺情報を取得する
# Charge → tells you the payment method, risk score, billing details, customer ID
curl -s -u "$STRIPE_SECRET_KEY:" "https://api.stripe.com/v1/charges/$CHARGE_ID"
# Customer → name, email, default payment source
curl -s -u "$STRIPE_SECRET_KEY:" "https://api.stripe.com/v1/customers/$CUSTOMER_ID"
# All invoices for the customer → look for previously-undisputed payments
curl -s -u "$STRIPE_SECRET_KEY:" \
"https://api.stripe.com/v1/invoices?customer=$CUSTOMER_ID&limit=100"
# Subscription (if recurring)
curl -s -u "$STRIPE_SECRET_KEY:" "https://api.stripe.com/v1/subscriptions/$SUB_ID"
同じカードで過去に行われた異議申し立てのない支払いは、fraudulent の申し立てに対する有用な補強材料です。必ず件数を集計しますが、それだけで証明になるとみなしてはなりません。
3. アプリのデータベースで顧客を検索する
これらのクエリをスキーマに合わせて調整します。証拠として有用な形式の例:
-- User profile and self-reported cancel reason
SELECT id, email, created_at, plan_tier, stripe_customer_id,
cancel_reason, cancelled_at, delete_reason
FROM users WHERE email ILIKE :email;
-- Login activity (timestamps + country + device)
SELECT created_at, country_code, device
FROM user_activity WHERE user_id = :uid ORDER BY created_at;
-- Things the customer created/used in your product
SELECT name, type, created_at, updated_at
FROM projects WHERE user_id = :uid AND deleted = false ORDER BY created_at;
-- Checkout / payment-related actions (proves intent)
SELECT timestamp, endpoint, payload FROM action_logs
WHERE user_id = :uid
AND endpoint ~* '(subscribe|checkout|stripe|upgrade|pay)'
ORDER BY timestamp DESC;
product_not_received の申し立てでは、ユーザーが自己申告した cancel_reason を確認します。「Poor user experience」や、利用したことを認める内容を理由に解約している場合、このフィールドは申し立てに直接反します。記載内容をそのまま引用しますが、ひとつの事実から勝率を推測してはなりません。
4. 裏付けとなる書類をダウンロードする
FOLDER="$EVIDENCE_DIR/$(echo $CUSTOMER_NAME | tr '[:upper:] ' '[:lower:]-')-$(date +%Y-%m)"
mkdir -p "$FOLDER"
# Invoice PDFs (URLs come from the Stripe invoice objects)
curl -sL "$INVOICE_PDF_URL" -o "$FOLDER/invoice.pdf"
5. 利用規約/解約ポリシーを PDF として取得する
Playwright(Node)を使用します。
node -e "
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1280, height: 900 } });
await page.goto(process.env.TERMS_URL, { waitUntil: 'networkidle' });
await page.pdf({ path: process.argv[1], format: 'A4', printBackground: true });
await browser.close();
})();
" "$FOLDER/cancellation_policy.pdf"
6. アクティビティログの PDF を生成する
簡潔で確認しやすい HTML アクティビティログを作成し、WeasyPrint で PDF に変換します。
from weasyprint import HTML
HTML('activity_log.html').write_pdf('activity_log.pdf')
顧客名や住所の文字化けを防ぐため、HTML には <meta charset="UTF-8"> を含める必要があります。
確認しやすいレイアウト:
- サマリーグリッド — 顧客/メールアドレス/内部ユーザー ID/Stripe 顧客 ID/アカウント作成日/プラン/サブスクリプション開始日/キャンセル日時(登録からの経過時間を含む)/自己申告のキャンセル理由/消費したクレジットまたはユニット数/購入時 IP アドレス/請求先住所/支払い方法(下 4 桁、ブランド)/Stripe のリスク評価/紹介元/支払いのきっかけ
- 支払い履歴テーブル — すべての請求書について、日付、金額、ステータスを記載します。異議申し立ての対象となった行を赤色で強調表示します。 「異議申し立て対象?」という列を追加し、明確に「はい」または「いいえ」を記載します。
- チェックアウト試行テーブル — 意図的に購入したことを示します(
fraudulentの申し立てを退ける材料になります)。 - 作成/使用したアイテムのテーブル — 名前、種類、タイムスタンプを記載します。具体的な使用状況は、形容詞よりも有効です。
- ログインアクティビティログ — すべてのセッションについて、タイムスタンプ、国、デバイスを記載します。一貫性があれば、同じカード所有者によるものだと示せます。
- タイムラインの概要 — 「そして $DATE に異議申し立てが提出されました。」で締めくくる、時系列順の簡潔な説明を記載します。
- 結論の段落 — ユーザー自身の
cancel_reasonが申告された異議申し立ての理由と矛盾する場合は、その内容を引用します。
形容詞よりも具体的な数値を優先します。「ログインセッション 29 回、名前付きプロジェクト 3 件、消費クレジット数 29,960」のほうが、「広範囲に利用」よりも有用です。
7. 送信前にすべてをユーザーに提示する
open "$FOLDER"
反論文、証拠ファイル、勝訴確率の評価を表示します。ユーザーから明示的な承認を得るまで待ちます。
8. 証拠ファイルを Stripe にアップロードする
ファイルのアップロード先は api.stripe.com ではなく files.stripe.com です。ホストが異なります。
curl -s -u "$STRIPE_SECRET_KEY:" \
-F "purpose=dispute_evidence" \
-F "file=@$FOLDER/activity_log.pdf" \
https://files.stripe.com/v1/files
{"id": "file_xxx", ...} が返されます。この id を控えてください。証拠フィールドで参照するのはこの値です。
異議申し立て 1 件につき file_id は 1 つです。 複数の異議申し立てで同じ file_id を再利用すると、Stripe は 400 "That file is already attached to something else" を返します(特に service_documentation の場合)。同じ顧客に対する N 件の異議申し立てに対応する際は、共通の PDF をそれぞれ N 部アップロードします。内容は同じでも、毎回新しい file_id を使用してください。
9. 証拠を提出する(提出は一度だけ — submit=true は最終操作です)
curl -s -u "$STRIPE_SECRET_KEY:" \
-X POST "https://api.stripe.com/v1/disputes/$DISPUTE_ID" \
-d "evidence[uncategorized_text]=$REBUTTAL_TEXT" \
-d "evidence[uncategorized_file]=$ACTIVITY_LOG_FILE_ID" \
-d "evidence[receipt]=$INVOICE_FILE_ID" \
-d "evidence[cancellation_policy]=$TERMS_FILE_ID" \
-d "evidence[cancellation_policy_disclosure]=$CANCEL_DISCLOSURE_TEXT" \
-d "evidence[refund_policy]=$TERMS_FILE_ID" \
-d "evidence[refund_policy_disclosure]=$REFUND_DISCLOSURE_TEXT" \
-d "evidence[cancellation_rebuttal]=$CANCEL_REBUTTAL_TEXT" \
-d "evidence[access_activity_log]=$ACCESS_LOG_SUMMARY" \
-d "evidence[service_date]=$SERVICE_START_DATE" \
-d "evidence[product_description]=$PRODUCT_DESCRIPTION" \
-d "evidence[customer_email_address]=$CUSTOMER_EMAIL" \
-d "evidence[customer_name]=$CUSTOMER_NAME" \
-d "evidence[customer_purchase_ip]=$PURCHASE_IP" \
-d "evidence[billing_address]=$BILLING_ADDRESS" \
-d "submit=true" \
"https://api.stripe.com/v1/disputes/$DISPUTE_ID"
レスポンスを確認します。
statusがunder_reviewであることevidence_details.has_evidenceがtrueであることevidence_details.submission_countが1であること
異議申し立ての理由別の証拠戦略
fraudulent
目標:カード所有者が購入したことを証明します。
- 同じカードで過去に行われた、異議申し立てのない支払い(最も有力)
- OAuth ログイン(Google/Apple)=本人確認済みの登録
- セッション間で一貫している IP アドレス/国/デバイス
- 購入前に複数回チェックアウトを試行していること=実在の人物が検討した証拠
- Stripe 独自のリスク評価が
normalだったこと - サブスクリプションが引き続き有効で、キャンセルされていないこと
product_not_received
目標:商品が提供され、使用されたことを証明します。
- ログインアクティビティログ
- 商品内で作成したアイテム/実行したアクション
- キャンセルしている場合は、顧客自身が申告したキャンセル理由を異議申し立ての主張と照らし合わせて、一字一句そのまま引用します。
- 領収書とウェルカムメール
product_unacceptable
目標:商品が説明どおりであり、顧客が使用したことを示します。
product_not_receivedと同じ証拠に加え、品質/返金ポリシーに関する利用規約の文言- 顧客がサポートチケットを一度も作成していないことを強調します。
subscription_canceled
目標:顧客がキャンセルしていないこと(または更新後にキャンセルしたこと)を証明します。
- 更新日時点で
cancel_at_period_end=falseを示すサブスクリプションオブジェクト - 更新日以降のすべてのログイン/利用アクティビティ
- 年間プランの更新には明示的なキャンセルが必要であると定めた利用規約の文言
反論テンプレート
uncategorized_text
[Customer name] は [date] に [auth method] を利用して [Product name] のアカウントを作成し、同じ [card brand] のカードで [plan]($[amount]/[interval])に登録しました。最初の [N] 回の支払いについては、異議申し立てが一度もありませんでした。顧客はサービスを積極的に利用していました。[country] から [device] で [N] 回ログインし、[N] 件のアイテム([list])を作成し、[N] [units] を消費しました。異議申し立ての対象となった請求は、[date] の [renewal/initial] 支払いです。サブスクリプションのステータスは [status] で、現在も [active/cancelled] です。顧客から、解約または返金を求める連絡がサポートに届いたことはありません。解約ポリシーと返金ポリシーは [TERMS_URL] に掲載しています。これは不正な取引ではありません。このアカウントでほかに [N] 回の異議申し立てのない支払いを [made/has made] したカード名義人本人による正当な購入です。
cancellation_policy_disclosure
解約ポリシーは [TERMS_URL] に掲載しています。登録者はいつでも解約でき、請求期間の終了まで引き続きアクセスできます。この顧客は解約していません。
refund_policy_disclosure
返金ポリシーは [TERMS_URL] に掲載しています。[N] 日間の返金保証を提供しています。顧客はその期間内にも、それ以外の時点にも、返金を求めていません。
重要な注意事項
- ファイルのアップロード先は
files.stripe.comです。api.stripe.comではありません - 異議申し立てごとに送信できるのは1回のみです。
submit=trueは取り消せません - 証拠の提出期限は
evidence_details.due_by(UNIX タイムスタンプ)です。期限後は提出できません - データベースへのクエリは読み取り専用にしてください。可能であれば、接続ロールを制限してください
- アクティビティログの PDF に、ほかの顧客のデータを含めないでください
- 同じ顧客から今後異議申し立てがあった場合に参照できるよう、証拠一式を毎回ディスクに保存してください
価値の高い矛盾のパターン
顧客が登録して製品を短時間利用し、アプリ内の解約フォームで「ユーザーエクスペリエンスが悪い」として数時間以内に解約した後、数日後に「製品を受け取っていない」と主張してチャージバックを申請します。
解約フォームに記載された理由は、チャージバックの主張と直接矛盾しています。手数料と過去の結果に基づく判断基準を適用しつつ、記載内容を一字一句そのまま反論書に引用してください。
異議申し立ての理由が product_not_received または product_unacceptable の場合は、必ず最初に users.cancel_reason(または同等の項目)を確認してください。