How to Enable and Test 3D Secure (OTP) with Square PHP SDK in Sandbox?

I am integrating Square payments using the PHP SDK in my application, and I want to test the 3D Secure (OTP-like flow) in the sandbox environment.

  • Do I need to configure anything specific in the PHP SDK to trigger the OTP verification?
  • How do I properly pass the verification_token in the PHP SDK?
  • Are there specific sandbox test cards that trigger 3DS authentication?

Below is my code
const payments = Square.payments(‘SANDBOX_APP_ID’, ‘sandbox’);
const card = await payments.card();
await card.attach(‘#card-container’);

document.getElementById(‘payment-button’).addEventListener(‘click’, async function () {
const result = await card.tokenize();
if (result.status === ‘OK’) {
// Send token to server
fetch(‘process_payment.php’, {
method: ‘POST’,
headers: { ‘Content-Type’: ‘application/json’ },
body: JSON.stringify({ token: result.token })
});
}
});
Please tell me the all steps. Any guidance would be greatly appreciated!

: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

OAuth Walkthrough: Test Authorization with Web Server
Test in the Sandbox
Sandbox Payments

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.

To test 3D Secure (OTP-like flow) in the sandbox environment, you need to use the verifyBuyer() function in your client-side code. This function triggers the 3D Secure authentication process and generates a verification_token that you can use in your server-side code.

Here’s how you can modify your client-side code:

document.getElementById('payment-button').addEventListener('click', async function () {
  const result = await card.tokenize();
  if (result.status === 'OK') {
    const verificationDetails = {
      intent: 'CHARGE',
      amount: '100',
      currencyCode: 'USD',
      billingContact: {
        familyName: 'Smith',
        givenName: 'John',
        email: '[email protected]',
        country: 'US',
        city: 'San Francisco',
        addressLines: ['123 Main St'],
        postalCode: '94114',
        phone: '4155551234'
      }
    };
    const verificationResult = await payments.verifyBuyer(result.token, verificationDetails);
    if (verificationResult.status === 'OK') {
      // Send token and verification token to server
      fetch('process_payment.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token: result.token, verificationToken: verificationResult.token })
      });
    }
  }
});

In your server-side PHP code, you can use the verification_token when creating a payment:

$apiClient = new \Square\SquareClient([
  'accessToken' => 'SANDBOX_ACCESS_TOKEN',
  'environment' => \Square\Environment::SANDBOX,
]);

$paymentsApi = $apiClient->getPaymentsApi();

$createPaymentRequest = new \Square\Models\CreatePaymentRequest(
  $_POST['token'],
  uniqid(),
  new \Square\Models\Money(100, 'USD'),
  ['buyerVerificationToken' => $_POST['verificationToken']]
);

try {
  $response = $paymentsApi->createPayment($createPaymentRequest);
  if ($response->isSuccess()) {
    $payment = $response->getResult()->getPayment();
    // Handle successful payment
  } else {
    $errors = $response->getErrors();
    // Handle errors
  }
} catch (\Square\Exceptions\ApiException $e) {
  // Handle API exception
}

For testing 3D Secure in the sandbox environment, you can use the test card number 4111 1111 1111 1111 with any future expiry date, CVV, and postal code. This card simulates a successful 3D Secure authentication.

This answer was reviewed by @Bryan-Square.