如果浏览器会话 cookie 在用户从支付提供商返回后丢失,如何从数据库重新加载 ruby 上 rails 中的会话

How to reload a session in ruby on rails from database if browser session cookie was lost after the user returned from payment provider

rails 上 ruby 的购物车。我继承了一个项目,不得不从头开始学习 rails 来管理它。一切顺利,但这个让我难住了。非常感谢任何输入。谢谢!

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

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

A NoMethodError occurred in payments#success:

undefined method id' for nil:NilClass app/controllers/payments_controller.rb:130:in block (2 levels) in success'

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

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

Parameters : {"PAY_REQUEST_ID"=>"51A3B42C-573E-085D-EE38-82E03A2817A3", "TRANSACTION_STATUS"=>"1", "CHECKSUM"=>"c38ba5ad8e69dad4b6cef26eb0831089", "controller"=>"payments", "action"=>"success"}

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

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

来自支付处理器的结果 return 是一个变量,我可以使用它在数据库中查找交易。 PAY_REQUEST_ID 是存储在 payments sql table.

中的值

付款 table 也有 user_id 列,因此我可以使用它来获取正确的用户 ID:

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

user_id = @payment.user_id

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

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

这是浏览器删除 cookie 后创建的不正确会话的示例。


Session:


  • session id: [FILTERED]
  • data: {"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 错误。

最简单的解决方案是最好的解决方案。我努力定义 current_user 并让用户自动登录。在我的问题中,我了解了很多有关 rails 工作原理的知识,并且我还意识到 re-invent 轮子不需要它。

通读 session_controller.rb 代码,其中创建和销毁了会话,我看到两个会话值是由“新”方法设置的。一个会话变量是 Auth 令牌,另一个是用户的默认货币。我知道授权令牌已经存储在用户 table 中,所以很容易获得 @user = User.find_by_id(@payment.user_id) 然后使用 @[=23 获得授权令牌=]

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

一旦设置了会话[:auth_token],用户就会自动登录,一切如常。不需要搞笑的生意。

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