处理支付成功但数据库更新失败

9
我正在尝试在我的Express.js路由中实现Stripe结帐流程。为此,我已经准备好了以下工具和资源:
  • 官方 Node.js Stripe 模块
  • 官方客户端 Stripe 模块
  • 一个 JSON 日志记录器,我用它来记录诸如 JavaScript 错误、来自 stripe、mongodb 等外部服务的传入请求和响应等信息
  • 使用 mongoose(MongoDB ODM)定义的订单模型 Order
我的步骤如下:
客户端:
  1. 提交包含 Stripe 支付令牌的订单详细信息。
服务器端:
  1. 创建一个未支付的订单并保存到数据库中(order.statuscreated
  2. 使用 Stripe 客户端对用户的信用卡/借记卡进行扣款
  3. 更新订单并将其保存到数据库中(根据 Stripe 的响应,order.status 要么是 accepted,要么是 failed
问题: 如果在第 2 步中支付成功,但在第 3 步中更新订单时发生错误(由于数据库服务器故障或类似原因),有哪些适当的方法可以处理这种失败情况并可能从中恢复?

1
一个确认系统?重试直到收到正面的ACK。 - JuliandotNut
好主意。可以使用 async.js retry 函数将 db save 调用进行包装,并尝试 5 次 (https://github.com/caolan/async#retry)。我认为还有进一步改进的空间。 - George Haidar
1个回答

4
使用支付系统时,您总是需要一个基于健康会计原则的汇总过程(每小时、每天、每月),以检查每一笔资金流是否匹配。
在您的情况下,我建议每个外部异步调用都记录发送的参数和接收到的响应。如果您在一定时间内没有得到响应,则知道外部系统(在您的情况下为Stripe)或从外部系统返回的方式出现了问题(您提到了自己那边的数据库故障)。
基本上,对于您生成的每个异步“交易”,您都知道何时开始它,并必须决定一个合理的结束时间。因此,您在数据库中有一个expected_end_ts。
如果您在expected_end_ts之后仍未收到答案,则知道出现了问题。然后,您可以向Stripe或另一个PSP询问状态。希望API会给您一个明智的答案,告诉您付款是否已经完成。
还要注意,在1和2之间应该添加一个步骤:重新阅读数据库。您想确保您发出的每个付款请求都真正存储在数据库中,并且完全按照您将要发送的方式存储。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接