mcpField
S
stripe-dispute

stripe-dispute

github.com/openclaudia其他722344 次安装1 周前更新
代码仓库

关于 stripe-dispute

stripe-dispute 是面向使用 Stripe 的 SaaS 团队的争议评估与举证技能。它先依据成本和历史结果判断是否值得抗辩,再在获批后整理并提交证据。

主要功能

  1. 01评估抗辩成本与预期价值
  2. 02查询争议及付款记录
  3. 03只读查询用户活动数据
  4. 04生成活动日志与条款 PDF
  5. 05获批后向 Stripe 提交证据

适用场景

  1. 01评估 Stripe 拒付是否值得抗辩
  2. 02为争议整理用户登录和使用记录
  3. 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)

先决定是否提出争议

接受争议也可能是正确的选择。绝不要仅仅因为存在争议案件就提交证据。

  1. 核实 Stripe 当前的价格。按目前美国标准定价,Stripe 会自动收取 15 美元的争议受理费,并在提交证据时再收取 15 美元的争议抗辩费。受理费无法退回。只有胜诉时才会退还抗辩费。如果这些金额有变动,请使用当前实时价格。
  2. 查询商户的 Stripe 实时争议历史。计算抗辩胜率时,只统计 evidence_details.submission_count > 0 的已结案争议。区分首次购买和续订;样本允许时,再细分到相同理由。报告胜诉数、败诉数、未结案件数和样本量。若没有完全匹配的先例,请明确说明。
  3. 计算盈亏平衡胜率,以及扣除抗辩费和整理证据所需人力成本后的预期价值。不要仅凭案件强度臆测胜率。
  4. 除非用户提供了不同阈值,否则采用保守的 30% 最低胜率阈值。如果可比数据无法支持达到该阈值,建议不回应争议。这样可以避免抗辩费,但争议金额和受理费仍无法挽回。
  5. 在整理文件、上传证据或提交之前,必须获得用户的明确批准。提交操作不可撤销且会产生费用。

步骤

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。如果用户取消时填写了“使用体验不佳”或任何承认使用过产品的内容,该字段就直接与索赔相矛盾。逐字引用该内容,但不要根据单一事实推断胜率。

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">,以免客户姓名和地址中的字符乱码。

便于审核的布局:

  1. 摘要网格 — 客户 / 电子邮件 / 内部用户 ID / Stripe 客户 ID / 账户创建时间 / 套餐 / 订阅开始时间 / 取消时间戳(附上与注册时间的间隔)/ 自述取消原因 / 已使用的点数或单位 / 购买 IP / 账单地址 / 付款方式(后四位、品牌)/ Stripe 风险评估 / 推荐来源 / 付款触发方式
  2. 付款历史表 — 列出每张发票的日期、金额和状态。用红色突出显示争议行。添加“是否有争议?”列,并明确填写“是”或“否”。
  3. 结账尝试表 — 证明客户有意购买(可反驳 fraudulent 争议理由)
  4. 已创建 / 已使用项目表 — 名称、类型、时间戳。具体用量比形容词更有说服力。
  5. 登录活动日志 — 每次会话均列出时间戳、国家/地区和设备。一致性 = 同一持卡人。
  6. 时间线摘要 — 按时间顺序撰写一段叙述,结尾为“随后于 $DATE 提交了争议。”
  7. 结论段落 — 如果用户自己的 cancel_reason 与所述争议理由矛盾,则引用该原因。

优先使用具体数字,而非形容词。“29 次登录会话、3 个已命名项目、已使用 29,960 点数”比“使用频繁”更有用。

7. 提交前向用户展示所有内容
open "$FOLDER"

展示反驳文本、证据文件和胜诉概率评估。等待用户明确批准。

8. 将证据文件上传到 Stripe

文件应上传至 files.stripe.com,而不是 api.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——你需要在证据字段中引用它。

每项争议都必须使用单独的 file_id。 如果你试图在多个争议中重复使用同一个 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] 笔付款均未遭到争议。该客户积极使用了这项服务:[device] 上来自 [country] 的 [N] 次登录会话,创建了 [N] 个项目([list]),并消耗了 [N] [units]。遭到争议的款项是 [date] 的[续订/初始]付款。订阅当时为 [status],目前仍为[有效/已取消]。该客户从未联系支持团队取消订阅或申请退款。我们的取消和退款政策发布于 [TERMS_URL]。这并非欺诈交易——这是持卡人发起的合法购买,该持卡人已在此账户上进行了其他 [N] 笔未遭争议的付款。

cancellation_policy_disclosure

我们的取消政策发布于 [TERMS_URL]。订阅者可随时取消,并在当前计费周期结束前继续使用服务。该客户从未取消订阅。

refund_policy_disclosure

我们的退款政策发布于 [TERMS_URL]。我们提供 [N] 天退款保证。该客户未在此期限内申请退款,也从未在任何时候申请退款。

重要说明

  • 文件上传至 files.stripe.com,而非 api.stripe.com
  • 每笔争议只能提交一次。submit=true 后即为最终提交
  • 证据提交截止时间为 evidence_details.due_by(Unix 时间戳)。超过截止时间后将无法再提交
  • 数据库查询必须为只读——如可行,请限制连接角色的权限
  • 活动日志 PDF 中不得包含其他客户的数据
  • 将每个证据包保存到磁盘,以便在该客户未来发生争议时查阅

高价值矛盾模式

客户注册后短暂使用产品,几小时内在应用内取消表单中以“用户体验不佳”为由取消,几天后却提出拒付,声称“未收到产品”。

取消表单中的原因与拒付声明直接矛盾。在驳回说明中逐字引用该内容,同时仍须遵循费用和历史结果决策门控。

当争议原因为 product_not_received 或 product_unacceptable 时,务必首先检查 users.cancel_reason(或等效字段)。

评论

支持 Markdown