Mollie is a tech-driven, European payment processor. Our payment products help companies grow by increasing their business and developer productivity. Mollie has a powerfully simple API which is used by more than 55.000 merchants every month. To make working with our API even easier for both developers and webshop owners, we develop and maintain API clients and e-commerce modules. These clients and modules enable other great initiatives to be built that further challenge the status quo in the financial and commercial markets.

We expanded our library of modules by shipping an official payment gateway for Spree Commerce. This payment gateway might be the most advanced gateway available for Spree. It hooks into every aspect of Spree Commerce: the front end, the API, and the refund and reimbursement processes. It also supports 17 payment methods from all over the world, global and localised ones, which makes it the most expansive payment gateway available for Spree.

To build this new Spree Commerce gateway, I had to dive back into Ruby on Rails. The last couple of years, I've focused on working with JavaScript and React. This adventure reminded me again of some of Ruby's magical features. In this article, I'll share some of those with you.

Spree Commerce

In 2014, we released our Ruby client. Since its release, we’ve received numerous requests to release an integration for Spree Commerce, an e-commerce platform which is popular within the Ruby on Rails community. Spree is built in a very modular and flexible manner, allowing developers to easily build extensions on top of it.

Spree can be used in two ways: via a customisable interface (comparable to e-commerce platforms like Magento) or via its advanced API. Most payment gateway implementations out there tend to work for one of those options, but not both.

Because we're a tech-driven company, but we also have a lot of smaller customers (without access to a developer), we wanted to build a payment gateway which takes full advantage of the Spree Commerce framework. We hope that by making it available to all users of Spree Commerce, it will be the #1 Spree gateway for everyone.

The front end challenge

When we started production on the gateway, we decided to start with the front end implementation because it's used more than the API. Before I started coding, I researched the way payments are processed within Spree. In the Spree developer documentation I found this:

Payment processing in Spree supports many different gateways, but also attempts to comply with the API provided by the active_merchant gem where possible.

– Spree Developer Guide

This was going to cause a problem because our code has to comply with the ActiveMerchant gateway interface, but it can't. ActiveMerchant processes payments within Spree's backend. It's mostly meant for credit card payments and expects the merchant to be PCI compliant. Because ActiveMerchant facilitates credit card payments it forces you to implement either one or multiple of these methods within your payment gateway:

authorize

capture

purchase

credit

void

Mollie obviously does more than just credit card payments, like iDEAL, Bancontact, and 15 other payments methods, and we handle the PCI compliance procedure for our merchants by redirecting to an external checkout. In essence, we don't use the above methods at all. What we do, is create a payment which returns a payment_url in the API response and that's where the payment gets done.

Since Spree is not planning to support offsite payments before it hits the 4.0 milestone, I had to find a way to make the redirect to the Mollie checkout work within one of ActiveMerchant ’s methods.

Luckily, Spree also comes with a process! method within the Spree::Payment::Processing class. Spree calls this method for every Spree::Payment and then calls either authorize! or purchase! . This appeared to be the perfect moment to create a new Mollie payment and associate it with the current Spree payment.

Let's see how I fixed it:

Creates a new Mollie payment when we process a Spree::Payment.

In this snippet, you'll see that I'm overwriting the process! 's logic. Now, every time process! is called, it will call the method create_transaction on the Mollie payment gateway (the variable payment_method ) and set the payment state to pending (by dispatching the :pend event).

Now I've bypassed the ActiveMerchant methods, but I still have to make sure the Spree front end redirects the user to the payment URL which Mollie returned. This is where Ruby’s metaprogramming magic helped out a lot: you can easily add new functionality without ever touching any of the original logic. Ruby made it possible to prepend a module within the Spree::CheckoutController . This module only adds logic if you’re currently in the payment state within the checkout.

Redirects to the Mollie checkout.

When consumers have decided on a payment method, they will be redirected to the Mollie payment screen. After the Mollie payment has been completed or has failed, Mollie notifies Spree of the new payment state. If the payment was successful, the Spree::Order state will transition to complete and the consumer will be redirected to the order confirmation screen.

One of the great advantages of using Ruby is that prepend allowed us to add massive amounts of logic into existing logic. Because of metaprogramming, like prepend , I was able to update existing logic with added functions and features and we managed to complete payments via the Spree front end. Even one-click payments worked!

The API challenge

Now, it's time to go through the order process via the Spree API.

The order process via the API is pretty straightforward: you create a new order, add some line_items to it and then start the checkout process. This process basically transitions the order through a couple of states:

cart This is the initial order state.

This is the initial order state. address You just started a new checkout process. Provide address details (shipping & billing address).

You just started a new checkout process. Provide address details (shipping & billing address). delivery Select a shipping method.

Select a shipping method. payment Select a payment method and pass extra details, like payment_method_name and issuer (check out the curl call below).

Select a payment method and pass extra details, like and (check out the call below). complete The order is completed. This doesn’t mean the order is paid for though.

To add a new Mollie payment to a Spree order, you'll have to add the payment details to the payment state. The details that you give as parameters are the payment method and the issuer, if relevant.

Something weird happened at this point. On the first call, everything works. The order is transitioned to complete and one Spree::Payment , which contains a Mollie payment_url , is created. But, after making the same call again, for instance because the payment wasn't completed or failed, another Spree::Payment is created but without a payment_url . So, if a consumer, for whatever reason, failed to complete the first payment, it would not be possible try again. This also meant that any consecutive Spree::Payment would not have a payment_url . The consumer is stuck.

It turns out that the Spree order process only calls the processing methods when it transitions to the complete state. If the order already is in that state (which it is after the first time), none of the methods are called and therefore no Mollie payment is created.

After some time of debugging and digging into the Spree source code, I found a solution: call the process! method manually after the second Spree::Payment is created. To do this, I override the build_source method, which is called right after a new Spree::Payment is created but only when order state is complete .

The fix: call process! again if the order is completed. This will create a new Mollie payment (and therefore a new payment_url).

This worked! Another problem fixed elegantly using Ruby. The flow now worked perfectly both in the Spree front end and through the API.

Conclusion

Mollie’s new Spree Commerce Gateway is one of the most advanced gateways available for Spree Commerce. It works for both the Spree front end and the Spree API, and it supports 17 global and localised payment methods. But the production came with some technical challenges. For the front end implementation, I used Ruby’s powerful metaprogramming features to expand existing logic. For the API implementation, I manually called the process! method to create a new Mollie payment_url . I hadn't used Ruby in a while, but this project rekindled my respect for the language.

Do you use Spree Commerce for your online store or work with Ruby? Go check out the gateway and easily implement better payments in your store.

I hope you enjoyed this write-up. Let me know what you think!