Implement an in-app checkout using an iframe based hosted payment page

Watch Video

Chargebee's embedded hosted page option is best suited if

  • You prefer your customers not to leave your site.
  • You do not want to handle the security and validation implications of designing your own payment form.
  • Your site is accessible via https protocol and have a proper certificate installed. Specifically the page that has the Chargebee's embedded hosted page should be accessible only via https.

The theme support   ensures that you carry over your branded website's design into the embedded payment form. Since it is 'hosted' at Chargebee, your servers don't handle any sensitive card information. This drastically reduces the security requirements, PCI compliance and more.

Honey Comics - Demo Application 

'Honey Comics', our demo application, is a fictitious online comic book store providing a subscription service for comics. We send comic books every week to subscribers. Users can sign up for a subscription from the website by providing their credit card information. Subscriptions have trial period and hence the subscriber is not charged immediately. Instead the subscription will remain in trial until the trial period is over. They will be charged automatically (by chargebee) at the end of the trial period.

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.
  • A plan with a trial period in your test site in Chargebee. You can setup the plan using the "Setup Configuration" option in the index page if you have downloaded code and started the tutorials locally.
  • 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.

Build the signup page 

In the demo we are using a two step checkout process. We get the account information in first step. We try to follow the "curl" parameter naming convention of Chargebee for input names as it is easier to pass information to Chargebee and also handle the errors.
A sample input element is shown below

  • php
  • Ruby
  • Java
  checkout_iframe/signup.html  -   View full code
<div class="form-group">
    <label for="customer[first_name]">First Name</label>
    <input type="text" class="form-control" name="customer[first_name]" 
           maxlength="50" required data-msg-required="cannot be blank">
    <small for="customer[first_name]" class="text-danger"></small>
</div>

Request a hosted page URL 

When user clicks the "Proceed to Payment" option, we submit the account information via ajax to the server.

  • php
  • Ruby
  • Java
  checkout_iframe/signup.html  -   View full code
/* Doing ajax form submit of the form data.
 */
$("#subscribe-form").on("submit", function(e) {
   if (!$(this).valid()) {
         return false;
   }
   var options = {
         beforeSend: showProcessing,
         error: subscribeErrorHandler, 
         success: subscribeResponseHandler, 
         contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
         dataType: 'json'
   };
   $(this).ajaxSubmit(options);
   return false;
})

In the server side we use the Chargebee's checkout new subscription API . We specify the iframe messaging parameter to be true.

The response  contains the hosted page url and id which we send as a json response back to client.

Embedding hosted page 

For embedding the hosted page we first need to include Chargebee Js. Chargebee Js takes care of the communicating with the hosted page within the iframe.

  • php
  • Ruby
  • Java
  checkout_iframe/signup.html  -   View full code
<script type="text/javascript" src="https://js.chargebee.com/v1/chargebee.js">            
</script>

Option 1: Embed hosted page as iframe

One way of showing the checkout page is as a embedded iframe. The below code shows how.

  • php
  • Ruby
  • Java
  checkout_iframe/signup.html  -   View full code
function subscribeResponseEmbedHandler(response) {
     var hostedPageId = response.hosted_page_id;
     var customerContainer = $('#customer-info');
     var iframeContainer = $('#checkout-info');
     ChargeBee.embed(response.url, response.site_name).load({
        /*
         * This function will be called when iframe is created.
         * addIframe callback will recieve iframe as parameter.
         * you can use this iframe to add iframe to your page.
         * Loading image in container can also be showed in this callback.
         * Note: visiblity will be none for the iframe at this moment
         */
         addIframe: function(iframe) {
             iframeContainer.append(iframe);
         },

        /*
         * This function will be called once when iframe is loaded.
         * Since checkout pages are responsive you need to handle only height.
         */        
         onLoad: function(iframe, width, height) {
             hideProcessing();
             $(customerContainer).slideUp(1000);
             var style= 'border:none;overflow:hidden;width:100%;';                            
             style = style + 'height:' + height + 'px;';
             style = style + 'display:none;';//This is for slide down effect
             iframe.setAttribute('style', style);
             $(iframe).slideDown(1000);
         },

         /*
          * This will be triggered when any content of iframe is resized.
          */        
         onResize: function(iframe, width, height) {
             var style = 'border:none;overflow:hidden;width:100%;';
             style = style + 'height:' + height + 'px;';
             iframe.setAttribute('style',style);
         },

         /*
          * This will be triggered when checkout is complete.
          */        
         onSuccess: function(iframe) {
             redirectCall(hostedPageId);
         },

         /*
          * This will be triggered when user clicks on cancel button. 
          */
         onCancel: function(iframe) {
             $(iframe).slideDown(100,function (){
                 $(iframeContainer).empty();
                 $(customerContainer).slideDown(200);
             });
             $(".alert-danger").show().text("Payment Aborted !!");
         }
     });
}

Option 2: Embed hosted page as popup

The other way of showing the checkout page is as a popup. Chargebee supports bootstrap 3 based popup. If you already have bootstrap js included in your page, then you can use this. If you are not using bootstrap then you could use the previous iframe based embed to show it in your own popup.

You need to have a modal container as below. Note: The data-cb-modal-body attribute should be set to body on the element the checkout iframe has to be added.

  • php
  • Ruby
  • Java
  checkout_iframe/signup.html  -   View full code
<div class="modal fade" id="paymentModal" tabindex="-1" role="dialog" aria-labelledby="paymentModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content" style="max-width: 540px;">
            <div class="modal-header">
                <h4 class="modal-title text-center">
                    Payment Information
                </h4>
            </div>
            <!--add custom attribute data-cb-modal-body="body" to modal body -->
            <div class="modal-body"  data-cb-modal-body="body" style="padding-left: 0px;padding-right: 0px;">
            </div>
        </div> 
    </div>
</div> 

Then invoke the ChargeBee.bootStrapModal method passing the hosted page url, site name and the modal id.

  • php
  • Ruby
  • Java
  checkout_iframe/signup.html  -   View full code
function subscribeResponsePopupHandler(response) {
     var hostedPageId = response.hosted_page_id;
     $('.subscribe-process').show();

     ChargeBee.bootStrapModal(response.url, 
                      response.site_name, "paymentModal").load({

     /**
      * This function is called once the checkout form is loaded in the popup.
      */
     onLoad: function() {
         hideProcessing();
         $('.submit-btn').attr("disabled", "disabled");
      },

      /* This function will be called after subscribe button is clicked 
       * and checkout is completed in the iframe checkout page.
       */
      onSuccess: function() {
          redirectCall(hostedPageId);
      },

      /* This function will be called after cancel button is clicked in 
       * the iframe checkout page.
       */
      onCancel: function() {
          $(".alert-danger").show().text("Payment Aborted !!");
          $('.submit-btn').removeAttr("disabled");
      }
    });
 }

Implement the thank you page 

On success we redirect the page to our redirect page passing the hosted page id that we had previously sent along with the url.

  • php
  • Ruby
  • Java
  checkout_iframe/signup.html  -   View full code
function redirectCall(hostedPageId){
   window.location.href = "/checkout_iframe/redirect_handler?id=" 
       + encodeURIComponent(hostedPageId);

}

In the redirect we check for the hosted page status before proceeding to the thankyou page. This check is needed to avoid malicious users trying to hack your checkout process by changing the status to success even in the case of failure as browsers are under their control.

We use the 'id' parameter to get the details of the checkout using the retrieve a hosted page  API.

The response   will contain the complete details regarding the subscription. If required we can synchronize our database using this information.

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.

  • 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.

  • 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.