Skip to content

Instantly share code, notes, and snippets.

@xxswingxx
Last active March 1, 2019 09:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save xxswingxx/295f8f0b3b9c66e4e1e46b9dcaad5ab5 to your computer and use it in GitHub Desktop.
Save xxswingxx/295f8f0b3b9c66e4e1e46b9dcaad5ab5 to your computer and use it in GitHub Desktop.
Quaderno.js v2 reference (deprecated)

Quaderno.js v2 Reference (deprecated)

Quaderno.js is a simple javascript library that allows you to process payments, calculate sales taxes (VAT, GST, etc.) on the fly, and send beautiful tax receipts to your customers.

Note: For more help, take a look at our examples.

Including Quaderno.js

Add these script tags to your page to get started with Quaderno.js.

<script src="https://js.stripe.com/v2/"></script> <!--if you're using Stripe -->
<script src="https://js.braintreegateway.com/v2/braintree.js"></script> <!--if you're using Braintree --> 
<script src="https://js.quaderno.io/v2/"></script>

Form Attributes

You have to add some extra attribute to your payment form, so that Quaderno will be able to create a transaction in the back-end.

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

Required

Attribute Description
data-key Your Quaderno publishable key.
data-plan The ID of the plan your customer want to subscribe (only for subscriptions, except PayPal).
data-charge JWT with info about the charge (only for one-off charges and PayPal subscriptions). More info below.
Optional
Attribute Description
data-amount The total amount (in cents) that’s shown to the user.
data-taxes Specify if the taxes are  included or excluded in the amount. The default is excluded.
data-transaction-type Specify the transaction type ( eserviceebook or standard). The default is eservice.
data-gateway Specify the payment gateway you’re using ( stripebraintree, or paypal). The default is stripe.

One-Off Charge Info

If the transaction is a one-off charge, the  data-charge attribute MUST contain the following data in a  JWT string, encoded with your Quaderno private key:
Attribute Type Mandatory Description
iat Integer Yes Current UNIX timestamp. We use it to prevent the reuse of the generated JWT after 10 minutes.
amount Integer Yes Total amount of the transaction in cents.
currency String No Currency of the amount (3-letter  ISO code). The default is USD.
description String No Description of the transaction.
item_number String No Only for PayPal. Pass-through variable for you to track product or service purchased.
quantity Integer No Only for PayPal. The quantity of item included in the transaction. The default is 1.
transaction-type String No Specify the transaction type ( eserviceebook or standard). The default is eservice

Here’s an example in Ruby for a €5.90 charge:

JWT.encode({
  iat: Time.now.to_i,
  amount: 590,
  currency: 'EUR'
}, YOUR_QUADERNO_SECRET_KEY)

PayPal Subscriptions

If you want to create a PayPal subscription, the  data-charge attribute MUST contain the following data in a JWT string, encoded with your Quaderno private key:

Attribute Type Mandatory Description
iat Integer Yes Current UNIX timestamp. We use it to prevent the reuse of the generated JWT after 10 minutes.
amount Integer Yes Total amount of the transaction in cents.
currency String No Currency of the amount (3-letter  ISO code). The default is USD.
description String No Description of the transaction.
subscription_unit String No Specify the units of the subscription frequency ( DWMY). The default is M
subscription_duration Integer No Specify the subscription frequency. The default is 1.
recurring_duration Integer No Number of times that subscription payments recur. The default is infinity.

Here’s an example in Ruby for a $9.99 PayPal subscription that is renewed every 3 months:

JWT.encode({
  iat: Time.now.to_i,
  amount: 999,
  subscription_unit: 'M',
  subscription_duration: 3
}, YOUR_QUADERNO_SECRET_KEY)

Form Fields

In order to calculate the right taxes and create a proper invoice in Quaderno, it’s necessary to add some extra inputs. These inputs have a  data-quaderno attribute. It is mandatory to include at least the customer’s first name and country to prevent unexpected results.

Required

Value Description
first-name Customer’s first name.
country Customer’s country (2-letter  ISO code).
Optional
Value Description
last-name Customer’s last name. Necessary for exact tax calculation.
street-line-1 Billing street (1 of 2 fields).
street-line-2 Billing street (2 of 2 fields).
city Billing city.
region Billing region or state.
postal-code Billing postal code (ZIP). Necessary for exact tax calculation.
email Billing email address where we’ll send the receipt.
vat-number Billing VAT number. Necessary for exact tax calculation.
language Customer’s preferred language (2-letter  ISO code). The default is your account language.
coupon The code of the coupon to apply (only for subscriptions).
quantity The quantity you’d like to apply (only for subscriptions).

Processing the Transaction

Quaderno.createSubscription

Quaderno.createSubscription is an ajax function that creates a Stripe subscription on the server and sends a receipt to your customer. This guide explains this flow in more detail.

Quaderno.createSubscription({
  success: quadernoSuccessHandler(status, response),
  error: quadernoErrorHandler(status, response),
  complete: quadernoResponseHandler(status, response)
});

Quaderno.createCharge

Quaderno.createCharge is an ajax function that creates a Stripe one-off charge on the server and sends a receipt to your customer. This guide explains this flow in more detail.

Quaderno.createCharge({
  success: quadernoSuccessHandler(status, response),
  error: quadernoErrorHandler(status, response),
  complete: quadernoResponseHandler(status, response)
});

Extra Fields

If you use the  data-amount form attribute and want to show live tax calculations, you can add the classes quaderno-subtotalquaderno-taxes, and quaderno-total to any DOM element to modify its inner HTML. For example:

<span class="quaderno-subtotal"></span>
<span class="quaderno-taxes"></span>
<span class="quaderno-total"></span>

Handling the Responses

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 JWT string, encoded with your Quaderno private key, that contains the following data:

{
  customer: 'CUSTOMER_ID',
  transaction: 'TRANSACTION_ID',
  type: 'subscription or charge',
  gateway: 'stripe',
  original_charge: 'Original JWT (only for one-off charges)',
  iat: UNIX timestamp 
}

Advanced Usage

Quaderno.init

If you include the identifier  payment-form, Quaderno will associate the necessary callbacks to your form. Nevertheless if the form is not present in the DOM when the page is loaded or if you want to use a different selector you can do it by calling:

Quaderno.init('#custom-form-selector')

Quaderno.calculateTaxes

In order to refresh the taxes calculations when the form is modified, Quaderno will associate the event  change handler on the inputs with the following values for data-quadernocompany-namecountrypostal-codevat-number, and quantity.

If you want to force a taxes calculation or associate your custom events to a taxes calculation, you can do it like this:

Quaderno.calculateTaxes({
  success: function(statusCode, response) { ... },
  error: function(statusCode, response) { ... },
  complete: function(statusCode, response) { ... } 
});

Quaderno.readQuadernoTaxes

If you just want to check the values of the last calculated tax, you can always call do:

Quaderno.readQuadernoTaxes(); // =>; Object {name: "IVA", rate: 22, notes: null} 
Quaderno.readQuadernoTaxes().name; // =>; "IVA" 
Quaderno.readQuadernoTaxes().rate; // =>; 22

taxCalculated.Quaderno

The event taxCalculated.Quaderno is dispatched on the payment form when a tax is successfully calculated. It’s useful if you want to bind some custom actions to the automatic taxes calculations made by Quaderno.js.

// With plain JavaScript
document.getElementById("payment-form").addEventListener('taxCalculated.Quaderno', function(data){
  alert(data.detail.message) // "A tax has been calculated"
})  

// With JQuery
$('#payment-form').on('taxCalculated.Quaderno', function(data){
  alert(data.namespace + ": " + data.detail.message) // "Quaderno: A tax has been calculated" 
})

The data argument is a javascript object that contains the following data:

{
  detail: {
    tax: 'the calculated tax rate',
    message: 'a string with the event message'
  }
}

Examples

Check out the following examples to learn how to use Quaderno.js in your project:

Using Quaderno.js v2 for One-Off Charges (deprecated)

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 charge 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-charge="JWT_WITH_THE_CHARGE_DATA">

    <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 the 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 your page, or as a direct descendant of the <body> at the end of your page.

<form action="" method="POST" id="payment-form"
  data-key="YOUR_QUADERNO_PUBLISHABLE_KEY"
  data-charge="JWT_WITH_THE_CHARGE_DATA">
  ...
</form>

The key form attributes are:

  • data-key: your Quaderno publishable key.
  • data-charge: a JSON Web Token (JWT) encoded with your Quaderno private key that contains the following data:
    • amount: amount of the transaction in cents.
    • currency: currency of the amount (3-letter ISO code). The default is USD.
    • description: the statement you want to show on your receipt.
    • iat: current UNIX timestamp. We use it to prevent the reuse of the generated JWT after 10 minutes.

You can get all your keys under  Settings > API in your account page.

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 charge 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.createCharge({
    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.createCharge.

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

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

  • success: if Quaderno manages to create the charge with no errors at all.
  • error: if any error prevents from creating the charge.
  • 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_CHARGE_ID',
  type: 'charge',
  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.

Using Quaderno.js for Subscriptions (deprecated)

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment