【问题标题】:Trigger rails controller function - Paypal Website Standard IPN触发 rails 控制器功能 - Paypal 网站标准 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中。

任何帮助将不胜感激。提前致谢!

【问题讨论】:

    标签: ruby-on-rails ruby paypal controller


    【解决方案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 =&gt; {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_nameitem_numberquantity。现在有几种方法可以将这些记录插入数据库,其中包含嵌套参数。您能否创建一个显示您的 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
    猜你喜欢
    • 2016-10-23
    • 2014-01-26
    • 2015-11-25
    • 2016-09-14
    • 1970-01-01
    • 2023-04-04
    • 2019-06-27
    • 2019-02-05
    • 1970-01-01
    相关资源
    最近更新 更多