Developing a Payment Plugin

Payment plugins integrate Kill Bill with a specific gateway (i.e. payment processor), such as Stripe or Braintree. While we already have many open-source payment plugins available on GitHub, this guide will give you pointers in case you need to develop your own.

Before reading this guide, make sure to familiarize yourself with the main payment userguide.

setDefaultPaymentMethod should mark the payment method as the default one in the gateway (if the associated account in the gateway has several payment methods)

getPaymentMethods should list the payment methods in the gateway for that account (used by the refresh endpoint, when payment methods are added directly in the gateway, bypassing addPaymentMethod)

resetPaymentMethods, called at the end of a refresh call, should associate to that account the payment methods specified (this is useful if Kill Bill knows payment methods that are not yet in the gateway)

searchPaymentMethods should return payment methods matching the specified searchKey (the implementation is up to the plugin)

buildFormDescriptor should return enough metadata for the front-end to build a form or a redirect to a hosted payment page

processNotification should process payloads from the gateway to transition payments states

If an operation is not supported, the plugin must:

return an empty list when the return type is a list

return a transaction with status CANCELED if the return type is a PaymentTransactionInfoPlugin (see below)

return empty objects otherwise

PaymentPluginStatus states overview

When building PaymentTransactionInfoPlugin objects, it is very important to correctly populate the status type:

if the payment is successful, the plugin should return PROCESSED

if the payment is rejected by the gateway (insufficient funds, fails AVS check, fraud detected, etc.), the plugin should return ERROR

if the payment requires a completion step (3D-S verification, HPP, etc.), the plugin should return PENDING

for all other cases (socket read timeout, 500 returned, etc.), the plugin should return UNDEFINED

You should try to avoid UNDEFINED as much as possible, because it is the only case where Kill Bill cannot retry payments (since the payment may or may not have happened). Kill Bill will also attempt to fix these states by polling the plugin via getPaymentInfo: if the plugin subsequently returns PROCESSED for example (maybe by querying the gateway directly), the internal payment state (as well as invoices balance, etc.) will be reflected.

Plugin Activation

When a payment operation occurs, Kil Bill will chose which payment plugin to go to based on the paymentMethodId specified. The paymentMethodId will map to an specific payment method, which in turns contains the name of the plugin to chose for the payment.

Payment plugins frameworks

To help with writing payment plugins, we developed Java and Ruby frameworks which ensure that the plugin will respect the previous mentioned conditions. If you are developing your own plugin, we strongly encourage you to use these libraries. The easiest is to copy an existing plugin and modify it for your gateway. The Adyen plugin (Java) and CyberSource (Ruby) plugins are good starting points.

ActiveMerchant plugin generation

ActiveMerchant is a Ruby gem supporting dozens of gateways. For convenience, we provide a tool to generate a plugin based on an ActiveMerchant connector (if your gateway is not supported by ActiveMerchant yet, it is almost always easier and faster to first write the ActiveMerchant connector and generate the plugin code, rather than implementing your plugin from scratch).

This will generate a tree of files ready to be plugged into Kill Bill. Most of the work will consist of filling in the blanks in api.rb (payment plugin API for ActiveMerchant gateways) and application.rb (sinatra application for ActiveMerchant integrations, i.e. Offsite Payments). For example, make sure the right constructor parameters are passed in the initialize method. Check the Stripe plugin for an example.

The generator comes with a series a basic unit and integration tests (the latter requires gateway credentials in your local YAML configuration file). To run them:

Not all tests will work with your gateway (maybe some features are not supported): feel free to remove them. But make sure some basic calls are working noneless (e.g. purchase), as it will make debugging in Kill Bill much harder otherwise.

Building Ruby plugins

Unlike Java plugins, which are deployed as jars, Ruby plugins need a specific directory structure on the filesystem to run (containing all of the gems dependencies). Fortunately, we provide scripts to generate self-contained artifacts: all you need to do is untar (or unzip) these.

Prerequisites

Ruby 2.1+ or JRuby 1.7.20+ is recommended. If you don’t have a Ruby installation yet, use RVM: