Integrating Payments with User Defined Forms

A short tutorial on how to accept payments through the Silverstripe User Forms module.
Published on Dec 16 2014 by Tim Larsen

What are we trying to do?

We're trying to take your amazing Silverstripe site to the next level by accepting payments! For not-for-profits and smaller businesses without the need for a fully-fledged e-commerce solution, this is a quick and easy process to get you started.

What you'll need:

If you want to make the process of getting all of the above easier, using Composer (OSX or Linux or Windows) just run the two commands below.

Setting Up SilverStripe

Note: If you've already got a site setup, you can skip this step.

composer create-project silverstripe/installer /path/to/project 3.1.8

What does this do?
Good question! This downloads the latest version of Silverstripe (CMS and Framework) and sets up a basic site for you in "/path/to/project" (you will probably want to change that). After running this script, test it out by going to your /path/to/project. You should be greeted by an install screen which will guide you through the rest of the setup. 

Setting Up the SilverStripe Userforms Payments Module

composer require souldigital/silverstripe-userforms-payments dev-master

What does this do?
This command adds the requirement of the "Silverstripe Userforms Payments Module" (a mouthful, I know) to your project. In doing so, it will download the latest version of said module and all of the module's requirements (of which there are many!).

Together, the above two commands will create your SilverStripe project, include the UserForms Payments module (by Soul Digital) and streamline the entire process by including all required modules (like Userforms and OmniPay). Make sure you run a /dev/build?flush=all to allow SilverStripe to use the module you downloaded.

Setting Up OmniPay

First of all - what is OmniPay?
OmniPay is an amazing payment gateway management tool - it streamlines the entire process of enabling Payment Gateways in your Silverstripe site. After you implement a single payment gateway, adding multiple is a super-easy process.

Sounds cool. Which payment gateways can I use?
These ones! At the time of posting this, there are almost 40 different Payment Gateways compatible with OmniPay (I've not heard of half of them, but that's beside the point!), so chances are, the Payment Gateway you want to use is compatible. Pick one and set up an account. For this tutorial, I am using SecurePay. SecurePay is a payment gateway that has a great support team and was recently bought out by Australia Post (so you know it's good).

Does OmniPay come with all of these gateways?
Nope. In order to get OmniPay working with any Payment Gateway (such as SecurePay, PayPal, Stripe, Pin Payments etc.) you'll need to download the associated "connector". For SecurePay, we can download the module from here or, we can include it in our awesome composer file by running the following command:

composer require omni-pay/securepay dev-master

Note: after adding any modules to your site, it's always a good idea to do a /dev/build. This basically forces Silverstripe to find any new modules that have been installed and make sure that they have their required section in the database. To do a dev/build, go to http://localhost/dev/build (or whatever your local url is).

Note again: that you must either be in dev mode, or be logged in as an admin to do a dev/build.

Done! Now what do I need to do?
After you've set up the connector, to set up OmniPay to accept payments, you'll need the API details from your payment gateway. This is out of the scope of this tutorial, but should be straight-forward enough once you know what you're looking for in the payment gateway's page. If you need help, the page for the OmniPay Connector for your selected Payment Gateway should be able to point you in the right direction.

What's a YAML?
Next, you'll need to create a YAML file in your `mysite/_config` folder. YAML stands for YAML Ain't Markup Language. It's essentially a human-readable way of serialising data. Instead of underscores, question marks and squiggly brackets, it uses spaces, colons and hyphens. YAML is super strict when it comes to formatting, so make sure you always use two spaces and not tabs when completing the following.

We'll name this file `payments.yml` and place it in `/mysite/_config`.

name: Payment
---
Payment:
  allowed_gateways:
    - 'SecurePay_DirectPost'
  parameters:
    SecurePay_DirectPost:
      merchantID: 'ABC1234'
      transactionPassword: '50ulDgTl'
      required_fields:
        - 'name'
        - 'number'
        - 'expiryMonth'
        - 'expiryYear'
        - 'cvv'
---
Except:
environment: 'live'
---
Payment:
  file_logging: 1
  parameters:
    SecurePay_DirectPost:
      testMode: true
---
Only:
environment: 'live'
---
Payment:
  parameters:
    SecurePay_DirectPost:
      transactionPassword: 'abc123'
---

 YAML? More like WTF!
Calm down! I know the above might look daunting, but if you go through it line-by-line it's actually fairly straightforward. See my example below. Note that anything to the right of a # is a comment, and won't affect the YAML file itself.

name: Payment   # we're just setting the name of this YAML file
---
Payment:             # we want to change the settings of the Payment module
  allowed_gateways:   # we're setting the gateways we want to allow here. 
    - 'SecurePay_DirectPost'  # we're only adding SecurePay for now, but next time we might want 2 or 3 options
  parameters:   
    SecurePay_DirectPost: # we're targeting the settings for SecurePay in the context of Payments (note the spaces)
      merchantID: 'ABC1234'  # this merchantID should be visible in the SecurePay admin area
      transactionPassword: '50ulDgTl' # I always make sure that i put the test password here
      required_fields: # this section is super important - it tells OmniPay which fields SecurePay needs for a payment
        - 'name'
        - 'number'
        - 'expiryMonth'
        - 'expiryYear'
        - 'cvv'
---
Except: # now this is some YAML trickery. We want to target the site when it's NOT in "live" mode
environment: 'live'
---
Payment:
  file_logging: 1 # log transactions - for science
  parameters:
    SecurePay_DirectPost:
      testMode: true # very important for debugging
---
Only: # some more YAML trickery! Now we're ONLY targetting "live" mode
environment: 'live'
---
Payment:
  parameters:
    SecurePay_DirectPost:
      transactionPassword: 'abc123' # this is the LIVE transaction password
---

Awesome.

So now, we have Silverstripe, Userforms, OmniPay and SecurePay set up. Let's make a payment form!

Building the form

Believe it or not, this is the easiest part of the process; we simply follow these steps to get started:

  1. Log in to the SilverStripe admin (by going to http://localhost/admin or similar)
  2. Click "Pages" on the left-hand column
  3. Click "Add New" towards the top of the screen
  4. Select the "User Defined Payment Form" type
  5. Build the page out as you normally would (Title, Content etc)
  6. In the Form tab, build out your payment form. Make sure you include a Field with the name "Amount" - this could be either a Numeric Field or Radio Field.
  7. In the Configuration tab, add text to the Show on Completion and Show on Error text areas. Note that the Show on Completion tab accepts the shortcode of [amount] that will substitute the [amount] value from the form data.
  8. Still in the Configuration tab, make sure you add in Email Recipients for each user that should receive an email. When adding Email Recipients, it's a good idea to send "Captured" emails to the purchaser as a form of receipt, and a copy to your site's admin so they are aware that they've received a payment. It might also be worth adding your own address for erroneous payments when setting up to keep track of any bugs.
  9. In the payment tab, select the FormField that you are using for the "Amount" - if your formfield doesn't appear in this list, save and refresh the page. 
  10. Still in the payment tab, select the name of the Payment Gateway that you have set up from your YAML file.
  11. As we are using the SecurePay payment gateway, we will need to select "Show Card Fields" and "Show Billing Fields" to ensure we have sufficient data for the payment to be successful. This will vary for each Payment Gateway - e.g. PayPal doesn't need any of this information at this stage. 

As a side note, rest assured that no sensitive credit card data will be stored on your server using the above settings. This is an intentional security measure that has been hard-coded in to ensure the privacy of your users' information. 

See it in action

We built and used this module (with some minor modifications) on a donation form for a fantastic site we built called Kildonan. Take a look at the donation form here.

Last Steps

Test the form out multiple times in dev mode, and once you're satisfied with how everything is working, switch over to live mode and complete a successful payment of $2 or more to yourself (stay away from $1 transactions - they can be picked up as scam transactions and will generally lead to more than $1 worth of headaches). 

This was lots of fun, but why doesn't the module do X?
Because I didn't even think of X! That's a great idea! You should add an issue on GitHubcontact us directly or add a comment below and let us know about this X.

Uhh, mate... this code is broken.
At the time of posting this, the above code worked. That said, the modules referenced in this article may change over time. Apart from that, I'm new to the whole blogging scene, so I may have made a typo or skipped over something. Let me know exactly what the problem is using the comments box below and I'll get back to you ASAP with a fix. 

Image credit: a screenshot taken from a small clip from Futurama (FOX/Comedy Central)