This version of Kill Bill is not supported anymore, please see our latest documentation

This is the reference guide to get started with Kill Bill Subscription Billing.

Introduction

Kill Bill, as a system, is composed of several components:

  • The core billing platform itself, which is embedded in a web server to offer a REST api. When we refer to Kill Bill in that documentation this is what we are referring to, unless explicitly specified

  • KAUI, the Kill Bill Admin UI, which is a Rails mountable engine, and communicates to the core billing platform using the REST api

  • A set of client libraries (Java, Ruby, PHP, Node.js, …​)

Let’s go through a common (web) use case of Kill Bill. One would create a custom webapp, which would contain the application’s specific business logic, and have that webapp interact with Kill Bill using the REST API. In that use case, the custom webapp would:

  • Offer a way for customers to select a plan from the Kill Bill catalog, which would result in the creation of a Subscription in Kill Bill

  • Offer a form for customers to enter their CC information — or any other payment method. The flow differs depending on the payment gateway and PCI compliance needs

  • Offer a way for customers to review/change their subscriptions

  • Offer a way for customers to review/change their payment methods

It is important to understand that Kill Bill solves the billing problem but not the custom flow required around the billing platform. Besides the main use case described above, there are other possible options if one requires going that path:

  • One could embed its webapp specific code inside Kill Bill, and therefore avoid having a separate web app.

  • Another use case would be to embed Kill Bill into the custom web app: Below the REST API, Kill Bill offers a set of Java APIs, and so it is possible to use Kill Bill as a billing library.

Requirements

We will assume:

  • You already went through the Getting started tutorial and have MySQL, Kill Bill and Kaui setup and running in Docker containers

  • You have a tenant configured with API key bob and API secret lazar

  • 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

Catalog

Overview

The catalog is the central configuration object of Kill Bill for all of your Business rules. It contains what the customer buys (products), how the customer pays for a product (plans), change rules, prices, etc.

In practice, the catalog is an XML file (see an example here). Please refer to the Catalog Configuration documentation to make Kill Bill use your own catalog.

The catalog is one of the most complex yet powerful tools provided by Kill Bill.

If you want to validate your catalog, you can use the catalog load-tool (where x.y.z is your current Kill Bill version):

# Download the tool from maven central:
curl -L -O 'http://search.maven.org/remotecontent?filepath=org/kill-bill/billing/killbill-catalog/x.y.z/killbill-catalog-x.y.z-load-tool.jar'
# Run the command
java -jar killbill-catalog-*-load-tool.jar /path/to/catalog.xml

If you see "Success: Catalog loads!", the catalog is valid.

Also, if you need an xsd file, you can find one here or generate one using the catalog xsd-tool:

# Download the tool from maven central:
curl -L -O 'http://search.maven.org/remotecontent?filepath=org/kill-bill/billing/killbill-catalog/x.y.z/killbill-catalog-x.y.z-xsd-tool.jar'
# Run the command
java -jar killbill-catalog-*-xsd-tool.jar schema.xsd

Introduction

uc?&id=0Bw8rymjWckBHcU9DbnVkY1FhR2M&w=960&h=480

The Catalog is at the heart of the billing system. It is a data model that captures the core configuration of the billing system. It is very important that all the business logic associated with the billing behaviour of your system is captured in the billing system. If your billing system is not capable of capturing that business logic it ends up being put in multiple places such as your purchase flow, Admin UI, human process etc. It becomes very difficult to keep all these places consistent, and very difficult to make changes when they are needed.

Kill Bill provides a very powerful catalog that, unlike other billing systems, allows the administrator to set up sophisticated business rules around cancellation and plan changes. For example, Kill Bill can just be told to “Cancel” a plan and Kill Bill can know when to perform the cancel, based on things like the type of plan, or whether it is in trial.

The things you can configure with the Kill Bill catalog include:

  • Trials and discount phases - plans can be configured with trial and discount phases so that they move automatically between different pricing schemes

  • Cancellation - business rules to determine when a cancellation should happen.

  • Plan Change - business rules to determine when to apply upgrades and downgrades.

  • Which add-ons are available with which products types, so that when the customer upgrades or downgrades add-ons that are not available are automatically cancelled

  • Billing Alignment - rules to determine if a Plan should be billed independently or on the account billing date.

  • Catalog change - ways to specify how and when catalog changes apply to new and existing subscriptions

Kill Bill also supports the concept of a Price List, which is a grouping of (usually discounted) plans that can be offered to a customer.

Of course, any catalog can only support a finite number of options. When you need to go further, and many people do, you can write plugins to implement pretty much anything you need.

Concepts

In this section we outline some key pieces of terminology that you will need to understand. Different billing systems use these same words to mean subtly different things so, even if you are familiar with the language, it is worth looking though exactly how we use the terms in Kill Bill.

Background Concepts
  • Customer – someone who buys your product

  • Administrator (or Admin) – the person who can use the Kill Bill UI to view and modify customer accounts

  • Kill Bill Administrator (or Kill Bill Admin) - the person responsible for installing or configuring Kill Bill

  • Account – a customer account. It represents what Kill Bill knows about a customer.

  • Subscription – a Subscription is a contract between you and a customer to purchase a particular product with particular terms. In the system it associates a Plan (see below) with an Account and a start date.

  • Subscription Bundle (or just Bundle) – Is a collection of subscriptions that are associated with a particular instance of a product. For example, you might have a voice plan, a data plan and a text plan for your mobile phone. In Kill Bill each plan would have its own subscription and we would represent the fact that they are associated with a single phone by grouping them in a Subscription Bundle. Of course an account might have multiple phones associated with it and a Kill Bill Account can have multiple Bundles associated with it.

What’s in a Catalog?

Writing a Kill Bill Catalog involves defining of the following pieces:

  • Products - the product is the thing that the customer actually buys (or rents). In the example depicted at the start of the chapter, the product available for rent is a Spy Car. There are actually three different products available, Standard, Sports and Super.

  • Plans - Plans specify the terms of the Subscription contract. In particular, they define, how much a customer pays for a product, and how often they pay it. For example, we could offer the Standard Spy Car product at $100 per month.

  • Plan Phase (or just Phase) - Kill Bill plans can have multiple phases and each phase can have a different price and payment term. In this way, we can have plans with built in trials or discount phases. Kill Bill automatically handles the transitions between phases. In our example above the plans have two phases, they start with a 30 day trial which is free and then move to a recurring phase at $100 per month.

  • Price List - A price list is a collection of plans. Price Lists are normally used to group discount plans that are associated with a particular customer group. For example, MI6 might have a special rental terms for their Spy Cars with the C.I.A. In which case they would create a C.I.A. Price List that grouped plans with those special terms together. When C.I.A. Agents come to the rental site, they will see plans from that price list. More importantly if they change plans, for example, if they upgrade from Sports to Super to meet the needs of a particularly difficult mission, they will upgrade to the Sports plan within the C.I.A. Price List.

  • Billing Period - The periodicity for when the customer is billed (e.g MONTHLY, ANNUAL, …​)

  • Rules - The catalog rules determine the behaviour that Kill Bill should display when a plan is created, cancelled or changed.

How is the Catalog Used Inside Kill Bill?

The catalog is first used by Kill Bill at the time the user creates a subscription, then subsequently if there is change of Plan (upgrade, downgrade), and then finally when the user cancels the subscription. During such operations, Catalog information is retrieved to make sure the system builds the right subscription (e.g. maybe there is a TRIAL phase to start). Information about how to perform such operations is configured in the catalog through the Subscription Alignment Rules. An overview of some of these rules:

  • Plan Cancellation Timing - Should the customer get a pro-ration credit when the subscription is cancelled before its next renewal date?

  • Plan Change Timing - Should a customer downgrading to a lower (paid) plan be active immediately or should the system wait for the next renewal date?

The catalog is also used by the invoicing system to make sure each each Customer is billed at the right time and for the right amount. Information about how the customer is billed and when the customer is billed is also defined in the catalog using alignments and their associated rules.

Catalog configuration allows to define if different subscriptions attached to a customer should be invoiced at the same time, or at the opposite if they should be billed separately on their own schedule (or a mix of both where some are grouped together on the same invoice and others are invoiced independently). In the simplest case, where all subscriptions are grouped together and there is a BCD defined (Billing Period is a multiple of the month), the customer gets one invoice per Billing Period on that (BCD) day. Note that grouping subscriptions together may by default lead to some leading pro-ration when the subscription is started on a different date than the BCD (as the system needs to realign invoicing on that particular date). This behavior is configured in the catalog through the Billing Alignment Rules.

Creating the Catalog

In this section we look at getting the top level catalog created and configured. Note that the catalog currently requires all attribute strings to be unique, and those strings cannot have space.

The XML document starts in a standard way. The main tag is “catalog”. Within the catalog opening tag you can specify the schema location. You can use the standard schema location (above) or you can have the code generate the current schema by executing: As an example, the killbill-catalog-x.y.z-xsd-tool.jar for the version 0.13.7 can be found here.

java -jar catalog/target/killbill-catalog-x.y.z-xsd-tool.jar <output_filename>

The order of content information in the catalog is important. The first tag should be the “effectiveDate” (when the catalog becomes effective), then “catalogName” and then “currencies”, as shown below.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="CatalogSchema.xsd">
        <effectiveDate>2013-02-08T00:00:00+00:00</effectiveDate>
        <catalogName>SpyCarBasic</catalogName>
        <currencies>
                <currency>USD</currency>
                <currency>GBP</currency>
        </currencies>
        ...
</catalog>

The following set of sections will provide a deeper overview of the various catalog concepts.

Products

uc?&id=0Bw8rymjWckBHT3dKd0U3a1RfcUE&w=960&h=480

The Product is a representation of the thing the customer is actually buying. Specifying a Product is very straightforward it has the following parameters:

  • Name - this is a string that is used to refer to the Product elsewhere in the catalog. For example “Super”

  • Category - The Product Category determines how Kill Bill allows the combining of products within a bundle. Kill Bill supports three categories of product: BASE, ADD_ON and STANDALONE.

  • Inclusion/Exclusion lists (optional) - these determine which addons can be purchased with a given base plan.

Plans

uc?&id=0Bw8rymjWckBHcl9mb2ZDMG12LXc&w=960&h=480

Each Plan has a name and refers to the purchase of a single product. Beyond that the Plans parameters are arranged by phase. In the illustration above we are showing a Plan with a 30 day Trial followed by an unlimited recurring or "evergreen" phase. For each phase of the plan we need to specify:

  • Phase Type - can be one of TRIAL, DISCOUNT, FIXEDTERM, EVERGREEN

  • Duration - the length of the phase in days, months, years or UNLIMITED

  • Billing Period - how frequently do we want to invoice for this phase. Can be DAILY, WEEKLY, BIWEEKLY, THIRTY_DAYS, MONTHLY, QUARTERLY, BIANNUAL, ANNUAL, BIENNIAL or NO_BILLING_PERIOD

  • Recurring Price - the recurring price that needs to be paid every billing period (unless no billing period was specified). The price needs to specify numeric values for every currency that the catalog supports.

  • Fixed Price - a fixed price charged at the beginning of the period in addition to the recurring price. This is also a multi currency price and must be specified for all currencies.

  • Usage Sections - outside the scope of that tutorial, which is focused on pure recurring subscriptions

Plan, Phase and Usage sections can have a prettyName element which would correspond to the display name (such information is subsequently available on invoice item). This is useful for instance if a product is rebranded to a new name in a subsequent version (plan names don’t need to be updated).

Note that unlike prettyName, the name elements need to be globally unique in the catalog and must be conform to the NCName definition (i.e. it cannot contain symbol characters like :, @, $, %, &, /, +, ,, ;,, whitespace characters or parenthesis, and it cannot begin with a number, dot or minus character).

For our example Spy Car catalog we specify three plans with two phases:

  1. The first phase is of type Trial and it has a duration of 30 days a Billing Period set to “NO_BILLING_PERIOD”. There is no recurring price specified, and a Fixed Price of £0/$0.

  2. The second phase is of type Evergreen and it has a Duration of UNLIMITED, a Billing Period of MONTHLY and recurring price of £75/$100 (or whatever is appropriate for the Product).

<plans>
     <plan name="standard-monthly">
         <product>Standard</product>
         <initialPhases>
             <phase type="TRIAL">
                 <duration>
                     <unit>DAYS</unit>
                     <number>30</number>
                 </duration>
                 <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
                 <fixedPrice> <!-- empty price implies $0 -->
                 </fixedPrice>
             </phase>
         </initialPhases>
         <finalPhase type="EVERGREEN">
             <duration>
                 <unit>UNLIMITED</unit>
             </duration>
             <billingPeriod>MONTHLY</billingPeriod>
             <recurringPrice>
                 <price>
                      <currency>GBP</currency>
                      <value>75.00</value>
                 </price>
                 <price>
                      <currency>USD</currency>
                      <value>100.00</value>
                  </price>
             </recurringPrice>
         </finalPhase>
     </plan>
     ...
</plans>

Add-ons

Having an explicit representation of Add-On products allows Kill Bill to be configured to only allow purchases of add-ons with particular base plans, and to trigger appropriate cancellations automatically when the base plan changes or is cancelled.

Kill Bill supports three categories of products:

  • Base Products

  • Add-On Products

  • Standalone Products

The terms Base Plan, Add-on Plan and Standalone Plan represent plans that are associated with these three types of product respectively.

A Subscription Bundle is a collection of subscriptions that correspond to an individual product instance, such as all the subscriptions associated with a single cell phone, or, in our example catalog all the subscriptions associated with the rental of Spy Car.

Subscription Bundles can either consist of a collection of subscriptions to stand-alone plans or a single Base Plan subscription with zero or more Add-On Plan subscriptions.

The Kill Bill catalog allows you to specify the inclusion and availability of Add-On Products with associated Base Products.

For example, suppose that we create some add-on products for our example catalog. Let’s add an OilSlick Product and a RemoteControl Product. Now, let’s discuss the availability and inclusion of these:

  • Neither of the products is available in the Standard Plan, meaning that you can’t purchase either of these add-ons if you are on Standard.

  • Both products are available on the Sport Plan.

  • RemoteControl is available on the Super Plan, but as we can see from the original Plan definition, OilSlick is already included in the Super Plan.

If we have this specified in the catalog then Kill Bill knows to disallow certain purchases, e.g. it will not allow the purchase of an OilSlick add-on in a Bundle with a Standard Base Plan. Similarly if the Base Plan in a Bundle containing Super and RemoteControl is downgraded to Standard, Kill Bill knows to automatically cancel the RemoteControl Add-On since it is no longer available. Finally, if the Base Plan of a Bundle containing Sports and OilSlick is upgraded to Super, Kill Bill knows to cancel the OilSlick Plan because its features are already included, by default, in the new Base Plan.

<products>
    <product name="Standard">
        <category>BASE</category>
    </product>
    <product name="Sports">
        <category>BASE</category>
        <available>
            <addonProduct>OilSlick</addonProduct>
            <addonProduct>RemoteControl</addonProduct>
        </available>
    </product>
    <product name="Super">
        <category>BASE</category>
        <included>
            <addonProduct>OilSlick</addonProduct>
        </included>
        <available>
            <addonProduct>RemoteControl</addonProduct>
        </available>
    </product>
    <product name="OilSlick">
        <category>ADD_ON</category>
    </product>
    <product name="RemoteControl">
        <category>ADD_ON</category>
    </product>
</products>

Price lists

uc?&id=0Bw8rymjWckBHTXcwbHNjTXBnYkE&w=960&h=480

Price Lists are collections of Plans, usually associated with a promotion or discount package.

For example, we might offer special rates on our Spy Car rental package for C.I.A. Agents, which offers 33% off for the first 3 months of hire. To do this, we create plans similar to the ones we have already. They should have the same trial phase and the same evergreen phase, but we insert a new discount phase which, for 3 months, charges the appropriate discount.

In this example we consider only the first of the three additional plans.

<plan name="discount-standard-monthly">
    <product>Standard</product>
    <initialPhases>
        <phase type="TRIAL">
            <duration>
                <unit>DAYS</unit>
                <number>30</number>
            </duration>
        <billingPeriod>NO_BILLING_PERIOD</billingPeriod>
            <fixedPrice> <!-- empty price implies $0 -->
            </fixedPrice>
        </phase>
        <phase type="DISCOUNT">
            <duration>
                <unit>MONTHS</unit>
                <number>3</number>
            </duration>
            <billingPeriod>MONTHLY</billingPeriod>
            <recurringPrice>
                <price>
                    <currency>GBP</currency>
                    <value>50.00</value>
                </price>
                <price>
                    <currency>USD</currency>
                    <value>66.00</value>
                </price>
            </recurringPrice>
        </phase>
    </initialPhases>
    <finalPhase type="EVERGREEN">
        <duration>
            <unit>UNLIMITED</unit>
        </duration>
        <billingPeriod>MONTHLY</billingPeriod>
        <recurringPrice>
            <price>
                <currency>GBP</currency>
                <value>75.00</value>
            </price>
            <price>
                <currency>USD</currency>
                <value>100.00</value>
            </price>
        </recurringPrice>
    </finalPhase>
</plan>

Once our additional plans have been created, we can add the new pricelist, after the default price list:

<priceLists>
    <defaultPriceList name="DEFAULT">
        <plans>
            <plan>standard-monthly</plan>
            <plan>sports-monthly</plan>
            <plan>super-monthly</plan>
        </plans>
    </defaultPriceList>
    <childPriceList name="CIA">
        <plans>
            <plan>discount-standard-monthly</plan>
            <plan>discount-sports-monthly</plan>
            <plan>discount-super-monthly</plan>
        </plans>
    </childPriceList>
</priceLists>

The alignment and price list change rules can be used to specify the behaviour to use when changing pricelists. In the example above, we would expect customers to be able to upgrade and downgrade within the discount phase of the subscription and stay in the discounted price list. We refer to this as a “sticky” price list. Kill Bill can also support “non-sticky” price lists, in which plan changes cause the customer to drop out of the pricelist that the are in and move to a different one (usually the Default). In the section on rules we explain how to configure these properties.

Rules

There several different Rules that can be configured in the Kill Bill Catalog. Each Rule answers a specific question. For example, one of the Rules answers the question "When should this plan change be applied?". Suppose Kill Bill receives a request for a subscription to have its plan upgraded, Kill Bill will check the rules, and based on the current plan, the phase it is in, the new plan etc. Kill Bill can determine whether the transition should happen immediately, or be deferred until later.

Rules consist of a series of Cases, each case is represented by a Predicate and a Result. Rules are evaluated against a Context. Each case is examined in order, and the Predicate for that Case is compared to the Context. If the Predicate is satisfied by the context, then the Result of that Case is applied.

For example, consider the following rule for the timing of applying a plan change:

  1. Predicate: phaseType=TRIAL ; Result: IMMEDIATE

  2. Predicate: phaseType=Evergreen AND fromProduct=Sports AND toProduct=Standard ; Result: END_OF_TERM

  3. Predicate: ; Result: END_OF_TERM

In this example there are three cases. The cases are evaluated from first to last and the first case for which the predicate matches the context is the one that is successful.

Consider following Context:

phaseType

EVERGREEN

fromProduct

Sports

fromProductCategory

BASE

fromBillingPeriod

MONTHLY

fromPriceList

DEFAULT

toProduct

Standard

toProductCategory

BASE

toBillingPeriod

MONTHLY

toPriceList

DEFAULT

To evaluate the Rule against this Context, we start by considering Case 1. The predicate in Case 1 requires that PhaseType=TRIAL, but the first line of our context has phaseType set to EVERGREEN, so Case 1 fails. However, when we consider Case 2, all the predicate clauses are satisfied by the above context: phaseType=Evergreen, fromProduct=Sports and toProduct=Standard. So, Case 2 succeeds and the Rule evaluates to "END_OF_TERM".

Notice that the predicates only need to specify the values of some of the fields in the context. Fields that are omitted in a predicate can take any value. For this reason Case 3 is a catch-all Case. It always succeeds because the predicate has no clauses so it will succeed with any Context.

The XML for the above rules is given below:

<rules>
...
    <changePolicy>
        <changePolicyCase>
            <phaseType>TRIAL</phaseType>
            <policy>IMMEDIATE</policy>
        </changePolicyCase>
        <changePolicyCase>
            <phaseType>EVERGREEN</phaseType>
            <fromProduct>Sports</fromProduct>
            <toProduct>Standard</toProduct>
            <policy>END_OF_TERM</policy>
        </changePolicyCase>
        <changePolicyCase>
            <policy>END_OF_TERM</policy>
        </changePolicyCase>
    </changePolicy>
...
</rules>

There are three types of Context:

  • Creation Context - provides the context for a new subscription

  • Subscription Context - this provides the context of an existing subscription, including details of the plan, phase, pricelist, product etc.

  • Change Context - this is used in the event of a plan change provides context not only about the phase of the correct subscription but also details of the new target plan.

Creation ContextSubscription ContextChange Context

product

product

phaseType

productCategory

productCategory

fromProduct

billingPeriod

billingPeriod

fromProductCategory

priceList

priceList

fromBillingPeriod

phaseType

fromPriceList

toProduct

toProductCategory

toBillingPeriod

toPriceList

In the remainder of this section we illustrate each type of rule supported by the system.

Billing Alignment Rules

This rule uses the Creation Context and configures type of billing alignment used with a subscription. There are three kinds of alignment available:

  • ACCOUNT - this means that the billing cycle of the subscription will be lined up with the bill cycle day of the account (if you didn’t specify a value, the system will generate one using the first recurring bill date of all subscriptions with an ACCOUNT billing alignment). In some cases, this is undesirable because it means that a proration charge will be applied on first billing to line up the cycles.

  • SUBSCRIPTION - this alignment will cause the subscriptions bill cycle to line up with the first bill day of the subscription plan. So, if the subscription starts on January 3rd and has a 15 day free trial, the first billed day with be January 18th and the bill cycle day for the subscription will be set to 18.

  • BUNDLE - setting the alignment to bundle is useful for add-ons because it sets the bill cycle day to be aligned with whatever the base plan is using.

Example:

  1. Predicate: productCategory=ADD_ON ; Result: BUNDLE

  2. Predicate: billingPeriod=MONTH ; Result: ACCOUNT

  3. Predicate: billingPeriod=ANNUAL ; Result: SUBSCRIPTION

  4. Predicate: ; Result: ACCOUNT

This example will align addons with the base plan, monthlies to the Account bill cycle day and annuals to their first billed day. Anything else is aligned with the Account.

<billingAlignment>
    <billingAlignmentCase>
        <productCategory>ADD_ON</productCategory>
        <alignment>BUNDLE</alignment>
    </billingAlignmentCase>
    <billingAlignmentCase>
        <billingPeriod>MONTHLY</billingPeriod>
        <alignment>ACCOUNT</alignment>
    </billingAlignmentCase>
    <billingAlignmentCase>
        <billingPeriod>ANNUAL</billingPeriod>
        <alignment>SUBSCRIPTION</alignment>
    </billingAlignmentCase>
    <billingAlignmentCase>
        <alignment>ACCOUNT</alignment>
    </billingAlignmentCase>
</billingAlignment>

Subscription Alignment Rules

Plan Creation Add-On Phase Alignment

This rule also uses the Creation Context and determines how the phases of an Add-On plan aligns with an existing subscription.

uc?&id=0Bw8rymjWckBHaDN0Y0NIbTFCaU0&w=960&h=480

There are two choices (illustrated above):

  • START_OF_BUNDLE - causes the phases of the addon to start on the date when the base plan was first created. This is for instance useful if you want to allow add-on trials during the trial phase of the base plan only. The addon plans must have a trial of the same length as the base plan and then the trials will expire at the same time whenever the add-on is created.

  • START_OF_SUBSCRIPTION - this causes the phases of the add-on to start when the add-on subscription is created. This is for instance useful if you want to allow add-ons to have trials that are occur independently of the base plan.

Example:

  1. Predicate: product=OilSlick ; Result: START_OF_BUNDLE

  2. Predicate: product=RemoteControl ; Result: START_OF_SUBSCRIPTION

  3. Predicate: ; Result: START_OF_BUNDLE

In this example the product OilSlick is aligned to the START_OF_BUNDLE and the product RemoteControl is aligned to START_OF_SUBSCRIPTION. The default for anything else is START_OF_BUNDLE.

<createAlignment>
    <createAlignmentCase>
        <product>OilSlick</product>
        <alignment>START_OF_BUNDLE</alignment>
    </createAlignmentCase>
    <createAlignmentCase>
        <product>RemoteControl</product>
        <alignment>START_OF_SUBSCRIPTION</alignment>
    </createAlignmentCase>
    <createAlignmentCase>
        <alignment>START_OF_BUNDLE</alignment>
    </createAlignmentCase>
</createAlignment>

For more information on Plan Creation Phase Alignment, and in particular to understand how that works with apis (Subscription create or Subscription Change Plan) that specify a target PhaseType, you can also refer to this documentation.

Plan Cancellation Timing

This rule uses the Phase Context and is used to specify when a cancellation should occur.

uc?&id=0Bw8rymjWckBHTjRMVkZjbUZ3OFE&w=960&h=480

There are two options (illustrated above):

  • END_OF_TERM - meaning that the cancellation will be applied at the end of the billed period. This is typical in a situation where we want to avoid generating credits.

  • IMMEDIATE - meaning that the cancellation will be applied immediately and the customer credited with the balance of the subscription that they have paid for but not yet used.

Example:

  1. Predicate: productCategory=BASE ; Result: END_OF_TERM

  2. Predicate: productCategory=ADD_ON ; Result: IMMEDIATE

  3. Predicate: ; Result: END_OF_TERM

In this example base plans are cancelled at the end of their term, add-on plans are cancelled immediately.

<cancelPolicy>
    <cancelPolicyCase>
        <productCategory>BASE</productCategory>
        <policy>END_OF_TERM</policy>
    </cancelPolicyCase>
    <cancelPolicyCase>
        <productCategory>ADD_ON</productCategory>
        <policy>IMMEDIATE</policy>
    </cancelPolicyCase>
    <cancelPolicyCase>
        <policy>END_OF_TERM</policy>
    </cancelPolicyCase>
</cancelPolicy>

Plan Change Timing

This rule uses the Change Context and, like the cancellation rule above, specifies when a plan change should occur.

uc?&id=0Bw8rymjWckBHV2huVmFqSlkwQ1E&w=960&h=480

There are three options (two of which are illustrated above):

  • END_OF_TERM - specifies that the change should happen at the end of the current billed period.

  • IMMEDIATE - specifies that the change should happen when requested.

  • ILLEGAL - plan change is not allowed (not illustrated).

Example:

  1. Predicate: phaseType=TRIAL ; Result: IMMEDIATE

  2. Predicate: fromProduct=Standard AND toProduct=Sports ; Result: IMMEDIATE

  3. Predicate: toProduct=Super ; Result: IMMEDIATE

  4. Predicate: ; Result: END_OF_TERM

In this example we specify that trials and upgrades occur immediately, anything else is to occur at end of term.

<changePolicy>
    <changePolicyCase>
        <phaseType>TRIAL</phaseType>
        <policy>IMMEDIATE</policy>
    </changePolicyCase>
    <changePolicyCase>
        <fromProduct>Standard</fromProduct>
        <toProduct>Sports</toProduct>
        <policy>IMMEDIATE</policy>
    </changePolicyCase>
    <changePolicyCase>
        <toProduct>Super</toProduct>
        <policy>IMMEDIATE</policy>
    </changePolicyCase>
    <changePolicyCase>
        <policy>END_OF_TERM</policy>
    </changePolicyCase>
</changePolicy>

Plan Change Phase Alignment

In the section "Plan Creation Add-on Phase Alignment" above, we specified how to align the phases of an add-on with a base plan. This rule, which uses the Change Context, specifies how the phases of a new plan should align with the phases of the existing plan when a plan is changed.

There are four options:

  • START_OF_SUBSCRIPTION - The plan phases start with the start of the subscription. This is the most common alignment and applies in most situations.

  • START_OF_BUNDLE - The plan phases should align with the start of the base subscription. This is only meaningful for addons.

  • CHANGE_OF_PLAN - The plan phases start at the time of the change

  • CHANGE_OF_PRICELIST - The plan phases start at the time of the last change of price list

Example:

  1. Predicate: toProductCategory=ADD_ON ; Result: START_OF_BUNDLE

  2. Predicate: toPriceList=SpecialDiscount ; Result: CHANGE_OF_PRICELIST

  3. Predicate: ; Result: START_OF_SUBSCRIPTION

<changeAlignment>
    <changeAlignmentCase>
        <toProductCategory>ADD_ON</toProductCategory>
        <alignment>START_OF_BUNDLE</alignment>
    </changeAlignmentCase>
    <changeAlignmentCase>
        <fromPriceList>SpecialDiscount</fromPriceList>
        <toPriceList>SpecialDiscount</toPriceList>
        <alignment>CHANGE_OF_PRICELIST</alignment>
    </changeAlignmentCase>
    <changeAlignmentCase>
        <alignment>START_OF_SUBSCRIPTION</alignment>
    </changeAlignmentCase>
</changeAlignment>

In this example, addon changes are aligned to the start of the bundle, changes to the SpecialDiscount price list are aligned to that change and everything else aligns to the start of the subscription.

For more information on Plan Change Phase Alignment, and in particular to understand how that works with apis (Subscription create or Subscription Change Plan) that specify a target PhaseType, you can also refer to this documentation.

Plan Change Price List Choice

This rule uses the Change Context and specifies which pricelist should be chosen for specific changes. The rule allows us to configure whether a price list is "sticky" or not.

For example, suppose we have affiliate pricelist with special prices for members of the CIA for Spy Car rental. Let’s say that this price list offers a 30% discount for the first 3 months of rental.

Now, Special Agent Mills from the CIA subscribes to a Sports product on that price list. However, 1 month after renting the car his daughter is kidnapped and he needs additional capabilities and decides to upgrade to a Super. Since he bought the original subscription on a special offer that still has two months to run we would expect the upgrade to put him into the corresponding 30% off Super plan and give him a further 2 months at that price. This is a “sticky” price list.

Alternatively, consider long term customer 003 who has been renting the Super for the last 4 years but decides that she wants to save money and calls to downgrade her plan. Our representative offers her a special Rescue Pricing plan that gives her 40% off for the next year and she decides to take it. However, a month later she changes her mind and decides to downgrade anyway. In this situation we want her to downgrade to the default price plan. This is a "non-sticky" price list.

Example:

  1. Predicate: fromPriceList=CIA ; Result: CIA

  2. Predicate: fromPriceList=SpecialDiscount ; Result: DEFAULT

  3. Predicate: ; Result: DEFAULT

<priceList>
   <priceListCase>
        <fromPriceList>SpecialDiscount</fromPriceList>
        <toPriceList>DEFAULT</toPriceList>
    </priceListCase>
   <priceListCase>
        <fromPriceList>CIA</fromPriceList>
        <toPriceList>CIA</toPriceList>
    </priceListCase>
   <priceListCase>
        <toPriceList>DEFAULT</toPriceList>
    </priceListCase>
</priceList>

Catalog Versions

This far in the discussion we have been considering single stand-alone catalogs, but Kill Bill allows the catalog to be modified over time. This is done by creating a set of catalogs, one XML file for each version: The system will rank such files based on their effectiveDate to create the various versions. There is no version number proper, the effectiveDate associated to each catalog XML constitutes the version and each catalog is superseded by the next. In this way we can change prices, add new Plans, Products, Price Lists etc, retire Plans, Products, Price Lists, etc.

Note that it is possible to remove entries in subsequent catalog versions: For example, removing a Plan in a new catalog version would prevent future custom to subscribe to such Plan. However existing subscriptions will still refer to them.

Deferred Price Change

Kill Bill supports the ability to make a price change to a plan that applies based on the catalog effective date for new purchases, but which is deferred for existing subscriptions. It is often the case that existing customers will need a notice period before prices are changed but you need to deliver the new prices to new purchases as soon as the change is announced.

This feature uses the field effectiveDateForExistingSubscriptions that is included on Plans. The semantics is simply that the changes to that plan will only take effect for existing subscriptions, after that date, but new subscription would use the new price immediately.

The drawing below summarizes how the system would apply the change for an existing subscription:

uc?&id=0Bw8rymjWckBHZGlqWGpGRnVDeVE&w=960&h=480

Usage Billing

Usage Modes

Kill Bill supports invoicing customers based on their usage data, and the definition of such pricing scheme is defined in the catalog. The Plan section of the Kill Bill catalog can contain one or several usage section(s) to define how customers will be billed. These sections can be defined in addition to other non usage based billing pricing scheme, such as fixed or recurring price.

Each usage section will need to specify a billingMode: The only billing mode supported today is the IN_ARREAR mode, which allows to bill customer based on usage data from previous periods. We plan to add the IN_ADVANCE mode in the future to support prepaids-like scenario — e.g toll bridge pass — where consumer purchases a certain number of units in advance and such units are decremented as consumer uses the service.

Each usage section will also need to specify a usageType and along with it, specify the unit (types) for which customer is being billed for — e.g cell phone/minutes. The usage type can be one of the following:

  • CONSUMABLE : This is is used for defining prices that are based on the number of units (of a certain types) being consumed — e.g water consumed in the last period.

  • CAPACITY : This is used for defining prices that are based on rates or upper bound values. In this scheme, we bill based on the maxium value seeing over the period — e.g MBytes/sec

The following blog post provides additional context about this use cases.

For each usage section, we support defining pricing tiers to allow billing customer differently based on their usage. Such tiers work differently depending of the usage type, CONSUMABLE versus CAPACITY.

Each usage section also needs to define the billingPeriod — e.g MONTHLY — to define how often and for which period consumers are being billed.

Consumable In Arrear Mode

In this mode, each tier definition contains a tieredBlock, that defines the limits and price associated to a particular unit type. We support two TierBlockPolicy policies:

  • ALL_TIER: Users are charged across each tier based on their usage; the idea is to offer some form of tiered pricing where the upper level prices can be charged to a lower amount — e.g clould usage where we want to reward users to consume more — or higher — e.g electricy bill to discourage users to consume more.

  • TOP_TIER: In this model we still go through each tier, but end up charging everything at the top tier pricing. In this model, it probably makes sense to offer lower pricing for the top tier, this is a rewarding model.

Consumable In Arrear Mode: ALL_TIER

Let’s start with an example of a tieredBlock definition: The following tier block section defines the pricing for the cell-phone-minutes unit, and can be understood the following way:

<tieredBlock>
    <unit>cell-phone-minutes</unit>
    <size>10</size>
    <prices>
        <price>
            <currency>EUR</currency>
            <value>1.00</value>
        </price>
    </prices>
    <max>100</max>
</tieredBlock>
  • This defines a block of size 10, where each block is priced at 1.00 EUR

  • The first 100 blocks of this size will be priced at 1.00 EUR

  • If a consumer uses more than 100 blocks of this size, he will be charged at the price of the next tier.

As mentionned previously, such usage section can contain multiple tiers and also charge for multiple unit types. The following section shows the defintion for 2 units, cell-phone-minutes and Mbytes, and define two tiers. The max value for the last tier is defined with -1 to allow for unbounded value:

<tiers>
    <tier>
        <blocks>
            <tieredBlock>
                <unit>cell-phone-minutes</unit>
                <size>10</size>
                <prices>
                    <price>
                        <currency>EUR</currency>
                        <value>1.00</value>
                    </price>
                </prices>
                <max>100</max>
            </tieredBlock>
            <tieredBlock>
                <unit>Mbytes</unit>
                <size>1</size>
                <prices>
                    <price>
                        <currency>EUR</currency>
                        <value>0.5</value>
                    </price>
                </prices>
                <max>1024</max>
            </tieredBlock>
        </blocks>
    </tier>
    <tier>
        <blocks>
            <tieredBlock>
                <unit>cell-phone-minutes</unit>
                <size>10</size>
                <prices>
                    <price>
                        <currency>EUR</currency>
                        <value>0.50</value>
                    </price>
                </prices>
                <max>-1</max>
            </tieredBlock>
            <tieredBlock>
                <unit>Mbytes</unit>
                <size>1</size>
                <prices>
                    <price>
                        <currency>EUR</currency>
                        <value>0.1</value>
                    </price>
                </prices>
                <max>-1</max>
            </tieredBlock>
        </blocks>
    </tier>
</tiers>

In the CONSUMABLE mode, when defining usage section with multiple unit (types), it is important to realize that the consumer is charged independently for each unit, so for example, with the definition provided above:

Given the following usage data for the period:

  • 1500 cell-phone-minutes

  • 2048 Mbytes

The total amount would be 739.4 and is calculated as follows;

Each unit is billed separately as;

cell-phone-minutes:

  • Tier 1: 100 blocks of size 10 at 1 EUR ⇒ 100 EUR

  • Tier 2: 50 blocks of size 10 at 0.5 EUR ⇒ 25 EUR

Mbytes

  • Tier 1: 1024 blocks of size 1 at 0.5 EUR ⇒ 512

  • Tier 2: 1024 blocks of size 1 at 0.1 EUR ⇒ 102.4

Total: 100 + 25 + 512 + 102.4 = 739.4

For more information on this model, see our tutorial.

Consumable In Arrear Mode: TOP_TIER

Using the same example from the previous section would lead to a different result:

The consumer would be charged for:

  • cell-phone-minutes: 150 blocks of size 10 at 0.50 EUR = 150 * 0.5 = 75

  • Mbytes: 2048 blocks of size 1 at 0.10 EUR = 2048 * 0.1 = 204.8

So the total amount would be 279.8

Capacity In Arrear Mode

In the CAPACITY mode, each tier definition contains a list of limit, specifying for each unit (type) what is the maxium value for this tier. In contrary to CONSUMABLE mode, the billing happens across the units. Let’s assume the following definition for one tier, with 2 different types of units, bandwith-meg-sec and members:

<tier>
   <limits>
       <limit>
           <unit>bandwith-meg-sec</unit>
           <max>100</max>
       </limit>
       <limit>
           <unit>members</unit>
           <max>500</max>
       </limit>
   </limits>
   <recurringPrice>
       <price>
           <currency>EUR</currency>
           <value>5.00</value>
       </price>
   </recurringPrice>
</tier>

Given the following usage data for the period:

  • bandwith-meg-sec: A peak of 50 in the period

  • members: A peak of 350 active members in the period

The user would be charged 5.00 EUR.

However if the members peak data was 501, this would move to the next tier — not shown for simplicity.

So, in this model, the peak data for each unit is used to define which tier to use, and based on the tier we simply apply the pricing defined.

Subscription and Entitlement

Overview

The Kill Bill entitlement system primarily offers an API for users to manage their subscriptions. The API allows a user to subscribe to a new product, change to a different product, pause, resume or cancel its subscription. Upon each of those API calls there are really two distinct set of operations that occur in the system:

  • When an entitlement change occurs, for instance upon creation, the user gains access to what she subscribed for The primary goal of that API is to give great flexibility through the use of dates or entitlement policies as to when things should start/stop,…​

  • As a consequence of the entitlement operation, the system will also compute the changes that should occur on the billing side. It is important to understand that the entitlement operation has an impact on billing, so the two are connected, but they are not necessarily aligned.

The philosophy behind that API is that the user (of the API) should be able to drive the entitlement so that it matches exactly its needs and let the system computes the billing aspect based on the policies that were configured in the catalog. Example:

  • First an administrator sets up Kill Bill to always perform the cancellation END_OF_TERM, which will result in never generating a credit for a particular product 'P'.

  • A customer comes in, subscribes to that product 'P', and gets invoiced…​

  • At a later date the customer decides that he no longer wants to use the product 'P' and so he decides to cancel that subscription immediately. From an entitlement point of view, the end date is now and so, as soon as the call returns, the customer loses access to its product 'P'.

  • However from a billing point of view, and because the administrator decided to configure the system that way, the end date will be computed by the system to match the end date of the last period invoiced, also referred to as charged through date (CTD), and that way there is no generated credit for that cancellation.

So, as a general rule, the administrator deals with the billing policies, and the user of the API controls the detail of its entitlement(s). The entitlement system exposes abstractions that reflect that model:

  • Entitlement: An entitlement is an abstraction which helps answer the following question: Is the user allowed (entitled) to use this service/product at a given time? So as such, it provides information about the dates where that service started, ended, was paused/resumed along with the specifics about the type of service/product.

  • Subscription: A Subscription is an abstraction that encapsulates the information contained in the Entitlement but also adds additional billing information, such as the dates at which the billing started, ended. When the system is configured to bill in advance, it also provides the date up to which the customer was invoiced (ChargeThroughDate).

  • SubscriptionBundle: Subscriptions are always part of a SubscriptionBundle. This allows Subscriptions to be grouped together so that specific operations — cancellation, change of plan-- on one Subscription may have an impact on the other Subscriptions in the same SubscriptionBundle. There can be at most one Subscription attached to a BASE Category in a SubscriptionBundle but there can be multiple ADD_ON Subscriptions in that same SubscriptionBundle. Typically, a BASE Category is used to make sure that any operation on the BASE Subscription will be reflected on the ADD_ON Susbcriptions in the same SubscriptionBundle.

Previously we laid out the general case where the user of the API controls the Entitlement and Kill Bill manages the billing aspect based on configuration policies. Some specific entitlement APIs also allow you to override the billing policies on a per call basis.

Alignments

The API allows you to provide the following matrix of combinations:

On the horizontal line, we have the various entitlement (ENT) policies or requested cancel date; on the vertical we have the same policies/requested cancel date for the billing side (BILL):

Entitlement Matrix Policy

The diagrams below summarize what happens when a cancellation occurs on a subscription that was billed in advance:

  • The green line shows the entitlement, and the red cross on that line shows the cancellation as seen by the customer; that is, once we hit the red cross the customer loses access to its entitlement.

  • The red portion below shows the current invoice; by default the customer was invoiced from the start of the period to the end of the period, also referred to as charged through date (CTD).

We can see that in all cases, cancelling a subscription has both an impact on the entitlement and the billing side, but we also see that those two are not necessarily aligned:

Entitlement policy scenarii

Invoicing

Overview

Most (all?) billing system are batch oriented: Invoice calculation occurs at certain specific times (often configurable), and the system goes through all accounts and generate the missing invoices. Kill Bill, on the other hand, generates new invoices as soon as there is a change in the system that requires such a new invoice:

  • there is a change for a subscription (creation, change of plan, cancellation, etc.)

  • on a recurring phase of a subscription, the system detects a recurring charge is due (e.g. monthly recurring subscriptions)

  • an operator either creates an external charge, adjusts a past invoice or triggers a future invoice

After an invoice has been generated, its balance is positive or zero. If it’s positive, the customer owes money and needs to pay its balance. Each time an invoice would become negative, the system automatically inserts a special item, called credit balance adjustment (CBA), to bring back the balance to zero. That credit is automatically added to the account and used on future invoices. If the invoice is paid, a payment is added against that invoice. If that invoice is adjusted later on, a CBA item will be automatically generated and appear on the invoice. Kill Bill invoices are for the most part static, with the exceptions of manual changes (manual credit, charge added on a specific invoice after the generation)

An invoice is made of invoice items and the various types of invoice items are:

  • RECURRING: Recurring charge. Used for items with a billing period. This item is always positive or zero

  • FIXED: Fixed (one-time) charge. Used for items without a billing period (non recurring phase, e.g. trials). This item is always positive or zero

  • EXTERNAL_CHARGE: Fixed (one-time) external charge, for items not in the catalog. This item is always positive

  • USAGE: Usage charge. This item is always positive or zero.

  • TAX: Tax item. This item is not added by the core system, but is added by tax plugins — when such plugins exist.

  • ITEM_ADJ: Invoice item adjustment, generated by an operator (often associated with a refund). This item is always negative

  • CREDIT_ADJ: Invoice level adjustment (credits), either at the account level (on its own invoice) or against an existing invoice. This item is always negative

  • REPAIR_ADJ: Internal adjustment, generated automatically by the system for an invoice on which the subscription was modified (immediate cancellation or change). The items is always negative

  • CBA_ADJ: Internal adjustment, generated automatically by the system for an invoice which became negative (account level credits). Positive when generating credits, negative when consuming account level credits. The sum of CBA items for an account should always be positive or zero

Recurring invoice items start and end on the same day of the month. For example, a monthly subscription starting on the 21st will have items for the service period 2012-08-21 to 2012-09-21, 2012-09-21 to 2012-10-21, etc. Fixed items only have a start date and never get pro-rated.

Invoice and Account Balance

The invoice balance is computed by summing all the charges, substracting credits and adjustments and then substracting the resulting paid amount:

  • The charge amount is computed from the following items: FIXED, RECURRING, EXTERNAL_CHARGE, REPAIR_ADJ, ITEM_ADJ, USAGE, TAX.

  • The resulting paid amount is the sum of the original paid amount and then substracting any refund amount.

The invoice balance is Zero in the following cases:

  • When the invoice was tagged with WRITTEN_OFF tag.

  • When the invoice is in DRAFT mode.

  • When this is a migration invoice (imported in the system).

  • When this is a child invoice for which parent summary invoice has been fully paid (HA feature).

The account balance is the sum of all the invoice balances and then substracting any account credit (so, if all invoices were fully paid, and if there is a $10 account credit, the account balance would be negative and equal to $-10).

Invoice Items

Fixed Item

An invoice for a subscription on a fixed phase of $0 (trial phase for example) would look like:

Invoice #TypeDescriptionAmountStart dateEnd date

1028

FIXED

Silver trial

$0

2013-03-10

Recurring Item

An invoice for a subscription on a recurring phase of $20 would look like:

Invoice #TypeDescriptionAmountStart dateEnd date

1029

RECURRING

Silver monthly

$20

2013-04-11

2013-05-11

Plan Changes

In a case where invoicing occurs in advance, a user gets charged for the upcoming period. For instance a user that subscribed to a monthly plan on 2013-04-11, would get a first invoice, charging for that month. Assuming he paid his invoice, his balance is now 0. Let’s assume he decides to upgrade on 2013-04-26:

Previous invoice:

Invoice #TypeDescriptionAmountStart dateEnd date

1029

RECURRING

Silver monthly

$20

2013-04-11

2013-05-11

On the new invoice, the system will generate a REPAIR_ADJ item for the part of the subscription on the old plan that was not used, and a new RECURRING item for the new plan on the remaining period.

Invoice #TypeDescriptionAmountStart dateEnd date

1030

RECURRING

Gold monthly

$15

2013-04-26

2013-05-11

1029

REPAIR_ADJ

Silver monthly

$-10

2013-04-26

2013-05-11

Note that if the absolute value of the amount of the REPAIR_ADJ had been greater than the amount of the new RECURRING item, the system would have generated a CBA_ADJ item whose purpose would have been to bring the balance to 0, and provide the customer some credit that would have been used on subsequent invoices.

Invoice Item Adjustment

An invoice item adjustment would look like (assuming the invoice wasn’t paid, otherwise a CBA_ADJ item would be added):

Invoice #TypeDescriptionAmountStart dateEnd date

1029

RECURRING

Silver monthly

$20

2013-04-11

2013-05-11

1029

ITEM_ADJ

$-20

2013-04-20

2013-04-20

Credit

Note that CREDIT_ADJ items are also used to represent credits created by the user (via APIs). In this case, a dummy invoice is created with a negative amount for the CREDIT_ADJ item. This makes the system generate a CBA_ADJ automatically, which in turn can be used as account credits. For example, here is how a $20 credit would be represented:

Invoice #TypeDescriptionAmountStart dateEnd date

1029

CREDIT_ADJ

$-20

2013-04-20

2013-04-20

Invoice Dry Run

Dry Run Modes

In some situations, it is necessary to preview what a given customer will be invoiced for at a given date or after making a subscription change. Kill Bill provides dry-run invoices apis to accomplish such goal, and there are a few flavours for different use cases:

  • Next upcoming invoice: When is the next upcoming invoice for a given customer, and what will such invoice contain (items, amount, date, …​)?

  • Next upcoming invoice associated with a given subscription or bundle: When is the next upcoming invoice for a given subscription/bundle, and what will such invoice contain (items, amount, date, …​)?

  • Given a targetDate, what invoice will the system generate ?

  • Subscription modification: Given a change in a subscription (new subscription, change of plan, cancellation, …​), which invoice will the system generate ?

Let’s assume a scenario where we created 2 annual subscriptions, the first one 261fe7b1-ff09-49c8-bbef-61d6e3ab876b aligned on July 25 and the second one 06b826ad-73e6-4bdd-92fe-c9770a1ba30a aligned on July 27. If we look at the existing invoice items we see the following:

*************************** 1. row ***************************
             id: 079e572e-a26c-42e4-8676-7213ad542af3
     account_id: 704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3
     invoice_id: 5725c77f-44af-409c-a32a-e36ed3c57283
subscription_id: 261fe7b1-ff09-49c8-bbef-61d6e3ab876b
           type: RECURRING
         amount: 10000.000000000
     start_date: 2017-07-25
       end_date: 2018-07-25
*************************** 2. row ***************************
             id: 1674c034-fcbe-46bb-9c04-f8825671f93f
     account_id: 704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3
     invoice_id: 65c5b4b8-67e6-4066-8699-70b0f49ee6df
subscription_id: 06b826ad-73e6-4bdd-92fe-c9770a1ba30a
           type: RECURRING
         amount: 10000.000000000
     start_date: 2017-07-27
       end_date: 2018-07-27

From this scenario, let’s now look at various use cases for dry-run options:

Next Upcoming Invoice

Let’s start with a dry-run invoice with UPCOMING_INVOICE, to see what is the next invoice that the system will generate for this account:

curl  \
-X POST \
-u admin:password \
-H "X-Killbill-ApiKey: bob" \
-H "X-Killbill-ApiSecret: lazar" \
-H "X-Killbill-CreatedBy: demo" \
-H "Content-Type: application/json" \
--data-binary '{"dryRunType":"UPCOMING_INVOICE"}' \
'http://127.0.0.1:8080/1.0/kb/invoices/dryRun?accountId=704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3'

This will result the following dry-run invoice, and as expected we only see the item for the first subscription aligned on the 25th:

{
  "amount": 10000,
  "currency": "USD",
  "status": "COMMITTED",
  "creditAdj": 0,
  "refundAdj": 0,
  "invoiceId": "3bbd33da-39c7-4748-a5a8-94d53e40cadc",
  "invoiceDate": "2017-12-14",
  "targetDate": "2018-07-25",
  "invoiceNumber": null,
  "balance": 10000,
  "accountId": "704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3",
  "bundleKeys": null,
  "credits": null,
  "items": [
    {
      "invoiceItemId": "937ac911-b51c-48a8-a004-4789bd3e0726",
      "invoiceId": "3bbd33da-39c7-4748-a5a8-94d53e40cadc",
      "linkedInvoiceItemId": null,
      "accountId": "704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3",
      "childAccountId": null,
      "bundleId": "54c2d76e-e84d-412d-8eac-afb6d0ea1a35",
      "subscriptionId": "261fe7b1-ff09-49c8-bbef-61d6e3ab876b",
      "planName": "basic-annual",
      "phaseName": "basic-annual-evergreen",
      "usageName": null,
      "itemType": "RECURRING",
      "description": "basic-annual-evergreen",
      "startDate": "2018-07-25",
      "endDate": "2019-07-25",
      "amount": 10000,
      "currency": "USD",
      "childItems": null,
      "auditLogs": null
    }
  ],
  "isParentInvoice": false,
  "auditLogs": null
}

Next Upcoming Invoice for a Given Subscription

Let’s now do a dry-run invoice with UPCOMING_INVOICE but with a filter on the subscription 06b826ad-73e6-4bdd-92fe-c9770a1ba30a:

curl  \
-X POST \
-u admin:password \
-H "X-Killbill-ApiKey: bob" \
-H "X-Killbill-ApiSecret: lazar" \
-H "X-Killbill-CreatedBy: demo" \
-H "Content-Type: application/json" \
--data-binary '{"dryRunType":"UPCOMING_INVOICE", "subscriptionId":"06b826ad-73e6-4bdd-92fe-c9770a1ba30a"}' \
'http://127.0.0.1:8080/1.0/kb/invoices/dryRun?accountId=704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3'

This will result in the following dry-run invoice, and as expected we only see the item for the second subscription 06b826ad-73e6-4bdd-92fe-c9770a1ba30a:

{
  "amount": 10000,
  "currency": "USD",
  "status": "COMMITTED",
  "creditAdj": 0,
  "refundAdj": 0,
  "invoiceId": "25fbf3f9-2b5b-4389-a940-84864fe5cd88",
  "invoiceDate": "2017-12-14",
  "targetDate": "2018-07-27",
  "invoiceNumber": null,
  "balance": 10000,
  "accountId": "704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3",
  "bundleKeys": null,
  "credits": null,
  "items": [
    {
      "invoiceItemId": "a4f525c4-014b-474b-85a9-6ccf4742fe5e",
      "invoiceId": "25fbf3f9-2b5b-4389-a940-84864fe5cd88",
      "linkedInvoiceItemId": null,
      "accountId": "704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3",
      "childAccountId": null,
      "bundleId": "c056fac0-1564-46cd-9e2a-d97e49e30177",
      "subscriptionId": "06b826ad-73e6-4bdd-92fe-c9770a1ba30a",
      "planName": "basic-annual",
      "phaseName": "basic-annual-evergreen",
      "usageName": null,
      "itemType": "RECURRING",
      "description": "basic-annual-evergreen",
      "startDate": "2018-07-27",
      "endDate": "2019-07-27",
      "amount": 10000,
      "currency": "USD",
      "childItems": null,
      "auditLogs": null
    }
  ],
  "isParentInvoice": false,
  "auditLogs": null
}

Next Invoice for a Given Target Date

Next, let’s run a dry-run invoice with TARGET_DATE set to 2018-07-27:

curl  \
-X POST \
-u admin:password \
-H "X-Killbill-ApiKey: bob" \
-H "X-Killbill-ApiSecret: lazar" \
-H "X-Killbill-CreatedBy: demo" \
-H "Content-Type: application/json" \
--data-binary '{"dryRunType":"TARGET_DATE"}' \
'http://127.0.0.1:8080/1.0/kb/invoices/dryRun?accountId=704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3&targetDate=2018-07-27'

This will result the following dry-run invoice, and as expected we will see the same result as the previous example. However, while the previous use case answered the question about the next upcoming invoice for subscription 06b826ad-73e6-4bdd-92fe-c9770a1ba30a, in this scenario we answer a different question: Given a targetDate what will the system generate?

{
  "amount": 10000,
  "currency": "USD",
  "status": "COMMITTED",
  "creditAdj": 0,
  "refundAdj": 0,
  "invoiceId": "d89d776a-b13e-4c53-baad-519bdd9ba6d0",
  "invoiceDate": "2017-12-14",
  "targetDate": "2018-07-27",
  "invoiceNumber": null,
  "balance": 10000,
  "accountId": "704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3",
  "bundleKeys": null,
  "credits": null,
  "items": [
    {
      "invoiceItemId": "9a872df2-1ab9-4250-8f34-8b2cf49ebbb9",
      "invoiceId": "d89d776a-b13e-4c53-baad-519bdd9ba6d0",
      "linkedInvoiceItemId": null,
      "accountId": "704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3",
      "childAccountId": null,
      "bundleId": "c056fac0-1564-46cd-9e2a-d97e49e30177",
      "subscriptionId": "06b826ad-73e6-4bdd-92fe-c9770a1ba30a",
      "planName": "basic-annual",
      "phaseName": "basic-annual-evergreen",
      "usageName": null,
      "itemType": "RECURRING",
      "description": "basic-annual-evergreen",
      "startDate": "2018-07-27",
      "endDate": "2019-07-27",
      "amount": 10000,
      "currency": "USD",
      "childItems": null,
      "auditLogs": null
    }
  ],
  "isParentInvoice": false,
  "auditLogs": null
}

Subscription Modification

Finally, we’ll generate a dry-run invoice associated to a change in the subscription: We want to see what kind of invoice would be generated if we were to change the billing period from ANNUAL to MONTHLY. Also note that this changed was made on 2018-01-24:

curl -X POST \
 -u admin:password \
 -H 'Content-Type: application/json' \
 -H 'X-Killbill-ApiKey: bob' \
 -H 'X-Killbill-ApiSecret: lazar' \
 -H 'X-Killbill-CreatedBy: demo' \
 -d '{"bundleId":"c056fac0-1564-46cd-9e2a-d97e49e30177", "dryRunType":"SUBSCRIPTION_ACTION",  "phaseType":"EVERGREEN", "productName":"Basic", "productCategory":"BASE", "billingPeriod":"MONTHLY", "priceListName":"DEFAULT", "subscriptionId":"06b826ad-73e6-4bdd-92fe-c9770a1ba30a", "billingPolicy":"IMMEDIATE", "dryRunAction":"CHANGE"}' \
 "http://127.0.0.1:8080/1.0/kb/invoices/dryRun?accountId=704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3"

The result is an invoice with 3 items:

  • RECURRING item to invoice the next MONTHLY period

  • REPAIR_ADJ item to generate a credit for remaining part of the year

  • CBA_ADJ item to bring back to balance to 0 and generate the resulting account credit.

More details below:

{
  "amount": -5008.84,
  "currency": "USD",
  "status": "COMMITTED",
  "creditAdj": 5008.84,
  "refundAdj": 0,
  "invoiceId": "e85306e2-2753-4888-b7df-543c308c367c",
  "invoiceDate": "2018-01-24",
  "targetDate": "2018-01-24",
  "invoiceNumber": null,
  "balance": 0,
  "accountId": "704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3",
  "bundleKeys": null,
  "credits": null,
  "items": [
    {
      "invoiceItemId": "f2156511-0273-4ef0-9c11-410a3f6f3872",
      "invoiceId": "e85306e2-2753-4888-b7df-543c308c367c",
      "linkedInvoiceItemId": null,
      "accountId": "704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3",
      "childAccountId": null,
      "bundleId": "c056fac0-1564-46cd-9e2a-d97e49e30177",
      "subscriptionId": "06b826ad-73e6-4bdd-92fe-c9770a1ba30a",
      "planName": "basic-monthly",
      "phaseName": "basic-monthly-evergreen",
      "usageName": null,
      "itemType": "RECURRING",
      "description": "basic-monthly-evergreen",
      "startDate": "2018-01-24",
      "endDate": "2018-01-25",
      "amount": 32.26,
      "currency": "USD",
      "childItems": null,
      "auditLogs": null
    },
    {
      "invoiceItemId": "f78a8843-3155-4f89-ae2a-ca4219936a2c",
      "invoiceId": "e85306e2-2753-4888-b7df-543c308c367c",
      "linkedInvoiceItemId": "1674c034-fcbe-46bb-9c04-f8825671f93f",
      "accountId": "704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3",
      "childAccountId": null,
      "bundleId": null,
      "subscriptionId": null,
      "planName": null,
      "phaseName": null,
      "usageName": null,
      "itemType": "REPAIR_ADJ",
      "description": "Adjustment (subscription change)",
      "startDate": "2018-01-24",
      "endDate": "2018-07-27",
      "amount": -5041.1,
      "currency": "USD",
      "childItems": null,
      "auditLogs": null
    },
    {
      "invoiceItemId": "4b13e745-eaa7-4fcd-bfc8-56a3ff3d5190",
      "invoiceId": "e85306e2-2753-4888-b7df-543c308c367c",
      "linkedInvoiceItemId": null,
      "accountId": "704b1a30-e5b9-4d01-b2b8-e9403a0ed0e3",
      "childAccountId": null,
      "bundleId": null,
      "subscriptionId": null,
      "planName": null,
      "phaseName": null,
      "usageName": null,
      "itemType": "CBA_ADJ",
      "description": "Adjustment (account credit)",
      "startDate": "2018-01-24",
      "endDate": "2018-01-24",
      "amount": 5008.84,
      "currency": "USD",
      "childItems": null,
      "auditLogs": null
    }
  ],
  "isParentInvoice": false,
  "auditLogs": null
}

Usage Billing

Usage Invoice Items

As described in the section Usage Billing, Kill Bill supports invoicing customers based on different usage type. The usage billing is always done on a per subscription level and for a given billing period; in addition, if the active Plan associated with the subscription contains multiple usage sections, each usage section is billed independently: As a result, we may see one or several USAGE invoice items per invoice, each associated with a given subscription, usage section and billing period.

So regarless of the usage type the following basic fields will always be seen:

  • planName: The name of the Plan in the catalog

  • phaseName: The name of the PlanPhase in the catalog

  • subscriptionId: The ID of the subscription

  • usageName: The name of the usage section in the catalog

  • startDate: The start date for the period being invoiced

  • endDate: The end date for the period being invoiced

In addition, depending on the usage type for the usage section (e.g CONSUMABLE), and depending on the configuration of the system, we will see additional information.

Capacity In Arrear Mode

For each capacity in arrear usage section, we will see some json in the field itemDetails, to provide additional information:

{
  "tierDetails": [
    {
      "tier": 2,
      "tierUnit": "bandwith-meg-sec",
      "tierPrice": 10,
      "quantity": 200
    },
    {
      "tier": 3,
      "tierUnit": "members",
      "tierPrice": 100,
      "quantity": 60
    }
  ],
  "amount": 100
}

In this example we see that we were invoiced for 2 different units, and this shows the tier details for each unit, and the amount that will be charged. Note that because unit members reached tier 3, in the capacity in arrear model, the amount will be based on the pricing for this tier.

Consumable In Arrear Mode

In this mode, we are going through each tier level to compute the price based on the tier price and quantity. As described prevously, we support both ALL_TIER and TOP_TIER TierBlockPolicy.

We can configure the invoicing system to output one item per tier, or one aggregate item for all tiers. The section below will consider a use case of ALL_TIER policy, but the idea between aggregate or detail mode remains the same.

Agrregate Mode

In the aggregate mode, we will see one USAGE item with the aggregate amount across unit and tiers. The itemDetails json will summarize the usage on a per tier basis and per unit basis:

{
  "tierDetails": [
    {
      "tier": 1,
      "tierUnit": "cell-phone-minutes",
      "tierPrice": 2,
      "tierBlockSize": 1,
      "quantity": 20,
      "amount": 40
    },
    {
      "tier": 2,
      "tierUnit": "cell-phone-minutes",
      "tierPrice": 20,
      "tierBlockSize": 1,
      "quantity": 100,
      "amount": 2000
    },
    {
      "tier": 1,
      "tierUnit": "Mbytes",
      "tierPrice": 10,
      "tierBlockSize": 1,
      "quantity": 10,
      "amount": 100
    }
  ],
  "amount": 2140
}

In this example, we see that we billed for two units cell-phone-minutes and Mbytes: For the cell-phone-minutes, the quantity recorded for the period was such, that we reached the maxium for tier 1 and started to bill some units for tier 2; for the Mbytes units, we billed everything in the tier 1. The amount reported is the sum of the amount : 40 + 2000 + 100 = 2140.

Detail Mode

Sometimes it is desirable to output one USAGE item per unit type and tier, so in this case the detail for the billing is inside each invoice item — and the aggregate amount is computed by summing the sum amount. In order to activate this mode, one needs to set the system property org.killbill.invoice.item.result.behavior.mode to DETAIL.

Each of the USAGE item will contain the following fields:

  • quantity: Quantity consumed for the unit (type) and on the given tier

  • rate: We reused the rate field normally reserved for RECURING type to output the price of the tier

Also, the itemDetails json field will provide some additional details:

{
  "tier": 1,
  "tierUnit": "cell-phone-minutes",
  "tierPrice": 2,
  "tierBlockSize": 1,
  "quantity": 20,
  "amount": 40
}

Past Usage Periods

By default the system is configured to look at the past 2 billing periods, but this can be changed by using the configuration org.killbill.invoice.readMaxRawUsagePreviousPeriod (default=2). Let’s assume a MONTHLY subscription that was invoiced for the following periods:

  • 2018-01-01 - 2018-02-01

  • 2018-02-01 - 2018-03-01

  • 2018-03-01 - 2018-04-01

On 2018-05-01, the system will by default look to invoice for the period 2018-04-01 - 2018-05-01, but it will also recompute items for the past 2 periods, 2018-03-01 - 2018-04-01 and 2018-02-01 - 2018-03-01.

Late Usage Data:

If for some reason, there is some late usage reported in these past 2 periods, the system will include this delta. Depending on the type of usage and mode (e.g AGGREGATE) we will see one or several USAGE item for this period to reflect such additional charge. If the late usage is older than these past 2 periods, it is simply ignored.

Missing Usage Data:

Currently it is considered an error to delete past usage data in these past 2 periods, the invoicing system would throw an error and prevent invoicing to happen correctly. If the late missing data is older than these past 2 periods, it is simply ignored.

One can set the system property — or per-tenant config — org.killbill.invoice.readMaxRawUsagePreviousPeriod to 0 to ignore any past data — late usage or missing data.

Invoice Payments

Payments can be made against existing invoices, either automatically by the system or manually by leveraging our apis. Kill Bill allows to have multiple partial payments against a given invoice, but the reverse — i.e one payment spanning multiple invoices is not (yet) supported.

One Payment against one invoice is the default model, and this happens automatically by the system provided the customer Account has a valid default payment method - in which case it used to make the payment. However, one can customize the system on a per Account level to disable this behavior, using the following mechanisms:

  • Account does not have a default payment method — the system will abort the payment.

  • Account has been tagged with one of the following:

    • AUTO_PAY_OFF: Prevent system from making automatic payments

    • MANUAL_PAY: Prevent system from making automatic payments and we expect those payments to happen outside of the Kill Bill system — e.g checks.

Anytime an Account has a positive balance, i.e. at least one Invoice was not (partially) paid, one can use our apis to issue a manual payment against such invoice. Based on what we said earlier, such situation can occur if the system was configured to not make payments or in cases where a payment was issued but failed.

The call below illustrates how to make such a payment — against an existing unpaid invoice 99f91a42-a83f-4d59-b337-9df1b53f79b1:

curl -v \
-u admin:password \
-H "Content-Type: application/json" \
-H "X-Killbill-ApiKey: bob" \
-H "X-Killbill-ApiSecret: lazar" \
-H 'X-Killbill-CreatedBy: demo' \
-X POST \
--data-binary '{
    "accountId":  "27cf01b3-ee14-4d7f-a63a-16ad632b7bbb",
    "paymentMethodId":  "7cb5362a-ca9a-4ae0-9623-381201ded137",
    "targetInvoiceId":  "99f91a42-a83f-4d59-b337-9df1b53f79b1",
    "purchasedAmount": 200.0
}' \
'http://127.0.0.1:8080/1.0/kb/invoices/99f91a42-a83f-4d59-b337-9df1b53f79b1/payments'

Kill Bill keeps track of the mapping between invoice and payments, in such a way that it can correctly compute the invoice balance — and also return the payment details associated with a given invoice. Such mapping, InvoicePayment, is logically part of the invoice subsystem, and is returned when one fetches invoices. There exists 3 types of InvoicePayment as described below:

If an invoice doesn’t have any corresponding row in invoice payment, this means the invoice isn’t paid (either because no payment was ever attempted, or the payment attempts weren’t successful).

A successful payment against an invoice would have a single row (of type ATTEMPT):

Invoice #TypePayment dateAmount

1029

ATTEMPT

2013-04-12 22:45:39

$20

Refund

Here is how a payment, followed by a refund would look like:

Invoice #TypePayment dateAmount

1029

ATTEMPT

2013-04-12 22:45:39

$20

1029

REFUND

2013-04-18 10:23:11

$-20

Chargeback

Here is how a payment, followed by a chargeback would look like:

Invoice #TypePayment dateAmount

1029

ATTEMPT

2013-04-12 22:45:39

$20

1029

CHARGED_BACK

2013-04-18 10:23:11

$-20

Payment

Overview

Kill Bill provides a core payment system, that is used in the subscription billing use case to issue payment requests against the generated invoices.

In order to accomodate for that use case, the payment logic has been split into two pieces:

First, there is a core payment system whose role is to manage the payment states, and route the operation to the correct payment plugin, which in turn interracts with the third party payment gateway. This core payment system is not specific to the subscription billing use case, and can actually be used as a standalone system to provide a layer in front of various payment gateways. For an overview of the payment system in Kill Bill, please check the payment guide.

In order to support the subscription billing use case, and issue payments against existing invoices, there is a payment control plugin embedded into Kill Bill core — see payment control plugin guide-- whose role is to provide the necessary logic to map the payments with the invoice:

  • The plugin is called prior the payment system attempts to make the payment call to provide the necessary sanity, such as verifying the invoice balance, whether the Account was tagged as AUTO_PAY_OFF, …​ and finally interract with the invoicing system to record the payment attempts.

  • The plugin is then called after the payment attempt to update the invoicing system about success/failure:

    • In the case of success, this makes the invoice balance drops to zero.

    • In the the case of failure, this provides the plugin with the opportunity to schedule a payment retry

Note: The plugin linking the payment view to the invoice view has not been implemented as a standalone plugin, but instead it is part of the core Kill Bill source code. However, it implements the PaymentControlPluginApi so logically it acts as such. It is possible to extend/change the behavior of such plugin by registering a standalone payment control plugin that would override the behavior of that default plugin, but this should only be used for advanced use case and extra caution would be required to not break the contract between the invoicing and payment system.

Payment Methods

A PaymentMethod represents an abstraction to identify a way of making payments for a specific Account. Each consumer Account can have several payment methods to allow making payments using different schemes — credit cards, debit cards, paypal,…​ In order to allow the system to automatically make payments against unpaid invoices, one must specify a default payment method.

The payment method really has two functions:

  • In the default use case, it allows the system to properly route the payment to the right Kill Bill plugin — and its associated third party payment gateway. Note however that the static configuration between the payment instrument — e.g the customer credit card — and the plugin can be overriden in a payment control plugin to provide payment routing capabilities.

  • It allows to track enough details to make the payment. For instance in the use case of a credit card, the system would keep track of a credit card token that can be used to issue the payment. Often, some of this information is stored inside the payment plugin.

Kill Bill also allows to configure a special payment method, called external payment method, to allow recording payments that occured outside of the system. A typical use case is the one where a customer was invoiced through Kill Bill, and later makes payment by check: The payment needs to be recorded into the system to mark the invoice as being paid — and brings its balance to zero.

One would typically create a default external payment method the following way, and later could use the returned paymentMethodId to issue external payments against invoices — see Invoice Payment section.

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 '{"pluginName":"__EXTERNAL_PAYMENT__","pluginInfo":{}}' \
     "http://127.0.0.1:8080/1.0/kb/accounts/268983f2-5443-47e4-a967-b8962fc699c5/paymentMethods?isDefault=true"

Payment Retries

Upon payment failure, the plugin may attempt a payment retry: There are 2 system properties, that will control the payment retry mechanism:

  • Upon PAYMENT_FAILURE — when the payment plugin returns a ERROR status --, the payment system will look at the property org.killbill.payment.retry.days, and possibly schedule some retries based on that value. By default, this property is set with a default value of 8,8,8, which means that a first retry would happen 8 days after the intial failure, and then if the first retry attempt failed, another attempt would be scheduled 8 days later and then finally a last one 8 days later. If last attempt fails, then payment remains in that state.

  • Upon PLUGIN_FAILURE — when the payment plugin returns a CANCELED status --, the payment system will look at the property org.killbill.payment.failure.retry.start.sec, and possibly schedule some retries based on that value. By default, this property is set with a default value of 300, which means that the payment would be scheduled to be retried one time 300 seconds — or 5 minutes — after the failure. PLUGIN_FAILURE are often linked to transient errors from third party gateway and so it often make sense to retry those fairly soon after the initial failure was seen, but of course this all depends on use case.

Payment retries in Kill Bill are implemented as payment transaction retries: For each retry attempt, the system will create a new PaymentTransaction associated with the same Payment object. Since the paymentMethodId is defined at the Payment level, it means that the same paymentMethodId will be used for each retry. If the goal is to retry with a new payment method, then one needs to create a new Payment associated with the different payment method. If there are ongoing retries scheduled, it is possible to cancel those but this is more for cleanliness, because once a payment has been successful, any other retry would be aborted — the system ensures that there cannot be any double payment.

Overdue

Overview

Kill Bill offers an Overdue (or also referred to as Dunning) feature, which is required for when users don’t pay their bills. In those cases, the merchant needs to take some action and so the feature must be customizable. Note that the Entitlement and Overdue modules in Kill Bill are tied to each other and are there to manage the customer experience with regards to her subscription(s):

  • The Entitlement module defines the behavior of the system when the user starts, cancels a subscription or makes some change in an existing subscription. It controls the level of service received by the user (from no service at all to full service) after such an operation occured.

  • The Overdue module is in charge of altering the customer experience when payments are not met, and that potentially includes some degradation or even cancelation of the service. The overdue state is defined at the account level, which means that if a user has multiple subscriptions, and an invoice associated with one of them has not been paid, the behavior of the system with regard to the overdue state will be global for all subscriptions.

The Overdue module in Kill Bill relies on a configuration file which drives its behavior. The file is specifed through the use of the org.killbill.overdue.uri system property. The Overdue module listens to payment events and then, based on the configuration it transitions the overdue state for an account to the appropriate state. Whether the payment was a failure or not, the Overdue module will recompute the state associated with the account and potentially make the transition to another state.

Configuration

The overdue configuration contains a list of the various states through which a customer who does not pay will go through. Each state has a name and a condition which is evaluated by the Overdue module. Currently the condition to transition to a given state is based on the properties below, and the system will evaluate to true if all the part of the conditions are true:

  • numberOfUnpaidInvoicesEqualsOrExceeds

  • totalUnpaidInvoiceBalanceEqualsOrExceeds

  • timeSinceEarliestUnpaidInvoiceEqualsOrExceeds

  • responseForLastFailedPaymentIn: (Not implemented)

  • controlTagInclusion

  • controlTagExclusion

Additionally, the definition of an overdue state will also specify some ways to alter the behavior of the system:

  • subscriptionCancellationPolicy: Whether or not to cancel the subscriptions associated with the account (and the cancellation policy that should be used). Choice is (NONE, IMMEDIATE, END_OF_TERM)

  • blockChanges: Specifies whether the customer is allowed to make any plan change on his subscriptions

  • disableEntitlementAndChangesBlocked : The name is a bit misleading; is specifies whether the subscriptions are being paused, which means service (entitlement) will be disabled and billing will also be disabled. If the overdue state clears, both entitlement and billing would resume at the time of the clearance.

One can add an externalMessage which can be retrieved by plugins listening to Overdue events, and displayed to the user.

Finally there is an additional property autoReevaluationInterval that tell the system when to re-evaluate the state when nothing happens in the system: When an account transition to one of the overdue state — specified by the xml file (overdue.xml), two things can happen:

  1. The user makes a payment OR the system retries previously failed payments

  2. No payment attempt is being made

In the first case, the Overdue system will detect a payment occurred and it will recompute the state, transitioning the a new state if required. In the second case, however, since there was no trigger, we need a way to tell the overdue system to re-evaluate the state every so often so it can advance into the next state if required. That is what the autoReevaluationInterval property is about.

If you need an xsd file, you can find one here or generate one using the overdue xsd-tool:

curl -O 'http://search.maven.org/remotecontent?filepath=org/kill-bill/billing/killbill-overdue/x.y.z/killbill-overdue-x.y.z-xsd-tool.jar'
java -jar killbill-overdue-*-xsd-tool.jar schema.xsd

Tags

Kill Bill offers the ability to tag resources (account, invoice, payment, subscription, …​) in the system. There are two main types of tags:

  • User tags: Those tags are not interpreted by the system; there are a convininent way for admins, third party system to annotate specific existing resources. For instance, the support team could tag account resource associated with specific customer to group them.

  • Control tags: Those tags are interpreted to modify the behavior of the system:

    • AUTO_PAY_OFF: This tag can only be associated to an account, and when set it means that the system will not attempt to trigger automatic payments after invoices have been generated. After this tag has been removed, the system will immediately attempt to issue the payments that were not made.

    • AUTO_INVOICING_OFF: This tag can only be associated to an account, and when set it means that the system will not attempt to invoice the customer. After this tag has been removed, the system will immediately attempt to issue invoice the account.

    • OVERDUE_ENFORCEMENT_OFF: This tag can only be associated to an account, and when set it means that the system will not attempt transition the account into an overdue state regardless of his potential failed payments. After this tag has been removed, the system will immediately recompute the current overdue state.

    • MANUAL_PAY: This tag can only be associated to an account, and when set it means that the system will not attempt to trigger automatic payments after invoices have been generated. The intent here is to have the customer make his payment outside of Kill Bill.

    • WRITTEN_OFF: This tag can only be associated to a specific invoice in such a way that it its balance is ignore by the system.

    • TEST: This tag can only be associated to an account, and it is used by analytics plugin so as to not be included set of accounts.

    • PARTNER: This tag can only be associated to an account, and it is used by analytics plugin so as to be interpreted differently.

Glossary

Account - An object representing a customer account. It contains details about the customer such as name, address, email address, phone number etc.

Bundle - A bundle is a collection of subscriptions associated with a single service instance. For example, I might have a base subscription for my phone plus an addon that gives me cheap international dialing. Because both Subscriptions are associated with the one phone, they are collected into a single bundle. An account may own several Bundles, each with one or more Subscriptions.

Catalog - Catalogs describes the set of Products, Plans, Price Lists and Rules that are being made availabel to customers. A catalog lets Kill Bill know what is being offered for sale and how much to charge for it.

Payment Method - Payment methods store the details required for Kill Bill to trigger a payment. They represent things like credit cards, debit cards, or Paypal accounts. Each account can have many Payment Methods and at most one Default Payment Method. Note that much of the representation of a Payment Method is plugin-specific and is actually stored by the Payment Plugin itself.

Plan - Plans are Catalog objects that define how a Product is to be paid for. They can have multiple phases (e.g. trial, discount, evergreen). The phase specifies the frequency of payment and the prices in multiple currencies. Each phase can have fixed and recurring prices associated with it. Each Product can have multiple Plans specifying different ways that the Product can be purchased (e.g. a monthly Plan and an annual Plan)

Price list - Price lists are collections of plans that might be associated with a particular program (e.g. an affiliate program or a discount program). A plan can be in many price lists. There must be a default price list that is used when no pricelist is specified. When a subscription changes plans, Catalog rules can be used to determine which Price list the new Plan should use.

Product - Products represent the product or service that the customer buys.

Subscription - A Subscription is a contract that associates an account with a plan and a specific start date. The subscription will trigger automated payments based on the terms of the plan.

Tag - Tags can be added to Accounts, Bundles or Subscriptions. There are two kinds of tags: System Tags and User Tags. System Tags can impact the behaviour of the system and include things like: AUTO_PAY_OFF or AUTO_BILLING_OFF. User Tags are informational only, and can be created through the admin UI. User Tags are used to identify collections of Users, Subscriptions or Bundles so that they can easily be found or reported on later.