Error on 400 on verification

I’m encountering an error when trying to call the verifybuyer and a URL with error 400 is being logged on the console. Is this a known issue?

Scenario:

Request:
var card = new Card.Builder()
.CustomerId(“HG42J5D18QEVXYZCFZFQAG4FGC”)
.Build();

var body = new CreateCardRequest.Builder(
idempotencyKey: “34d9dda6-be9f-4426-8dfa-d9bd70927a9c”,
sourceId: “cnon:CBASEBjo43E4a1khCfDrs10mjZsoAg”,
card: card)
.VerificationToken(“verf:CA4SEHyUjH3ba_fJl7rxs8E24UUgACgC”)
.Build();

try
{
var result = await client.CardsApi.CreateCardAsync(body: body);
}
catch (ApiException e)
{
Console.WriteLine(“Failed to make the request”);
Console.WriteLine($“Response Code: {e.ResponseCode}”);
Console.WriteLine($“Exception: {e.Message}”);
}

Response:
{
“errors”: [
{
“category”: “PAYMENT_METHOD_ERROR”,
“code”: “CARD_DECLINED_VERIFICATION_REQUIRED”,
“detail”: “Card declined. A verification is required to process this payment. See Strong Customer Authentication for more information.”
}
]
}

:wave: I’m Square Dev AI, here to help answer your question!
Based on the information you’ve provided, the following documentation will help answer your question:

Additional Documentation

Cards API
Handling Errors
Handling Errors

If this documentation helped you find a solution, please check the box indicating that this reply solves the problem.
Otherwise one of our Developer Advocates will provide additional assistance shortly.

What test value are you using to get this error? Also have you seen our new payment flow that handles verifyBuyer for you? :slightly_smiling_face:

Hi Bryan,

Thank you for letting me know that there’s a new payment flow for tokenization. Unfortunately, I’m unable to follow the guide on the link as is.
It didn’t mention where tokenize() is coming from and what is the new URL for the square javascript source. If I use the code as is it will throw an error saying tokenize is undefined.
The square script source I’m using is https://sandbox.web.squarecdn.com/v1/square.js, please let me know if you have new script source for this new payment flow.

Do you have a sample code for this? I was following the code that was in the github web payments quickstart. The code in github is also failing with the same error message when testing with SCA.

Attached is the sample code as my test/POC code.

(Attachment Index.cshtml is missing)

The attachement was rejected here’s the script portion of the code:

const payments = Square.payments(‘sandbox-sq0idb-QPb20WLhVKbDwKQELlEX7w’, ‘LW5ZTGY0ZPR95’);
const card = await payments.card();

async function verifyBuyer(payments, token) {
const verificationDetails = {
amount: ‘1.00’,
/* collected from the buyer */
billingContact: {
addressLines: [‘123 Main Street’, ‘Apartment 1’],
familyName: ‘Doe’,
givenName: ‘John’,
email: ‘[email protected]’,
countryCode: ‘GB’,
phone: ‘3214563987’,
state: ‘LND’,
city: ‘London’,
},
currencyCode: ‘GBP’,
intent: ‘STORE’,
};

const verificationResults = await payments.verifyBuyer(
token,
verificationDetails
);
return verificationResults.token;
}

await card.attach(‘#card-container’);

card.addEventListener(“cardBrandChanged”,
(event) => {
console.log(Card brand changed);
console.log(event.detail.cardBrand);
console.log(event.detail);
})

const cardButton = document.getElementById(‘card-button’);
cardButton.addEventListener(‘click’, async () => {
const statusContainer = document.getElementById(‘payment-status-container’);

try {
let billingContact = {
givenName: ‘John’,
familyName: ‘Doe’,
email: ‘[email protected]’,
phone: ‘3214563987’,
addressLines: [‘123 Main Street’, ‘Apartment 1’],
city: ‘London’,
state: ‘LND’,
countryCode: ‘GB’,
};

const result = await card.tokenize();
if (result.status === ‘OK’) {
console.log(Payment token is ${result.token});

const verifiedToken = await verifyBuyer(payments, result.token);
console.log(Verified Payment token is ${verifiedToken});

statusContainer.innerHTML = “Payment Successful”;
//Add the call to the backend code to process the payment here passing the token and the verified token if using 3DS(SCA)
} 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”;
}
});

Hi Bryan,

On a side note, the new payment flow you mentioned is tagged as “Beta” when will this be released to production? Should we support the new payment flow or the old one? Or both? If both or the old one then can you help as the old one is giving me the reported error?

We don’t have a public roadmap for when this will GA however beta functionality is publicly available and breaking changes follow the normal Square API versioning process. Beta functionality is documented and clearly tagged in the developer documentation. The interfaces are considered stable and closely represent what Square intends for final release, but fixes and updates to the interfaces might still be made. :slightly_smiling_face:

Hi Bryan,

In that case, I will be using the current payment flow for now. Can you help me take a look why I’m getting error when trying to do SCA? This is the code that I currently have.

const payments = Square.payments(‘sandbox-sq0idb-QPb20WLhVKbDwKQELlEX7w’, ‘LW5ZTGY0ZPR95’);
const card = await payments.card();

async function verifyBuyer(payments, token) {
const verificationDetails = {
amount: ‘1.00’,
/* collected from the buyer */
billingContact: {
addressLines: [‘123 Main Street’, ‘Apartment 1’],
familyName: ‘Doe’,
givenName: ‘John’,
email: ‘[email protected]’,
countryCode: ‘GB’,
phone: ‘3214563987’,
state: ‘LND’,
city: ‘London’,
},
currencyCode: ‘GBP’,
intent: ‘STORE’,
};

const verificationResults = await payments.verifyBuyer(
token,
verificationDetails
);
return verificationResults.token;
}

await card.attach(‘#card-container’);

card.addEventListener(“cardBrandChanged”,
(event) => {
console.log(Card brand changed);
console.log(event.detail.cardBrand);
console.log(event.detail);
})

const cardButton = document.getElementById(‘card-button’);
cardButton.addEventListener(‘click’, async () => {
const statusContainer = document.getElementById(‘payment-status-container’);

try {
let billingContact = {
givenName: ‘John’,
familyName: ‘Doe’,
email: ‘[email protected]’,
phone: ‘3214563987’,
addressLines: [‘123 Main Street’, ‘Apartment 1’],
city: ‘London’,
state: ‘LND’,
countryCode: ‘GB’,
};

const result = await card.tokenize();
if (result.status === ‘OK’) {
console.log(Payment token is ${result.token});

const verifiedToken = await verifyBuyer(payments, result.token);
console.log(Verified Payment token is ${verifiedToken});

statusContainer.innerHTML = “Payment Successful”;
//Add the call to the backend code to process the payment here passing the token and the verified token if using 3DS(SCA)
} 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”;
}
});

Regards,

  1. Quotes: Ensure you’re using consistent quotes. JavaScript typically uses either single (') or double (") quotes. It seems like you might have some smart quotes (, ) in your code. Replace them with regular single or double quotes.
  2. Console Logs: In your cardBrandChanged event listener, you have console.log(Card brand changed);. This should be wrapped in quotes: console.log("Card brand changed");.
  3. Template Literals: You’re using template literals for strings with variables, which is correct. Make sure you’re using backticks (```) for template literals, like in console.log(Payment token is ${result.token});. This should be console.log(\Payment token is ${result.token});.
  4. Error Handling: Your error handling is good, but ensure that the error messages are displayed correctly.
  5. Verify Buyer: The verifyBuyer function seems correctly structured, assuming you have the correct API keys and environment setup. Just make sure the payments object is correctly initialized and that verifyBuyer is called with the correct token.
  6. Element IDs: Ensure that the elements with IDs like #card-container and #card-button exist in your HTML.
  7. Event Listeners: Your use of event listeners seems correct. Make sure the elements they are attached to are present in the DOM when this script runs.

Here’s a slightly cleaned-up version of your code:

const payments = Square.payments('sandbox-sq0idb-QPb20WLhVKbDwKQELlEX7w', 'LW5ZTGY0ZPR95');
const card = await payments.card();

async function verifyBuyer(payments, token) {
  const verificationDetails = {
    amount: '1.00',
    billingContact: {
      addressLines: ['123 Main Street', 'Apartment 1'],
      familyName: 'Doe',
      givenName: 'John',
      email: '[email protected]',
      countryCode: 'GB',
      phone: '3214563987',
      state: 'LND',
      city: 'London',
    },
    currencyCode: 'GBP',
    intent: 'STORE',
  };

  const verificationResults = await payments.verifyBuyer(
    token,
    verificationDetails
  );
  return verificationResults.token;
}

await card.attach('#card-container');

card.addEventListener("cardBrandChanged", (event) => {
  console.log("Card brand changed");
  console.log(event.detail.cardBrand);
  console.log(event.detail);
});

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}`);

      const verifiedToken = await verifyBuyer(payments, result.token);
      console.log(`Verified Payment token is ${verifiedToken}`);

      statusContainer.innerHTML = "Payment Successful";
      // Add the call to the backend code to process the payment here passing the token and the verified token if using 3DS(SCA)
    } 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";
  }
});

Make sure to replace the placeholder API keys and IDs with your actual values. Also, ensure that your HTML file contains the necessary container and button elements for the script to interact with. :slightly_smiling_face:

I cleaned it up but the window pop up for the SCA still didn’t show up. Also there’s an error logged in the console but the verifybuyer still returned a verified token.

This is the URL on the error https://connect.squareupsandbox.com/v2/analytics/verifications/verf:CA4SEBn5npJrBJpppoKFILl_pnAgACgC/three-ds-authentication.

And when I tried to use the generated tokens to create card in the API explorer it says “CARD_DECLINED_VERIFICATION_REQUIRED”.

Below is the request and response.

Request:
curl https://connect.squareupsandbox.com/v2/cards
-X POST
-H ‘Square-Version: 2024-10-17’
-H ‘Authorization: Bearer ACCESS_TOKEN’
-H ‘Content-Type: application/json’
-d ‘{
“card”: {
“customer_id”: “HG42J5D18QEVXYZCFZFQAG4FGC”
},
“idempotency_key”: “34d9dda6-be9f-4426-8dfa-d9bd70927a9c”,
“source_id”: “cnon:CBASENiKhRdad7wgfG5ADxFTxkgoAg”,
“verification_token”: “verf:CA4SEAtpkS0x7BpA3YJrgAkEggwgACgC”
}’

cache-control: no-cache
content-length: 246
content-type: application/json
date: Tue, 22 Oct 2024 07:51:40 GMT
square-version: 2024-10-17

{
  "errors": [
    {
      "category": "PAYMENT_METHOD_ERROR",
      "code": "CARD_DECLINED_VERIFICATION_REQUIRED",
      "detail": "Card declined. A verification is required to process this payment. See [https://developer.squareup.com/docs/sca-overview](https://developer.squareup.com/docs/sca-overview) for more information."
    }
  ]
}

Any ideas?

Regards,

You got a verification token so that’s working. What test value did you use? Also please don’t share you access token even if its sandbox they are secret. :slightly_smiling_face: