捐赠页本身半天就做完了:几个可选金额、一个自填框、姓名、是否匿名、一句留言,5 个字段。剩下的时间都在跟支付回调较劲。
回调那两件事
第三方支付通知我们的地址,第一版我们收到就改订单状态、记一笔捐赠。上线第三天出问题:同一笔捐赠被记了 2 次。查日志,对方把同一条通知重发了,我们没做幂等。
改成按商户订单号加唯一索引,重复通知直接返回成功,不再写库。这里有个坑:得先校验签名再判重,别看到一个重复号就回成功,万一是伪造的。
第二件事更麻烦:有一笔通知延迟了 40 分钟才到。用户在页面上早就看到「支付成功」,后台还挂着未确认,财务那边的当天汇总就少了它。
主动查单
光等回调不够。加了一个定时任务,每 30 分钟扫一次「已创建但未确认」且超过 10 分钟的订单,主动调支付方的查单接口,以对方结果为准。
主动查单和被动回调都往同一张 donations 表写,靠那个唯一索引挡重复。两边谁先到都行,这是关键。
另外给财务留了个手动「补单」入口,凭商户订单号查一次,需要权限,操作留日志。上线到现在用过 2 次,都是对方那边真丢了通知。
每天下午那张表
财务要的是能对账的东西,不是后台页面。每天下午 5 点导出一张 Excel:商户订单号、捐赠人、金额、支付方式、支付时间、是否匿名、留言,7 列,按支付时间排。匿名那行捐赠人写「匿名」,但订单号还在,能对上。
头一周对出 3 笔差异:2 笔是回调延迟、1 笔是用户付了又立刻取消,状态不同步。都在查单那步补上了。
6 月 28 号
上线那天下午,第一笔捐款是 200 元,留言栏写着「给学弟学妹买书」。我们把那行截了图,没发群里,存在项目文件夹里。
后来页面加过一个「开具票据」的勾选,字段从 5 个变 6 个。改动很小,倒是财务那张导出多了两列,折腾了一小时。

