Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails - handling the PayPal IPN callback using the paypal-recurring gem

I am using the paypal-recurring gem to handle recurring payments in a Rails app. The majority of my code is from this excellent Railscast but I also want to add a payment_notification model to accept the IPN callback and store any relevant data. This Railscast goes over how to set up notifications. However, I am having a hard time figuring out how to send the paypal-recurring gem IPN callback to my PaymentNotification model.

How can I set the :ipn_url to correctly write the IPN callback to my PaymentNotification model. I tried the following so far:

1) Adding ipn_url: "http://my-app-name.com/payment_notifications" to the process method (under options) or payment_notifications_url

2) Trying the solution suggested at the bottom of this GitHub issue page

3) Using Paypal's Instant Payment Notification (IPN) simulator to send to "http://my-app-name.com/payment_notifications", but I get an error: IPN delivery failed. HTTP error code 401: Unauthorized

EDIT

I have been able to successfully simulate the delivery of the IPN to my payments_notifications_url. Now I just need to figure out how to point the recurring gem to send the ipn to there.

Any pointers would be greatly appreciated. Below is some of my current code. If I am forgetting any relevant parts, please let me know.

PaypalPayment Model

 class PaypalPayment
   def initialize(subscription)
     @subscription = subscription
   end

   def checkout_details
     process :checkout_details
   end

   def checkout_url(options)
     process(:checkout, options).checkout_url
   end

   def make_recurring
     process :request_payment
     process :create_recurring_profile, period: :monthly, frequency: 1, start_at: Time.zone.now
   end

   def cancel_recurring
     process :cancel
   end

 private

   def process(action, options = {})
     options = options.reverse_merge(
       token: @subscription.paypal_payment_token,
       payer_id: @subscription.paypal_customer_token,
       description: @subscription.plan.name,
       amount: @subscription.plan.monthly_price,
       currency: "JPY"
     )
     response = PayPal::Recurring.new(options).send(action)
     raise response.errors.inspect if response.errors.present?
     response
   end
 end

PaymentNotifications Controller

 class PaymentNotificationsController < ApplicationController
   protect_from_forgery :except => [:create]

   def create
     PaymentNotification.create!(:params => params, :status => params[:payment_status], :transaction_id => params[:txn_id])
     render :nothing => true
   end
 end
like image 596
diasks2 Avatar asked Sep 30 '12 08:09

diasks2


1 Answers

I got it working. In case anyone in the future runs into trouble with PayPal IPN, here are a few things I had wrong:

1) In my Subscriptions Controller I was calling if @subscription.save instead of if @subscription.save_with_payment so the save_with_payment method was actually never even being called.

2) In the process method I added ipn_url: "https://my-app-name.com/payment_notifications",

   def process(action, options = {})
     options = options.reverse_merge(
       token: @subscription.paypal_payment_token,
       payer_id: @subscription.paypal_customer_token,
       description: @subscription.plan.name,
       amount: @subscription.plan.monthly_price,
       ipn_url: "https://my-app-name.com/payment_notifications",
       currency: "JPY"
    )
     response = PayPal::Recurring.new(options).send(action)
     raise response.errors.inspect if response.errors.present?
     response
   end

3) In PayPal's developer sandbox, click on 'Test Accounts' and then click on the 'Enter Sandbox Test Site' orange button. Once there, log in with your sandbox seller credentials. Once inside go to 'My Account' and 'Profile' and under 'Selling Preferences' click on 'Instant Payment Notification Preferences'. Set your notification url to match the url you set up to receive the IPN POST and set message delivery to enabled.

like image 162
diasks2 Avatar answered Sep 30 '22 14:09

diasks2