LaunchSchool - An Online School for Developers /

Blog

Process Payments With Paypal in Rails, Part 3 - Recurring Payments

This is the third article in the “Process Payments with Paypal in Rails” tutorial series:

In this article we will adapt these two payment processes to accept recurring payments. We will sell an on-line “Cookery Master in Oriental Food” which has one year duration and is paid monthly.

For this post, we will work on the recurring branch:

1
2
3
4
5
6
7
8
git clone -b recurring git@github.com:gotealeaf/paypal-basics.git
cd paypal-basics
rake db:drop
rake db:create
rake db:migrate
rake db:seed
rails s
open http://localhost:3000

There are two previous steps needed, which were covered in the Process Payments With Paypal in Rails, Part 2 – Charge Credit Cards post:

  • Step 1. Create Paypal Pro account: create a merchant Pro account to test in Sandbox
  • Step 3. Configure Active Merchant: Configure the application to accept credit cards

Now let’s see how to set up recurring payments!

Step 1. Modify our model to offer recurring courses

To process our Master we need the following parameters:

  • recurring?: a boolean value to determine if the course has recurring payments or not
  • period: possible values are: [“Day”, “Week”, “SemiMonth”, “Month”, “Year”]
  • cycles: number of charges
1
2
rails g migration AddRecurringColumnsToCourses recurring:boolean period:string cycles:integer
rake db:migrate

We will add our new Master in our ‘db/seeds.rb’ file:

1
Course.create name: "COOKERY MASTER IN ORIENTAL FOOD (1 Year)", price: 475, recurring:true, period: "Month",cycles: 12

You can reload the courses executing rake db:seed

And we need to fix our view in order to announce our recurring courses properly. Just add the course period to the price if this is recurring. In app/views/courses/_index.html.haml put the condition in the button:

1
%button.btn{style: "color: white;background: rgb(242, 118, 73);"} Register ($#{course.price} #{("per " + course.period) if course.recurring})

This will show our catalog properly to our clients:

Step 2. Modify Paypal method to pay recurring courses

Here we just need to notify to Paypal through the URL to make recurring charges. Modifying paypal_url method in Registration model app/models/registration.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  def paypal_url(return_path)
    values = {
        business: "merchant@gotealeaf.com",
        upload: 1,
        no_shipping: 1,
        return: "#{Rails.application.secrets.app_host}#{return_path}",
        notify_url: "#{Rails.application.secrets.app_host}/hook",
        invoice: id,
        item_name: course.name
    }
    values = if course.recurring
                values.merge(
                    cmd: "_xclick-subscriptions",
                    a3: course.price,
                    p3: 1,
                    srt: course.cycles,
                    t3: course.period.first
                )
              else
                values.merge(
                    cmd: "_xclick",
                    amount: course.price,
                    item_number: course.id,
                    quantity: '1'
                )
              end

    "#{Rails.application.secrets.paypal_host}/cgi-bin/webscr?" + values.to_query
  end

The code is pretty self-explicative, just add recurring values if the course need them. The other values such as notify hook, return url, business account … are the same.

If your use case needs to include more parameters, you can take a look at HTML Variables for PayPal Payments Standard

Test Paypal method

As we described in Process Payments with Paypal in Rails, Part 1 – Basic Checkout post, we need a HTTP tunnel published on the web in order to be properly returned and notified of the payment.

We get this with ngrok service, just executing ngrok 3000, and annotating in config/secrets.yml the publish URL (‘http://7491c056.ngrok.com’ today)

Now we can go to this direction (having our app running in localhost, port 3000):

Here you should fill the form and choose Paypal payment method:

You will be redirected to the Paypal authentication page, and here, you can see the recurring payment detail:

You should login and Accept the payment. Then you go to Successful purchase page:

When you click in the “Return To SandboxTest Account’s Test Store” you will return to Invoice page:

Where you can see that is Completed, so the /hook is also running with revurring registrations.

In the buyer@gotealeaf.com account you can see the Subscription created towards our merchant@gotealeaf.com account:

Step 3. Modify Credit Card payment method to pay recurring courses

You just need to modify the Card model, app/models/card.rb:

  • Access directly to the course from the card model, to simplify our code:
1
  has_one :course, through: :registration
  • The purchase option should call to one or another method of the Gateway:
1
2
3
4
5
6
7
8
9
10
  def purchase
    response = if course.recurring
                 GATEWAY.recurring(price_in_cents, credit_card, purchase_options)
               else
                 GATEWAY.purchase(price_in_cents, credit_card, purchase_options)
               end
    create_card_transaction(action: "purchase", amount: price_in_cents, response: response)
    registration.update_attribute(:purchased_at, Time.now) if response.success?
    response.success?
  end
  • And the options are different for recurring payments:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  def purchase_options
    values = {
            ip: ip_address,
            billing_address: {
                name:      "Flaying Cakes",
                address1:  "123 5th Av.",
                city:      "New York",
                state:     "NY",
                country:   "US",
                zip:       "10001"
            }
        }
    if course.recurring
      values.merge(
        period: course.period,
        frequency: 1,
        cycles: course.cycles,
        description: course.name,
        start_date: Time.now
      )
    else
      values
    end
  end

Finally, just for seen the Profile ID (this is a subscription, not a transaction), we will show the profile in the invoice:

1
2
3
4
5
6
  - if @registration.course.recurring
    %strong Profile Idetntifier:
    = @registration.card.card_transaction.params["profile_id"]
  - else
    %strong Transaction Identifier:
    = @registration.card.card_transaction.params["transaction_id"]

Test Credit Card method

Just select the Master and fill the form including Credit card:

Directly your invoice is created:

You can see at the merchant account how the recurring payment has been created:

Conclusions

Recurring payments make good business sense for many applications. In this tutorial we have shown that you can manage recurring payments, and receive all of them in your Paypal Pro account.

For more details you can read HTML Variables for PayPal Payments Standard. You also read more details about the ActiveMerchant Paypal Gateway.