GAE / P:API调用的交易安全性

时间:2019-04-27 23:09:16

标签: python google-app-engine transactions app-engine-ndb

假设您使用交易来处理Stripe付款并更新用户实体:

@ndb.transactional
def process_payment(user_key, amount):
    user = user_key.get()
    user.stripe_payment(amount) # API call to Stripe
    user.balance += amount
    user.put()

Stripe API调用可能会成功,但是put可能会因为争用而失败。然后会向用户收费,但他的帐户不会反映付款。

您可以将Stripe API调用从事务中拉出,然后再进行事务,但是看来您仍然遇到相同的问题。收费成功,但交易失败,并且未记入用户的帐户。

这似乎是一个非常普遍的情况。如何正确处理呢?

1 个答案:

答案 0 :(得分:2)

为使操作正常,事务功能必须是幂等的。因此,您无法在此类函数内进行条纹调用,因为这将使其成为非幂等。

我将分开调用数据条,并且在API成功后,我将调用一个事务处理功能来更新用户的帐户余额(在发生争用时可以安全地重试)。

甚至可以创建一个单独的独立实体来反映条纹API调用结果?这样的实体应该没有争用的余地,因为它只写入一次(发生条带事务时)。这将使您能够:

  • 保留帐户交易记录-指向这些实体
  • 进行一些健全性检查,以查找孤立的条带交易(如果由于某种原因,即使重试后帐户交易调用也失败了),并对此进行处理。

@thebjorn的评论很不错:多步骤方法可以使该过程非常可靠:

  • 一种交易功能,旨在执行条纹交易来更新帐户,该交易也transactionally enqueues a push task来执行条纹API调用。仅当事务成功时,任务才入队
  • 推送队列任务进行数据条API调用(最终创建数据条交易实体),并在成功后调用交易功能以更新帐户余额