5 Comments

Integrating Paypal Express with Rails 3.1 – Part 2

Picking up from my last post, we will now look at the next PaypalExpressController action: review. We first need to modify our routes.rb file:

Second addition to routes.rb

   get "paypal_express/review"

We are now ready to add the `review` action to the PaypalExpressController.

PaypalExpressController#review

class PaypalExpressController < ApplicationController
  
  before_filter :assigns_gateway

  include ActiveMerchant::Billing
  include PaypalExpressHelper

  def checkout
    # implemented in the previous blog post
  end

  def review
    if params[:token].nil?
      redirect_to home_url, :notice => 'Woops! Something went wrong!' 
      return
    end

    gateway_response = @gateway.details_for(params[:token])

    unless gateway_response.success?
      redirect_to home_url, :notice => "Sorry! Something went wrong with the Paypal purchase. Here's what Paypal said: #{gateway_response.message}" 
      return
    end

    @order_info = get_order_info gateway_response, @cart
  end

  private
    def assigns_gateway
      # implemented in the previous blog post
    end
end

Based on how the checkout action was setup from the previous post, the review action will be called after the customer returns from Paypal. Now I will explain what this action does:

  1. We check that params contains the :token key since that’s what’s passed back from Paypal. If the request does not have such key, we redirect to the home page.
  2. Next, we use the :token to retrieve order information (such as shipping address, order total, etc.) from Paypal using ActiveMerchant’s details_for method.
  3. Next, we check whether the Paypal transaction went through successfully or not. If it failed, we again redirect to the home page.
  4. Lastly, if the transaction was processed successfully, we now extract the order information from the gateway response.

You will notice the review action makes use of get_order_info to extract the order information. The method is defined in the PaypalExpressHelper module here:

module PaypalExpressHelper
  def get_setup_purchase_params(cart, request)
     # implemented in the previous blog post
  end

  def get_order_info(gateway_response, cart)
    subtotal, shipping, total = get_totals(cart)
    {
      shipping_address: gateway_response.address,
      email: gateway_response.email,
      name: gateway_response.name,
      gateway_details: {
        :token => gateway_response.token,
        :payer_id => gateway_response.payer_id,
      },
      subtotal: subtotal,
      shipping: shipping,
      total: total,
    }
  end

  def get_shipping(cart)
    # define your own shipping calculation rules here
  end

  def get_items(cart)
    # implemented in the previous blog post
  end

  def get_totals(cart)
    # implemented in the previous blog post
  end

  def to_cents(money)
    # implemented in the previous blog post
  end
end

The order information includes important data such as shipping address, email, and the customer’s name. Please also note that subtotal, shipping, and total are all in cents and not dollars.

With @order_info populated, here’s a sample review.html.haml to render it:

%h3 Example of rendering Order Information

%h4 Your Total
%p= "Subtotal: #{number_to_currency @order_info[:subtotal]}"
%p= "Shipping: #{number_to_currency @order_info[:shipping]}"
%p= "Total: #{number_to_currency @order_info[:total]}"

%h4 Shipping Address
%table
  %tr
    %td
      ==Name
    %td
      = @order_info[:shipping_address]['name']
  %tr
    %td
      ==Company
    %td
      = @order_info[:shipping_address]['company']
  %tr
    %td
      == Address 1
    %td
      = @order_info[:shipping_address]['address1']
  %tr
    %td
      ==Address 2
    %td
      = @order_info[:shipping_address]['address2']
  %tr
    %td
      == City
    %td
      = @order_info[:shipping_address]['city']
  %tr
    %td
      == State
    %td
      = @order_info[:shipping_address]['state']
  %tr
    %td
      == Country
    %td
      = @order_info[:shipping_address]['country']
  %tr
    %td
      == Zipcode
    %td
      = @order_info[:shipping_address]['zip']

%h4 Your Email: 
= @order_info[:email]
%h4 Your Paypal account holder name: 
= @order_info[:name]


= link_to 'Complete Purchase', paypal_express_purchase_path(:token => @order_info[:gateway_details][:token], :payer_id => @order_info[:gateway_details][:payer_id])

A few points to notice about the view:

  • Pay close attention to the data :shipping_address contains.
  • Also pay close attention to the “Complete Purchase” link. This is the link that the customer needs to click to complete the purchase. The link must contain :token and :payer_id; both of which were sent by Paypal in the review action.

The method we have not defined is paypal_express_purchase_path which is the last controller action we need to implement. That will be covered in Part 3. Stay tuned!