Posted at

ActiveMerchant and Payment Gateways

More than 1 year has passed since last update.


Introduction

Note: For native English speakers and high ability non-native speakers

I have attempted to write this post using simplified English grammar to hopefully aid reading comprehension for English learners, and to also aid machine translation. So, I may use shorter sentences and less complicated grammar constructs.


Overview

In this post I will write about Payment Gateways and the card purchase process. After, I will then write about the ActiveMerchant RubyGem.


Payment Gateways and Credit Card Processing


How are Credit Card purchases processed?


Entities in Purchase process

CardProcessingActors.png


The Process

The diagram above shows the key actors in the process. In my previous and current work experience, I've been writing the software at two places. First was for Issuing banks. (Integration from Bank to Visa). More recently, it is software at the Merchant.

During a purchases purchase:

1. Card Details (or a token representing a card) are passed from Customer

2. ... Into Merchant Software (the EC Site)

3. ... Sends request to Payment Gateway

4. ... Gateway selects which Payment Processor to communicate with

5. ... Sends request to Payment Processor

6. ... Sends request to correct Card Association

7. ... Sends request to Issuing Bank (except American Express and Discover, who are ALSO the Issuing Bank)


Payment Flow and State Transition

Below is generic description of the purchase flow.

CardProcessStateTransition.png

Different Gateways may provide different, or additional functionality. In fact, each Gateway will have very specific differences which the merchant needs to handle.

Examples:


  • Some Gateways only support AUTH and SALE using the Card Token obtained during STORE.

  • Some Gateways may NOT support VOID after a CAPTURE, and/or SALE.

  • Some Gateways may NOT support VOID after a CAPTURE, and/or SALE, if a certain time has expired.

  • Gateways will have different expirations for AUTH. If x time passes, and AUTH will be automatically VOIDed by Gateway, and a CAPTURE will fail.

  • Some Gateways may not support SALE.

  • Some Gateways may NOT support partial REFUND.

This means, if a Merchant needs to support multiple Gateways, a large amount of custom code will need to be written.

A merchant could write their own adapter layer. This will provide a unified API to the main merchant Store software.

The alternative is to use Open Source software.


ActiveMerchant

ActiveMerchant is a RubyGem written and maintained by Shopify. It's goal is to provide a simple unified API to a lot of different Payment Gateways.

The source code is open source. So, you can contribute code for new gateways. You could also fork, and maintain your own version with custom Gateway integration.

In my previous employment, I maintained an ActiveMerchant fork. This contained our code for integration with three Payment Gateways not supported by the master ActiveMerchant branch.


Gateways

ActiveMerchant provides a guide on how to use and write your own integration.

Typically, you will use an existing subclass of ActiveMerchant::Billing::Gateway, or write a new one.


Standard Methods

Typically, each ActiveMerchant::Billing::Gateway will provide implementation for the following:

Method
State Equivalent
Notes

purchase
SALE
Perform a combined AUTH/CAPTURE, with specified amount, using supplied Card Token (or supplied card details

authorize
AUTH
Perform an AUTH, for a specified amount, using supplied Card Token (or supplied card details

capture
CAPTURE
Capture a previous AUTH

void
VOID
Cancel a previous SALE, AUTH, or CAPTURE (if gateway supports it)

refund
REFUND
Perform a second transaction, to repay Cardholder. Partial may be possible.

verify

Some Gateways support verification of card details

store
STORE
Use supplied card details, and obtain a card token.

unstore


Example Code

STRIPE requires the use of JSON in their calls. post is a Ruby hash with request parameters. These are then sent to STRIPE.

Also note, the payment parameter with STRIPE can ONLY be a card token (a String). It cannot be a ActiveMerchant::Billing::CreditCard instance, which the base class supports.


stripe.rb

# To create a charge on a card or a token, call

#
# purchase(money, card_hash_or_token, { ... })
#
# To create a charge on a customer, call
#
# purchase(money, nil, { :customer => id, ... })
def purchase(money, payment, options = {})
if ach?(payment)
direct_bank_error = "Direct bank account transactions are not supported. Bank accounts must be stored and verified before use."
return Response.new(false, direct_bank_error)
end

MultiResponse.run do |r|
if payment.is_a?(ApplePayPaymentToken)
r.process { tokenize_apple_pay_token(payment) }
payment = StripePaymentToken.new(r.params["token"]) if r.success?
end
r.process do
post = create_post_for_auth_or_purchase(money, payment, options)
commit(:post, 'charges', post, options)
end
end.responses.last
end


The full code is available here.


braintree_blue.rb

def authorize(money, credit_card_or_vault_id, options = {})

create_transaction(:sale, money, credit_card_or_vault_id, options)
end

def capture(money, authorization, options = {})
commit do
result = @braintree_gateway.transaction.submit_for_settlement(authorization, amount(money).to_s)
response_from_result(result)
end
end

def purchase(money, credit_card_or_vault_id, options = {})
authorize(money, credit_card_or_vault_id, options.merge(:submit_for_settlement => true))
end


BrainTree Blue has a different implementation. But, you can see it exposes the same API to the calling Merchant code.


Sample Architecture

sample_architecture.png

The diagram is a very rough layout of a possible architecture.

In the case of a monolithic Rails application, ActiveMerchant is included directly via Gemfile. Then, we could write some form Gateway Service class layer. Here, we could write code to store and manage Gateway configuration. There should be code to instantiate the correct ActiveMerchant Gateway instance. Perhaps we would wrap this in a decorator.

If necessary, the decorator could store Gateway specific information that may be necessary for certain operations.

The EC site code would then call the appropriate decorator class when payment operations are required.

Alternatively, the Gateway code could be extracted out into a micro-service. This micro-service would include ActiveMerchant in it's Gemfile. The EC site code would then call the Payment micro-service.


References, Further Reading