Shopify.info Redesigned

Daniel, our designer, has just finished the redesign of the Shopify brochure page and it looks fantastic. The page features a beautiful redesign, fantastic video overview of some of Shopify's features, as well as profiles and interviews with some of Shopify's highest profile clients. If you're in the market for an e-commerce store or if you're into eye candy then you'll definitely want to go and check it out.

PayPal Express Payments with ActiveMerchant

There is a lot of confusion over the myriad of services that PayPal offers for accepting PayPal payments. In reality there are two ways of accepting PayPal payments.

PayPal Website Payments Standard

Website Payments Standard is the basic service PayPal offers for accepting PayPal payments. Website Payments Standard requires the creation of an HTML form that is posted to PayPal. The user is redirected to the PayPal website where they complete their payment. They are then redirected back to the seller's website at the end of the process where it is possible to display an order confirmation, or other information. Very basic, easy to setup, but also quite limited.

PayPal Express

PayPal Express is a much more powerful alternative to PayPal Website Payments Standard. The downside is that it is slightly more complicated. However, I am going to show how easy it is to get PayPal Express working with ActiveMerchant. PayPal Express has several benefits including support for Authorization and Capture. Website Payments Standard also has support for Authorization and Capture, but the seller has to actually login to their PayPal account to capture the funds. PayPal Express also keeps control of the payment flow on your page, instead of PayPal's. The user is only redirected to PayPal briefly to confirm payment, and then they are sent back to the seller's page to complete the payment. There are several advantages to this, but I think the biggest is that you can rely on PayPal to provide address information for the buyer and then determine additional shipping or other charges to add to the total of the order.

Now that I've provided a bit of background on PayPal Express I'm going to show how simple it is to integrate into Rails application. The code is based on the integration of PayPal Express into Shopify. The applicable integration points from the PayPal Express Checkout Integration Guide will be noted throughout the example. If you like you can download the completed Sprockets application sprockets.tar.gz. You will need at least Rails 2.0.2 Gems to run the Sprockets application. You will only need to add your API credentials into the application, which is described in the example text.

First, in order to use the sandbox, you'll need a PayPal Sandbox buyer and seller to work with. See Sandbox Testing for more information on getting these accounts setup. The seller account must be either a Premier Account or Business Account in order to work with PayPal Express. Don't forget to activate the account using the Test Email link in Developer Central. Email isn't really sent in the sandbox. It just accumulates in the Developer Central inbox. Then you'll have to confirm your bank account using the Get Verified link while logged in as the test user.

Create a new Rails application. I am going to name my project Sprockets, which is what I'll be selling on my site:


$ rails sprockets

Now you can enter the project and install ActiveMerchant as a plugin:


$ cd sprockets
$ ./script/plugin install http://activemerchant.googlecode.com/svn/trunk/active_merchant

The first thing to do is to configure ActiveMerchant. By default ActiveMerchant uses the production environment of a payment gateway, so we have to force ActiveMerchant into test mode while we're running in the Rails development environment. This is easily accomplished by opening up config/environments/development.rb and adding the following code to the bottom of the file:

1
2
3
config.after_initialize do
  ActiveMerchant::Billing::Base.mode = :test
end

The preceding code ensures that the PayPal Sandbox will be used for the test payments, and waits until the entire application is loaded before doing the configuration.

The next thing to do is to login to the PayPal Sandbox and launch the sandbox for the seller account you previously created. Click the My Account link followed by the Profile _ link. Then click _API Access underneath Account Information. Select Request API signature and then click Agree and Submit. Record the API username, API Password, and Signature. We'll be using them shortly.

Now that all of the configuration has been completed we can move onto actually accepting payments. Let's generate a controller PaymentsController that will be used to accept the payments from PayPal.


$ ./script/generate controller payments index confirm complete

We created the controller with the action index, confirm, complete actions in the controller along with their associated views. Let's open up the index.html.erb template and add the PayPal Express logo that the customer will click to make payment.

The first thing we need to do is include the ActiveMerchant::Billing namespace into the controller so that we can access the classes from ActiveMerchant with less typing:

1
2
3
class PaymentsController < ApplicationController
  include ActiveMerchant::Billing
end

I'm assuming that you have created a common layout, such as application.html.erb to provide the required HTML structure for the page. The index action represents Integration Point 1a from the Integration Guide. index.html.erb looks as follows:

1
2
3
4
5
6
<h1>Purchase Sprockets</h1>
<p>Thank you for your decision to purchase our sprockets.</p>
<p>Your order total is $50.00</p>
<p>
  <%= link_to image_tag('https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif'), :action => 'checkout' %>
</p>

Clicking the PayPal Express button do a GET request on the checkout action. The checkout action is where we setup the purchase with PayPal and get the token identifying the purchase from PayPal. We didn't generate the checkout action initially because it doesn't require a view. The checkout action represents Integration Point 1b from the Integration Guide. Define the checkout action as follows:

1
2
3
4
5
6
7
8
def checkout
  setup_response = gateway.setup_purchase(5000,
    :ip                => request.remote_ip,
    :return_url        => url_for(:action => 'confirm', :only_path => false),
    :cancel_return_url => url_for(:action => 'index', :only_path => false)
  )
  redirect_to gateway.redirect_url_for(setup_response.token)
end

gateway is actually a method which constructs the PaypalExpressGateway if it hasn't been already:

1
2
3
4
5
6
7
8
private
def gateway
  @gateway ||= PaypalExpressGateway.new(
    :login => 'API Login',
    :password => 'API Password',
    :signature => 'API Signature'
  )
end

As you can see, we're constructing the gateway using the credentials provided to us earlier in the PayPal Sandbox and returning the new instance of the gateway.

The setup_purchase() method informs PayPal of the details of the purchase we're going to make and returns a token. 5000 is the amount in cents of the purchase, which is $50.00. ActiveMerchant only accepts amounts in cents. The customer's IP address, passed in using the :ip option, is a required option, and helps PayPal reduce fraud. The :return_url option is the absolute URL that the customer will be redirected to after their purchase, and :cancel_return_url is the URL the customer will return to if they cancel the purchase.

Finally, we redirect the customer to PayPal. The URL is constructed by passing the token returned in the setup_purchase() call to the redirect_url_for() method provided by the gateway.

Now if you load http://localhost:3000/payments in your browser and click the PayPal Express button you should be redirected to PayPal. You will need to be logged into the PayPal Developer Central at the time you click the button in order for the sandbox to load correctly. You can now log in to PayPal using the Sandbox buyer account that you created earlier. Once logged in you will see the details of the purchase. You'll also see the link to cancel the transaction below the Continue button. The time spent on PayPal's site represents Integration Point 2a and Integration Point 2b from the Integration Guide. Clicking the Continue button will redirect your browser back to the Sprockets application confirm action. The redirection back to our application represents Integration Point 2c from the Integration guide. We already have a confirm action, but it just displays the default message put in the template by the Rails generator.

Let's enhance the confirm action as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
def confirm
  redirect_to :action => 'index' unless params[:token]
  
  details_response = gateway.details_for(params[:token])
  
  if !details_response.success?
    @message = details_response.message
    render :action => 'error'
    return
  end
    
  @address = details_response.address
end

First, we request the details of the purchase from PayPal using the details_for() method, which takes the token param as its first argument. If we successful get the details for the purchase then we display the confirm.html.erb template. Otherwise, we render the the error.html.erb template. error.html.erb looks as follows:

1
2
<h1>Error</h1>
<p>Unfortunately an error occurred: <%= @message %></p>

The confirm.html.erb templates displays the customer's PayPal address and asks them if they want to complete the payment. Displaying the review page represents Integration Point 3a from the Integration guide. This is the customer's opportunity to review the details of their order, change shipping methods, etc. It looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<h1>Please Confirm Your Payment Details</h1>

<table>
  <tr><td>Name</td><td><%= @address['name'] %></td></tr>
  <tr><td>Company</td><td><%= @address['company'] %></td></tr>
  <tr><td>Address 1</td><td><%= @address['address1'] %></td></tr>
  <tr><td>Address 2</td><td><%= @address['address2'] %></td></tr>
  <tr><td>City</td><td><%= @address['city'] %></td></tr>
  <tr><td>State</td><td><%= @address['state'] %></td></tr>
  <tr><td>Country</td><td><%= @address['country'] %></td></tr>
  <tr><td>Zip</td><td><%= @address['zip'] %></td></tr>
</table>

<% form_tag :action => 'complete', :token => params[:token], :payer_id => params[:PayerID] do %>
  <%= submit_tag 'Complete Payment' %>
<% end %>

When the customer clicks the Complete Payment button they will post their token, and PayerID, which were returned from PayPal, back to the complete action where we'll inform PayPal to complete the purchase. Completing the purchase represents Integration Point 3b from the Integration Guide. It looks as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
def complete
  purchase = gateway.purchase(5000,
    :ip       => request.remote_ip,
    :payer_id => params[:payer_id],
    :token    => params[:token]
  )
  
  if !purchase.success?
    @message = purchase.message
    render :action => 'error'
    return
  end
end

This looks similar to when we initially setup the purchase, but we're calling purchase() instead of setup_purchase(). If the purchase is successful then we render the complete.html.erb template. Displaying the final success message represents Integration Point 4 from the Integration Guide, which is the final step. It looks like:


<p>Thank you for your purchase</p>

The entire flow of the purchase is very flexible. The initial amount of the setup_purchase() method doesn't even need to match the final amount sent in purchase(). This allows for the buyer to change their mind about their order details during the checkout flow in your site. This is useful for situations where the customer may want to add high priority shipping, a discount code, or gift wrapping while reviewing their order. There is a lot of data that can be provided to PayPal throughout the integration. Take a look at the Integration Guide for a complete overview of all that is possible.

Scrivener, the best writing tool since sliced bread

Have you ever wanted to write something, but felt so bogged down by the tools that you gave up? Even worse is if you don't even have the option of giving up. When I was writing RJS Templates for Rails using the O'Reilly Word template there were many moments when I thought that I may end it all. Thankfully, that didn't happen.

I have a profound hatred for Microsoft Word. I feel like its entire codebase exists solely to make my writing experience miserable. Capitalizing everything I need lowercase, formatting my paragraphs in ways that I don't want, just messing with my document to ruin my weekend. I'm sure it is possible to make Word do what I want, but I just don't feel like it is worth the effort. I don't want to waste my time figuring out how to make Word work for me, when what I want to do is really simple. I just want to write text. Is this a lot to ask for?

Thankfully, Tobias Lütke let me know about Scrivener. What can I say? Scrivener is fantastic. Scrivener not only gets out of my way when I'm writing, it actually has features that help with the process of writing. Scrivener helps in all the areas where it counts when it comes to writing. Organization, taking notes, keeping lists of reference material, storing research documents right in the project. Scrivener feels like a combination of a simple text editor with the power of an organizational tool like Omni Outliner built right in. You can create an outline in minutes, reorganize by dragging sections around, look at high level views of a section in a cork board view, and then turn off the entire UI when you're ready to get down to writing by entering the full screen typewriter mode.

There are many, many more killer features that I won't get into here. Do yourself a favour and get the demo. Better yet, just buy it. It only costs $34.99, which is less than you're going to spend next week at Starbucks anyway. You can get up to speed with all the features in less than an hour with the included tutorials.

ActiveMerchant PeepCode Screenshot