你的 Stripe 支出不是你的收入:如何将 Stripe 与账簿核对
Your Stripe Payouts Are Not Your Revenue: How to Reconcile Stripe to Your Books
我们发现了什么
你的 Stripe 支出不是你的收入:如何将 Stripe 与账簿核对。Bennett Financials 创始人 Arron Bennett:我接触的大多数自筹资金型 SaaS 公司账簿都有一个不易察觉的错误。
- 来源:DEV Community(发现于 2026-10-28)
- 证据等级:B · 来源中出现收入或付费客户自述;本站未核对该金额,不代表本站背书。
- 商业模式:Subscription SaaS
- 主题:独立产品
- 初筛评分:16/100 · 收录 1 次
证据,比故事更重要。
规则清洗与初筛,未经人工商业核验。原文语境、实际客户和付费情况仍需自行验证。
引用与数字披露
来源类型(原作者自述/第三方测算/媒体转引)需采集端标注,本版尚未落字段。
- 作者
- 未标注
- 抓取日期
- 来源类型
- 未标注
- 币种
- 未标注
- 口径
- 未标注
- 披露主体
- 未标注
- 披露日期
- 未标注
上下文核对:来源原文含限定词MRRforecast预测,中文摘要未逐字保留 —— 引用或跨期比较前请回原文核对,别把估算读成已实现。
中文辅助译文(全文)
Arron Bennett,Bennett Financials 创始人
我接触过的自筹资金型 SaaS 公司,其账目往往都有同一个不易察觉的错误。每笔 Stripe 付款到账都进了银行,于是有人把每笔付款都记作收入。银行余额能够对上。账目看起来也很干净,但收入数字仍然是错的,建立在其上的每一项利润率指标也都错了。
Stripe 付款并不是一笔销售,而是一组销售减去手续费、退款和拒付后的净额,并在资金到账几天后汇出。本文将介绍一笔付款实际包含哪些内容、如何用一段简短的脚本将其拆分,以及如何设置账务体系,使两者保持一致。
核心要点
- Stripe 付款是净额,其中包含总收款额、Stripe 手续费、退款和拒付。
- 将付款记作收入会低估收入、隐藏手续费,并掩盖退款。
- 应将总收款额记作收入,将手续费记作费用,然后让二者都通过 Stripe 结算账户处理。
- 余额交易 API(或 Payout reconciliation 报告)可以准确告诉你每笔付款包含哪些内容。
Stripe 对账究竟意味着什么?
Stripe 对账是指证明:银行中的每笔付款都等于 Stripe 所称构成该付款的收款、手续费、退款和拒付之和,并且每个部分都记入了正确的账户。收入计入收入账户,手续费计入费用账户,退款冲减收入。当结算账户的余额净额归零时,你就已完成对账。
银行永远只能看到净额,而你的账本需要的是总额。
为什么 Stripe 付款不等于收入?
Stripe 在向你付款之前会先扣除手续费。退款和败诉的拒付也会从同一余额中扣除,而且付款按既定时间表汇出,因此一个月最后几天的收款要到下个月才会进入银行账户。如果把存款记作收入,所有这些差异都会被吞没在一个错误的数字里。
下面是一个假设示例。一家由两名创始人经营、专门托管开发者文档的 SaaS 公司 MRR 为 $29,000,全部通过 Stripe 收款。以下所有数字均为虚构,旨在说明其运作机制。请替换为你自己的数据。
该公司在一个月内向客户收取 $31,200,退款 $640,发生一笔 $480 的拒付损失和 $15 的拒付手续费(这是一个假定数字,因此请核对你自己的数据),并支付 $1,150 的处理费。
因此,付款总额为 $28,915,即 $31,200 − $640 − $480 − $15 − $1,150。
如果簿记员将 $28,915 记作收入,收入就被低估了 $2,285。其中 $1,165 的手续费和拒付成本从未作为费用入账,另有 $1,120 的退款和拒付损失完全没有得到体现。仅手续费一项就占总收款额的 3.7%,但在损益表上没有任何对应项目。
如何查看 Stripe 付款中包含的内容?
Stripe 余额中的每笔变动都是一条余额交易,其中包含总额 amount、手续费 fee 和净额 net,所有金额均以该货币的最小单位表示,例如美元的分。对于自动付款,你可以列出某笔付款中已汇出的全部余额交易,并按 reporting_category 对其分组。
下面是一个最小化的 Python 版本。请使用权限受限的只读密钥。
import os
from collections import defaultdict
import stripe
stripe.api_key = os.environ["STRIPE_READ_KEY"] # restricted, read-only
def explain_payout(payout_id):
payout = stripe.Payout.retrieve(payout_id)
totals = defaultdict(lambda: {"gross": 0, "fee": 0, "net": 0})
txns = stripe.BalanceTransaction.list(payout=payout_id, limit=100)
for t in txns.auto_paging_iter():
if t.type == "payout":
continue # the payout itself, not what's inside it
row = totals[t.reporting_category]
row["gross"] += t.amount
row["fee"] += t.fee
row["net"] += t.net
net_sum = sum(r["net"] for r in totals.values())
for cat, r in sorted(totals.items()):
print(f"{cat:<12} gross {r['gross']/100:>11,.2f} fee {r['fee']/100:>9,.2f} net {r['net']/100:>11,.2f}")
print(f"payout {payout.amount/100:,.2f} | sum of nets {net_sum/100:,.2f} | match: {net_sum == payout.amount}")
explain_payout("po_...")最后一行才是关键检查。如果各净额之和等于付款金额,你就准确知道了这笔存款包含哪些内容。如果不相等,差额就是需要查明的原因,例如调整、储备金或手动付款。payout 筛选条件仅适用于自动付款。如果你是手动触发付款,请改用 Stripe Dashboard 中的 Payout reconciliation 报告。
你不需要永远对每笔付款都运行这段脚本。可以先用一个月的数据运行它来验证方法,然后让你的记账工具通过 Stripe 集成,或依靠月度报告完成日常处理。
账本中应如何设置 Stripe?
应将 Stripe 当作一个银行账户处理。创建一个“Stripe 结算”账户,将总收款额记入该账户作为收入,从该账户扣除手续费作为费用,从该账户扣除退款并冲减收入,并将每笔付款记作从结算账户转入银行的转账。月末时,结算账户余额应等于 Stripe 账户余额。
对于这个文档托管示例,当月账目应如下:
- 收入:总收款额 $31,200。
- 退款和拒付损失:$1,120,冲减收入。
- 支付处理费:$1,165,列为运营费用。
- 转入银行:$28,915,这笔金额不应计入收入。
结算账户增加 $31,200,并分别减少 $1,120、$1,165 和 $28,915,因此最终余额为零。如果付款时间延后至月末之后,余额就不会为零,而会等于 Stripe 仍为你保留的金额,这是正常的。余额如果每个月都在变动,就说明有某些项目被遗漏了。
还有一点值得关注。如果 Stripe 曾在你的账户中保留储备金,这笔钱属于你,但你无法动用。它应计入结算账户,而不应计入现金预测。我写过更多关于支付处理商储备金与可用现金的文章。
这篇短文并非只针对 Stripe。它讨论的是同一个问题从另一侧呈现的结果:损益表显示盈利,银行账户却无法支付工资。正是这种差异促使我希望账本和银行讲述同一个故事。
账目正确后会发生什么变化?
三件事会同时变得真实。收入会反映客户实际支付了多少钱。处理费会作为一项可以管理的成本显现出来。退款也会变得可见,从而避免产品或新手引导问题被隐藏在金额较小的存款中。
当你第一次查看毛利率、制定套餐价格,或与任何会仔细审视你数字的人交流时,例如贷款人、投资者或买家,这一点都很重要。对 SaaS 业务进行尽职调查时,需要将 Stripe 与银行和账本进行核对。最好由你先找出其中的差异。
这也能让退款成为一个可供采取行动的指标。如果发现退款持续上升,应在同一次审查中查看支付失败与挽回。两者都会让收入悄然流失。
周一应该做什么?
从选上个月开始。调取每笔付款,运行脚本或 Payout reconciliation 报告,并汇总总收款额、手续费、退款和拒付。将总收款额与账本中的收入进行比较。如果账本记录的是付款总额,请设置 Stripe 结算账户,并以正确方式重新登记该月的账目。然后将这套规则用于之后的每一个月。
这件事需要两个小时,而且能永久修正你的收入项目。
常见问题
我应该将 Stripe 手续费记作费用,还是从收入中抵减?
应将其记作费用。收入应当是客户实际支付的金额。手续费是收取收入所产生的成本,而只有看得见的成本才能得到管理。
为什么我的 Stripe 付款与当月销售额不一致?
因为付款是扣除手续费、退款和拒付后的净额,并且按既定时间表汇出。一个月最后几天的销售额通常要到下个月才会进入银行存款。
Stripe 付款是否包含退款和拒付?
是的。退款和败诉的拒付会减少你的 Stripe 余额,因此会从下一笔付款中扣除。如果退款金额超过收款额,一笔付款甚至可能为负数。
我需要软件来对 Stripe 进行对账吗?
开始时不需要。Payout reconciliation 报告或一段简短的脚本就足以处理一个月的数据。在此之后,一旦设置好结算账户,大多数会计工具的 Stripe 集成都可以为你登记总收款额、手续费和退款。
译文由上游机器翻译生成,可能有误;判断请以英文原文为准。
英文原文(来源本站未改写)
Arron Bennett, Founder of Bennett Financials
Most bootstrapped SaaS books I open have the same quiet error. Every Stripe payout landed in the bank, and someone booked each one as revenue. The bank matches. The books look clean. The revenue number is still wrong, and so is every margin built on top of it.
A Stripe payout isn't a sale. It's a bundle of sales, minus fees, minus refunds, minus disputes, sent a few days after the money came in. This post covers what a payout actually contains, how to split one apart with a short script, and the bookkeeping setup that keeps the two in step.
Key takeaways
- A Stripe payout is a net number. Gross charges, Stripe fees, refunds and disputes are all inside it.
- Booking payouts as revenue understates revenue, hides fees, and buries refunds.
- Book gross charges as revenue and fees as an expense, then run both through a Stripe clearing account.
- The balance transactions API (or the Payout reconciliation report) tells you exactly what each payout contains.
What does Stripe reconciliation actually mean?
Stripe reconciliation means proving that every payout in your bank equals the charges, fees, refunds and disputes Stripe says made it up, and that each piece is booked in the right account. Revenue goes to revenue, fees to expenses, refunds against revenue. When the clearing account nets to zero, you're reconciled.
Your bank only ever sees the net. Your books need the gross.
Why are Stripe payouts not the same as revenue?
Stripe takes its fees out before it pays you. Refunds and lost disputes come out of the same balance, and payouts arrive on a schedule, so charges from the last days of a month land in next month's bank account. Book the deposit as revenue and every one of those differences disappears into a single wrong number.
Here's a hypothetical example. A two-founder developer-docs hosting SaaS at $29,000 of MRR, all on Stripe. Every number below is made up to show the mechanics. Swap in yours.
In one month the business charges customers $31,200. It refunds $640, loses one $480 dispute plus a $15 dispute fee (an assumed figure, so check your own), and pays $1,150 in processing fees.
So the payouts total $28,915, which is $31,200 − $640 − $480 − $15 − $1,150.
If the bookkeeper records $28,915 as revenue, revenue is understated by $2,285. That's $1,165 of fees and dispute costs that never show up as an expense, and $1,120 of refunds and lost disputes that never show up as anything. The fees alone are 3.7% of gross, and they have no line on the P&L.
How do you see what's inside a Stripe payout?
Every movement in your Stripe balance is a balance transaction with a gross amount, a fee and a net, all in the smallest currency unit, so cents for USD. For automatic payouts, you can list every balance transaction that was paid out in one payout and group them by reporting_category.
Here's a minimal Python version. Use a restricted, read-only key.
import os
from collections import defaultdict
import stripe
stripe.api_key = os.environ["STRIPE_READ_KEY"] # restricted, read-only
def explain_payout(payout_id):
payout = stripe.Payout.retrieve(payout_id)
totals = defaultdict(lambda: {"gross": 0, "fee": 0, "net": 0})
txns = stripe.BalanceTransaction.list(payout=payout_id, limit=100)
for t in txns.auto_paging_iter():
if t.type == "payout":
continue # the payout itself, not what's inside it
row = totals[t.reporting_category]
row["gross"] += t.amount
row["fee"] += t.fee
row["net"] += t.net
net_sum = sum(r["net"] for r in totals.values())
for cat, r in sorted(totals.items()):
print(f"{cat:<12} gross {r['gross']/100:>11,.2f} fee {r['fee']/100:>9,.2f} net {r['net']/100:>11,.2f}")
print(f"payout {payout.amount/100:,.2f} | sum of nets {net_sum/100:,.2f} | match: {net_sum == payout.amount}")
explain_payout("po_...")The last line is the check that matters. If the sum of nets equals the payout amount, you know exactly what's in that deposit. If it doesn't, the gap is something you need to find, such as an adjustment, a reserve or a manual payout. The payout filter only works for automatic payouts. If you trigger payouts by hand, use the Payout reconciliation report in the Stripe Dashboard instead.
You don't need to run this on every payout forever. Run it on one month, prove the method, then let your bookkeeping tool's Stripe integration or a monthly report do the routine work.
How should Stripe be set up in the books?
Treat Stripe like a bank account. Create a "Stripe clearing" account, record gross charges into it as revenue, take fees out of it as an expense, take refunds out of it against revenue, and record each payout as a transfer from clearing to the bank. At month end, the clearing balance should equal the Stripe balance.
For the docs-hosting example, the month books like this:
- Revenue: $31,200 of gross charges.
- Refunds and lost disputes: $1,120, against revenue.
- Payment processing fees: $1,165, as an operating expense.
- Transfers to the bank: $28,915, which revenue never touches.
The clearing account goes up by $31,200 and down by $1,120, $1,165 and $28,915, so it lands on zero. If payouts lag the month end, it won't be zero. It'll equal whatever Stripe still holds for you, and that's correct. A balance that drifts every month means something is being missed.
One more thing worth watching. If Stripe ever holds a reserve on your account, that money is yours but you can't spend it. It belongs in clearing, not in your cash forecast. I've written more on processor reserves and available cash.
This short isn't about Stripe. It's about the same gap from the other side: a profitable P&L and a bank account that can't cover payroll. That gap is the reason I want the books and the bank telling the same story.
What changes when the books are right?
Three things get honest at once. Revenue shows what customers really paid. Processing fees show up as a cost you can manage. And refunds become visible, so a product or onboarding problem stops hiding inside a smaller deposit.
That matters the first time you look at gross margin, price a plan, or talk to anyone who will read your numbers closely, such as a lender, an investor or a buyer. Diligence on a SaaS business reconciles Stripe to the bank and the books. Better that you find the gaps first.
It also makes refunds a number you can act on. If you find refunds climbing, look at failed payments and recovery in the same review. Both are revenue leaving quietly.
What should you do on Monday?
Pick last month. Pull every payout, run the script or the Payout reconciliation report, and total gross charges, fees, refunds and disputes. Compare gross charges with the revenue in your books. If the books show the payout total instead, set up a Stripe clearing account and rebook the month the right way. Then make it the rule for every month after.
It's a two-hour job. It fixes your revenue line for good.
FAQ
Should I record Stripe fees as an expense or net them against revenue?
Record them as an expense. Revenue should be what customers paid. Fees are a cost of collecting it, and you can only manage a cost you can see.
Why doesn't my Stripe payout match my sales for the month?
Because payouts are net of fees, refunds and disputes, and they arrive on a schedule. Sales from the last few days of a month often land in next month's bank deposits.
Does a Stripe payout include refunds and disputes?
Yes. Refunds and lost disputes reduce your Stripe balance, so they come out of the next payout. A payout can even come out negative if refunds outrun charges.
Do I need software to reconcile Stripe?
Not to start. The Payout reconciliation report or a short script covers one month. After that, most accounting tools' Stripe integrations can post gross, fees and refunds for you, once the clearing account is set up.
这条还缺什么证据?
下面每条都由本条已有字段推出(等级、理由、商业模式、来源次数、是否演示), 本站不生成推测性结论;通用验证方法放在方法论页。
- 只有单一来源找一手站点或其他渠道是否重复出现同一产品;社区热帖数量不等于商业进展。
通用验证清单(谁有这个问题/谁愿意付费/一个人能交付哪一小步)见我们的筛选方法。