最近看到一篇关于“Figma 所有套餐 0 元购”的文章,核心说法是利用地区、SEPA 付款和 IBAN 信息去尝试开通付费套餐。这类内容不能当成教程传播,但它背后的安全问题值得认真复盘:为什么有些订阅系统会让人感觉“没真正付款也拿到了权益”?漏洞到底出在前端、支付方式,还是服务端状态机?
先声明:本文仅做安全学习和防护复盘,不提供真实网站绕过支付、伪造付款资料、滥用 SEPA/IBAN 或开通未授权订阅的操作步骤。下面的“实战”是本地模拟场景,目的是帮助开发者理解风险并修好自己的系统。
这类传闻的本质
网上流传的 Figma 0 元购思路,大致会围绕几个关键词展开:
- 切换地区
- 选择 SEPA 一类的银行扣款方式
- 填写某种格式正确的 IBAN
- 让系统先进入付费套餐状态
真正值得关注的不是某个工具或某个国家,而是这个问题:
订阅系统到底是在“用户提交了付款资料”时发放权益,还是在“支付真正成功并可结算”后发放权益?
如果系统在前者就发权益,就容易出现空窗期:用户还没有真实付款,甚至付款之后可能被拒付、退回、撤销,但业务侧已经把套餐升级了。
为什么 SEPA 类支付更容易被误解
银行卡支付通常会给人一种即时成功或失败的感觉,但银行扣款、借记、转账类支付在很多场景下不是这样的。它可能有几个阶段:
- 创建付款意图
- 收集付款资料
- 等待银行处理
- 扣款成功
- 扣款失败
- 退款或争议
如果 SaaS 系统只看到了“付款资料已提交”或者“支付流程已创建”,就把账号升级为付费版,那么用户侧就会看到一种错觉:好像只要填一组看起来合法的信息,就能拿到付费权益。
严格来说,这不是“IBAN 本身万能”,而是系统把“支付流程中的中间状态”误当成了“最终到账状态”。
本地模拟:一个容易出问题的订阅流程
假设我们有一个 SaaS 产品,用户要升级到 Pro。错误设计可能是这样的:
用户选择套餐
-> 前端选择国家和付款方式
-> 服务端创建订阅
-> 支付服务商返回 checkout session created
-> 服务端立即把用户改成 Pro
-> 后续再等支付结果
这个流程最大的问题在第四步到第五步。
checkout session created 只代表“结账会话创建了”,不代表钱已经到账。对于某些异步支付方式,它更不代表最终成功。
错误伪代码大概长这样:
func HandleCheckoutCreated(userID string, plan string) {
// 错误:创建结账会话不等于支付成功
UpdateUserPlan(userID, plan)
}
这样一来,只要用户能让系统走到“结账会话创建成功”,就可能短暂拿到付费权益。
正确做法:支付状态机要分层
更稳妥的设计应该把订阅状态拆开:
free
pending_payment
active
past_due
canceled
blocked
用户提交付款资料后,最多进入 pending_payment,不能直接进入 active。
只有支付服务商通过可信回调告诉你“支付成功”,并且服务端校验金额、币种、订单、用户、套餐都一致后,才能发放权益。
更合理的伪代码是:
func HandleCheckoutCreated(userID string, plan string) {
CreateSubscription(userID, plan, "pending_payment")
}
func HandlePaymentSucceeded(event PaymentEvent) error {
order := FindOrder(event.OrderID)
if order.UserID != event.UserID {
return errors.New("user mismatch")
}
if order.Amount != event.Amount || order.Currency != event.Currency {
return errors.New("amount mismatch")
}
if !VerifyProviderSignature(event) {
return errors.New("invalid signature")
}
ActivateSubscription(order.UserID, order.Plan)
return nil
}
func HandlePaymentFailed(event PaymentEvent) {
MarkSubscriptionPastDue(event.UserID)
}
注意这里有几个关键点:
- 权益发放只发生在可信支付成功事件之后
- 支付事件必须验签
- 金额、币种、订单号、用户 ID、套餐必须逐项核对
- 失败、拒付、撤销要能把权益收回或冻结
前端为什么不是防线
很多“0 元购”文章会提到地区、地址、付款方式、前端结账页选择项。开发者容易误判为“只要前端不显示某个支付方式就安全了”。
这不够。
前端运行在用户浏览器里,用户可以:
- 修改请求参数
- 重放接口
- 使用代理观察流量
- 篡改前端状态
- 调用隐藏接口
- 使用脚本自动化提交
所以前端可以做体验控制,但不能做最终信任边界。
服务端必须重新判断:
- 该国家或地区是否允许这个支付方式
- 用户是否有资格使用这个价格
- 套餐和价格是否来自服务端价格表
- 优惠和折扣是否真实有效
- 付款资料是否来自支付服务商的可信 token
- 支付结果是否已经最终成功
Figma 免费版其实能覆盖什么
如果只是想正常用 Figma,不一定要上来就买付费版。按照 Figma 官方帮助文档,Figma 有 Starter、Professional、Organization、Enterprise 四类主套餐;Figma for Education 还为符合条件的学生和教育工作者提供免费访问。
普通个人使用,Starter 通常够做这些事:
- 学习 Figma 基础操作
- 做少量个人设计稿
- 查看和评论文件
- 轻量协作
- 尝试 FigJam、Slides、Design 等基础工作流
真正需要付费的场景,一般是:
- 团队项目和文件数量变多
- 需要更完整的版本、权限和协作管理
- 需要组织级设计系统
- 需要集中管理插件、组件库、成员和工作区
- 企业需要审计、安全、SSO、合规和更强的治理能力
所以与其冒账号和法律风险去找所谓“0 元购”,不如先判断自己到底卡在哪个限制上。
合法省钱思路
更稳妥的方式有几种:
- 个人学习先用 Starter。
- 学生和教师看是否符合 Figma for Education 条件。
- 团队先从少量付费席位开始,不要全员一刀切升级。
- 定期清理不用的编辑者席位。
- 把只需要查看、评论的人设为合适的非编辑权限。
- 年付前先用月付验证团队是否真的需要。
- 对企业需求,直接走官方销售和合规采购。
这些方式不刺激,但可持续,也不会把账号、项目文件和团队数据置于风险里。
SaaS 支付系统防护清单
如果你在做 SaaS 订阅系统,可以按下面这份清单自查。
订单与价格:
- 价格、币种、税费、折扣只由服务端计算
- 前端提交的 plan、price、country 只能作为候选输入
- 服务端保存订单快照,后续回调按快照核对
支付状态:
checkout_created不发放正式权益- 异步支付先进入
pending_payment - 只有
payment_succeeded或等价的最终成功事件才激活 payment_failed、dispute、refund、chargeback要能降级或冻结
回调安全:
- 所有支付回调必须验签
- 回调必须幂等
- 金额、币种、订单、用户、套餐逐项校验
- 失败事件不能被静默忽略
风控:
- 新账号高价值套餐延迟发放或限制高风险功能
- 异常地区、代理、设备、付款方式组合进入审核
- 同一支付资料、IP、设备、邮箱域名异常聚合要告警
- 免费试用、优惠券、异步支付方式要有单独限额
日志和审计:
- 记录 checkout session、payment intent、subscription、user、provider event 的关联
- 敏感字段脱敏
- 保留权益发放和收回日志
- 能快速回答“这个用户为什么被升级”
一句话总结
所谓 Figma 0 元购这类传闻,真正暴露的是订阅系统的信任边界问题:不能把“用户提交了付款资料”当成“支付已经成功”。对 SaaS 来说,防护重点不是藏前端按钮,而是把价格、订单、支付状态、权益发放全部收回服务端,并以支付服务商的可信成功事件作为唯一发放依据。
参考资料
- 原始选题来源:https://blog.chatai.codes/archives/10/
- Figma Pricing:https://www.figma.com/pricing/
- Figma plans and features:https://help.figma.com/hc/en-us/articles/360040328273-Figma-plans-and-features