Ruby on rails 定制Paypal Express';s使用ActiveMerchant查看页面

Ruby on rails 定制Paypal Express';s使用ActiveMerchant查看页面,ruby-on-rails,paypal,activemerchant,Ruby On Rails,Paypal,Activemerchant,我正在使用ActiveMerchant让我的rails应用程序访问Paypal的快速结账。 我希望将订单详细信息包括在审查页面中,如下所述: 这能做到吗 目前,我的控制器代码如下所示: def paypal #currently, options is unused, I'm not sure where to send this info options = { :L_NAME0=>"Tickets", :L_QTY0=

我正在使用ActiveMerchant让我的rails应用程序访问Paypal的快速结账。 我希望将订单详细信息包括在审查页面中,如下所述:

这能做到吗

目前,我的控制器代码如下所示:

def paypal
  #currently, options is unused, I'm not sure where to send this info
  options = { 
              :L_NAME0=>"Tickets", 
              :L_QTY0=>@payment.quantity, 
              :L_DESC0=>"Tickets for #{@payment.event_name}",
              :L_AMT0=>@payment.unit_price
            }

  #the actual code that gets used
  setup_response = gateway.setup_purchase(@payment.amount,
    :ip=> request.remote_ip,
    :return_url=> url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
    :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false)
  )
  redirect_to gateway.redirect_url_for(setup_response.token)
end
def paypal
  options = { 
    :name => "Tickets", 
    :quantity => @payment.quantity, 
    :description => "Tickets for #{@payment.event_name}",
    :amount => @payment.unit_price
    :ip => request.remote_ip,
    :return_url => url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
    :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false)
  }

  # the actual code that gets used
  setup_response = gateway.setup_purchase(@payment.amount, options)
  redirect_to gateway.redirect_url_for(setup_response.token)
end
options = {
  :items => [
    { 
      :name => "Tickets", 
      :quantity => @payment.quantity, 
      :description => "Tickets for #{@payment.event_name}",
      :amount => @payment.unit_price
    },
    { 
      :name => "Other product", 
      :quantity => @other_payment.quantity, 
      :description => "Something else for #{@other_payment.event_name}",
      :amount => @other_payment.unit_price
    }
  ]
  :ip => request.remote_ip,
  :return_url => url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
  :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false) 
}
def begin_paypal
  # ...
  options = express_options(@order)
  # ... 
  response = EXPRESS_GATEWAY.setup_purchase(@order.gross_price_in_cent, options)
  redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
end

private
def express_options order
  options = {}
  options[:ip] = request.remote_ip
  options[:order_id] = order.bearbeitungsnummer

  # subtotal, shipping, handling and tax must sum up to the orders total value
  # subtotal must be the sum of all amounts of all items
  options[:subtotal] = order.gross_price_in_cent
  options[:shipping] = 0
  options[:handling] = 0
  options[:tax] = 0

  options[:items] = order.line_items.map do |line_item|
    {
      :name => line_item.product.name,
      :number => line_item.product.kcode,
      :quantity => line_item.quantity,
      :description => line_item.product.beschreibung,
      :amount => line_item.gross_price_in_cent,
      :url => nil
    }
  end
  # ...
end

如果我试图做的是可能的,我需要更改什么?

您可以在此表中看到可用的参数(只有中间列适用,因为activemerchant正在使用SOAP API):

为了更好地理解activemerchant的工作方式,可能需要直接查看实现。您可以看到从第98行开始在SOAP XML请求中插入相关参数(当前),其中插入了
OrderTotal

  xml.tag! 'n2:Name', options[:name]
  xml.tag! 'n2:Amount', options[:amount]
  xml.tag! 'n2:Quantity', options[:quantity]

注意参数是如何从
选项
散列中提取的,这样您就可以在这里看到要传递给每个参数的正确符号

在您的情况下,当您列出以下参数时,您可以这样做:

def paypal
  #currently, options is unused, I'm not sure where to send this info
  options = { 
              :L_NAME0=>"Tickets", 
              :L_QTY0=>@payment.quantity, 
              :L_DESC0=>"Tickets for #{@payment.event_name}",
              :L_AMT0=>@payment.unit_price
            }

  #the actual code that gets used
  setup_response = gateway.setup_purchase(@payment.amount,
    :ip=> request.remote_ip,
    :return_url=> url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
    :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false)
  )
  redirect_to gateway.redirect_url_for(setup_response.token)
end
def paypal
  options = { 
    :name => "Tickets", 
    :quantity => @payment.quantity, 
    :description => "Tickets for #{@payment.event_name}",
    :amount => @payment.unit_price
    :ip => request.remote_ip,
    :return_url => url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
    :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false)
  }

  # the actual code that gets used
  setup_response = gateway.setup_purchase(@payment.amount, options)
  redirect_to gateway.redirect_url_for(setup_response.token)
end
options = {
  :items => [
    { 
      :name => "Tickets", 
      :quantity => @payment.quantity, 
      :description => "Tickets for #{@payment.event_name}",
      :amount => @payment.unit_price
    },
    { 
      :name => "Other product", 
      :quantity => @other_payment.quantity, 
      :description => "Something else for #{@other_payment.event_name}",
      :amount => @other_payment.unit_price
    }
  ]
  :ip => request.remote_ip,
  :return_url => url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
  :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false) 
}
def begin_paypal
  # ...
  options = express_options(@order)
  # ... 
  response = EXPRESS_GATEWAY.setup_purchase(@order.gross_price_in_cent, options)
  redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
end

private
def express_options order
  options = {}
  options[:ip] = request.remote_ip
  options[:order_id] = order.bearbeitungsnummer

  # subtotal, shipping, handling and tax must sum up to the orders total value
  # subtotal must be the sum of all amounts of all items
  options[:subtotal] = order.gross_price_in_cent
  options[:shipping] = 0
  options[:handling] = 0
  options[:tax] = 0

  options[:items] = order.line_items.map do |line_item|
    {
      :name => line_item.product.name,
      :number => line_item.product.kcode,
      :quantity => line_item.quantity,
      :description => line_item.product.beschreibung,
      :amount => line_item.gross_price_in_cent,
      :url => nil
    }
  end
  # ...
end
但请注意: activemerchant当前不支持
名称
数量
金额
字段。您将不得不分叉存储库,自己插入这些文件,并使用项目的副本。当您查看代码并了解如何使用其他代码时,这是非常简单的

例如,要添加订单名称、项目数量和项目单价,您可以在插入
OrderDescription
后放置以下行:

  xml.tag! 'n2:Name', options[:name]
  xml.tag! 'n2:Amount', options[:amount]
  xml.tag! 'n2:Quantity', options[:quantity]
希望有帮助

更新: 好的,我认为根据SOAP API的XML模式,您必须在activemerchant中这样指定它:

xml.tag! 'n2:PaymentDetails' do
  items = options[:items] || []
  items.each do |item|
    xml.tag! 'n2:PaymentDetailsItem' do
      xml.tag! 'n2:Name', item[:name]
      xml.tag! 'n2:Description', item[:desc]
      xml.tag! 'n2:Amount', item[:amount]
      xml.tag! 'n2:Quantity', item[:quantity]
    end
  end
end
您可以在Rails应用程序中传递所有项目,如下所示:

def paypal
  #currently, options is unused, I'm not sure where to send this info
  options = { 
              :L_NAME0=>"Tickets", 
              :L_QTY0=>@payment.quantity, 
              :L_DESC0=>"Tickets for #{@payment.event_name}",
              :L_AMT0=>@payment.unit_price
            }

  #the actual code that gets used
  setup_response = gateway.setup_purchase(@payment.amount,
    :ip=> request.remote_ip,
    :return_url=> url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
    :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false)
  )
  redirect_to gateway.redirect_url_for(setup_response.token)
end
def paypal
  options = { 
    :name => "Tickets", 
    :quantity => @payment.quantity, 
    :description => "Tickets for #{@payment.event_name}",
    :amount => @payment.unit_price
    :ip => request.remote_ip,
    :return_url => url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
    :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false)
  }

  # the actual code that gets used
  setup_response = gateway.setup_purchase(@payment.amount, options)
  redirect_to gateway.redirect_url_for(setup_response.token)
end
options = {
  :items => [
    { 
      :name => "Tickets", 
      :quantity => @payment.quantity, 
      :description => "Tickets for #{@payment.event_name}",
      :amount => @payment.unit_price
    },
    { 
      :name => "Other product", 
      :quantity => @other_payment.quantity, 
      :description => "Something else for #{@other_payment.event_name}",
      :amount => @other_payment.unit_price
    }
  ]
  :ip => request.remote_ip,
  :return_url => url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
  :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false) 
}
def begin_paypal
  # ...
  options = express_options(@order)
  # ... 
  response = EXPRESS_GATEWAY.setup_purchase(@order.gross_price_in_cent, options)
  redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
end

private
def express_options order
  options = {}
  options[:ip] = request.remote_ip
  options[:order_id] = order.bearbeitungsnummer

  # subtotal, shipping, handling and tax must sum up to the orders total value
  # subtotal must be the sum of all amounts of all items
  options[:subtotal] = order.gross_price_in_cent
  options[:shipping] = 0
  options[:handling] = 0
  options[:tax] = 0

  options[:items] = order.line_items.map do |line_item|
    {
      :name => line_item.product.name,
      :number => line_item.product.kcode,
      :quantity => line_item.quantity,
      :description => line_item.product.beschreibung,
      :amount => line_item.gross_price_in_cent,
      :url => nil
    }
  end
  # ...
end
希望效果更好,祝你好运

@Soleone 我尝试你的解决方案,但不适合我

xml.tag! 'n2:OrderDescription', options[:description]
xml.tag! 'n2:Name', options[:name]
xml.tag! 'n2:Description', options[:desc]
xml.tag! 'n2:Amount', options[:amount]
xml.tag! 'n2:Quantity', options[:quantity]
我认为xml结构不正确,订单项是多个的,所以应该是这样

xml.tag! 'n2:OrderItems' do
    xml.tag! 'n2:OrderItem' do
        xml.tag! 'n2:Name', options[:name]
        xml.tag! 'n2:Description', options[:desc]
        xml.tag! 'n2:Amount', options[:amount]
        xml.tag! 'n2:Quantity', options[:quantity]
    end
end
但我现在真的不知道正确的结构

==更新

我找到了SOAP api文档

但也不管用,谁能帮忙

====更新====

我尝试了添加PaymentDetails参数的方法,但似乎仍然不起作用,我找到了SetExpressCheckoutReq xml的模式,PaymentDetails没有定义,这是谁做的,希望您的帮助

=======决赛========


我已经解决了这个问题,新版的ActiveMerchant支持订单详细信息审查,mwagg为此推出了补丁,你们可以使用这个版本

确保你们有
ActiveMerchant
版本不低于
1.12.0

EXPRESS_GATEWAY.setup_purchase(220, :items => [{:name => "Tickets", :quantity => 22,:description => "Tickets for 232323", :amount => 10}], :return_url => 'example.com', :cancel_return_url => 'example.com' ) EXPRESS\u GATEWAY.设置\u购买(220, :items=>[{:name=>“Tickets”,:quantity=>22,:description=>“232323的Tickets”,:amount=>10}], :return_url=>'example.com', :cancel\u return\u url=>'example.com' )
希望这有帮助:)

我也遇到了一些问题,无法让它正常工作。解决方案是,所有项目的金额之和必须是订单的小计,其中小计、装运、处理和税务必须合计为订单的总价值。我的paypal控制器如下所示:

def paypal
  #currently, options is unused, I'm not sure where to send this info
  options = { 
              :L_NAME0=>"Tickets", 
              :L_QTY0=>@payment.quantity, 
              :L_DESC0=>"Tickets for #{@payment.event_name}",
              :L_AMT0=>@payment.unit_price
            }

  #the actual code that gets used
  setup_response = gateway.setup_purchase(@payment.amount,
    :ip=> request.remote_ip,
    :return_url=> url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
    :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false)
  )
  redirect_to gateway.redirect_url_for(setup_response.token)
end
def paypal
  options = { 
    :name => "Tickets", 
    :quantity => @payment.quantity, 
    :description => "Tickets for #{@payment.event_name}",
    :amount => @payment.unit_price
    :ip => request.remote_ip,
    :return_url => url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
    :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false)
  }

  # the actual code that gets used
  setup_response = gateway.setup_purchase(@payment.amount, options)
  redirect_to gateway.redirect_url_for(setup_response.token)
end
options = {
  :items => [
    { 
      :name => "Tickets", 
      :quantity => @payment.quantity, 
      :description => "Tickets for #{@payment.event_name}",
      :amount => @payment.unit_price
    },
    { 
      :name => "Other product", 
      :quantity => @other_payment.quantity, 
      :description => "Something else for #{@other_payment.event_name}",
      :amount => @other_payment.unit_price
    }
  ]
  :ip => request.remote_ip,
  :return_url => url_for(:action=>:confirm, :id=>@payment.id, :only_path=>false),
  :cancel_return_url => url_for(:action=>:show, :id=>@payment.id, :only_path=>false) 
}
def begin_paypal
  # ...
  options = express_options(@order)
  # ... 
  response = EXPRESS_GATEWAY.setup_purchase(@order.gross_price_in_cent, options)
  redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
end

private
def express_options order
  options = {}
  options[:ip] = request.remote_ip
  options[:order_id] = order.bearbeitungsnummer

  # subtotal, shipping, handling and tax must sum up to the orders total value
  # subtotal must be the sum of all amounts of all items
  options[:subtotal] = order.gross_price_in_cent
  options[:shipping] = 0
  options[:handling] = 0
  options[:tax] = 0

  options[:items] = order.line_items.map do |line_item|
    {
      :name => line_item.product.name,
      :number => line_item.product.kcode,
      :quantity => line_item.quantity,
      :description => line_item.product.beschreibung,
      :amount => line_item.gross_price_in_cent,
      :url => nil
    }
  end
  # ...
end

工作正常

此解决方案对我不起作用。我已经添加了您在代码片段中描述的项目,并且从paypal返回了一个无效的事务错误。使用此选项后,我将被重定向到live环境,而不是我想要的沙箱。如果没有
:items
选项,它可以正常工作,并正确重定向到sandboxI。我尝试了这个方法,但我被重定向到了live站点,而不是paypal上的沙盒。你知道我如何解决这个问题吗?