I’ve been trying to port over the web-payments-quickstart with card payments to fit into my Vue JS app for a while now and I keep running into the issue that the tokenization fails with an unknown error. I am certain the the Application ID and the Location ID are correct and the sandbox CDN is also imported in a script tag in the index.html file. Has anyone run into the same issue when trying to use Square payments with a JS framework?
Here’s my JS code:
<script>
// import axios from "axios"
import CONST from "../helpers/constants.vue"
export default {
name: 'payment',
data() {
return {
appId: 'sandbox-sq0idb-bub0FOKgPJgECKJ5OSrZPg',
locationId: 'LE56BBNQJRGDY',
payments: null,
card: null
}
},
async mounted() {
if (!window.Square) {
throw new Error('Square.js failed to load properly');
}
// Initialize Payment
try {
this.payments = window.Square.payments(this.appId, this.locationId);
// console.log(this.payments)
} catch {
const statusContainer = document.getElementById(
'payment-status-container'
);
statusContainer.className = 'missing-credentials';
statusContainer.style.visibility = 'visible';
return;
}
// Initialize Card
try {
this.card = await this.initializeCard(this.payments);
} catch (e) {
console.error('Initializing Card failed', e);
return;
}
// const cardButton = document.getElementById('card-button');
// cardButton.addEventListener('click', async function (event) {
// await this.handlePaymentMethodSubmission(event, this.card);
// });
},
methods: {
async initializeCard(payments) {
const card = await payments.card();
await card.attach('#card-container');
return card;
},
async createPayment(token) {
let locationId = this.locationId
const body = JSON.stringify({
locationId,
sourceId: token,
});
let url = CONST.URLS.ReservationUrls.CreatePayment(token,this.reservationCode);
const paymentResponse = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body,
});
if (paymentResponse.ok) {
return paymentResponse.json();
}
const errorBody = await paymentResponse.text();
throw new Error(errorBody);
},
async tokenize(paymentMethod) {
const tokenResult = await paymentMethod.tokenize();
if (tokenResult.status === 'OK') {
return tokenResult.token;
} else {
let errorMessage = `Tokenization failed with status: ${tokenResult.status}`;
if (tokenResult.errors) {
errorMessage += ` and errors: ${JSON.stringify(
tokenResult.errors
)}`;
}
throw new Error(tokenResult);
}
},
displayPaymentResults(status) {
const statusContainer = document.getElementById(
'payment-status-container'
);
if (status === 'SUCCESS') {
statusContainer.classList.remove('is-failure');
statusContainer.classList.add('is-success');
} else {
statusContainer.classList.remove('is-success');
statusContainer.classList.add('is-failure');
}
statusContainer.style.visibility = 'visible';
},
async handlePaymentMethodSubmission(paymentMethod) {
// event.preventDefault();
// console.log(paymentMethod)
const cardButton = document.getElementById('card-button');
try {
// disable the submit button as we await tokenization and make a payment request.
cardButton.disabled = true;
const token = await this.tokenize(paymentMethod);
const paymentResults = await createPayment(token);
this.displayPaymentResults('SUCCESS');
console.debug('Payment Success', paymentResults);
} catch (e) {
cardButton.disabled = false;
this.displayPaymentResults('FAILURE');
console.error(e.message);
}
}
}
}
</script>
And here is the corresponding HTML:
<template>
<div>
<form id="payment-form" @submit.prevent="this.handlePaymentMethodSubmission(this.card)">
<div id="card-container"></div>
<button id="card-button" type="submit">Pay $1.00</button>
</form>
<div id="payment-status-container"></div>
</div>
</template>