Using Quaderno.js for Subscriptions

This guide helps you build your first checkout form to create a subscription on Stripe. If you need help, please email us to  support@quaderno.io.

Note: Quaderno.js also works for Braintree and PayPal. Take a look at  the specification page for more info.
At a high level, here’s what you’ll accomplish in this guide:
  1. Set up the form and collect billing information with Quaderno.js.
  2. Convert those details to a single-use token.
  3. Create a Stripe subscription via Quaderno and send the data to your server.

Before we get to the first step, let’s take a quick look at a typical checkout form. This is the part you can build with your web framework, or by hand in HTML.

<form action="" method="POST" id="payment-form" 
    data-key="YOUR_QUADERNO_PUBLISHABLE_KEY" 
    data-plan="YOUR_PLAN_ID">

  <span class="payment-errors"></span>

    <!-- Billing fields -->
    <fieldset>
      <legend>Billing Data</legend>
      <div class="form-row">
        <label>
          <span>* First Name</span>
          <input data-quaderno="first-name"/>
        </label>
      </div>

      <div class="form-row">
        <label>
          <span>Last Name</span>
          <input data-quaderno="last-name"/>
        </label>
      </div>

      <div class="form-row">
        <label>
          <span>Email</span>
          <input data-quaderno="email"/>
        </label>
      </div>

      <div class="form-row">
        <label>
          <span>* Country</span>
          <select data-quaderno="country">
          ...
          </select>
        </label>
      </div>

      <div class="form-row">
        <label>
          <span>VAT Number</span>
          <input data-quaderno="vat-number"/>
        </label>
      </div>
    </fieldset>

    <!-- Credit card fields -->
    <fieldset>
      <legend>Credit Card Data</legend>
      <div class="form-row">
	<div id="card-element" style="width:300px;"></div>
      </div>
    </fieldset>

    <button type="submit">Submit Payment</button>
</form>

Fairly standard. Note how input fields representing sensitive card data (number, CVC, expiration month and year) do not have a “name” attribute. This prevents them from hitting your server when the form is submitted. We’re also including a data-quaderno attribute on the relevant fields, which we’ll discuss later in the tutorial.

Step 1: Collecting billing information

First, include stripe.js and quaderno.js in your page:

<script src="https://js.stripe.com/v3/"></script>
<script src="https://js.quaderno.io/v2/"></script>

To prevent problems with some older browsers, we recommend putting the script tag in the  <head> tag of the page, or as a direct descendant of the <body> at the end of your page.

First notice you must add some extra data to your form:

  • data-key: your Quaderno publishable key. You can get it under Settings > API in your account page.
  • data-plan: the Stripe Plan Id.
<form action="" method="POST" id="payment-form"   
  data-key="YOUR_QUADERNO_PUBLISHABLE_KEY"   
  data-plan="YOUR_PLAN_ID">
...
</form>

In order to calculate the right taxes and create the contact on Quaderno, you also need to add the following inputs:

  • first-name (mandatory): the first name of your customer.
  • country (mandatory): the country where your customer is based.
  • postal-code (optional): Your customer's postal code.
  • vat-number (optional): the VAT number for EU customers.

Step 2: Create a single use token

Next, we will want to create a single-use token that can be used to represent the credit card information your customer enters. Note that you should not store or attempt to reuse single-use tokens. 

After the code we just added, in a separate script tag, we’ll add an event handler to our form. We want to capture the  submit event, and then use the credit card information to create a single-use token.

<script>
  var $form = $('#payment-form');
  var stripe = null;
  var elements = null;
  var card = null;

  jQuery(function($) {
    // initialize Stripe Elements
    $form.on('gatewayKeyRetrieved.Quaderno', function(e){
      stripe = Stripe($form.data('gateway-key'));
      elements = stripe.elements();
      card = elements.create('card', { hidePostalCode: true });
      card.mount('#card-element');

      // Handle errors
      card.addEventListener('change', function(event) {
        var $displayError = $('.payment-errors');
        if (event.error) {
          $displayError.html(event.error.message);
        } else {
          $displayError.html('');
        }
      });
    })
    
    // Tokenize the card
    $form.submit(function(event) {
      stripe.createToken(card, {
        address_country: $('#quaderno-countries').val()
      }).then(function(result) {
        if (result.error) {
          // Inform the customer that there was an error.
          $displayError = $('.payment-errors');
          $displayError.html(event.error.message);
        } else {
          // Send the token to Quaderno.
          stripeTokenHandler(result.token);
        }
      });

      // Prevent the form from submitting with the default action
      return false;
    });
  });
</script>

The important code to notice is the call to  stripe.createToken. The first argument is the card element containing credit card data entered by the user. It returns a Promise which resolves with a result object. This object has either:

  • result.token: a token was created successfully.
  • result.error: there was an error. This includes client-side validation errors.

The example above works as follows:

  • If the card information entered by the user returned an error, it gets displayed on the page.
  • If no errors were returned (i.e. a single-use token was created successfully), the handler invokes stripeTokenHandler.

You should provide at least the card number and expiration info. The complete list of fields you can provide and how the handler works are available in the  Stripe.js documentation.

Step 3: Create the Stripe subscription via Quaderno and send the data to your server

After retrieving the response in the promise from  stripe.createToken, you can create the charge via Quaderno in the stripeTokenHandler

The code would be:

function stripeTokenHandler(token) {
  $form = $('#payment-form');

  // Insert the token into the form so it gets submitted to the server
  $form.append($('<input type="hidden" data-quaderno="cardToken" />').val(token));
  Quaderno.createSubscription({
    success: quadernoSuccessHandler(status, response),
    error: quadernoErrorHandler(status, response)
  });
};

This handler just adds the returned token to the form in the cardToken field and then create a subscription via Quaderno by calling  Quaderno.createSubscription.

Please note it is  mandatory to create the input with the data-stripe=“cardToken” to make things work properly.

Quaderno.createSubscription is an ajax function and accepts as argument a Javascript object which should contains three possible handlers:

  • success: if Quaderno manages to create the subscription with no errors at all.
  • error: if any error prevents from creating the subscription.
  • complete: whether the response is a success or an error; in this case you’re responsible to manage the response status.

All the handlers accept two arguments:

  • status: the code of the request (200, 201, 401, etc.).
  • response: a Javascript object with the following structure:
{
  message: 'The message of the response as a string',
  details: 'A JWT string with information about the transaction'
}

The details attribute is a  JSON Web Token (JWT), encoded with your Quaderno private key (not your publishable key). It contains the following data:

{
  customer: 'STRIPE_CUSTOMER_ID',   
  transaction: 'STRIPE_SUBSCRIPTION_ID',   
  type: 'subscription',      
  gateway: 'stripe',   
  iat: UNIX timestamp 
}

As an example, the success handler code could be something like this:

function quadernoSuccessHandler(status, response) {
  $form = $('#payment-form');
  $form.append($('<input type="hidden" name="transactionDetails" />').val(response.details);
  $form.get(0).submit();
}

As you can see, the success handler is called creates an input with the transaction details and sends the form to your server. We call  submit() on the form directly, so that we don’t run into an infinite loop. The data will be sent as an HTTP POST to the URL in the form action.

The error handler code would be like this:

function quadernoErrorHandler(status, response) {
  $form = $('#payment-form');
  $form.find('button').prop('disabled', false);
  $form.find('.payment-errors').text(response.message);
}

In this case, the handler shows the error message and reactivate the payment button.

Take a look at the  full example form to see everything put together.

Still need help? Contact Us Contact Us