触发 rails 控制器功能 - Paypal 网站标准 IPN
Posted
技术标签:
【中文标题】触发 rails 控制器功能 - Paypal 网站标准 IPN【英文标题】:Trigger rails controller function - Paypal Website Standard IPN 【发布时间】:2016-10-25 06:16:18 【问题描述】:我的应用中有一个 PaymentNotificationsController
中的 Paypal IPN。但是,一些变量取决于购物车中的商品数量,所以我想在创建 PaymentNotification 之前提取它们。
到目前为止,我有:
class PaymentNotificationsController < ApplicationController
protect_from_forgery except: [:create]
def create
PaymentNotification.create!(params: params,
item_number: params[:item_number], item_name: params[:item_name], quantity: params[:quantity]
render nothing: true
end
end
但是,当通知来自 PayPal 时,它以item_name1, item_number1, quantity1, item_name2, item_number2, quantity2
等形式出现。
即使它只是一项,它也会以item_name1, item_number1, quantity1, option1
等形式出现。
我有这个函数来尝试提取变量,但我不知道如何触发这个函数。我尝试在控制器顶部使用before_action
,但它不起作用。返回wrong number of arguments(0 for 1)
:
ITEM_PARAM_PREFIXES = ["item_name", "item_number", "quantity"]
def extract_ipn_items_params(params)
item_params = []
loop do
item_num_to_test = item_params.length + 1
item_num_suffix = item_num_to_test.to_s
possible_param_name = ITEM_PARAM_PREFIXES[0] + item_num_suffix
if params.include?(possible_param_name)
this_item_params =
ITEM_PARAM_PREFIXES.each do |prefix|
this_item_params[prefix] = params[prefix + item_num_suffix]
end
item_params.push this_item_params
else
return item_params
end
end
end
所以我在问,我如何触发函数来提取变量并将它们放入购物车中每个项目的 params[:item_number]、params[:item_name]、params[:quantity] 中,如果有两个项目,是否会创建两个单独的 PaymentNotification?
注意:两种方法都在同一个PaymentNotificationsController
中。
任何帮助将不胜感激。提前致谢!
【问题讨论】:
【参考方案1】:我假设您的方法 extract_ipn_items_params
已经获取了您需要的数据,您可以删除该方法的 params 参数,因为参数始终在控制器的 actions/methods
中可用。
ITEM_PARAM_PREFIXES = ["item_name", "item_number", "quantity"]
def extract_ipn_items_params
mod_params = Hash.new|k, v| k[v] =
ITEM_PARAM_PREFIXES.each do |item_data_key|
key_tracker = 1
loop do
current_key = (item_data_key + key_tracker.to_s).to_sym
if params.include? current_key
mod_params[key_tracker][item_data_key] = params[current_key]
else
break
end
key_tracker += 1
end
end
mod_params
end
该方法返回一个哈希值,例如:
1 => item_name: 'Item 1', item_number: 1084, quantity: 15
,如果您为用户设置了嵌套属性,我认为您应该能够做类似的事情,虽然不太确定,但应该可以:
user.update(payment_notifications_attributes: extract_ipn_items_params)
让我知道这是否适合你。
更新
根据 Github Gist,我想出了以下几点:
class PaymentNotificationsController < ApplicationController
protect_from_forgery except: [:create]
ITEM_PARAM_PREFIXES = ["item_name", "item_number", "quantity", "option_name"]
def create
extract_ipn_items_params.each do |key, values|
# this approach loops through all the returned results, nested attributes may help abstract this though
PaymentNotification.create(values)
render nothing: true
end
def details
# params.extract_ipn_items_params #this doesn't exist as params is an instance of ActionController::Parameters
PaymentNotification.update_attributes(line_item_id: params[:item_number], product_title: params[:item_name], option_name: params[:option_name], quantity: params[:quantity])
end
private
def additional_attributes
# create this for additional merge attributes. A better place for these would be the parent of this
params: params,
cart_id: params[:invoice],
status: params[:payment_status],
transaction_id: params[:txn_id],
first_name: params[:first_name],
last_name: params[:last_name],
email: params[:payer_email],
address_name: params[:address_name],
address_street: params[:address_street],
address_city: params[:address_city],
address_state: params[:address_state],
address_zip: params[:address_zip],
address_country: params[:address_country]
end
def extract_ipn_items_params
mod_params = Hash.new|k, v| k[v] = .merge(additional_attributes)
ITEM_PARAM_PREFIXES.each do |item_data_key|
key_tracker = 1
loop do
current_key = (item_data_key + key_tracker.to_s).to_sym
if params.include? current_key
mod_params[key_tracker][item_data_key] = params[current_key]
else
break
end
key_tracker += 1
end
end
mod_params
end
end
如果这能解决您的问题,请告诉我。
【讨论】:
感谢您的回答。因此,如果我只是在create
操作之前添加它,它会在运行创建之前提取项目?这是文件的样子 >> https://www.dropbox.com/s/2f508296wb378wc/sublime.png?dl=0
数据来自paypal到PaymentNotificationsController
不,在创建之前运行它不会影响参数 ATM,因为您没有更改参数的状态,只是提取您需要的属性。在这种情况下,item_name
、item_number
和 quantity
。现在有几种方法可以将这些记录插入数据库,其中包含嵌套参数。您能否创建一个显示您的 PaymentNotificationsController
的 Github Gist,以便我可以使用另一种使用循环插入记录的方法来更新我的答案
刚试过但没用>>gist.github.com/d1t/7f3a9451500579da617134468beeca96 附上模型,让大家了解整个画面
非常感谢!它可以工作,但我需要在创建时填充变量,因为我在模型中有 after_create 回调。我尝试使用 fetch 从哈希中删除每个单独的变量,但很挣扎。有时间请看>>https://gist.github.com/d1t/7f3a9451500579da617134468beeca96【参考方案2】:
您应该有 payment_id 以便您可以使用 gem 'paypal-sdk-rest'
找到它
payment = PayPal::SDK::REST::Payment.find payment_id
然后您可以在支付对象中看到所有详细信息
【讨论】:
我已经可以看到细节了。当通知到来时,它会创建除变量之外的其他变量:item_name、item_number 等,因为 PayPal 将它们作为 item_name1、item_number1 发送。在创建之前,我只需要一种 Rails 方式从通知中提取它们! 我也在使用 Paypal 网站标准,而不是 REST API以上是关于触发 rails 控制器功能 - Paypal 网站标准 IPN的主要内容,如果未能解决你的问题,请参考以下文章
在 Rails 控制器中包含库时,Paypal SDK Ruby 错误
Rails PayPal Checkout SDK 在视图而不是控制器中存储请求正文
Rails PayPal IPN activemerchant 控制器 rspec 测试
Rails:Paypal 端点 /v2/checkout/orders 返回 http 401