Yes, that’s where the amount is set for the example.
Thanks! 2 more questions:
- Where do I find this key? idempotencyKey
- Where in the code do I insert this?
The idempotency_key
is generated when the page loads and is passed to the CreatePayment
call with the generated card token.
Thanks. I couldn’t find documentation on that. So, where in the code do I insert this payment module? This is my code. Is everything in the right place?
const payments = Square.payments('sandbox-sq0idb-Nuk92epp6btmsawLFjH-Wg', 'L1HB3S2965R0W');
const card = await payments.card();
await card.attach('#card-container');
const cardButton = document.getElementById('card-button');
cardButton.addEventListener('click', async () => {
const statusContainer = document.getElementById('payment-status-container');
try {
const result = await card.tokenize();
if (result.status === 'OK') {
console.log(`Payment token is ${result.token}`);
statusContainer.innerHTML = "Payment Successful";
try {
const response = await client.paymentsApi.createPayment({
sourceId: ‘cnon:card-nonce-ok’,
idempotencyKey: ‘{UNIQUE_KEY}’,
amountMoney: {
amount: 100,
currency: ‘USD’
}
});
console.log(response.result);
} catch(error) {
console.log(error);
}
window.location.href = "process1-action.cfm";
} else {
let errorMessage = `Tokenization failed with status: ${result.status}`;
if (result.errors) {
errorMessage += ` and errors: ${JSON.stringify(
result.errors
)}`;
}
throw new Error(errorMessage);
}
} catch (e) {
console.error(e);
statusContainer.innerHTML = "Payment Failed";
}
});
Thanks.
Our quickstart creates it and passes to the CreatePayment call already. It’s here in the quickstart.
I was using this script previously, but each time I run it, I get Payment Failed. It’s not working for me. The other script was working, FYI. Can you troubleshoot my script, please?
const appId = ‘sandbox-sq0idb-Nuk92epp6btmsawLFjH-Wg’;
const locationId = ‘L1HB3S2965R0W’;
async function initializeCard(payments) {
const card = await payments.card();
await card.attach('#card-container');
return card;
}
async function createPayment(token, verificationToken) {
const body = JSON.stringify({
locationId,
sourceId: token,
verificationToken,
idempotencyKey: window.crypto.randomUUID(),
});
const paymentResponse = await fetch('/payment', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body,
});
if (paymentResponse.ok) {
return paymentResponse.json();
}
const errorBody = await paymentResponse.text();
throw new Error(errorBody);
}
async function 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(errorMessage);
}
}
// Required in SCA Mandated Regions: Learn more at https://developer.squareup.com/docs/sca-overview
async function verifyBuyer(payments, token) {
const verificationDetails = {
amount: '1.00',
billingContact: {
givenName: 'John',
familyName: 'Doe',
email: '[email protected]',
phone: '3214563987',
addressLines: ['123 Main Street', 'Apartment 1'],
city: 'London',
state: 'LND',
countryCode: 'GB',
},
currencyCode: 'GBP',
intent: 'CHARGE',
};
const verificationResults = await payments.verifyBuyer(
token,
verificationDetails,
);
return verificationResults.token;
}
// status is either SUCCESS or FAILURE;
function 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';
}
document.addEventListener('DOMContentLoaded', async function () {
if (!window.Square) {
throw new Error('Square.js failed to load properly');
}
let payments;
try {
payments = window.Square.payments(appId, locationId);
} catch {
const statusContainer = document.getElementById(
'payment-status-container',
);
statusContainer.className = 'missing-credentials';
statusContainer.style.visibility = 'visible';
return;
}
let card;
try {
card = await initializeCard(payments);
} catch (e) {
console.error('Initializing Card failed', e);
return;
}
async function handlePaymentMethodSubmission(event, card) {
event.preventDefault();
try {
// disable the submit button as we await tokenization and make a payment request.
cardButton.disabled = true;
const token = await tokenize(card);
const verificationToken = await verifyBuyer(payments, token);
const paymentResults = await createPayment(
token,
verificationToken,
);
displayPaymentResults('SUCCESS');
console.debug('Payment Success', paymentResults);
} catch (e) {
cardButton.disabled = false;
displayPaymentResults('FAILURE');
console.error(e.message);
}
}
const cardButton = document.getElementById('card-button');
cardButton.addEventListener('click', async function (event) {
await handlePaymentMethodSubmission(event, card);
});
});
What example did you get to work? What you provided works for me.
This code worked, but I wasn’t sure where to put the payment code within this script:
const payments = Square.payments('sandbox-sq0idb-Nuk92epp6btmsawLFjH-Wg', 'L1HB3S2965R0W');
const card = await payments.card();
await card.attach('#card-container');
const cardButton = document.getElementById('card-button');
cardButton.addEventListener('click', async () => {
const statusContainer = document.getElementById('payment-status-container');
try {
const result = await card.tokenize();
if (result.status === 'OK') {
console.log(`Payment token is ${result.token}`);
statusContainer.innerHTML = "Payment Successful";
try {
const response = await client.paymentsApi.createPayment({
sourceId: ‘cnon:card-nonce-ok’,
idempotencyKey: ‘{UNIQUE_KEY}’,
amountMoney: {
amount: 100,
currency: ‘USD’
}
});
console.log(response.result);
} catch(error) {
console.log(error);
}
window.location.href = "process1-action.cfm";
} else {
let errorMessage = `Tokenization failed with status: ${result.status}`;
if (result.errors) {
errorMessage += ` and errors: ${JSON.stringify(
result.errors
)}`;
}
throw new Error(errorMessage);
}
} catch (e) {
console.error(e);
statusContainer.innerHTML = "Payment Failed";
}
});
You didn’t get a Payment Failed notice? This is the only error I get, nothing more.
This is what I was telling you last week. It says there is an error in the QuickStart Code at line 197.
You’ll have to have the CreatePayment
call in your server side code. The form is just for securely tokenizing the card. That token you’ll then pass with the idempotency_key
to your server to process the payment. You’ll need to have this code written in PHP, ASP, Ruby, Java, or similar on the back end. This is code that runs behind the scenes on your hosting provider.
We do not allow API calls directly from the browser. This would expose your API credentials, which would allow anyone to gain access to your Square account.
I have code that I found, but I don’t know where to put it. Where does the script go, and where does the server side code go? Nothing is clear to me that I am finding.
Thanks.
What backend language are you using?
ColdFusion. But, I can’t even get this code to run on the front-end without getting a Payment Failed error each time.
const appId = 'sandbox-sq0idb-Nuk92epp6btmsawLFjH-Wg';
const locationId = 'L1HB3S2965R0W';
async function initializeCard(payments) {
const card = await payments.card();
await card.attach('#card-container');
return card;
}
async function createPayment(token, verificationToken) {
const body = JSON.stringify({
locationId,
sourceId: token,
verificationToken,
idempotencyKey: window.crypto.randomUUID(),
});
const paymentResponse = await fetch('/payment', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body,
});
if (paymentResponse.ok) {
return paymentResponse.json();
}
const errorBody = await paymentResponse.text();
throw new Error(errorBody);
}
async function 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(errorMessage);
}
}
// Required in SCA Mandated Regions: Learn more at https://developer.squareup.com/docs/sca-overview
async function verifyBuyer(payments, token) {
const verificationDetails = {
amount: '1.00',
billingContact: {
givenName: 'John',
familyName: 'Doe',
email: '[email protected]',
phone: '3214563987',
addressLines: ['123 Main Street', 'Apartment 1'],
city: 'London',
state: 'LND',
countryCode: 'GB',
},
currencyCode: 'GBP',
intent: 'CHARGE',
};
const verificationResults = await payments.verifyBuyer(
token,
verificationDetails,
);
return verificationResults.token;
}
// status is either SUCCESS or FAILURE;
function 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';
}
document.addEventListener('DOMContentLoaded', async function () {
if (!window.Square) {
throw new Error('Square.js failed to load properly');
}
let payments;
try {
payments = window.Square.payments(appId, locationId);
} catch {
const statusContainer = document.getElementById(
'payment-status-container',
);
statusContainer.className = 'missing-credentials';
statusContainer.style.visibility = 'visible';
return;
}
let card;
try {
card = await initializeCard(payments);
} catch (e) {
console.error('Initializing Card failed', e);
return;
}
async function handlePaymentMethodSubmission(event, card) {
event.preventDefault();
try {
// disable the submit button as we await tokenization and make a payment request.
cardButton.disabled = true;
const token = await tokenize(card);
const verificationToken = await verifyBuyer(payments, token);
const paymentResults = await createPayment(
token,
verificationToken,
);
displayPaymentResults('SUCCESS');
console.debug('Payment Success', paymentResults);
window.location.href = "process1-action.cfm";
} catch (e) {
cardButton.disabled = false;
displayPaymentResults('FAILURE');
console.error(e.message);
}
}
const cardButton = document.getElementById('card-button');
cardButton.addEventListener('click', async function (event) {
await handlePaymentMethodSubmission(event, card);
});
});
I found this code online as a reference, but when I run it, I get errors. And it’s not showing all of the code that I copied and pasted. A bunch of the code is missing. I’m not sure how to show it to you if it’s not visible on screen.
Struct (ordered)
errors
Array
1
Struct (ordered)
category
string AUTHENTICATION_ERROR
code
string UNAUTHORIZED
detail
string This request could not be authorized.
<cfset params = {
“card_nonce” = “CBASEFO1lvpcxGS_FzAJQNrOuuwgAQ”,
“amount_money” = {
“amount” = 100,
“currency” = “USD”
},
“idempotency_key” = CreateUUID(),
“delay_capture” = false
}>
<cfif IsJson(response)>
This is the URL that contains the ColdFusion code. I couldn’t copy and paste it in a response to you. https://groups.google.com/g/cfpayment/c/iBZ8bvYfTIA
Is tokenize()
returning a nonce
?
I’m not sure. You can test it here. I have hard-coded a couple of pieces of code, not related to the Square code, so the session won’t expire.
https://mccroskeyonline.com/process.cfm
I’m not sure how to create or call the card nonce in this code:
<cfset params = {
“card_nonce” = “CBASEFO1lvpcxGS_FzAJQNrOuuwgAQ”,
“amount_money” = {
“amount” = 100,
“currency” = “USD”
},
“idempotency_key” = CreateUUID(),
“delay_capture” = false
}>
Yeah, it’s calling tokenize but it’s redirecting right after with the error. Why does it redirect so fast to that error page. Is your backend calling CreatePayment
and getting that error?
Where should the redirect then, if it’s in the wrong place? I put it right after the “Payment Successful” message. Where should it go?
const payments = Square.payments('sandbox-xxxxx-Nuk92xxxxxxtmsawLFjH-xx', 'L1HB3S2965R0W');
const card = await payments.card();
await card.attach('#card-container');
const cardButton = document.getElementById('card-button');
cardButton.addEventListener('click', async () => {
const statusContainer = document.getElementById('payment-status-container');
try {
const result = await card.tokenize();
if (result.status === 'OK') {
console.log(`Payment token is ${result.token}`);
statusContainer.innerHTML = "Payment Successful";
window.location.href = "process3.cfm";
} else {
let errorMessage = `Tokenization failed with status: ${result.status}`;
if (result.errors) {
errorMessage += ` and errors: ${JSON.stringify(
result.errors
)}`;
}
throw new Error(errorMessage);
}
} catch (e) {
console.error(e);
statusContainer.innerHTML = "Payment Failed";
}
});
The error page contains the server side ColdFusion code. That’s producing the error. In the example I found, the card_nonce is hard-coded, which is incorrect, but I’m not sure how to reference it.