Implementing Square’s Payment Form in Reaction Commerce

Implementing Square’s Payment Form in Reaction Commerce

Get Square's payment form implemented in your Reaction Commerce App

Under the Payment Card Industry Data Security Standard (PCI-DSS), to process payments securely, you must minimize the amount of sensitive cardholder data that you handle. If you don’t, you could be vulnerable to a breach, lose your ability to process payments, or incur fines from your processor.

No payments = no money & no money = no business.

As soon as you accept, process, store, or transmit sensitive cardholder data, you become responsible for safeguarding that data. So how can you be sure that your customer’s data is secure? We know hackers are constantly innovating new ways to steal sensitive information. At Square, we provide PCI compliant products and services so you do not need to individually validate your state of compliance.

Square helps you avoid handling sensitive payment information altogether by providing the SqPaymentForm JavaScript library to allow safe handling of customer payment information. SqPaymentForm is a hosted JavaScript library that you load on your page and it helps generate an iframe form that safely captures a customer’s payment information. When the form is processed, it will generate a nonce which replaces sensitive cardholder details with a stand-in token. You can reference this token to process your customer’s payment and to perform other actions using Square’s APIs.

To give a demonstration around how to implement a secure payment form, I went ahead and implemented one using Reaction Commerce. For those unfamiliar, Reaction Commerce is an open source eCommerce platform that is built using Meteor. This lets us show ways of loading the payment form in a trickier environment that forces us to use a less straightforward implementation.

So with all of these descriptions out of the way, let’s actually dig into examples and walk through one way to implement SqPaymentForm inside of Reaction Commerce.

Normally, you need to include SqPaymentForm on the page where you want to process a customer’s payment using a script tag (usually this is on the checkout page).

<script type="text/javascript" src="https://js.squareup.com/v2/paymentform">
</script>

The above will work really well whenever you can simply use HTML tags to include your scripts. Unfortunately, we cannot use this approach for our implementation since Meteor has a unique templating system (Blaze) that makes including external scripts difficult. In order to guarantee that the SqPaymentForm object is accessible at checkout, we could add the script tag to the headers of the main HTML template. The problem with that is it just seems clunky to be including this script in the main HTML template and loading it for every page of the application when we only really need it for checkout.

The main problem with trying to include the script in the template for the checkout is that we cannot guarantee that Square’s payment form script has been loaded by the time we’re trying to instantiate the SqPaymentForm object. We can circumvent this using jQuery’s getScript() method since Reaction Commerce provides this for us, and we can guarantee we have loaded the script when we’re trying to use the SqPaymentForm object in our client-side script.

$.getScript("https://js.squareup.com/v2/paymentform").done(function () {
  paymentForm = new SqPaymentForm({
    // Setup your SqPaymentForm object, see https://docs.connect.squareup.com/payments/sqpaymentform/sqpaymentform-setup
    // for more details
  });
  // We're manually building the form here, since the page is already loaded and won't trigger the event SqPaymentForm
  // is expecting
  paymentForm.build();
});

You can see that we’re now gaining access to the SqPaymentForm object within the promise chain of the getScript() method. In my fork of Reaction Commerce, I had actually wrapped this all in a function so that it could be called again in case we needed to destroy the payment form and recreate it again (see more on this in the troubleshooting section of our tutorials here).

This should get us far enough that we can get the payment form to load and have the stylings that we want, but we’re still missing functionality around generating our nonce for processing the payment. The first step to this is triggering paymentForm to request a card nonce for us.

Template.squarePaymentForm.onRendered(function () {
  $(document).ready(function () {
    createPaymentForm();
  });
  $("#submitCard").on("click", function () {
    paymentForm.requestCardNonce();
  });
});

So here we’ve just added a listener on our submit button to intercept the submission so that we can trigger the requestCardNonce() method first. Once we have the nonce, we can then trigger the form to actually submit with the returned nonce placed in a hidden input field. SqPaymentForm provides us a callback to use for knowing when we’ve received the card nonce response, called cardNonceResponseReceived().

cardNonceResponseReceived: function(errors, nonce, cardData) {
  if (errors) {
    // Log errors from nonce generation to the Javascript console
    console.log("Encountered errors:");
    errors.forEach(function(error) {
      console.log("  " + error.message);
    });
    return;
  }
  console.log(cardData);
  console.log("nonce: %s", nonce);
  // Assign the nonce value to the hidden form field
  $("#card-nonce").val(nonce);
  $("#square-payment-form").submit();
}

We have very basic error logging here in case there was an issue generating or receiving the nonce, but then we resume or usual form submission process after injecting the nonce into our hidden nonce input field.

AutoForm.addHooks("square-payment-form", {
  onSubmit: function (doc) {
    submitting = true;
    const template = this.template;
    hidePaymentAlert();
    const form = {
      cardNonce: doc.nonce      // Here is where we're placing our nonce
    };
    Meteor.subscribe("Packages", Reaction.getShopId());
    const packageData = Packages.findOne({
      name: "square-paymentmethod",
      shopId: Reaction.getShopId()
    });
    Square.authorize(           
      form,                     // This is where we're passing the nonce back to the server
      {
        total: Cart.findOne().getTotal(),
        currency: Shops.findOne().currency
      },
      function (error, transaction) {
        // Omitted for brevity
      }
    );
    return false;
  },
  beginSubmit: function () {
    this.template.$(":input").attr("disabled", true);
    this.template.$("#btn-complete-order").text("Submitting ");
    return this.template.$("#btn-processing").removeClass("hidden");
  },
  endSubmit: function () {
    if (!submitting) {
      return uiEnd(this.template, "Complete your order");
    }
  },
  onSuccess: function () {
    paymentForm.destroy();       // To prevent issues if they decided to continue shopping, we destroy the form
  }
});

Since Reaction Commerce uses AutoForm for handling all of their form processing, I figured it would be better to try utilizing this to be more inline with how the platform is configured. AutoForm has a few lifecycle methods for handling the form submission, which is where we’ll be processing our nonce and passing it back to the server for processing. Within AutoForm, there is a onSubmit hook that we can use for processing everything.

The form values are passed into the onSubmit function through the doc variable, and we can use this for pulling out our nonce to send to the server. We also add in the paymentForm.destroy() after a successful processing, so that there aren’t any issues if they decide to continue shopping right after making their order.

Here is our final form loaded on the checkout page.Here is our final form loaded on the checkout page.

Now we have a successfully generated and processing payment form using SqPaymentForm! All that would be left to do is implement the back-end processes for processing the payment. This was just to be a quick run through of implementing the front-end of payment processing in a non-normal environment so that you can get the card nonce generated and sent to your back-end server.

You can check out my fork over at https://github.com/mootrichard/reaction to see all of it (it still only has the front-end forms setup to be working and still has some unnecessary logging). Please try it out for yourself, leave me a comment and let me know what you think about it. You can sign-up for your own Square developer account at https://connect.squareup.com/apps to get started and if you’re interested in learning more about Square’s developer platform then signup for our newsletter.

View More Articles ›