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
Join Us