Skip to content

Adding a new Gateway

Ananya Bahadur edited this page Jan 31, 2018 · 2 revisions

Adding a new gateway

The public API is well documented and your implementation must comply with it.

Payment Gateways offer a multitude of features and integration with gringotts requires just a few methods. Please refer the Gateway's docs to understand their operation and API.

Make sure you base your work off the dev branch.

After cloning the repo and checking out dev, compile and generate the docs locally:

mix compile
MIX_ENV=test mix compile
mix docs

Refer to these docs, as the docs on hexdocs.pm are generated from the master branch, which naturally lags behind.

gringotts.new

gringotts comes with a handy Mix task, gringotts.new which will generate a barebones gateway implementation and an empty test-suite.

Let's say you wish to implement a module for the DiagonAlley gateway, this is how you might use it,

$ mix gringotts.new "Diagon Alley"
Generating barebones implementation for Diagon Alley.
Hit enter to select the suggestion.

Module name [DiagonAlley] 

Homepage URL [https://www.diagonalley.com] 

Filename [diagon_alley.ex] 

Comma separated list of required configuration keys:
(This can be skipped by hitting `Enter`)
>  foo, bar

Does this look good?
[gateway: "Diagon Alley",
 gateway_module: "DiagonAlley",
 gateway_underscore: "diagon_alley.ex",
 gateway_filename: "diagon_alley.ex",
 required_config_keys: [:foo, :bar],
 gateway_url: "https://www.diagonalley.com",
 mock_test_filename: "diagon_alley_test.exs",
 mock_response_filename: "diagon_alley_mock.exs"]
> [Yn] y
* creating lib/gringotts/gateways/diagon_alley.ex
* creating test/integration/gateways/diagon_alley_test.exs

We highly recommend starting off from this stock implementation to stay consistent with other ones. Moreover the docs contain instructions which will guide you in not only implementing the methods, but also writing clear, complete and conscise documentation.

An aside on PCI-DSS compliance

It's likely that this Gateway provides a solution for both PCI-DSS compliant and non-compliant merchants. Currently, (ie. v1.0.x) gringotts provides partial support for non-compliant merchants (even though the supported gateways provide such mechanisms).

Track progress on this here (this is on our roadmap too).

We found the following resources on PCI-DSS extremely helpful for refreshing one's understanding of the same: The PCI FAQ and a video on PCI 101.

Simply put, a PCI-DSS non-compliant merchants cannot accept Card details on to their servers and have to make the client's browser directly talk to the Payment Gateway's servers.

On the other hand, compliant merchants can use gringotts on their server and make requests to the Gateway using gringotts.

Setting up your environment

We recommend adding some frequently used bindings (like a CreditCard struct and some module aliases) to your IEx context/session by keeping a local .iex.exs to super-charge it. See an example in this gist.

Workflow

Build

After you are familiar with the Gateway's operations, start building the request for a method, say you start with authorize/3, and make it return "hello world!:

def authorize(amount, card, opts) do
    "hello world!"
end

Rapid tests

Super charge your IEx session by creating a .iex.exs at the project root:

# .iex.exs
#
alias Gringotts.Gateways.GatewayXYZ
alias Gringotts.{CreditCard, Address, Response}

card = %CreditCard{
    first_name: "Harry",
    last_name: "Potter",
    number: "4200000000000000",
    year: 2099,
    month: 12,
    verification_code:  "123",
    brand: "VISA"
}

customer = %{"givenName": "Harry",
             "surname": "Potter",
             "merchantCustomerId": "the_boy_who_lived",
             "sex": "M", 
             "birthDate": "1980-07-31", 
             "mobile": "+15252525252", 
             "email": "masterofdeath@ministryofmagic.go v",
             "ip": "1.1.1", 
             "status": "NEW"}

amount = %{amount: Decimal.new(42), currency: "USD"}
auth = [config: %{userId: "8a8294186003c900016010a285582e0a", password: "hMkqf2qbWf"]
opts = auth ++ [customer: customer]

Test the method in your super-charged IEx session quickly:

iex> GatewayXYZ.authorize(amount, card, opts)
"hello world!

Code-Test-Repeat!

Submitting a PR

Make sure you've finished this checklist before submitting a pull request.

Adding an Example

gringotts has two example repos,

Clone the repos and edit the mix.exs to correctly define gringotts as dependency. Since your new Gateway may not be merged into gringotts:master yet, you'll have point mix to your local clone of gringotts.
Assuming you have the library and example app in the same directory,

# mix.exs
  defp deps do
    [
      # {:gringotts, "~> 1.0"},
      {:gringotts, path: "../gringotts"}
    ]
  end

Take inspiration from the example for MONEI.