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 client library 

We first have to download and import  the client library of our choice. Then we need to configure the client library with our test site and our test api key.

For the tutorials we have configured the site and the credentials in a properties file from which the client library is configured at the webapp is initialized.

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

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

For the tutorials we have configured the site credentials in Config.php which is included in other php files.

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: We use the jQuery form validation  plugin to check whether the user's input in fields(email, zip code and phone number) is 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 app 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 exception in this demo with appropriate error messages.

  • General API Errors: Chargebee might return error responses due to various reasons such as invalid configuration. To identify specific reasons for all error responses you can check the API documentation  and 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