Build your custom checkout form with dynamically changing order summary

Watch Video

In-app checkout page provides you with the flexibility to be able to provide a unique checkout experience for your users. The drawbacks are you need to ensure security. Also if you want to show a order summary , then you would have to do the various calculations (like tax , coupon support) etc.
Chargebee's Estimate API  allows you to dynamically update the order summary based on user selections without having to hard-code the prices or validate coupons.

Alternative options

The simplest way to setup your checkout process with Chargebee is by using the hosted payment pages  or the Hosted Pages + API  integration method. Chargebee's hosted pages are built using the Bootstrap themes.

Overview 

What is Estimate API?

Estimate api  allows you to calculate the 'invoice' that would be raised on completion of a operation such as creating a subscription  or updating a subscription . Using the returned estimate you could show a order summary. This allows you to dynamically update the order summary based on user selection. You can avoid hard-coding the prices or validating the coupon codes for updating it.

How do I use it?

Whenever a user selects an addon or applies a coupon you just need to call the estimate api  to get the line items for the order summary. Additionally if you want allow users to apply coupon codes, you should handle the coupon errors such as wrong code and show the message appropriately.

Honey Comics - Demo Application 

'Honey Comics', our demo application, is a fictitious online comic book store providing a subscription service for comics. We send physical comic books every month. In addition to comic books we sell wallpapers of the famous heros and also provide a option for users to opt for a e-book version of the comic to be sent along with comics.
The wallpapers and e-book are modeled as add-ons in Chargebee.


Prerequisites 

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

  • A Chargebee account. Signup for a free trial if you don't have one.
  • Create the following configuration in your Chargebee site. (Note: You can setup the plan and addons for the demo using the "Setup Configuration" option in the index page if you have downloaded code and started the tutorials locally).
    1. A plan  with id 'monthly' in your Chargebee Site.
    2. A 'On Off' addon  with id 'e-book' in Chargebee.
    3. A 'Quantity' type addon  with id 'wall-poster' in Chargebee.
  • Your Chargebee API key for your test site.

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.

For the tutorial, we have configured the site credentials in config/environments/development.rb

We setup the client library in config/initializers/chargebee.rb

For the tutorial, we have configured the site credentials in Config.php

Implementing the dynamic order summary using Estimate api 

Requesting updated order summary in client

We will start with the client side implementation. Whenever the user changes e-book option (or updates wallpaper quantity or applies a coupon) we will request the server for the updated order summary. We do this via javascript as shown below

  • php
  • Ruby
  • Java
  estimate.js  -   View full code
$('#order_summary').on('click', '#apply-coupon', function(e) {
    if ($('#coupon').val().trim() == '') {
        $('.error_msg').text("invalid coupon code");
        $('.error_msg').show();
    } else {
        sendAjaxRequest();
    }
})

$('#order_summary').on('click', '#remove-coupon', function(e) {
    $('#coupon').removeAttr("value");
    sendAjaxRequest();
})

$('.addons').on('change', '.wallposters-quantity', function(e) {
    sendAjaxRequest();
})

$('.addons').on('change', '.ebook', function(e) {
    sendAjaxRequest();
})

function sendAjaxRequest() {
    var wallpostersQuantity, ebook, coupon;
    if ($('.wallposters').is(":checked")) {
        wallpostersQuantity = $('.wallposters-quantity').val();
    }
    if ($('.ebook').is(':checked')) {
        ebook = "true";
    }
    if ($('#coupon').val().trim() != '') {
        coupon = $('#coupon').val().trim();
    }
    parameters = {"wallposters-quantity": wallpostersQuantity,
        "ebook": ebook,
        "coupon": coupon
    }
    orderSummaryAjaxHandler(parameters)
}

function orderSummaryAjaxHandler(dataContent) {
    $.ajax({
        url: "order_summary",
        data: dataContent,
        beforeSend: function(data, textstatus, jqXHR) {
            $('.text-danger').text('');
            $('.ajax-loader').show();
        },
        success: function(data, textstatus, jqXHR) {
            $('#order_summary').html(data);
        },
        error: function(data, textstatus, jqXHR) {
            try {
                var error = JSON.parse(data.responseText);
                $('.error_msg').text(error.error_msg);
            } catch (e) {
                $('.error_msg').text("Internal Server Error");
            }
            $('.error_msg').show();
        },
        complete: function() {
            $('.ajax-loader').hide();
        }

    });
}

Handling order summary requests in server

We will invoke the invoke the estimate api  with the various options selected by the user.

The response  contains the estimate based on the options. We use it to create our order summary snippet which we send back to client.

Implementing checkout. 

When user subscribes by providing card and other details we first validate the inputs in client for immediate feedback incase of error. We are using Stripe's client validation library  for the card related validations.

  • php
  • Ruby
  • Java
  estimate.js  -   View full code
var validatePaymentDetails = function(form) {
    var errorMap = {};
    if (!$.payment.validateCardNumber($('#card_no').val())) {   
        errorMap[$('#card_no').attr('name')] = 'invalid card number';
    }
    if (!$.payment.validateCardExpiry($('#expiry_month').val(),
            $('#expiry_year').val())) {
        errorMap[$('#expiry_month').attr('name')] = 'invalid expiry date';
    }
    if (!$.payment.validateCardCVC($('#cvc').val(), 
               $.payment.cardType($('#card_no').val()) ) ) {
        errorMap[$('#cvc').attr('name')] = 'invalid cvc number';
    }
    if(jQuery.isEmptyObject(errorMap)){
        return true;
    }else{
        $(form).validate().showErrors(errorMap);
        return false;
    }
};

On the server side we fill the parameters required for create subscription api .

We also add the addons and coupons based on the customer's input

We then invoke the api. The response  contains the subscription details which we could store in our db. We also update the shipping address via a separate api call  . At the end we forward the user to the 'thank you' page.

Validation and Error Handling

Here's how we validate user inputs and handle API call errors in this demo:

  • Client Side Validation: Chargebee uses jQuery form validation  plugin to check whether the user's field inputs(email, zip code and phone number) are valid or not.

  • Credit Card Validation: We use Stripe's client validation library  to validate credit card details.

  • Server Side Validation: As this is a demo application we have skipped the server side validation of all input parameters. But we recommend you to perform the validation at your end.

  • Coupon Errors: If a user enters a coupon that is invalid, expired, exhausted or not applicable to a given plan, Chargebee returns an error response  that contains the following attributes: api_error_code, param. Using these attributes you will be able to identify different coupon errors and display custom error messages.

  • Payment Errors: If a payment fails due to card verification or processing errors, Chargebee returns an error response  which is thrown as a payment exception by the client library. We handle the exceptions in the demo application with appropriate error messages.

  • General API Errors: Chargebee might return error responses due to various reasons such as invalid configuration, bad request etc. To identify specific reasons for all error responses you can check the API documentation . Also take a look at the error handler file to check how these errors can be handled.

Test cards 

Now that you're all set, why don't you test your integration with some test transactions. Here are some credit card numbers that you can use to test your application.

Valid Card
4111 1111 1111 1111
Verification Error Card
4119 8627 6033 8320
Transaction Error Card
4005 5192 0000 0004