More Tutorials

Metered Billing Using Webhooks With the Invoice API

Metered Billing
Product Catalog 1.0

Metered billing in Chargebee can be used if you need to bill the same customer varying amounts for every billing period based on usage. See the docs for more details.

Overview

How does it work?

If metered billing is enabled Chargebee will create an event invoice_created (see Event types) when one of these 2 conditions occur:

  • Subscription Renewal.
  • Plan changes (upgrade/downgrade or quantity changes) in the subscription.

You will receive generated invoices via webhooks in your webhook handler, and after receiving the invoice, you can use the ID of the invoice resource to add the usage charges to the invoice received.

Note: For the first invoice for a subscription, the invoice will not be moved to pending state but rather it will be collected immediately. For example, the invoice created during signup or during activation (incase of trial) will be collected immediately.

What are Webhooks?

Webhooks are a great way of being notified of changes that occur within your billing system. Once configured, Chargebee will notify your service whenever a event occurs. View the documentation for further details.

Prerequisites

To try out the tutorial yourself, you'll need the following:

Setup the Chargebee client library

You have to download and import the client library of our choice. Then, configure the client library with your test site and its api key.

For the tutorial, we have configured the site and the credentials in a separate properties file. When the webapp is initialized, the client library gets configured.

EnvInitializer.javaView full code
/**
  * The credentials are stored in a properties file under WEB-INF
  * The live site api keys should be stored securely. It should preferably
  * be stored only in the production machine(s) and not hard coded
  * in code or checked into a version control system by mistake.
  */
Properties credentials = read("WEB-INF/ChargeBeeCredentials.properties");
Environment.configure(credentials.getProperty("site"), credentials.getProperty("api_key"));

Enable metered billing

To enable metered billing, login to the admin console, go to Settings > Site Info, enable “Notify for Pending Invoices” and click on “Update Site Info”. Once this is done, you are all set.

Listening to events

Chargebee calls the configured webhook url with the event details sent as json in the request body. First we need to parse it to obtain the event.

WebhookHandler.javaView full code
/*
* Getting the json content from the request.
*/
BufferedReader reader = request.getReader();

/* 
* Assigning the recieved content to ChargeBee Event object.
*/
Event event = new Event(reader);

Then we check if the event is of type invoice_created.

WebhookHandler.javaView full code
/*
* Checking the event type as Pending Invoice Created to add Charge for Meter Billing.
*/
EventType eventType = event.eventType();
if (EventType.PENDING_INVOICE_CREATED.equals(eventType)) {
    String invoiceId = event.content().invoice().id();
    Invoice invoice = Invoice.retrieve(invoiceId).request().invoice();
    if( invoice.status().equals(Invoice.Status.PENDING) ) { 
        new MeterBilling().closePendingInvoice(invoice);
        response.getWriter().write("Invoice has been closed successfully");
    } else {
        response.getWriter().write("Invoice is not in pending state");
    }
}

Adding usage charges

We get the details from the invoice received from webhook.

MeterBilling.javaView full code
String invoiceId = invoiceObj.id();
String subscriptionId = invoiceObj.subscriptionId();

Timestamp invoiceDate = invoiceObj.date();

We then add a unmodeled charge to the invoice for the time period via add charge to pending invoice api

MeterBilling.javaView full code
int chargeInCents = getUsageCharge(invoiceDate, subscriptionId);

/*
* Calling ChargeBee Add Charge Invoice API and add Charge to invoice 
* based on the usage made by customer.
*/
Invoice.addCharge(invoiceId).amount(chargeInCents)
                        .description("monthly usage")
                        .request();

We also add a addon based charge using add addon to pending invoice api

MeterBilling.javaView full code
Integer addonQuantity = getQuantityUsed(invoiceDate, subscriptionId);

/* 
* Calling the ChargeBee Add Addon Charge Invoice API and add the no of 
* addons used by customers to the invoice.
*/  
Invoice.addAddonCharge(invoiceId).addonId("wallpapers")
        .addonQuantity(addonQuantity)
        .request();

Once done we invoke the close pending invoice api.

MeterBilling.javaView full code
/*
* Closing the invoice and Collecting the payment(if auto collection is on)
* by calling the ChargeBee Collect Invoice API.
*/
Invoice.close(invoiceId).request();

Note: Securing the webhook url

The webhook url needs to be secured either using Basic Authentication or via a secret parameter.

WebhookHandler.javaView full code
/**Check if the request is from chargebee. 
* You can secure the webhook either using
*   - Basic Authentication
*   - Or check for specific value in a parameter.
*<br/>
* For demo purpose we are using the second option though 
* basic auth is strongly preferred. Also store the key 
* securely in the server rather than hard coding in code.
*/
private static boolean checkIfRequestIsFromChargeBee(HttpServletRequest req,
        HttpServletResponse resp) throws IOException{
    if(!"DEMO_KEY".equals(req.getParameter("webhook_key"))){
        resp.sendError(HttpServletResponse.SC_FORBIDDEN,
                "webhook_key is not correct");
        return false;
    }
    return true;
}
Was this tutorial helpful ?
Need more help?

We're always happy to help you with any questions you might have!

support@chargebee.com