Paypal Standard integration with RoR Application – Integrating IPN

Paypal IPN(Instant Payment Notification) is a paypal feature which enables you to get the Payment notification at your application end whenever the payment is complete. This feature enables you to have infinite flexibility at your hand when you want to perform some post payment operations such as shipping etc. Since this blog is a continuation in the series of paypal integration with RoR app, I strongly suggest that you go through our previous article of Basic Paypal Integration with Rails application. Lets go step by step to integrate IPN into our rails application: Enable IPN in the Paypal merchant account: First of all we need to enable IPN in our paypal account. Login to merchant account -> Profile -> Instant Payment Notification Preferences -> Enter notification url and select radio button “Receive IPN messages” -> Save notification url is the url at which the paypal will send the messages to. Handling IPN in the rails application After getting IPN, you can make any operation according to your application’s need. For the demonstration application, I am going to update the payment status as soon as we receive IPN. For this, Generate a new model order and migrate it to database. This model references our old model product and represents an order placed by our user.
 $ rails generate model order product_id:integer quantity:integer amount:decimal status:string

$ rake db:migrate 
Define the required associations. This the order belongs_to a product and product has many orders, we say:
  • In app/models/product.rb, add
has_many : orders
  • In app/models/order.rb, add
belongs_to :product
Make route to receive IPN. Open config/route.rb, replace
 resources :products 
with
resources :products do

collection do

post 'notification'

end

Add new method in app/controllers/products_controller.rb, for handling IPN
def notification
if params[:item_number1] && !params[:item_number1].empty?
#paypal sends an IPN even when the transaction is voided.
#save the payment status along with the amount of the transaction.
if params[:payment_status] != 'Voided'
@product = Product.find(params[:item_number1].to_i) rescue nil
@product.orders.build(:quantity => 1, :amount => params[:mc_gross_1], :status =>                                                           params[:payment_status]).save unless @product.nil?
end
end
render :nothing => true
end
In app/views/products/index.html.erb, replace product.paypal_url(products_url) with
product.paypal_url(products_url, notification_products_url)
and add a new line after :return => return_url in paypal_url method (in app/models/product.rb), for supporting notify_url:
:notify_url => notify_url,
also change signature of this method to accept notify_url parameter, it will look like:
def paypal_url(return_url, notify_url)
This will basically send the notify_url as a parameter to the paypal informing paypal to send the notification at this url instead of one defined in the paypal merchant control panel. This feature comes in very handy when you need to define the notification url on per product basis. We are now done with implementing the IPN on our RoR application side. Debugging the IPN: Paypal provides a handy tool to check the IPN history. Login to merchant account -> History -> IPN History. You can see the IPN calls being sent and HTTP results for each of them. This comes in pretty handy while debugging the IPN based logic. Enjoy your payments !! The fully implemented application is uploaded on heroku: http://paypal-integration.herokuapp.com