#146
Jan 26, 2009

PayPal Express Checkout

PayPal Express Checkout is easy to add to an existing ordering system. See how in this episode.
Download (29.5 MB, 15:24)
alternative download for iPod & Apple TV (22 MB, 15:24)

Resources

script/generate migration add_express_token_to_orders express_token:string express_payer_id:string
rake db:migrate
# config/environments/development.rb
config.after_initialize do
  ActiveMerchant::Billing::Base.mode = :test
  paypal_options = {
    :login => "seller_1229899173_biz_api1.railscasts.com",
    :password => "FXWU58S7KXFC6HBE",
    :signature => "AGjv6SW.mTiKxtkm6L9DcSUCUgePAUDQ3L-kTdszkPG8mRfjaRZDYtSu"
  }
  ::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options)
  ::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
end

# config/environments/test.rb
config.after_initialize do
  ActiveMerchant::Billing::Base.mode = :test
  ::STANDARD_GATEWAY = ActiveMerchant::Billing::BogusGateway.new
  ::EXPRESS_GATEWAY = ActiveMerchant::Billing::BogusGateway.new
end

# config/environments/production.rb
config.after_initialize do
  ActiveMerchant::Billing::Base.mode = :production
  paypal_options = {
    :login => "seller_1229899173_biz_api1.railscasts.com",
    :password => "FXWU58S7KXFC6HBE",
    :signature => "AGjv6SW.mTiKxtkm6L9DcSUCUgePAUDQ3L-kTdszkPG8mRfjaRZDYtSu"
  }
  ::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options)
  ::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
end

# routes.rb
map.resources :orders, :new => { :express => :get }

# orders_controller.rb
def express
  response = EXPRESS_GATEWAY.setup_purchase(current_cart.build_order.price_in_cents,
    :ip                => request.remote_ip,
    :return_url        => new_order_url,
    :cancel_return_url => products_url
  )
  redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
end

def new
  @order = Order.new(:express_token => params[:token])
end

# models/order.rb
def purchase
  response = process_purchase
  transactions.create!(:action => "purchase", :amount => price_in_cents, :response => response)
  cart.update_attribute(:purchased_at, Time.now) if response.success?
  response.success?
end

def express_token=(token)
  write_attribute(:express_token, token)
  if new_record? && !token.blank?
    details = EXPRESS_GATEWAY.details_for(token)
    self.express_payer_id = details.payer_id
    self.first_name = details.params["first_name"]
    self.last_name = details.params["last_name"]
  end
end

private

def process_purchase
  if express_token.blank?
    STANDARD_GATEWAY.purchase(price_in_cents, credit_card, standard_purchase_options)
  else
    EXPRESS_GATEWAY.purchase(price_in_cents, express_purchase_options)
  end
end

def standard_purchase_options
  {
    :ip => ip_address,
    :billing_address => {
      :name     => "Ryan Bates",
      :address1 => "123 Main St.",
      :city     => "New York",
      :state    => "NY",
      :country  => "US",
      :zip      => "10001"
    }
  }
end

def express_purchase_options
  {
    :ip => ip_address,
    :token => express_token,
    :payer_id => express_payer_id
  }
end

def validate_card
  if express_token.blank? && !credit_card.valid?
    credit_card.errors.full_messages.each do |message|
      errors.add_to_base message
    end
  end
end
<!-- carts/show.html.erb -->
<%= link_to image_tag("https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif"), express_new_order_path %>

<!-- orders/new.html.erb -->
<% form_for @order do |f| %>
  <%= f.error_messages %>
  <% if @order.express_token.blank? %>
    ...
  <% else %>
    <%= f.hidden_field :express_token %>
    <p>Name: <%=h @order.first_name %> <%=h @order.last_name %></p>
    <p>TODO Display order confirmation details</p>
  <% end %>
  <p><%= f.submit "Complete Order" %></p>
<% end %>

RSS Feed for Episode Comments 31 comments

1. Bertg Jan 26, 2009 at 01:07

When overriding the express_token= method, you set the express_token "attribute" via the self[] method. This is not the best way.

According to the Rails manuals it is better to use write_attribute when overriding an attribute setter (and read_attribute when overriding the getter)

Great cast otherwise ;)


2. Udo Urbantschitsch Jan 26, 2009 at 05:35

Hi Ryan,

thank you very much for another useful and interesting Railscast!

Keep up the good work.

Greetings from Austria,
Udo


3. Igor Jan 26, 2009 at 05:46

Hi, Ryan

Thanks for your work. Can't wait the end of work day to watch it ;)

However it's 6 screen casts regarding payment gateways. How much more you planning to spend on it, when we will see your screencasts with another rails tips?

Thanks


4. Ryan Bates Jan 26, 2009 at 07:16

@Bertg, thanks for the correction, I'll update the code in the show notes.

@Igor, This is the last cast on e-commerce for a little while. Expect some more regular episodes over the next few weeks.


5. Sam Jan 26, 2009 at 07:54

Hi Ryan,

Thanks again for the screen cast - very useful.

Still new to Ruby and Rails and had a quick question. If the purchase fails it goes to a failure page rather than rendering the new action again. Should this be changed? I'm not sure if this is a bad practice or if it was just to simplify it for the screencast.


6. ron Jan 26, 2009 at 15:10

No screencast on recurring billing? That's too bad. Anyway, love the series. Thanks a lot!


7. Scott Jan 26, 2009 at 18:55

+1 for Recurring Billing!


8. Gustavo Scanferla Jan 26, 2009 at 21:08

@ron and @Scott,
Ryan said that he would that in previous episodes! =D


9. jflcooper Jan 27, 2009 at 02:46

AWESOME!!!!!!!

Recurring billing still to come...
awwwwwwww


10. Vincent Jan 27, 2009 at 13:24

It is my understanding that (like mentioned in episode 145) informations (even more so for sensitive ones) should be gathered in HTTPS... I'm not sure if i missed an episode where the process of doing just that is explained but wouldn't it be a good episode subject otherwise ?

Great screencasts, btw ! keep up the great work !


11. Nick Jan 27, 2009 at 17:38

Ryan, Just wanted to thank you for all the recent merchant casts, have been very helpful for setting up my shop. Keep up the good work :)


12. Ray Rogers Jan 28, 2009 at 06:54

I'm missing the boat on something. How do I add the shipping information into my orders table when using the express pay. I have the first and last name just like the screen cast. But when I try and add the shipping address or any of the shipping information, its not updating the orders table.

Ryan. Thanks for the great series on Active Merchant and PayPal.


13. Vinay Jan 29, 2009 at 00:59

You use current_cart.build_order.price_in_cents in the controller to setup your response. And then the request cycle goes to paypal and then returns and then im losing the cart_id for the order.
Could someone check that?

Great series of casts Ryan! VERY helpful!


14. Andrea Jan 31, 2009 at 02:37

Thanks a lot Ryan! But why not ending in great style with a recurring bill episode? :(
Was one of the most important features!

Thanks aniway :)


15. Ben Feb 03, 2009 at 03:11

I found a handy pdf to get you started with credit card processing:
http://jumpstartcc.com/

Most of the things were already mentiond by ryan, but its a nice overview.


16. Justin Feb 18, 2009 at 10:54

There have been a lot of ecommerce related Railscasts lately, but I think that is because it is a complex topic. I'll throw in a +1 for recurring billing.

Thanks for all of your work. Railscasts are one of the best resources for the community and they are free. Thanks again.


17. Raymond Law Feb 20, 2009 at 11:54

I had to do PayPal recurring payment before the Railscast becomes available. So I put together an extention and wrote a blog post about it.

http://rayvinly.com/articles/2009/02/20/paypal-recurring-billing-with-activemerchant-in-ruby-on-rails/

I hope it works out you all who need to do similar things. There are stuff you can configure. ActiveMerchant is real nice.

Feedback will be appreciated.


18. richard Apr 14, 2009 at 05:58

I'm trying to get this code to work from the git repo but its complaining about current_cart in line_items_controller.rb the create on line 4. any ideas?


19. richard May 05, 2009 at 17:47

Any plans for authorize.net processing ryan? I'm trying to get it work but just can't was hoping you might give some insight.


20. bigshiny90 Jun 03, 2009 at 13:28

great screencast, got me most of the way. i still have questions about integrating a list of ordered products on the confirmation page (after going to paypal).

i can't seem to get the cart line items to list on the confirm page. (this is the Orders -> new.html.erb page).

specifically i thought i would be able to access the cart thru @orders.cart.line_items, but i'm obviously missing something. in fact the @orders.cart_id seems nil.

does this get lost in the Express situation?


21. bigshiny90 Jun 03, 2009 at 13:59

second thoughts...

if i'm understanding this correctly, i can get all the order details (and items) thru the returned express_token. (since i'm actually sending PaymentDetailItems in my purchase).

question: can i access the token details directly on my orders new ERB? or is there a better way to do this?


22. bigshiny90 Jun 03, 2009 at 14:29

oh, i just included the current cart as in the new method of the OrderController. silly me...


23. Darren Jul 03, 2009 at 11:04

+ eight gazzilion billon for recurring billing, Ryan this !#*$ is the bomb.


24. Tinu Cleatus Jul 28, 2009 at 07:16

Looking forward to the recurring billing episode. Many thanks for the series on Paypal.


25. Muthhus Aug 27, 2009 at 06:21

I got the following error, when i followed your code, please assist me..
Thanks

 NameError in OrdersController#express

undefined local variable or method `products_url' for #<OrdersController:0xb6933454>

RAILS_ROOT: /home/shanmuga/shapero/shapero
Application Trace | Framework Trace | Full Trace

app/controllers/orders_controller.rb:6:in `express'

Request

Parameters:

None


26. Brett Francis Oct 13, 2009 at 21:47

How can I use Active Merchant to set Express Checkout's taxamt field? I need to set tax on orders shipping to my state.

Thanks!


27. hello Oct 16, 2009 at 01:38

[url=http://www.rs2guru.com/]wedding invitations[/url]
[url=http://www.rs2guru.com/]wedding invitation[/url]
[url=http://www.rs2guru.com/]unique wedding invitations[/url]


28. CalebHC Nov 11, 2009 at 17:55

Thank you so much for this series! It helped me out an incredible amount. This saved me days of researching and learning. Thank you! :)


29. artemave Dec 17, 2009 at 07:11

Before considering PayPal, consider this:

http://blog.apparentsoft.com/business/124/is-paypal-good-for-your-microisv-business-a-short-paypal-horror-story/


30. Bijesh Dec 23, 2009 at 03:33

Hi Ryan,

There is one issue.

When you are redirecting to PayPal sandbox for Payment, you are not showing the amount which User is going to PAY ?

How can we show the AMOUNT on PayPal site which user is going to PAY ?

Thanks,
Bijesh


31. Mark Richman Jan 26, 2010 at 12:09

+1,210,000,000 for recurring billing. Killer screencast.


32. adidasshoes May 14, 2010 at 02:13

http://www.adidas-cheap.com/


33. permatec Jun 24, 2010 at 05:35

Nice share


34. free directory list Aug 11, 2010 at 22:32

I think this is very dangerous


35. Electrical fan Aug 19, 2010 at 01:27

It is long lifespan, fast weld, anti-oxidize and never fade in color.
The heater is made of stainless steel with different kinds of shape, such as D shape, round shape, square shape and so on.


36. China Electric heater Aug 19, 2010 at 01:28

A heater will keep you warm well into the fall and help make your entertainment events cozy and having comfortable days during the winter


37. China Fitness Equipment Aug 19, 2010 at 01:32

These products are been exporting to Europe, United States, Asia, the Middle East, Russia and Latin America countries. We are expecting more partners from all over the world.


38. PV module Aug 19, 2010 at 01:34

Teamed with excellent scientists and engineers, we can offer you one-stop solution package for PV system design, installation consulting, purchase, delivery,etc.


39. Hydraulic Valves Aug 19, 2010 at 01:36

specializing in production of hydraulic valves, hydraulic systems and hydraulic components.


40. Cable seal Aug 19, 2010 at 01:38

In 2006, we renamed our company into e-Sun Industrial Co., Ltd in Hong Kong, which is known as Pearl of the Orient. After years of developing, we have already set up our production plants separately in the North of China and the South of China to meet the rapid developing demands.


41. Bathroom sanitary ware Aug 19, 2010 at 01:40

Our ceramic sanitary ware factory was found in 2002, with an area of over 40000m2. We've been concentrating on production of best quality ceramic sanitary ware. We've been enjoying high reputation throughout the word, especially in Europe market


42. nike dunks low Aug 19, 2010 at 21:02

Awesome, custom rspec matchers for Moonshine are in my backlog. Great informative post thanks for sharing. I really appreciate what you post. If only i could think of a plugin to actually write. I will instantly grab your rss feed to stay informed of any updates.


43. wholesale new era hats Aug 20, 2010 at 20:47

Fantastic Read! Looking forward to more! Bookmarked the site and will be back again!


44. replicahandbags Aug 23, 2010 at 18:11

I have always liked Outdoor movies, a child standing at the window, looked out from home to the following. Will be able to see the staff busy figure, a huge white cloth has a child hang up and soon will be able to see the movie.


45. Milton Longton Aug 26, 2010 at 07:17

Sorry to go a bit off the topic but can anybody recommend a good kitchen supplier in the United Kingdom.


46. louis vuitton shoes Aug 26, 2010 at 21:04

Thanks for sharing your article. I really enjoyed it. I put a link to my site to here so other people can read it. My readers have about the same interets


47. Wholesale Electronics Aug 27, 2010 at 00:15

Discount Wholesale Electronics, Wholesale Cell Phones, Electronic Gadgets and More from the Best Dropship Wholesaler


48. snow boots Aug 30, 2010 at 21:12

After years of developing, we have already set up our production plants separately in the North of China and the South of China to meet the rapid developing demands.


49. louis vuitton sunglasses Sep 01, 2010 at 21:33

Very good post. Made me realize I was totally wrong about this issue. I figure that one learns something new everyday. Mrs Right learned her lesson! Nice, informative website by the way.

Add your comment:

(SKIP THIS ONE)

(required)

(not shown)


(use pastie or gist for code)

sponsored by:
if you want to help:
required:
Get Quicktime Player
Give Back to Open Source