Patterns & Standards - activemerchant/active_merchant GitHub Wiki

ActiveMerchant is predicated on the idea of providing a common Ruby API to payment gateway API's. Towards this goal, this (currently very rough draft form) Patterns & Standards guide seeks to lay out what that common API is, how to test it, and what is within the scope of it.

Currently this document is broken down by public API - where each API can potentially encompass multiple public methods - and then further by sections on expected behavior and testing guidelines.

API's

purchase

This is the bare minimum API for a gateway to support, and consists of a single call:

def purchase(amount, payment_method, options={}) #=> Response

This method is expected to authorize payment and transparently trigger eventual settlement. Preferably it is implemented as a single call to the gateway, but it can also be implemented as chained authorize and capture calls.

Arguments:

authorize/capture/void

authorize should authorize funds on a payment instrument that will not be settled without a following call to capture within some finite period of time. When implementing this API, authorize and capture are both required. void is an optional (but highly recommended) supplement to this API that should immediately cancel an authorized charge, clearing it off of the underlying payment instrument without waiting for expiration.

def authorize(amount, payment_method, options={}) #=> Response
def capture(amount, identifier, options={}) #=> Response
def void(identifier, options={}) #=> Response

Arguments:

capture

Partial captures, if supported by the gateway, are achieved by passing an amount. Not passing an amount to capture should always cause the full amount of the initial authorization to be captured.

If the gateway does not support partial captures, calling capture with an amount other than nil should raise an error indicating partial capture is not supported.

refund

Cancels settlement or returns funds as appropriate for a referenced prior purchase or capture.

def refund(amount, identifier, options={}) #=> Response

Arguments:

verify

When supported by the payment method, verifies that the instrument is valid.

Ideally this will be implemented for credit cards as a zero dollar authorization. Unfortunately, many gateways do not support zero dollar authorizations, in which case this should be implemented as an authorize immediately followed by a void.

def verify(payment_method, options={}) #=> Response

Arguments:

store/unstore/update

Tokenizes a supported payment method in the gateway's vault. ActiveMerchant treats all tokenization as a simple token -> payment method mapping. If the gateway conflates tokenization with customer management, ActiveMerchant should hide all customer management and any customer identifier(s) within the token returned. It's certainly legitimate to have a library that interacts with all the features in a gateway's vault, but ActiveMerchant is not the right place for it.

def store(payment_method, options={}) #=> Response
def unstore(token, options={}) #=> Response
def update(token, payment_method, options={}) #=> Response

Arguments:

store

It's critical that store returns a token that can be used against purchase and authorize. Currently the standard is to return the token in the Response#authorization field.

update

While it's OK to pass along basic customer information for update in the options to this call, it is only designed to support the case of wanting to change/update the payment method mapped to a token. It's critical that the token is the token returned from store, and that the call fails if not passed a payment method.

credit

Puts funds directly onto a supported payment method. Typically hard to get approval for usage.

def credit(amount, payment_method, options={}) #=> Response

Arguments:

Standard Arguments

amount

The amount to charge as an integer (never a float). In the case of currencies that support fractional amounts, should be the integer amount of the smallest fractional (so, in the case of USD, the integer number of cents).

payment_method

The instrument to charge. The minimum instrument required to be supported is a bare credit card; ActiveMerchant does not support gateways that solely allow transacting against tokens acquired elsewhere.

Currently supported instruments:

  • CreditCard: As per above, a raw credit card, including a PAN at a minimum.
  • BankAccount: Checking account information, for echeck transactions.
  • String/token: Representation of a payment method tokenized via store
  • String/identifier: Representation of a previous transaction that can be transacted against ("reference transaction")

CreditCard attributes

Card specific data should only come from the CreditCard object when executing transactions.

CreditCard.number
CreditCard.first_name
CreditCard.last_name
CreditCard.verfication_value
CreditCard.month
CreditCard.year

options

Gateway-specific options hash, that nevertheless has some standard keys:

  • :billing_address
  • :shipping_address
  • :ip
  • :email
  • :phone
  • :order_id
  • :currency

Beyond the standard keys, optional additional information can be included from the options hash in the gateway request.