Payment Forms

Including Pin.js in your website or web application allows you to accept card payments using your own form, without the need to send payment card details to your server.

Your customer’s web browser sends the payment card details securely and directly to Pin Payments. It gets back a token representing the card and sends it to your web server along with the purchase details. You can use the token to perform a charge against the card using the charges API.

Example

This example shows how to include the Pin.js script in your page, configure it with your publishable API key, and then capture the form submission event to convert the payment card details into a Pin Payments card token. When this is set up correctly, your customer’s web browser will submit the form with the Pin Payments card token—not the raw card details—to your server.

1. Include Pin.js

Place the following code in the head section of the web page containing your payment form:

<script src='https://cdn.pin.net.au/pin.v2.js'></script>

2. Create a payment form

The lack of name attributes on the card-related input elements prevents raw card details from being submitted to your server. To ensure that the form submits correctly, do not give any elements an ID or name of “submit”.

<form action='/url_to_your_server_to_create_charge' class='pin' method='post'>
  <div class='errors' style='display:none'>
    <h3></h3>
    <ul></ul>
  </div>
  <fieldset>
    <legend>Billing</legend>
    <!--
      The lack of 'name' attributes on these inputs prevents
      the browser from submitting them to your server
    -->
    <label for='address-line1'>Address 1</label>
    <input id='address-line1'>
    <label for='address-line2'>Address 2</label>
    <input id='address-line2'>
    <label for='address-city'>City</label>
    <input id='address-city'>
    <label for='address-state'>State</label>
    <input id='address-state'>
    <label for='address-postcode'>Postcode</label>
    <input id='address-postcode'>
    <label for='address-country'>Country</label>
    <input id='address-country'>
  </fieldset>
  <fieldset>
    <legend>Payment</legend>
    <!--
      The lack of 'name' attributes on these inputs prevents
      the browser from submitting them to your server
    -->
    <label for='cc-number'>Credit Card Number</label>
    <input id='cc-number' type='text'>
    <label for='cc-name'>Name on Card</label>
    <input id='cc-name' type='text'>
    <label for='cc-expiry-month'>Expiry Month</label>
    <input id='cc-expiry-month'>
    <label for='cc-expiry-year'>Expiry Year</label>
    <input id='cc-expiry-year'>
    <label for='cc-cvc'>CVC</label>
    <input id='cc-cvc'>
  </fieldset>
  <!--
    In order for the form to submit correctly, please be sure not
    to give any elements in the form an id or name of 'submit'.
  -->
  <input type='submit' value='Pay now'>
</form>

3. Add the submit handler

The submit handler prevents your customer’s browser from submitting the form in the usual way. It causes the browser to instead retrieve a card token from Pin Payments and then submit the form to your server with the card token, not the raw card details.

// 1. Wait for the page to load
$(function() {

  // 2. Create an API object with your publishable api key, and
  // specifying 'test' or 'live'.
  //
  // Be sure to use your live publishable key with the live api, and
  // your test publishable key with the test api.
  var pinApi = new Pin.Api('your publishable key', 'test');

  var form = $('form.pin'),
      submitButton = form.find(":submit"),
      errorContainer = form.find('.errors'),
      errorList = errorContainer.find('ul'),
      errorHeading = errorContainer.find('h3');

  // 3. Add a submit handler to the form which calls Pin.js to
  // retrieve a card token, and then add that token to the form and
  // submit the form to your server.
  form.submit(function(e) {
    e.preventDefault();

    // Clear previous errors
    errorList.empty();
    errorHeading.empty();
    errorContainer.hide();

    // Disable the submit button to prevent multiple clicks
    submitButton.attr({disabled: true});

    // Fetch details required for the createToken call to Pin Payments
    var card = {
      number:           $('#cc-number').val(),
      name:             $('#cc-name').val(),
      expiry_month:     $('#cc-expiry-month').val(),
      expiry_year:      $('#cc-expiry-year').val(),
      cvc:              $('#cc-cvc').val(),
      address_line1:    $('#address-line1').val(),
      address_line2:    $('#address-line2').val(),
      address_city:     $('#address-city').val(),
      address_state:    $('#address-state').val(),
      address_postcode: $('#address-postcode').val(),
      address_country:  $('#address-country').val()
    };

    // Request a token for the card from Pin Payments
    pinApi.createCardToken(card).then(handleSuccess, handleError).done();
  });

  function handleSuccess(card) {
    // Add the card token to the form
    //
    // Once you have the card token on your server you can use your
    // private key and Charges API to charge the credit card.
    $('<input>')
      .attr({type: 'hidden', name: 'card_token'})
      .val(card.token)
      .appendTo(form);

    // Resubmit the form to the server
    //
    // Only the card_token will be submitted to your server. The
    // browser ignores the original form inputs because they don't
    // have their 'name' attribute set.
    form.get(0).submit();
  }

  function handleError(response) {
    errorHeading.text(response.error_description);

    if (response.messages) {
      $.each(response.messages, function(index, paramError) {
        $('<li>')
          .text(paramError.param + ": " + paramError.message)
          .appendTo(errorList);
      });
    }

    errorContainer.show();

    // Re-enable the submit button
    submitButton.removeAttr('disabled');
  };
});

4. Handle the request on your server

Now you can use the card token with the Pin Payments API. For example, you can create a single charge with the charges API or create multiple charges over time with the customers API.

Note: This example above used jQuery, but you don't have to—Pin.js itself does not depend on any front-end library.