More Tutorials

3DS supported Braintree.js Integration with Chargebee APIs

Braintree
3D Secure
Product Catalog 1.0

Tutorial Scope

We will address the 3DS flow specifics of creating a subscription in Chargebee using Braintree’s Hosted Fields, integrated through Braintree.js and Chargebee APIs. We have also included the example code and Github links to it. This way, you can try out the tutorial with our mock checkout.

Braintree.js: Overview

Braintree.js is a JavaScript library, which is made accessible via APIs to tokenize customer information by collecting sensitive card data using customizable Braintree Hosted Fields. For further details, take a look at Braintree's documentation.

Steps: Overview

Here's a detailed set of steps on how the Braintree.js & Chargebee 3DS checkout flow works:

  • After the customer is led to the checkout page, a unique client token is embedded into the checkout page (this unique client token needs to be generated from the server using Braintree's SDK).
  • When the customer submits the payment form, Braintree encrypts the card information and returns it as a payment method nonce(temporary token).
  • This payment method nonce is then used to perform 3DS verification, which returns a 3DS-verified nonce.
  • The 3DS-verified nonce is then passed to Chargebee along with the other parameters, to create a subscription using the create subscription API.

Honey Comics - Demo Application

Honeycomics is Chargebee’s demo application. You can download its code and create the application to test out the flow mentioned in this tutorial.

Prerequisites

Before trying out this tutorial, you need to setup the following:

Client Side Implementation

Step 1: Build the checkout form

The client side implementation starts by building a form for users to sign up. The sample form we've used here contains fields for customer and card information.

The form snippet below shows customer detail fields. In this case the name attribute is set, and has to be passed to Chargebee demo application’s server.

braintree_js_3ds/checkout.htmlView full code
<div className="col-sm-6">
  <div className="form-group">
    <label for="customer[email]">Email</label>
    <input id="email" type="text" className="form-control" name="customer[email]" maxlength="50"
      data-rule-required="true" data-rule-email="true"
      data-msg-required="Please enter your email address"
      data-msg-email="Please enter a valid email address">
    <small for="customer[email]" className="text-danger"></small>
  </div>
</div>

Step 2: Integrate Braintree.js

Now that the form is built, integrate Braintree.js into the checkout form by adding it to the checkout page’s header tag.

braintree_js_3ds/checkout.htmlView full code
<script src="https://js.braintreegateway.com/web/3.29.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.29.0/js/three-d-secure.js"></script>
<script src="https://js.braintreegateway.com/web/3.29.0/js/hosted-fields.js"></script>

Step 3: Estimate Subscription amount

While loading the payment details collection page, call Chargebee’s Estimate API from your server to get the subscription amount.

The amount returned will be in sub-units(cents) and needs to be converted into units(euros). After that, send it to Braintree using the verifyCard function.

braintree_js_3ds/checkout.htmlView full code
var estimateamount;
fetch('/braintree-js-3ds/estimate', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    sub_plan_id: 'professional' // provide your plain id
  })
}).then(response => response.json()).then(function (responseJSON) {
  estimateamount = responseJSON.invoice_estimate.total;
  // convert the cents to actual amount since chargebee returns the amount in cents
  estimateamount =  estimateamount/100;
});

Step 4: Create client token from the server

A Client token has to be embedded into the checkout form. This token is unique and has to be generated from the server using Braintree's SDK.

braintree_js_3ds/checkout.htmlView full code
<script type="text/javascript">
  //Replace it with your key
  var clientToken = new braintree.api.Client({ clientToken : "<%= getBraintreeClientToken()%>"});
</script>

Step 5: Create components using Client token

Now that you have Client token on your side, create components for temporary nonce and 3DS verification using the code given below:

braintree_js_3ds/checkout.htmlView full code
function onClientCreate(err, client) {
        components.client = client;
        braintree.hostedFields.create({
            client: client,
            styles: {
                input: {
                    'font-size': '14px',
                    'font-family': 'monospace'
                }
            },
            fields: {
                number: {
                    selector: '#number',
                    placeholder: '4000 0000 0000 002'
                },
                cvv: {
                    selector: '#cvv',
                    placeholder: '123'
                },
                 expirationDate: {
                    selector: '#date',
                    placeholder: '01 / 20'
                }

            }
        }, onComponent('hostedFields'));
        braintree.threeDSecure.create({
            client: client,
            version: 2,
        }, onComponent('threeDSecure'));

    }
    function onComponent(name) {
        return function (err, component) {

            components[name] = component;

        }
    }

Step 6: Tokenization & Verification

After the customer clicks on submit, you need to send the card details to Braintree and create a temporary token using hostedFields.tokenize() function.

In the callback function, you will get the temporary token. Using the temporary token, send verifyCard() request to Braintree.

Braintree then performs 3DS verification for the card and will respond with the 3DS verified nonce if successful. This nonce can then be passed on to Chargebee’s create subscription API.

If the card issued does not support 3DS, verification will not happen and Braintree would return an unusable nonce(Not accepted by Chargebee APIs).

braintree_js_3ds/checkout.htmlView full code
components.hostedFields.tokenize(function (err, payload) {
  components.threeDSecure.verifyCard({
      amount: estimateamount,
      nonce: payload.nonce,
      addFrame: addFrame,
      removeFrame: removeFrame,
      onLookupComplete: function (data, next) {
          next();
      }
  }, function (err, payload) {

          if ($("input[name='braintreeToken']").length == 1) {
              $("input[name='braintreeToken']").val(payload.nonce);
          }
          else{
              form.append("<input type='hidden' name='braintreeToken' value='" + payload.nonce + "' />");
          }
          var options = {
            error: subscribeErrorHandler,
            success: subscribeResponseHandler,
            complete:  hideProcessing,
            contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
            dataType: 'json'
          };
          $(form).ajaxSubmit(options);
      });
});

Server Side Implementation

Setup Chargebee’s Client library

Download and import the client library of your choice. Then, configure the client library with Chargebee Test site and its full-access 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.

/**
 * 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"));

Creating a subscription

To create a subscription in Chargebee, the 3DS-verified nonce fetched earlier has to be passed along with the other POST parameters (from the checkout page's form submit event) using the create subscription API.

String planId = "professional"; // replace your plan id
Result result = Subscription.create()
    .planId(planId)
    .customerFirstName(request.getParameter("customer[first_name]"))
    .customerLastName(request.getParameter("customer[last_name"))
    .customerEmail(request.getParameter("customer[email]"))
    .customerPhone(request.getParameter("customer[phone]"))
    .paymentIntentGatewayAccountId("<braintree-gateway-account-id>")
    .paymentIntentGwToken(request.getParameter("braintreeToken"))
    .request();

Though the parameters have been validated at the client side, for additional security, we strongly recommend that you perform these validations on the server side as well.

For demonstrative purposes, we have skipped validating the parameters on the server's side.

Chargebee response:

  • Chargebee returns a success response in the JSON format which is wrapped in the form of a 'result' class by the client library.
  • In case of an error, Chargebee returns an error response which is an exception thrown by the client library.

In case of successful checkout, you can redirect the user to a simple '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.
  • 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.
  • 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. Exceptions are handled 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

When you're all set, test your integration with some test transactions. Here are some credit card numbers that you can use to test the application:

Visa 4000 0000 0000 0002
Mastercard 5555 5555 5555 4444
American Express 3782 822463 10005

For more test cards for testing different scenarios click here.

Was this tutorial helpful ?
Need more help?

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

support@chargebee.com