Search code examples
ruby-on-railsruby-on-rails-3devisepaypalpaypal-sandbox

User Registration with Devise and Paypal


I want to integrate Paypal within the Devise user registration process. What I want is to have a standard rails form based on the devise resource, that also has custom fields belonging to the user's model.

When a user fills in those fields and clicks on signup, it will be redirected to Paypal, when he clears from paypal and returns to our site then the user data must be created.

For the scenario where the user fill's out the paypal form but doesn't come back to our site, we have to keep record of user before redirecting to Paypal.

For this we can create a flag in user model and use Paypal IPN and when the user transaction notified, set that flag.

But in the case when the user is redirected to Paypal but doesn't complete the transaction, if the user returns to registration and signup again, our model should not throw error saying that the email entered already exists in the table.

How can we handle all these scenarios, is there any gem or plugin available to work with?


Solution

  • Here i am posting the detail code for performing the whole process.

    registration_controller.rb

    module Auth
      class RegistrationController < Devise::RegistrationsController
        include Auth::RegistrationHelper
    
        def create
          @user = User.new params[:user]
          if @user.valid?
            redirect_to get_subscribe_url(@user, request)
          else
            super
          end
        end
      end
    end
    

    registration_helper.rb

    module Auth::RegistrationHelper
      def get_subscribe_url(user, request)
        url = Rails.env == "production" ? "https://www.paypal.com/cgi-bin/webscr/?" : "https://www.sandbox.paypal.com/cgi-bin/webscr/?"
        url + {
            :ip => request.remote_ip,
            :cmd => '_s-xclick',
            :hosted_button_id => (Rails.env == "production" ? "ID_FOR_BUTTON" : "ID_FOR_BUTTON"),
            :return_url => root_url,
            :cancel_return_url => root_url,
            :notify_url => payment_notifications_create_url,
            :allow_note => true,
            :custom => Base64.encode64("#{user.email}|#{user.organization_type_id}|#{user.password}")
        }.to_query
      end
    end
    

    payment_notification_controller.rb

    class PaymentNotificationsController < ApplicationController
      protect_from_forgery :except => [:create]
      layout "single_column", :only => :show
    
      def create
        @notification = PaymentNotification.new
        @notification.transaction_id = params[:ipn_track_id]
        @notification.params = params
        @notification.status = "paid"
        @custom = Base64.decode64(params[:custom])
        @custom = @custom.split("|")
        @user = User.new
        @user.email = @custom[0]
        @user.organization_type_id = @custom[1].to_i
        @user.password = @custom[2]
        if @user.valid?
          @user.save
          @notification.user = @user
          @notification.save
          @user.send_confirmation_instructions
        end
        render :nothing => true
      end
    
      def show
      end
    end