有没有适用于Ruby on Rails的PayPal IPN代码示例?

21

有几种语言的官方代码示例,但找不到Rails的。

7个回答

31
我在这里贴出了一个Rails控制器的工作代码示例,它实现了验证功能。希望对您有所帮助。
class PaymentNotificationsController < ApplicationController
  protect_from_forgery :except => [:create] #Otherwise the request from PayPal wouldn't make it to the controller
  def create
    response = validate_IPN_notification(request.raw_post)
    case response
    when "VERIFIED"
      # check that paymentStatus=Completed
      # check that txnId has not been previously processed
      # check that receiverEmail is your Primary PayPal email
      # check that paymentAmount/paymentCurrency are correct
      # process payment
    when "INVALID"
      # log for investigation
    else
      # error
    end
    render :nothing => true
  end 
  protected 
  def validate_IPN_notification(raw)
    live = 'https://ipnpb.paypal.com/cgi-bin'
    sandbox = 'https://ipnpb.sandbox.paypal.com/cgi-bin'
    uri = URI.parse(sandbox + '/webscr?cmd=_notify-validate')
    http = Net::HTTP.new(uri.host, uri.port)
    http.open_timeout = 60
    http.read_timeout = 60
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER
    http.use_ssl = true
    response = http.post(uri.request_uri, raw,
                         'Content-Length' => "#{raw.size}",
                         'User-Agent' => "My custom user agent"
                       ).body
  end
end

这段代码受到了Railscast 142Tanel Suurhans的启发。


5
非常有帮助,谢谢!不过需要注意的是,如果确实想要安全,请务必使用 OpenSSL::SSL::VERIFY_PEER。 - Mohamed Hafez
3
这真的为我节省了相当大的下午时间。现在我可以早点回家了。非常感谢! - superluminary
这节省了我很多时间,谢谢!还要记得在非生产模式下使用SANDBOX PayPal URL进行验证!(https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_notify-validate) - Tom Lord
哦,关于“检查txnId是否已被先前处理”,这里有一个重要的陷阱。如果在“完成”付款状态之前收到“待定”付款状态,则两者将具有相同的交易ID。换句话说,为了澄清,您必须验证只接收到一个带有该txn_id的“已完成”通知。 - Tom Lord
1
网址已更改,我在意识到问题之前已经折腾了半天。以下是新的网址: live = 'https://ipnpb.paypal.com/cgi-bin' sandbox = 'https://ipnpb.sandbox.paypal.com/cgi-bin' uri = URI.parse(sandbox + '/webscr?cmd=_notify-validate') - Maayan Naveh
显示剩余2条评论

3

1
请务必在您的控制器中添加protect_from_forgery except: [:notify],以便POST请求不会因为无法验证CSRF令牌的真实性而被拒绝。 - scarver2

2

0

我在我的一个项目中实现了IPN,你的代码看起来很好。那么你遇到了什么问题?


嗨,Rovin。是的,我的代码运行良好,谢谢你的确认。我在这里发布它,因为我花了一些时间才想出可行的解决方案,而且由于没有官方示例,我认为其他人也可以从中受益。 - joscas

0

你知道PayPal标准支付是否支持所有国家吗?根据Active Merchant的文档,以下是支持的PayPal网关:PayPal Express Checkout - 美国,加拿大,新加坡,澳大利亚 PayPal Payflow Pro - 美国,加拿大,新加坡,澳大利亚 PayPal Website Payments Pro (英国) - 英国 PayPal Website Payments Pro (加拿大) - 加拿大 PayPal Express Checkout - 美国 PayPal Website Payments Pro (美国) - 美国 - joscas
@joscas,抱歉,不行。我在英国和美国都使用过AM的PayPal IPN,没有任何问题。很抱歉我不能提供更多帮助。 - Nazar

0

0

有一些PayPal宝石,至少其中一个(paypal-sdk-rest)包括PayPal::SDK::Core::API::IPN.valid?方法。

以下是如何使用它:

class YourController < ApplicationController

  skip_before_action :verify_authenticity_token, only: :your_action

  def your_action
    verified = PayPal::SDK::Core::API::IPN.valid?(request.raw_post)

    if verified
      # Verification passed, do something useful here.
      render nothing: true, status: :ok
    else
      # Verification failed!
      render nothing: true, status: :unprocessable_entity
    end
  end

end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接