This is the reference guide to get started with Kill Bill Payments Platform.
Introduction
Kill Bill Payments Platform is designed to offer a single payment API for any type of payment gateway, processors, bank,… and to support any kind of payment flows. It is typically used to charge customers in eCommerce Shopping Cart type flows.
Requirements
We will assume:
-
You have gone through What is Kill Bill and are familiar with Kill Bill
-
You have gone through the Getting started tutorial and have Kill Bill, Kaui and the database setup and running
-
You have a tenant configured with API key
bob
and API secretlazar
-
You have cURL installed. This is only to be able to run the setup steps and examples from this documentation. In practice, your application will use one of our client libraries. If you are on Windows, we recommend that you use Git Bash to run the cURL commands.
Overview
Kill Bill is a generic platform to build billing and payment infrastructures and as such, it is agnostic of payment gateways. However, it provides a framework to register payment plugins, which in turn implement gateway specific APIs.
Terminology
Throughout this document, we will be using the following terminology:
E-commerce application/merchant website/client application - Application that integrates with Kill Bill.
End-user/customer - User that uses the e-commerce application.
Payment-related APIs - Kill Bill APIs that perform payment related operations.
Payment plugin - Piece of code that resides within Kill Bill and implements payment gateway specific APIs/interacts with the payment gateway.
Payment gateway/payment provider - Entity that processes the payment.
Account - A customer account in Kill Bill corresponding to an end-user.
Payment Method - A record of the details required for Kill Bill to trigger a payment. Payment Methods represent things like credit cards, debit cards, or PayPal accounts. An account can have multiple payment methods corresponding to different payment gateways.
Payment - A Kill Bill record that encapsulates charging an end-user against a payment method. It has a state that indicates the status of the underlying transaction.
How Payment Works
The following diagram provides a high level overview of the payment system in Kill Bill:
The Kill Bill payment system consists of Kill Bill’s payment related APIs and payment plugins. The Kill Bill APIs can be used by an external e-commerce application (to trigger one-off payments), by the Kill Bill core engine (to process recurring payments) and by Kill Bill Admin UI (Kaui)) (to process refunds, chargebacks, etc). The payment-related APIs then interact with the payment gateway via a payment plugin specific to the gateway.
Payment Methods Overview
As explained earlier, a payment method represents an abstraction corresponding to a payment scheme like a credit card, debit card, or PayPal. An account can have multiple payment methods corresponding to different payment gateways. For example, an account can have a credit card payment method as well as a Paypal payment method.
Each account also has a default payment method associated with it. When the account needs to be charged for recurring payments, the default payment method is used. Additionally, a client application can also override the payment method to use on a per payment call.
Payment Plugins Overview
As explained earlier, each payment gateway needs to have a gateway specific plugin within Kill Bill. Thus, at any time, there can be multiple payment plugins registered with Kill Bill, each of which interacts with a different payment gateway. When the Kill Bill system charges a customer against a particular payment method, the plugin associated with that payment method is used.
The figure below shows the relationship between a Kill Bill Account
, its various PaymentMethods
, each of which points to a Kill Bill plugin
, which in turn interacts with a third party payment gateway.
Kill Bill provides many open-source payment plugins corresponding to different payment gateways. In addition, Kill Bill also has a Plugin API that can be used for developing a custom payment plugin corresponding to a specific payment gateway (as explained in the Plugin Development Guide).
By default, Kill Bill does not come configured with any payment plugins. So, if you would like to install an existing plugin or a custom plugin, you need to do this seprately as explained in the Plugin Installation Guide.
However, Kill Bill does have a built-in payment method called __EXTERNAL_PAYMENT__
. This can be used to track payments that occur outside of Kill Bill. For example, a customer may be invoiced through Kill Bill and may later make a payment by check. The payment needs to be recorded into the system to mark the invoice as being paid and to bring its balance to zero. In such cases, the payment can be recorded against the __EXTERNAL_PAYMENT__
payment method.
Payment Methods
A payment method refers to the end-user’s payment details. When an end-user enters his/her payment details (like card information) into a merchant website, these payment details need to be saved in Kill Bill in order for Kill Bill to be able to process recurring payments. Additionally, the payment details may need to be saved within the payment gateway so that the end user does not have to enter their payment details each time.
The PaymentApi#addPaymentMethod is the entry point for saving a payment method in Kill Bill. Thus, a merchant website needs to invoke this method in order to save the payment details as a payment method in Kill Bill.
Payment Method Flows Overview
Payment method flows describe how a payment method gets created in Kill Bill.
Kill Bill supports three main payment method flows as follows:
-
Client-Side Tokenization - In this case, the end user’s payment method details are converted into a token which is sent to Kill Bill.
-
Hosted Payment Page - In this case, the merchant website redirects the end-user to a page on the payment gateway, which collects the payment method details. Kill Bill then fetches a gateway-specific token from the payment gateway.
-
Server-Side Tokenization - In this case, the end-user’s payment details are sent to Kill Bill, which then sends these to the payment gateway to perform tokenization.
The flow diagrams below explain these payment method flows. We consider the following actors:
-
Browser: The end-user sitting behind a browser and initiating the payment method flow
-
Merchant Site: customer facing web site which receives the order
-
Kill Bill - The Kill Bill system
-
Checkout Servlet - Plugin servlet that initiates setting up the payment method.
-
Payment Plugin: Kill Bill plugin corresponding to the payment gateway.
-
Payment Gateway: Entity that processes the payment.
Client-side Tokenization Payment Method Flow
In this case, the merchant website collects the end-user’s payment details. These are then converted into a token (either via a payment gateway specific Javascript or iFrame). This token is sent to Kill Bill. Kill Bill then saves it in the Kill Bill database and uses it to charge the customer.
The following diagram explains this payment method flow:
-
The end user enters payment details on the merchant website.
-
The merchant website converts it into a token and invokes the
addPaymentMethod
in Kill Bill with this token. This saves the token in the Kill Bill database. -
Some payment gateways require the token to be saved within the gateway so as to be able to process recurring payments. In such cases, Kill Bill invokes the
addPaymentMethod
in the payment plugin corresponding to the payment gateway. -
The payment plugin then makes a gateway specific call to save the payment token within the gateway.
Hosted Payment Page Payment Method Flow
Sometimes, a merchant site may not provide a payment form/may not want to collect payment data and tokenize it. The hosted payment page flow is useful in such situations. In such cases, the merchant site needs to perform a two-step process. In the first step, it needs to invoke Kill Bill to obtain the URL to redirect the user and redirect the user to this page. Once the end-user enters his/her payment details on this page, the merchant site needs to invoke Kill Bill to add the payment method. Kill Bill then retrieves the payment details from the payment gateway and saves them in the Kill Bill database. This information is then used by Kill Bill to charge the customer.
The following diagram explains this payment method flow:
-
The end user initiates the checkout process.
-
The merchant website invokes a checkout servlet in Kill Bill.
-
The checkout servlet invokes the PaymentPluginApi#buildFormDescriptor method in the payment plugin.
-
The
PaymentPlugin#buildFormDescriptor
method makes a gateway-specific call and obtains a redirect URL. -
The merchant website redirects the end user to this URL.
-
The end user enters payment details on this page.
-
If successful, the payment gateway redirects the user to a success URL on the merchant site.
-
The merchant site then invokes the
KillBill#addPaymentMethod
-
Kill Bill in turn invokes the
PaymentPlugin#addPaymentMethod
. -
The
PaymentPlugin#addPaymentMethod
performs a gateway specific call and obtains a gateway specific payment method id. This is then saved in the Kill Bill database.
Server-side Tokenization Payment Method Flow
Sometimes, a merchant site may collect the card details from the end-user and send them to Kill Bill. In this case, Kill Bill makes a call to the payment gateway to tokenize the card information. However, this approach is used very rarely as this requires a merchant website to be PCI Level 1 compliant. To know what it takes to be PCI Level 1 compliant, you can read this article.
The following diagram explains this payment method flow:
-
The end user enters payment details on the merchant website.
-
The merchant website invokes the
KillBill#addPaymentMethod
with the payment details. -
Kill Bill invokes the
PaymentPlugin#addPaymentMethod
method. -
The
PaymentPlugin#addPaymentMethod
performs a gateway specific call to tokenize the payment details and obtains a token. This is saved within the Kill Bill database.
Payment Methods and plugin names
By default, each plugin has a name which is specific to the plugin and configured in the plugin code. On start-up, Kill Bill detects all the plugins and starts them. When a plugin is started, it gets registered with Kill Bill with its name.
When a payment method is added in Kill Bill via the KillBill#addPaymentMethod
, the name of the plugin corresponding to the payment method needs to be specified by the merchant application. This gets saved in the Kill Bill database as part of the payment method record.
Kill Bill then uses the plugin name to route the payment processing to the appropriate plugin. So, while charging a customer against a payment method, the plugin name corresponding to the payment method is retrieved from the Kill Bill database and the payment is processed by the corresponding plugin.
As explained earlier, each end-user has an account
in Kill Bill. Each account
has a default payment method associated with it. In case the end-user is to be charged against the default payment method, the plugin name corresponding to the default payment method is retrieved and used. A merchant application can also explicitly specify a payment method against which the end-user should be charged. In such cases, the plugin name corresponding to the specified payment method is retrieved and used.
Payment Methods and plugin names example
Suppose there are two payment plugins named PluginA and PluginB. When Kill Bill is started, it starts both plugins which register themselves with Kill Bill as PluginA and PluginB respectively. Now suppose an end-user enters payment method details corresponding to PluginA. When the merchant application invokes KillBill#addPaymentMethod
, PluginA needs to be specified along with the payment method details for PluginA. This creates a PaymentMethod
record in the Kill Bill database with the payment method details and plugin name as PluginA.
An end-user can choose to enter multiple payment methods. So, if the end-user chooses to enter payment method details corresponding to PluginB, the merchant application needs to invoke KillBill#addPaymentMethod
with plugin name as PluginB. This creates another PaymentMethod
record in the Kill Bill database corresponding to PluginB.
Assuming that PluginA is the default payment method associated with the account, Kill Bill then retrieves the plugin name (PluginA) from the database and routes the payment processing to the PluginA code.
In case the merchant application wishes to override the default payment method and charge the customer using PluginB, it needs to specify the payment method id corresponding to PluginB. Kill Bill then retrieves the plugin name (PluginB) corresponding to the payment method id and charges the customer using PluginB.
Payments
When an end-user is charged against a payment method, this is encapsulated as a payment in Kill Bill. These details need to be recorded in Kill Bill.
Payment flows overview
Payment flows describe the flows that occur when a merchant site invokes the Kill Bill payment APIs for charging a customer. Thus, these flows are not applicable for recurring payments initiated by Kill Bill.
Kill Bill supports two main payment flows, referred to as Hosted Payment Pages (or HPP) and as Gateway integration:
-
A HPP flow is when the payment is completely outsourced, either by redirecting the user to a third-party website or by hosting a form or an iframe, that submits the information to a third-party website
-
A Gateway integration flow is when the customer doesn’t leave your website and Kill Bill processes the payment directly by calling a gateway API
For a concrete example on how the two flows can be implemented, take a look at our Adyen demo.
In the flow diagrams below, we consider the following actors:
-
Browser: user sitting behind a browser and initiating the payment flow
-
Merchants Site: customer facing web site which receives the order and shields the payment system (i.e. Kill Bill)
-
Payments: the payment system (i.e. Kill Bill and its specific payment plugins which interact with the payment providers) offering APIs for the various flows
-
Payment Provider: also called Payment Service Provider (PSP), Payment Gateway or simply Gateway, this is the entity that will process the payment
-
Access Control Server (optional): in the case of 3D-Secure checkout, the user is redirected to some third party entity to enter custom information that will validate whether he can pursue with the payment flow
Hosted Payment Page flow
During an HPP flow, the customer enters his payment method information (either on the main Merchants Site or a third-party site) and then submits a form containing that information to make the payment. To obtain the information required to present the user with a payment form (specific form fields or URL where the form is hosted), call the buildFormDescriptor API.
The result of the API call will depend on the type of HPP integration:
-
If the payment form is hosted on your own website (but the form data will be sent to a third-party website), the response will list the exact fields to set, such as required visible fields (the names will vary depending on the gateway, for instance some expect a
Sum
field instead ofamount
) and required hidden fields (e.g.merchantId
value). For PayPal Payments Standard Buttons for example, the API would return the values of the fields cmd, hosted_button_id and submit. The browser submits the payment information to the payment provider, which then redirects the customer to a landing page upon success or failure. -
If the payment form is completely hosted on a third-party website, the response will contain a URL to redirect the user to. This URL can be generic or unique (generated by the payment plugin either by submitting the order information to the gateway or by constructing the special URL via query parameters). For Adyen HPPs for example, the API would return a url like https://live.adyen.com/hpp/select.shtml. The browser is redirected to the payment provider website for the customer to complete the payment before being redirected back to a landing page upon success or failure.
Note that after calling buildFormDescriptor, the payment may or may not exist in Kill Bill: this will depend on the plugin. If it does however, it will be most likely in a PENDING state.
Here are a few common scenarios:
-
the HPP provider doesn’t provide an API to retrieve the state of the payment, nor sends notifications: the only way to record the payment is when the user is redirected to the Merchants Site. In that case, buildFormDescriptor can simply return the data to create the form and/or redirect the user without creating any payment. When the user completes the payment and is redirected back to the site, the Merchants Site will need to record the payment explicitly by calling the createPurchase API. Alternatively, if you want to keep track of abandoned purchases, the plugin could create a payment in a PENDING state during the buildFormDescriptor call. After the redirect, the Merchants Site will still call the createPurchase API to complete the payment, but will pass the paymentId returned by the previous buildFormDescriptor call.
-
the HPP provider provides an API to retrieve the state of the payment but does not send notifications. In this case, the URL constructed during the buildFormDescriptor call is most likely unique, and contains enough information for the plugin to poll the provider for the payment status. During the buildFormDescriptor call, the plugin will need to create a PENDING payment. Kill Bill will automatically poll the plugin calling the getPaymentInfo API, which should query the provider for the latest payment status. Example: Boleto with PayU Latam.
-
the HPP provider doesn’t provide an API to retrieve the state of the payment but does send notifications. In this case, buildFormDescriptor can simply return the redirect URL without creating a payment, which will be created when the notification is received. Similarly to the first case above, you could create a PENDING payment if you want to track abandoned purchases, just make sure that the plugin has enough metadata to reconcile the notification with the payment. When the notification is received, either use the notifyPendingTransactionOfStateChanged Kill Bill API to transition the payment, or wait for Kill Bill to poll the plugin via the getPaymentInfo API. Example: any HPP provided by Adyen.
The conceptual flow below shows a 3D-Secure variation of the previous flows. The main difference is that prior redirecting the browser to the landing page, it is first redirected to the access control server where the user can enter custom information.
Gateway Integration Flow
For gateway integrations, the entry point for any payment is either the createAuthorization (to authorize a credit card), createPurchase (to charge a payment method, for example authorizing and capturing a credit card, to initiate an ACH transfer, to withdraw money from a Bitcoin wallet, etc.) or createCredit (to deposit money on a payment method, without any reference to a previous payment) APIs. The payment state will be in *_INIT
state before calling the plugin.
There are two main types of scenarios:
-
When payment gateways provide synchronous APIs, transactions end up in a terminal state right away. The following figure demonstrates this scenario:
Figure 7. Gateway integration (With Synchronous Payment API)The payment is initiated using one of the createAuthorization or createPurchase APIs. Kill Bill then connects to its payment plugin, which in turn contacts the gateway to perform the required operation. Upon success/failure, the end-user is redirected to a landing page.
NoteNote: Before any payment operation can occur, the user must first enter his/her payment information and a payment method must be created as explained in the payment method flows section. This is not represented in the flow above; it can happen either in a prior step or during the payment using one of our combo payment call. -
In some cases, a plugin can choose to set the status to PENDING. For example, this is the case for 3D-Secure transactions (until the issuer verifies the payment after redirecting the user), for direct debit transfers (e.g., ACH, which usually takes a couple of days for banks to acknowledge), or for Bitcoin transfers (until blockchain confirms the transaction). Additionally, some gateways don’t always provide synchronous responses (e.g., when using Adyen to capture funds), in which case the plugin has to rely on asynchronous notifications to transition the payment into a terminal state. The Kill Bill Janitor can also be used to automatically fix PENDING states.
The following figure demonstrates the Janitor scenario:
Figure 8. Gateway integration (With Asynchronous payment)
Payment States
A payment consists of multiple payment transactions. Also, a payment has a state which determines the set of possible subsequent operations available.
Initially a client of the api can make either an authorization, a purchase, or a credit call (all other operations such as refund would require an initial payment to have already existed).
That initial operation will create a Payment and an initial PaymentTransaction.
The user can then submit additional requests for the same payment (capture, refund, …) and each of those calls will result in additional PaymentTransaction
attached to the same payment.
The payments have a state which will drive the set of possible subsequent operations available. For instance, it is possible to make a capture call against a payment in a state AUTH_SUCCESS
but it is not possible to make such an operation against a payment in an AUTH_ERRORED
state.
The set of payment state transitions are configured in an xml file and the Kill Bill payment subsystem is in charge to enforce the transitions. The following diagram below shows all the possible transitions:
In addition to the payment state transitions, each PaymentTransaction
has a status to reflect the result of the operation. The PaymentTransaction
status depends on the plugin result and it can be summarized below:
plugin result | payment transaction status | payment state | http response | description |
---|---|---|---|---|
PROCESSED |
SUCCESS |
{AUTH,CAPTURE,..}_SUCCESS |
201 - Created |
The payment transaction went through and was successful |
PENDING |
PENDING |
{AUTH,CAPTURE,..}_PENDING |
201 - Created |
Successful asynchronous operation (e.g. ACH transfer) or multi-step call (e.g. 3D-Secure authorization) |
ERROR |
PAYMENT_FAILURE |
{AUTH,CAPTURE,..}_FAILED |
402 - Payment Required |
The payment transaction went through but failed (e.g insufficient funds) |
CANCELED |
PLUGIN_FAILURE |
{AUTH,CAPTURE,..}_ERRORED |
502 - Bad Gateway |
The payment transaction did not happen (e.g unable to connect to the provider, error in plugin, etc) |
UNDEFINED, timeout or any exception |
UNKNOWN |
{AUTH,CAPTURE,..}_ERRORED |
503 - Service Unavailable 504 - Gateway Timeout |
The payment transaction may or not have succeeded, manual review needed |
Note that the first 3 cases are normal cases but the last 2 are errors that are unrelated to the user being able to make the payment operation:
-
in the case of a hard plugin failure (CANCELED result code), the gateway was probably down and the payment wasn’t attempted: there is no attempt to fix those.
-
in the case of a plugin timeout (or UNDEFINED result code), the operation might actually have completed; Kill Bill will run a background task to detect those cases and will query the plugin to verify if the state is actually known and when it is, it will update the transaction status and move the payment to its appropriate state. If the plugin cannot tell if the payment went through, the transaction will stay in an UNKNOWN state. It is advisable to check that those are rare instances and fix the data appropriately (by checking manually the status in the gateway for example). See the section Janitor below for more details.
If a payment is aborted by a control plugin, a payment attempt row is recorded with a state of ABORTED (no payment nor payment transaction is created). Kill Bill will return a 422 HTTP code.
Janitor
PENDING and UNKNOWN transaction states should be temporary; the payment plugin needs to eventually tell Kill Bill what the final state of these transactions should be. This can be done explicitly by the plugin by calling the PaymentApi.notifyPendingTransactionOfStateChanged
(for instance, when receiving a webhook event from the gateway) or implicitly by the Janitor.
The Janitor refers to a set of internal Kill Bill features to help ensure transactions end up in a terminal state; these are the Janitor notification queue and the on-the-fly Janitor. They both work by calling the plugin (via PaymentPluginApi.getPaymentInfo
) and updating the state owned by Kill Bill if it has changed. For this mechanism to work, it is imperative that payment plugin developers take great care when implementing this API (see our Payment Plugin developer documentation for more details).
Janitor Notification Queue
A Janitor notification entry is inserted whenever a payment results in a non terminal state (whether the payment was initiated internally by Kill Bill or externally via our payment APIs). Kill Bill will then periodically poll the plugin to attempt to fix the state.
The polling delay is configured via the org.killbill.payment.janitor.unknown.retries
property for UNKNOWN transactions (default 5m,1h,1d,1d,1d,1d,1d
) and the org.killbill.payment.janitor.pending.retries
property for PENDING transactions (default 1h,1d
). You can configure these properties as explained in the Configuration Guide. Companies that rely on PENDING for offline payment methods (ACH, Boleto, etc.) should increase the number of attempts, as such payments can be slow (i.e., take multiple days to execute).
On-The-Fly Janitor
The on-the-fly Janitor is invoked:
-
Whenever a payment (or set of payments) is retrieved via API and the flag
withPluginInfo
is set. In this case, aGET
operation might result in data being written to disk (but it’s not really a new state, it’s just an existing state being updated that was incomplete). -
Whenever an operation is performed on an existing payment (either initiated internally by Kill Bill or externally via our payment APIs): the Janitor is invoked first to get the latest state to ensure the internal state machine prevents disallowed transitions in case the state couldn’t be fixed (or if it’s already in a final state). For example, if an authorization state is currently UNKNOWN and you attempt to capture it, the Janitor will ask the plugin first to fix the state and either let the capture go through (if the authorization is fixed as SUCCESS) or disallow it (if the authorization couldn’t be fixed or was unsuccessful).
Note however that the notifyPendingPaymentOfStateChanged
operation will not invoke the Janitor (as this API is often called from payment plugins, we don’t want the state to be fixed twice).
Janitor and Control Plugins
When the Janitor fixes a payment, it will re-run the Payment Control state machine (i.e. go through Payment Control plugins) if needed. For instance, invoice payments that were created as part of a RECURRING invoice may end up being fixed automatically by the Janitor, and the balance associated with the invoice would then be correctly reflected.
Any invoice payment triggered by API and fixed by the Janitor would not be retried, in order to leave full control to the caller to decide what to do and whether to retry. Invoice payments triggered automatically by the system and fixed by the Janitor would however be retried as configured.
Payment-related APIs
API Overview
Kill Bill’s payment related APIs can mainly be classified as follows:
-
Payment Methods APIs - Used for operations related to payment methods like adding/deleting a payment method, etc.
-
Payment APIs - Used for payment related operations. These are used by:
-
The Kill Bill core billing engine to charge for subscriptions
-
Kaui (the Kill Bill Admin UI) to handle refunds, chargebacks, adjustments, etc. for invoices and payments associated with such subscriptions.
-
Directly by an e-commerce application to trigger payments for one-off charges or to create payment forms and redirect URLs in case of hosted payment pages.
-
Plugin Properties
The Payment Method and Payment APIs have been built to be as generic as possible. Because each plugin/gateway has its own specificities, you can pass extra data by using plugin properties:
-
For each API, one can specify custom properties by using query parameters — those query parameters should be URL encoded
-
Kill Bill will deserialize the query parameters and pass them straight to the plugin
This mechanism allows to pass information from the client of the API to the plugin, while being opaque to Kill Bill; for instance, in order to specify the following two plugin properties:
{ "city" => "San Francisco", "billing_address" => "address[postcode]=94114" }
One would have to add the following query parameters (note that this needs to be URL encoded):
pluginProperty=San%3DFrancisco&pluginProperty=billing_address%3Daddress%5Bpostcode%5D%3D94114
The mechanism also works for receiving information back from the plugin; the plugin can return a piece of json that will be embedded in the json response; for instance, the plugin could return a specific key:
"pluginInfo": {
"properties": [{
"key": "pluginSpecificKey",
"value": "9876543210"
}]
Payment Method APIs
The first step when registering payment methods is to create an account in Kill Bill. This needs to be done once:
curl -v \
-X POST \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
--data-binary '{"name":"john","email":"[email protected]","currency":"USD"}' \
"http://127.0.0.1:8080/1.0/kb/accounts"
This call will return a 201 Location header containing the id associated with the newly created account. The rest of this document will assume this id is 268983f2-5443-47e4-a967-b8962fc699c5
, make sure to update your commands accordingly.
To add a payment method, POST the following information:
curl -v \
-X POST \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
--data-binary '{"pluginName":"__EXTERNAL_PAYMENT__","pluginInfo":{}}' \
"http://127.0.0.1:8080/1.0/kb/accounts/268983f2-5443-47e4-a967-b8962fc699c5/paymentMethods?isDefault=true"
This will create a default payment method associated with our account and the EXTERNAL_PAYMENT plugin. The pluginInfo
fields are specific to the plugin and can be seen as a contract between the client of the API and the plugin itself (opaque to Kill Bill). For example, to add a payment method corresponding to Stripe via a token, the Stripe plugin expects a field named token
, with the value of the Stripe token.
curl -v \
-X POST \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
--data-binary '{
"pluginName": "killbill-paypal-express",
"pluginInfo": {
"properties": [{
"key": "token",
"value": "20G53990M6953444J"
}]
}
}' \
"http://127.0.0.1:8080/1.0/kb/accounts/268983f2-5443-47e4-a967-b8962fc699c5/paymentMethods?isDefault=true"
Check our Stripe demo for an implementation example.
You can add as many payment methods as needed to a given account (across one or multiple plugins). You can specify for each payment call the payment method to use, or leave it blank to use the default.
Each payment method in Kill Bill has a unique uuid associated to it. Use this uuid to change the default payment method on the account (in this example, the payment method id a91161b0-d159-11e3-9c1a-0800200c9a66
becomes the default one):
curl -v \
-X PUT \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
"http://127.0.0.1:8080/1.0/kb/accounts/268983f2-5443-47e4-a967-b8962fc699c5/paymentMethods/a91161b0-d159-11e3-9c1a-0800200c9a66/setDefault"
To get information on a payment method, use the following endpoint:
curl -v \
-u admin:password \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
"http://127.0.0.1:8080/1.0/kb/paymentMethods/a91161b0-d159-11e3-9c1a-0800200c9a66?withPluginInfo=true"
The withPluginInfo
query parameter tells Kill Bill to fetch plugin specific properties. These properties are custom key/value pairs the plugin knows about the payment method, that are specific to that payment method.
To delete a payment method:
curl -v \
-X DELETE \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
"http://127.0.0.1:8080/1.0/kb/paymentMethods/a91161b0-d159-11e3-9c1a-0800200c9a66"
The payment method will be marked as inactive in Kill Bill. The actual deletion of the information is plugin specific (delete the information in the gateway, etc.).
Note that by default you cannot delete the default payment method on an account (because it is assumed to be used for recurring payments). If you really want to delete it though, you can pass the query parameter deleteDefaultPmWithAutoPayOff=true to the previous call. This will delete it and set the account in AUTO_PAY_OFF (invoices won’t be paid automatically anymore).
Payment APIs
Direct Payments APIs
A payment object is associated with a set of transactions (authorization, multiple captures, etc.). You can retrieve that object via:
curl -v \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
"http://127.0.0.1:8080/1.0/kb/payments/078a4500-d15e-11e3-9c1a-0800200c9a66"
The calls below describe how to create payments. For each call, you can specify in the body a transactionExternalKey string to tag your payments (it represents a unique identifier in an external system).
Authorization
To create an authorization on the default payment method of the account:
curl -v \
-X POST \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
--data-binary '{"transactionType":"AUTHORIZE","amount":"10","currency":"USD","transactionExternalKey":"INV-001-AUTH"}' \
"http://127.0.0.1:8080/1.0/kb/accounts/268983f2-5443-47e4-a967-b8962fc699c5/payments"
This will return a direct payment object. We will assume its uuid is 078a4500-d15e-11e3-9c1a-0800200c9a66
in the examples below.
Notes:
-
For multi-steps authorization (e.g. 3DS), you can specify a
paymentId
field in the body for subsequent calls -
You can specify another payment method (other than the default one) via the
paymentMethodId
query parameter
Capture
curl -v \
-X POST \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
--data-binary '{"amount":"5","currency":"USD","transactionExternalKey":"INV-001-CAPTURE"}' \
"http://127.0.0.1:8080/1.0/kb/payments/078a4500-d15e-11e3-9c1a-0800200c9a66"
Notes:
-
You can call this endpoint multiple times for partial captures (all of these captures will share the same direct payment id)
Purchase
This call is similar to the authorization one:
curl -v \
-X POST \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
--data-binary '{"transactionType":"PURCHASE","amount":"10","currency":"USD","transactionExternalKey":"INV-001-PURCHASE"}' \
"http://127.0.0.1:8080/1.0/kb/accounts/268983f2-5443-47e4-a967-b8962fc699c5/payments"
Notes:
-
You can specify another payment method (other than the default one) via the
paymentMethodId
query parameter
Void
curl -v \
-X DELETE \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
--data-binary '{"transactionExternalKey":"INV-001-VOID"}' \
"http://127.0.0.1:8080/1.0/kb/payments/078a4500-d15e-11e3-9c1a-0800200c9a66"
Refund
curl -v \
-X POST \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
--data-binary '{"amount":"5","currency":"USD","transactionExternalKey":"INV-001-REFUND"}' \
"http://127.0.0.1:8080/1.0/kb/payments/078a4500-d15e-11e3-9c1a-0800200c9a66/refunds"
Credit
This call is similar to the authorization one:
curl -v \
-X POST \
-u admin:password \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey:bob' \
-H 'X-Killbill-ApiSecret:lazar' \
-H 'X-Killbill-CreatedBy: creator' \
--data-binary '{"transactionType":"CREDIT","amount":"10","currency":"USD","transactionExternalKey":"INV-001-CREDIT"}' \
"http://127.0.0.1:8080/1.0/kb/accounts/268983f2-5443-47e4-a967-b8962fc699c5/payments"
Notes:
-
You can specify another payment method (other than the default one) via the
paymentMethodId
query parameter
Hosted pages helpers
Build form descriptor
The buildFormDescriptor
API is used to prepare a Hosted Payment Page (HPP) payment. In the body of the request, you need to pass custom fields that are plugin specific.
For example, given an order of $10, here is how you can get the redirect URL using the Adyen plugin:
curl -v \
-u admin:password \
-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'Content-Type: application/json' \
-H 'X-Killbill-CreatedBy: demo' \
-X POST \
--data-binary '{
"formFields": [
{
"key": "country",
"value": "DE"
},
{
"key": "paymentProviderType",
"value": "CREDITCARD"
},
{
"key": "serverUrl",
"value": "http://killbill.io"
},
{
"key": "resultUrl",
"value": "?q=test+adyen+redirect+success"
},
{
"key": "amount",
"value": 10
},
{
"key": "currency",
"value": "USD"
}
]
}' \
"http://127.0.0.1:8080/1.0/kb/paymentGateways/hosted/form/268983f2-5443-47e4-a967-b8962fc699c5"
Notes:
-
Replace 268983f2-5443-47e4-a967-b8962fc699c5 with the account id
-
You can specify another payment method (other than the default one) via the
paymentMethodId
query parameter
Process gateway notifications
Gateway notifications (Adyen notifications, Recurly push notifications, PayPal or BitPay IPN, etc.) can be processed through the processNotification
API.
For example, here is the payload that Adyen would send:
curl -v \
-u admin:password \
-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'Content-Type: application/json' \
-H 'X-Killbill-CreatedBy: demo' \
-X POST \
--data-binary '<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<ns1:sendNotification xmlns:ns1="http://notification.services.adyen.com">
<ns1:notification>
<live xmlns="http://notification.services.adyen.com">true</live>
<notificationItems xmlns="http://notification.services.adyen.com">
<NotificationRequestItem>
<additionalData xsi:nil="true"/>
<amount>
<currency xmlns="http://common.services.adyen.com">EUR</currency>
<value xmlns="http://common.services.adyen.com">2995</value>
</amount>
<eventCode>AUTHORISATION</eventCode>
<eventDate>2013-04-15T06:59:22.278+02:00</eventDate>
<merchantAccountCode>TestMerchant</merchantAccountCode>
<merchantReference>325147059</merchantReference>
<operations>
<string>CANCEL</string>
<string>CAPTURE</string>
<string>REFUND</string>
</operations>
<originalReference xsi:nil="true"/>
<paymentMethod>visa</paymentMethod>
<pspReference>4823660019473428</pspReference>
<reason>111647:7629:5/2014</reason>
<success>true</success>
</NotificationRequestItem>
</notificationItems>
</ns1:notification>
</ns1:sendNotification>
</soap:Body>
</soap:Envelope>' \
"http://127.0.0.1:8080/1.0/kb/paymentGateways/notification/killbill-adyen"
Make sure to replace killbill-adyen
with your plugin name.
The plugin will deserialize either the request body and/or the url query parameters to process the notification and return a properly formatted HTTP response object for the gateway (some gateways require specific response codes or headers to consider the notification processed and prevent retries).
Because this endpoint needs to be on a public IP (to be accessible from the gateway), we recommend using the Kill Bill Notifications Proxy to avoid exposing the entire Kill Bill server.