【问题标题】:Stripe API call is producing multiple subscriptions when using Node.js使用 Node.js 时,Stripe API 调用产生多个订阅
【发布时间】:2017-08-13 18:34:03
【问题描述】:

我正在我的节点应用程序中实现条带 API。我遇到的问题是,如果我非常快速地多次单击提交按钮,则会多次调用 api,并且条带客户突然有多个订阅和费用。

这种情况是当用户拥有一个没有订阅的条带客户帐户时,因为他们之前已取消订阅。现在他们想重新订阅一个新计划,因为旧计划已被删除。

我的代码逻辑如下:

1. Submit form
2. I retrieve the user from my mongo db
3. I retrieve the customer from stripe using a stored customer id (api call)
4. I create a customer subscription (api call)
5. I update the stripe customer object with their credit card (api call)
6. Respond back to user
  • 以上所有操作都是使用异步瀑布完成的,随后的每个异步调用都在一个单独的函数中

我想要什么:

  • 在第 3 步和第 4 步之间,我想检索客户并检查他或她是否已经订阅,如果用户已经有活动订阅,则防止第 4 步和第 5 步发生。

问题:

  • 我正在测试用户多次单击提交按钮并最终被收取多次订阅费用的场景。我相信它与节点如何一次发送多个请求有关,因为它是异步的,我想检查一个 api 调用以检查是否设置了一些东西需要太长时间,并且节点在发送所有请求时不会等待请求。

我该如何解决这个问题。

注意:当然,我有前端处理这个以防止用户多次提交表单,但这并不理想,也不希望这是我唯一的防线。

谢谢

【问题讨论】:

    标签: javascript node.js api asynchronous stripe-payments


    【解决方案1】:

    Stripe 具有内置功能来帮助您防止这种情况。 https://stripe.com/docs/api/idempotent_requests

    您需要生成一个唯一的字符串并将其与条带请求一起发送。

    将其以隐藏形式(例如您的 CORS 令牌)放入 HTML 中,然后将其读出并将其放入 Stripe 调用将防止双击/重试。

    【讨论】:

      【解决方案2】:

      第一次点击后立即使用 javascript 禁用前端中的按钮。

      【讨论】:

        【解决方案3】:

        一种方法是保留最近交易的缓存(在 Redis 或类似中),由从关键交易值(例如客户 ID、日期、时间、金额)派生的哈希索引。

        在提交订阅请求到条带化之前,将当前事务与缓存进行比较。如果您遇到问题,您可以显示错误、自动忽略事务或让用户选择是否继续。

        【讨论】:

          【解决方案4】:

          使用强大的速率限制器库

          https://github.com/jhurliman/node-rate-limiter

          var RateLimiter = require('limiter').RateLimiter;
          
          // Allow 1 requests per minute
          var limiterPayments = new RateLimiter(1, 'minute');
          
          exports.payWithStripe = function(req,res){
              limiterPayments.removeTokens(1,function(err,remainingRequests){
              if (err){
                  return res.sendStatus(429);
              } else {
                  // continue with stripe payment
              }
          }
          

          这将限制每个会话(每个用户浏览器)

          【讨论】:

          • 我试了一下,它似乎阻止了每个用户,而不仅仅是那个用户。我的应用程序是无状态的,因此没有任何会话。我使用 JSON Web Token 进行身份验证以防止需要会话。
          • 啊,抱歉。每个用户的限制器类似于npmjs.com/package/redis-rate-limiter,其中键是 req.connection.remoteAddress
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-07-03
          • 1970-01-01
          • 2015-07-26
          • 2020-10-22
          • 2021-02-22
          • 2020-06-06
          • 2021-07-08
          相关资源
          最近更新 更多