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

2024-03-16

假设您使用交易来处理 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 调用从事务中取出,然后再执行事务,但似乎您仍然遇到同样的问题。扣款成功,但交易失败,且用户账户未记入。

这似乎是一个非常常见的场景。如何正确处理这一问题?


为了正确操作,事务功能需要是幂等的。因此,您不能在此类函数内进行条带调用,因为这会使其成为非幂等的。

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

甚至可能创建一个单独的、独立的实体来反映条带 API 调用结果?此类实体should没有争用的空间,因为它只写入一次 - 当条带事务发生时。这将使您能够:

  • 保留账户交易历史记录 - 指向这些实体
  • 进行一些健全性检查,查找孤立条带交易(如果由于某种原因帐户交易调用即使在重试后仍失败)并对此采取措施。

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

  • 更新帐户的事务函数,旨在执行条带事务,这也以事务方式将推送任务排入队列 https://cloud.google.com/appengine/docs/standard/python/taskqueue/push/creating-tasks#enqueuing_tasks_in_cloud_datastore_transactions执行条带 API 调用。仅当事务成功时任务才会入队
  • 推送队列任务进行 Stripe API 调用(最终创建 Stripe 交易实体),并在成功后调用交易函数来更新账户余额
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GAE/P:API 调用的交易安全 的相关文章

随机推荐

  • 有没有办法通过 Express + Node.js 使用多个视图引擎

    Scenario 我使用开发了一些交易页面Node js http nodejs org Express http expressjs com 车把 http handlebarsjs com 作为视图引擎和MongoDB http www
  • 更新对象属性

    我正在使用 Struts 2 我的问题是我不想更新所有对象属性 因为我得到了一些敏感数据 这是我的代码示例 public class person private name private email private password 例如
  • for 循环的简写是否缓存可迭代对象的引用?

    我可能试图变得过于高效 但我一直想知道以下两个代码示例中哪一个会执行得更快 假设您有一个对包含以下内容的对象的引用ArrayList of Strings并且您想要迭代该列表 以下哪项更有效 即使效率有限 for String s foo
  • Objective-C 结构体的默认值以及如何测试

    我正在尝试测试属性是否已设置 我知道我拥有的对象 CGRect ppGoalFrame LocalPlaySetup localPlaySetup 我可以测试 if localPlaySetup nil 但如果我尝试用 nil 或 NULL
  • 实体框架如何决定是引用现有对象还是创建新对象?

    只是出于我的好奇心 以及未来的知识 Entity Framework 5 如何决定何时创建新对象与引用现有对象 我可能只是做错了什么 但似乎时不时地 如果我做一些类似的事情 using TestDB db new TestDB var cu
  • jruby - ruby​​ lambda 语法 -> 不是一个重要的考虑因素吗?

    我注意到 即使在最新的 1 6 4 jruby 版本中 也不支持 Ruby 1 9 中的新 lambda 语法 gt 所以 我猜测这种语法在 ruby 社区中并不常用 是因为语法是新的还是有其他缺点 x gt y y 1 x call 2
  • Python - 从不断变化的文本文件中实时更新图形

    我有一个线程每 2 秒连续写入一个文本文件 Matplotlib 图 实时更新图 引用同一文件 因此 当我启动脚本时 我打开一个图表并在线程上启动文件写入过程 文件正在更新 但我的图表没有更新 只有在文件写入完成后 文件上的数据才会显示在图
  • Visual Studio 2017 Update 3 - 找不到指定的 SDK“Microsoft.NET.Sdk.Web”

    Error C WebApp WebApp csproj 错误 找不到指定的 SDK Microsoft NET Sdk Web C WebApp WebApp csproj 我正在尝试打开 Dotnet 核心项目 但收到上述错误 我已经安
  • 数据库理论-两个表之间的关系

    我有一个包含两个表的数据库 让我们称它们为 Foo 和 Bar 每个 foo 可以与任意数量的 bar 相关 每个 bar 也可以与任意数量的 foo 相关 我希望能够通过一个查询检索与特定 bar 关联的 foo 以及与特定 foo 关联
  • Android USB 配件多线程

    我遇到了由多线程和 Android Open Accessory 引起的问题 我需要与 USB 附件通信 但我需要从 2 个线程进行通信 一个线程生成并发送数据 另一个线程读取数据 为什么我不使用单线程 因为在读取之前可能有 1 次或多次写
  • 使用 Rust 从不同偏移量的文件中读取

    我正在开发一个项目 该项目涉及从不同偏移量的文件中读取不同的信息 目前 我正在使用以下代码 SECTORS PER CLUSTER starts at 13 opened file seek SeekFrom Start 13 unwrap
  • 如果在 javascript 中返回,如何抓取搜索结果(使用 python)

    我想要抓取的网站使用 JavaScript 填充返回 我可以简单地以某种方式调用脚本并处理其结果吗 当然 没有分页 我不想运行整个过程来抓取生成的格式化 HTML 但原始源是空白的 看一看 回报的来源很简单
  • 问:在 rmarkdown html 中的 for 循环中创建传单地图

    我正在尝试在 rmarkdown 文件中创建带有 for 循环的传单地图 这是一个最小的例子 title Test output html document r quakes echo F data quakes library leafl
  • AMP Html 无法在 iphone safari 浏览器上运行以进入新窗口

    最近 我正在使用 Accelerated Mobile Pages AMP 开发渐进式 Web 应用程序 我必须添加锚链接target blank 以便用户单击该链接将被重定向到带有锚点位置的新窗口 a href External Url
  • Angular.js ng-style 不会绑定值

    我在 angularjs 上遇到了问题 即使经过研究 我也找不到错在哪里 我需要重新计算元素的 css 值 left 我正在使用 ng style 指令和一个将返回具有 css 值的对象的方法 这就是 据我所知 我必须做的 但是当我更新值时
  • 项目骑手 - 构建时查看 msbuild 输出

    当我尝试构建解决方案时 我想查看 msbuild 日志 它最初是 Visual Studio 2015 的解决方案 Rider 的输出构建窗口 视图 gt 工具窗口 gt 构建 显示 Microsoft R 构建引擎版本 14 0 2542
  • 使用 git rebase 时自动跳过空提交

    通常 你必须做git rebase skip 如果有一个开关可以自动跳过这些空提交 那就太好了 有人知道怎么做吗 非常古老的话题 但对我来说是搜索引擎上的第一个结果 我终于发现有一个 empty参数可以采用以下值之一 keep drop 和
  • Android 词典应用程序

    我想在字典之上开发一个应用程序 即使用字典作为其一部分的应用程序 市场上有用于此目的的任何字典应用程序吗 遵循 GPL 的应用程序是更好的 还有那些使用本地数据库的应用程序而不是使用网络连接是更好的选择 如果没有 市场上是否有可用的词典数据
  • 使用 Android Studio 将 iTextG 包含在 Android 项目中

    在 Android Studio 中包含 iTextG 时出现以下错误 com android dex DexException Multiple dex files define Lcom itextpdf awt geom Affine
  • GAE/P:API 调用的交易安全

    假设您使用交易来处理 Stripe 付款并更新用户实体 ndb transactional def process payment user key amount user user key get user stripe payment