【问题标题】:How to reload a session in ruby on rails from database if browser session cookie was lost after the user returned from payment provider如果用户从支付提供商返回后浏览器会话 cookie 丢失,如何从数据库重新加载 ruby​​ on rails 中的会话
【发布时间】:2020-12-10 15:12:34
【问题描述】:

带有红宝石的购物车。我继承了一个项目,不得不从头开始学习 Rails 来管理它。一切正常,但这个让我难过。非常感谢任何输入。谢谢!

一些用户遇到的问题是,当他们在成功购买后从支付处理器返回时,他们的浏览器会清除 cookie(我假设在浏览器更新/防病毒等方面实施了一些安全措施)当他们返回时该站点,将自动创建一个新会话。这似乎是一个随机事件,但经过调查,我发现我可以通过在点击“立即付款”之前使用浏览器工具删除购物车的会话 cookie 来模拟问题。

按照设置,当原始 cookie 丢失时,系统无法告诉返回用户是谁。该页面无法呈现,导致他们的交易仍然显示为未付款,即使付款成功并且从他们的银行账户中扣除了钱。在这种情况下,用户只会看到一个空白屏幕。我已经设置了错误报告,这就是我得到的:

支付中发生 NoMethodError#success:

未定义方法id' for nil:NilClass app/controllers/payments_controller.rb:130:in block(2级)成功'

这是有道理的,因为系统无法检索用户 ID,或者在这种情况下无法从 current_user.id 获取 @user.id,因为我假设如果缺少正确的经过身份验证的 cookie,则未定义 current_user。

从支付处理器收到的 POST 变量:

参数:{"PAY_REQUEST_ID"=>"51A3B42C-573E-085D-EE38-82E03A2817A3", "TRANSACTION_STATUS"=>"1", "CHECKSUM"=>"c38ba5ad8e69dad4b6cef26eb0831089", "controller"=>"payments", “行动”=>“成功”}

我对此深思熟虑,花了大约 6 个小时试图让它发挥作用。

从逻辑上讲,我认为解决方案必须遵循以下思路:

支付处理器的结果返回一个变量,我可以使用该变量在数据库中查找交易。 PAY_REQUEST_ID 是存储在 payments sql 表中的值。

支付表也有 user_id 列,所以我可以使用它来获取正确的用户 ID:

@payment = Payment.where('authorisation = ?', params[:PAY_REQUEST_ID]).first

user_id = @payment.user_id

我将会话存储从浏览器更改为数据库,因此有一个包含会话的表,我可以从中检索信息。

那么我的问题: 如何从数据库中的会话表中检索正确的会话并使用提取的@user.id 作为搜索键来加载它? (如果它可以在浏览器中自动创建正确的“引用”cookie,那么 ruby​​ 就知道从数据库中获取哪个会话,那就完美了!)

以下是浏览器删除 cookie 后创建的错误会话示例。


会话:


  • 会话 ID:[过滤]
  • 数据:{"session_id"=>"197af40fddddb7811a6bd0af5641c498", "currency"=>"USD"}

我尝试使用以下内容重新填充 current_user: current_user = User.where('id = ?', @payment.user_id) 但似乎我创建的 current_user 与正确的 current_user 变量应该是不同的“类型”或数据结构,所以这导致进一步的问题和代码中断。

如前所述,代码中有一行@user = current_user,后来它被称为voucher.user_id = @user.id 如果会话 cookie 被浏览器擦除,则会触发 noMethod 错误。

【问题讨论】:

    标签: ruby-on-rails session-cookies payment-gateway


    【解决方案1】:

    最简单的解决方案就是最好的解决方案。我努力定义 current_user 并自动登录用户。在我的问题中,我学到了很多关于轨道如何工作的知识,并且我也意识到不需要重新发明轮子。

    阅读 session_controller.rb 代码,其中创建和销毁会话,我看到两个会话值是由“新”方法设置的。一个会话变量是 Auth 令牌,另一个是用户的默认货币。我知道身份验证令牌已经存储在 users 表中,因此很容易获取 @user = User.find_by_id(@payment.user_id) 然后使用 @user.auth_token 获取身份验证令牌

    current_user = User.where('id = ?', @payment.user_id)
    @user = User.find_by_id(@payment.user_id)
    session[:currency] = @user.currency_ind
    session[:auth_token] = @user.auth_token
    

    一旦设置了 session[:auth_token],用户就会自动登录,一切照常。不需要有趣的事情。

    希望这能帮助遇到同样问题的其他人。

    【讨论】:

      猜你喜欢
      • 2020-12-26
      • 2017-02-06
      • 2020-12-05
      • 1970-01-01
      • 2020-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-18
      相关资源
      最近更新 更多