Solidus and Apple Pay

Apple recently made their Apple Pay mobile payment service accessible on the web. This allows users of iOS version 10 or later to store credit cards on their phone to pay for goods online. This is fantastic news for e-commerce sites looking to maximize their conversion rate on mobile devices. As soon as Stembolt found out about the new feature, we started working on a Solidus extension to make it easy to integrate this type of payment into your store. Today, we're excited to share the extension with everyone. I'm going to walk through the basics of setting up the extension and some of the common gotchas we've run into while integrating Apple Pay into stores.

The Apple Pay sheet

Before we get started, there are a few preconditions that need to be met for Apple Pay. First, you'll need an Apple developer account and to ensure you meet Apple's acceptable use guidelines. Next, you'll need a Braintree account. We found their Apple Pay integration to be by far the easiest to work with and extend. They've also got some excellent documentation to help you through the initial configuration. Once you've got the prerequisites set up you're ready to start integrating the extension.

As with all Solidus extensions, the first step is including it in your Gemfile.

gem 'solidus_paypal_braintree'

Next, you'll want to bundle and run the installation generator.

bundle exec rails g solidus_paypal_braintree:install

Now that you've got the extension installed, let's configure it. The Braintree documentation will guide you through the process of registering your domain. SolidusPaypalBraintree::Gateway is configured the same as any other gateway. Instead of using the admin, we can use Solidus's static_model_preferences to keep the secrets out of our database.

# config/initializers/solidus.rb
  private_key: ENV["PRIVATE_KEY"],
  public_key: ENV["PUBLIC_KEY"],
  merchant_id: ENV["MERCHANT_ID"],
  environment: Rails.env.production? ? "production" : "sandbox",

With our site configured, we're ready to start implementing the client-side JavaScript for accepting Apple Pay payments. There are three primary pieces required: 1. Creating an ApplePaySession 2. Responding to the onvalidatemerchant callback. 3. Responding to the onpaymentauthorized callback. In order to simplify this process, the extension provides some JavaScript that wraps most of this logic. A bare-bones implementation would look something like this:

var applePayButton = document.getElementById('your-apple-pay-button');
SolidusPaypalBraintree.fetchToken(function(clientToken) {
  SolidusPaypalBraintree.initialize(clientToken, function(braintreeClient) {
    SolidusPaypalBraintree.setupApplePay(braintreeClient, "YOUR-MERCHANT-ID", funtion(applePayInstance) {
      applePayButton.addEventListener('click', function() { beginApplePayCheckout(applePayInstance) });

beginApplePayCheckout = function(applePayInstance) {
    applePayInstance: applePayInstance,
    storeName: 'Your Store Name',
    currentUserEmail: Spree.current_email,
    paymentMethodId: Spree.braintreePaymentMethodId,
  }, (session) => {
    // Additional callback logic goes here.

Let's walk through what this is doing behind the scenes. First up, we're calling SolidusPaypalBraintree.fetchToken() which will make an API call to the server to get a distinct token from Braintree to use for this transaction. We pass that method a callback to run when it's finished that calls SolidusPaypalBraintree.initialize(). initialize is responsible for creating the Braintree client that we'll use to make all future calls to Braintree. Finally, we call SolidusPaypalBraintree.setupApplePay(). This method will check whether the device viewing the site is capable of performing Apple Pay transactions, and if so will create the Braintree Apple Pay client instance. We will later use that instance to initialize an Apple Pay session.

Now that we've done all the work to set up a Braintree Apple Pay client instance, we need to register a click event handler on our button. Every time a customer clicks the button, we need to create a new Apple Pay session and register two handlers on it: onvalidatemerchant and onpaymentauthorized. The first is called immediately after the session has been created and is used to ensure the request came from a valid merchant. onpaymentauthorized is called after the customer has authorized the payment and is where we'll tokenize the response and move the order forward. Since these two callbacks are critical to accepting Apple Pay payments, default implentations are set up by SolidusPaypalBraintree.initializeApplePaySession() that will be sufficient for the large majority of implementations.

initializeApplePaySession allows adding additional callback logic. There are two other handlers you may want to implement based on the needs of your store: onshippingcontactselected and onshippingmethodselected. The first will fire after the customer has provided their shipping address details. This callback is an excellent time to calculate any taxes that should be added to the order and provide a list of possible shipping methods back to the customer. The latter is fired after the customer chooses one of the shipping methods you provided in the previous callback. Both of these callbacks are optional. You'll want to implement them if your store has multiple shipping methods or needs to calculate taxes based on shipping address.

Hopefully this brief guide through incorporating the solidus_paypal_braintree extension into your Solidus store has proved useful. As with all of our open source extensions, any feedback is greatly appreciated. Improvements via pull-requests doubly so!