订阅功能刚上线时,我把逻辑塞进了最顺手的地方:前端。浏览器管界面、发起结账、处理跳转,顺便把订阅状态也更新了。省事,但埋下了一个结构性隐患。
浏览器是好用的交互层,却不是可靠的信任边界。一旦涉及资金和账户权限,这个区别就很要命。
最近我重做了整个流程。账单和认证不再依赖浏览器里的状态,而是走服务端验证的路由;生产环境的会话传输收紧;订阅状态靠对账和Webhook驱动更新,而不是UI的乐观假设。
目标不是"绝对安全"——是让系统在认证和账单状态不一致时,更容易判断对错、更容易防御、更容易推理。
客户端主导账单的毛病从哪来
很多账单系统变"前端重",是一系列合理决策堆出来的:客户端发起结账、客户端处理跳转返回、客户端立即更新套餐状态、客户端成了订阅状态的第一解释者。
但这些事件不等价。跳转是用户体验事件,不是本地应用状态正确的证明。一旦钱和账户权限卷进来,这个区分就至关重要。
账单状态越依赖浏览器时机、浏览器假设、乐观UI更新,出问题时越难信任系统。
架构怎么改
核心变化很简单:浏览器可以请求账单操作,但不能当账单结果的权威。
新模型分成四层:浏览器负责交互,服务端验证身份,账单提供商确认商业状态,数据库记录权益,Webhook长期纠正订阅漂移。
真正的转变是:浏览器不再充当账单状态的记录系统。
边界为什么重要
账单逻辑离浏览器太近,几种故障模式会很常见:陈旧UI状态被误认为真实权益、跳转被当成成功激活、提供商和应用状态分道扬镳、账单正确性难以审计、故障难以定位。
把账单移到服务端验证流程后面,并没有消除复杂度,只是把复杂度挪到了更合适的运行时。
好架构不是逻辑更少,是逻辑放在对的地方。
具体改了四块
第一,账单敏感操作移到认证后的服务端路由。不再让浏览器直接跟Stripe打交道,而是走带会话验证的端点,服务端确认调用者身份后再执行。
第二,生产环境收紧会话传输。开发时图方便用的设置,上线后全部加固。
第三,用Webhook和定期对账替代乐观更新。UI可以猜测状态,但真实权益以服务端记录为准,提供商的回调和主动对账负责纠偏。
第四,认证和账单路由共享同一套会话验证。减少边界处的特殊处理,降低"这里认、那里不认"的混乱。
不是变安全,是变正确
改完之后,系统没有"更安全"的绝对感。但状态不一致时,排查路径清晰了;审计时,数据来源确定了;出问题时,责任边界明确了。
浏览器回到它该在的位置:请求事情,但不决定事情。
热门跟贴