|
2023年11月,微信广州一个做服装批发生意的支付老板老陈,在凌晨两点收到一条微信支付到账提醒:18450元。漏洞他翻了个身继续睡。微信第二天早上打开手机,支付发现那笔钱确实进了零钱账户,漏洞但对应的微信订单——一个陌生ID拍的十件羽绒服——根本没发货。他查了后台,支付订单状态显示"已关闭"。漏洞钱却到了。微信 这不是支付灵异事件。老陈后来在同行群里一说,漏洞炸出七八个遇到过类似情况的微信人。有人收到过三块五,支付有人收到过两千多。漏洞共同点是:订单最终都关闭了,钱却留在账户里。金额不大不小,刚好卡在不会立刻触发风控的区间。 微信支付的逻辑漏洞,往往藏在"异步"两个字里。用户下单、支付、订单状态更新、资金清算,这几个动作在系统里不是一条直线跑完的。它们像几列不同时刻发车的火车,偶尔会错开。错开的那几秒或几分钟,就是缝隙。 我拿到过一个测试案例。某小程序商城做促销,库存只有1件,两个用户同时点击"立即购买"。支付请求几乎同时到达微信服务器。按正常流程,先完成支付的那个应该锁定库存,另一个支付失败。但实际结果是:两笔钱都扣了,库存只减了1。第二个用户的钱在支付成功页面上显示"已支付",但订单被系统自动关闭。退款?没有自动退。要用户自己找客服,客服再走工单,工单流转三天,钱才回来。 这里面有个关键角色叫"支付回调"。微信支付成功后,会向商户服务器发一个通知:"这笔钱到了,你可以发货了。"如果商户服务器因为网络抖动、代码bug、或者单纯处理慢了,没有及时回应"收到",微信会重试。重试间隔是15秒、15秒、30秒、3分钟、10分钟……一直到24小时内多次尝试。有些商户系统没做幂等处理——同一个回调通知来两次,它就当两笔订单处理。结果就是:用户付了一笔钱,系统记了两笔账。 更隐蔽的是"退款接口"的并发问题。一个用户同时发起两笔退款申请,金额相同,收款方相同。商户后台如果没加锁,两笔退款请求可能同时读到同一个可退余额,然后各自扣减。最终用户收到两笔退款,商户账户被多扣一次。这个漏洞在2022年之前被几个薅羊毛团伙盯上过,专挑中小电商下手,单笔金额控制在500以内,一天刷几十笔。 微信官方对这些问题的回应一直很克制。他们有个"支付安全中心",但普通商户很难直接对接。大部分漏洞的修复方式是把责任推给商户:你要自己做幂等,你要自己加分布式锁,你要自己处理回调重试。可中小商户的技术能力摆在那里,很多人连"幂等"这个词都没听过。 我认识一个做SaaS服务的技术负责人,他给客户做微信支付对接时,强制加了一层"支付中间件"。所有回调先落库,标记唯一ID,再异步处理业务逻辑。退款请求全部走队列,串行执行。这套东西不复杂,但能挡住九成以上的并发漏洞。他说了一句话我印象很深:"微信支付把便利给了用户,把复杂度给了开发者。可很多开发者根本接不住这个复杂度。" 老陈那笔18450元,最后被微信风控系统追回了。方式是直接从他的零钱账户扣走,没有提前通知。他收到一条"资金异常变动"的站内信,点进去看,钱已经没了。他打电话给客服,客服说"系统检测到异常交易,已自动处理"。老陈问什么异常,客服说"无法告知具体规则"。 所以你看,漏洞这东西,有时候是技术问题,有时候是规则问题。微信支付每天处理十几亿笔交易,绝对不出错是不可能的。但出错之后怎么处理、谁来承担、规则透不透明,这些问题的答案,比漏洞本身更值得琢磨。 |