Nuxt is a fantastic front-end framework for building dynamic web apps. Square is a massively popular point of sale system used by small businesses.
When tasked with building a custom ecommerce solution for a company that already uses Square, wouldn’t it make sense if their website simply integrated into that on-the-ground system?
I think so, fortunately Square has built an array of libraries for us to use in building custom systems that can interface with their systems.
The stack
In this project, I was using Node on the back end and Nuxt on the front end. Simple enough, here are the two libraries I used:
Back-end: Square’s Node JS SDK (not covered in this article)
github.com/square/square-nodejs-sdk
Front-end: Square’s Web Payments SDK
developer.squareup.com/reference/sdks/web/payments
Bigger picture
How these two systems work together is mostly back-end heavy. Square’s Node JS SDK does many more things than you might need, but processing payments is one of them. This is handled on the back end to protect your API key.
However, you don’t really want to be sending card information back to the server. You definitely don’t want to be sending it back to your database. So instead that card information is handled on the front end, a one-time card nonce is generated on Square’s servers and sent back to your front end, which you will then send to your server to be processed by Node.
On the front end, Square’s Web Payment’s SDK is the tool we use to create that nonce.
Square’s Web Payments SDK
There wasn’t any good documentation out there for using Square’s Web Payments SDK (WP-SDK) with Nuxt specifically, so let’s run through how I got it to work.
Let’s take it as read that you have a working knowledge of Nuxt JS, you’ve got a vuex cart system which the customer has filled with products, and a form ready to receive your customer’s order information.
First, you’ll need to pull the WP-SDK code into your app as an external file. This is done in your nuxt.config.js, in the head:
nuxt.config.js
head: {
title: 'Your website title',
meta: [ ...meta tags ]
script: [
{
type: 'module',
src: 'https://sandbox.web.squarecdn.com/v1/square.js'
}
]
Notice the src link says sandbox… you’ll want to remove the word ‘sandbox’ before deploying to production.
Now, to build out the interface. You won’t actually be sending data to an API endpoint hosted by Square, at least not by hand, this is handled within the SDK you just imported, but Square’s WP-SDK needs a div to populate to build that form for the card.
Let’s create that, I placed mine below the customer info and right above the button that submits the order.
<div id="card-container"></div>
When Square’s library is initialized, Square will generate well designed inputs for card capturing and insert them into that div.
To initialize an instance of this card info form, you want it done before any activity on the page, so you’ll be working in Nuxt’s mounted() lifecycle hook, with async.
mounted: async function() {
const payments = Square.payments('Application_ID', 'Location_ID');
const card = await payments.card();
await card.attach('#card-container');
this.card = card
},
Replace Application_ID and Location_ID with your keys respectively. If you don’t have any, now is a good time to set them up on Square’s developer portal.
A few things are happening here:
- Square.payments is connecting to Square for the building blocks this is stored in the variable I’ve assigned as ‘payments’
- ‘payments’ now has access to the card() function, which builds the form
- This form is then attached to the div you created in your order form
- ‘this.card = card’ allows you to access the card component, it’s functions, and the nonce it will create from your methods hook
The form should look like this, below the ‘Payment info’ header and above the ‘Process Order’ button.
Oh, but ‘this.card’ has to be defined before mounted() happens in order for you to access its nonce data. Let’s do that:
data: () => ({
card: null,
...your other variables
})
So now you have a handle on that card component.
Once the customer has filled everything out perfectly, they’re going to hit the submit button. You need to obtain that nonce before all this order information is sent back to the server for payment processing.
To keep this agnostic to component frameworks, I’ll remove my error handling snackbar and everything, but I’ll leave axios in there.
Let’s just say you’ve got a button that calls a function named sendOrder() in your methods.
This button will generate the nonce, fail if there’s no nonce, and hit your endpoint if there is a nonce (along with all your other validated form data).
methods: {
sendOrder(){
// show some flair, start a loading indicator
this.card.tokenize().then(res => {
// if successful, card nonce is in res.token
this.yourOrderInfoObject.cnon = res.token;
if(res.token) {
// now that you're nonce'd up, send it
this.$axios.$post(`your back-end here`, {
body: this.yourOrderInfoObject
}).then(()=>{
// clear vuex cart here
// stop loading indicator here
// handle ui progression here
}).catch(error => {
// handle error here (failed on your back-end)
// stop loading indicator here
})
} else {
// no nonce
// handle error here
// stop loading indicator here
}
}).catch(error => {
// no nonce
// handle error here
// stop loading indicator here
});
}
}
This should be all you need. Still being in development, using Square’s sandbox, you’ll want to test it out using their test card values found here.
Now you’re able to get a nonce for your customer’s order, and send it back to your server to be processed.