VerifyBuyer() works in sandbox but is returning 400 Bad Request in Production

Issue: verifyBuyer() Failing with 400 Error in Production

Context

I’m using the Web Payments SDK to implement Strong Customer Authentication (SCA). Everything works as expected in Sandbox, including the verifyBuyer() function, which correctly processes 3D Secure (3DS). However, when switching to Production, the verifyBuyer() function consistently fails and returns:

POST https://connect.squareup.com/v2/analytics/verifications 400 (Bad Request)

Problem

Regardless of what I send in the verificationDetails, the response is always a 400 Bad Request error.

  • The nonce is generated correctly and passed to the verifyBuyer() function.
  • Payments for cards without 3D Secure work fine.
  • The app is authenticated correctly, and there are no issues with other payment flows.

Here’s the relevant code:

// Function to handle 3D Secure verification (SCA)
async function verifyBuyer(nonce) {
    // Prepare 3D Secure verification details
    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',
    };

    try {
        console.log('Preparing to call verifyBuyer with:', verificationDetails, nonce);

        // Initialize Square Payments SDK
        const payments = window.Square.payments(appId, locationId);

        // Attempt 3D Secure verification
        const verificationResult = await payments.verifyBuyer(nonce, verificationDetails);
        console.log('verificationResult:', verificationResult);

        if (verificationResult.token) {
            const verificationToken = verificationResult.token;
            document.getElementById('verification').value = verificationToken;
            console.log('Card tokenized and 3D Secure verified successfully.', verificationToken);
            return verificationToken;  // Return verification token if successful
        } else {
            console.log('3D Secure Verification failed:', verificationResult);
            displayError('3D Secure verification failed.');
            return null;  // Return null if 3D Secure verification fails
        }
    } catch (error) {
        console.error('Error during 3D Secure verification:', error);

        // Log more detailed error information if available
        if (error.response) {
            console.error('Error response data:', error.response.data);
        }

        // Display an error message (optional)
        displayError('3D Secure verification failed.');
        return null;  // Return null if verification encounters an error
    }
}

What I’ve Tried

  • I have tried different variations of the verificationDetails object, including omitting optional fields (e.g., addressLines, state, etc.).
  • I verified that the App ID and Location ID are correct for production.
  • I reviewed the Square Documentation for verifyBuyer() to ensure compliance.

Questions

  1. Are there any additional steps or configurations needed to make verifyBuyer() work in production?
  2. Could the 400 error be caused by any specific field formatting in the verificationDetails object?
  3. Does production require more specific billing information than sandbox?

Any guidance or suggestions would be greatly appreciated. Thank you!

What’s your application ID? :slightly_smiling_face:

I took a look at the account and it looks like you processed our test cards in production. You have to use a valid card in production. Test values only work in sandbox. :slightly_smiling_face:

Thank you for checking and clarifying that the error was due to using test cards in production. I appreciate your help with this.

I understand that test card values work only in sandbox. However, I’m curious about the response behavior in production. When an invalid card is entered, could there be a more specific error message, such as “Invalid Card” or something similar? Receiving a 400 error without additional details makes troubleshooting quite difficult.

Additionally, could you provide guidance on how to test the 3D Secure flow in production? I currently only have access to US-based cards, which might not trigger the SCA requirements often seen with European cards. Are there any recommendations for handling this scenario?

Looking forward to your suggestions.

Unfortunately more detailed error messages aren’t currently available. When a customers payment fails we alway encourage them to contact the bank for additional information.

As for testing in production you will need to use a valid card. You can setup risk rules in the Risk Manager to trigger checks. Otherwise you’ll have to use a valid UK card that will trigger SCA. :slightly_smiling_face:

Thank you for the clarification regarding error messages and SCA testing.

I want to highlight that I’ve attempted to process payments in production using my personal US-based card, which is valid. Despite this, I’m consistently getting the same 400 Bad Request error, regardless of the card entered. This suggests that the issue might not be related to card validity alone.

Could there be other potential causes for this response that I should investigate? For example, could it be related to configuration settings, account permissions, or missing required fields in the request?

I appreciate your assistance and any additional guidance you can provide.

Errors received when entering a valid US-Based card with valid expiration, CVV, etc.

POST https://connect.squareup.com/v2/analytics/verifications 400 (Bad Request)

POST https://o160250.ingest.sentry.io/api/1516559/envelope/?sentry_key=4197e265423545aba2d849d023e8cd33&sentry_version=7&sentry_client=sentry.javascript.browser%2F7.111.0 net::ERR_BLOCKED_BY_CLIENT

Is the page hosted where I can inspect it? :slightly_smiling_face:

Looks like the reason it’s failing is because you still have your sandbox location_id configured.

:slightly_smiling_face:

Wow, that makes sense! I’ll update the Location ID to the production environment and give it a shot.

I’m still curious, though: why do all other payment processes work with the sandbox Location ID, except for verifyBuyer()? It’s confusing that everything except the 3D Secure verification proceeds without issues, even with the incorrect Location ID.

Also, is it recommended or safe to always call verifyBuyer() for US-based accounts, or should this be conditional based on region?

Thanks for the guidance!

They shouldn’t fail. What currency do you have configured? :slightly_smiling_face: