ActiveMerchant and Payment Gateways

# 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

<img width="995" alt="CardProcessingActors.png" src="https://qiita-image-store.s3.amazonaws.com/0/23846/ab5e8030-53c0-08af-e75a-1aadd188c5a9.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.

<img width="636" alt="CardProcessStateTransition.png" src="https://qiita-image-store.s3.amazonaws.com/0/23846/ebe2d56e-0a71-9d44-5acc-1b4e2db5f803.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 `VOID`ed 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](https://www.shopify.com). 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](https://github.com/activemerchant/active_merchant/wiki/Contributing).

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. 

```ruby: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.](https://github.com/activemerchant/active_merchant/blob/master/lib/active_merchant/billing/gateways/stripe.rb)

```ruby: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](https://github.com/activemerchant/active_merchant/blob/master/lib/active_merchant/billing/gateways/braintree_blue.rb) has a different implementation. But, you can see it exposes the same API to the calling Merchant code.

### Sample Architecture

![sample_architecture.png](https://qiita-image-store.s3.amazonaws.com/0/23846/f34f5ac2-af83-4cab-870b-b448b7c6ecd4.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

- https://en.wikipedia.org/wiki/Payment_gateway
- https://github.com/activemerchant/active_merchant
- [ActiveMerchant v1.51 Gem Documentation](http://www.rubydoc.info/gems/activemerchant/1.51.0/index)