Web Payments SDK. Virtual Terminal

As part of our customers order forms we require name, address, telephone and email. When it comes to payment many customers pay over the phone. So we have to key in the card details. I manged to use the web payments API without the verification (as it’s over the phone and therefore not required) in much the same way the Virtual Terminal would work. However, some cards Require Verification and so return an error. I obviously can’t enable verification for this use case.

I know I can use Terminal API to send customer details to the device and input card number on there, but frankly entering the card numbers on the terminal device is frustratingly fiddly. (Often doesn’t allow entering a postcode besides the first letter at all). Is there another way?
Or am I able to send the ‘customer id’ with other data to the Virtual Terminal via URL perhaps? I see that it populates the URL with the merchant number already.

Hi there,

Virtual Terminal (VT) does support a customer ID query parameter called contactToken. For example:

https://squareup.com/terminal/?contactToken=<CUSTOMER_ID>

If the customer has a card-on-file, it will be loaded and automatically selected. Unfortunately there are no other query parameters related to customers.

Sorry for the delay on this. When you are taking payments over the phone are you setting customer_details.seller_keyed_in to true? This will let the bank know that the customer isn’t present when they would have otherwise required verification. :slightly_smiling_face:

1 Like
<head>
  
  	<title>HTML Button Generator</title>
	<style>
		button {
			color: #efa817;
			background-color: #001e0c;
			font-size: 19px;
			font-family: georgia;
			border: 3px solid #ffffff;
			border-radius: 50px;
			padding: 15px 50px;
			cursor: pointer;
          	
		}
		button:hover {
			color: #001e0c;
			background-color: #efa817;
		}
	</style>
  
  
  
  <link rel="stylesheet" href="/reference/sdks/web/static/styles/code-preview.css" preload>
  <script src="https://web.squarecdn.com/v1/square.js"></script>
</head>
<body>
<div id="payment-form">
  <div id="payment-status-container"></div>
  <div id="card-container"></div>
  <button id="card-button" type="button">Charge</button>
 
</div>
  <script type="module">
    const payments = Square.payments('redacted', 'redacted');
    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}`);
    	                
              		window.parent.postMessage(result,"redacted");
//        window.parent.postMessage(result,"*");   
               
          statusContainer.innerHTML = "Payment Successful";
        } else {
          let errorMessage = `Tokenization failed with status: ${result.status}`;
             window.parent.postMessage(result.status,"redacted")
          if (result.errors) {
            errorMessage += ` and errors: ${JSON.stringify(
              result.errors
                        )}`;
          }

          throw new Error(errorMessage);
        }
      } catch (e) {
        console.error(e);
        statusContainer.innerHTML = "Payment Failed";
      }
    });
  </script>
</body>

Where should I put it please?

The customer_details isn’t set in the client side code. It’s set in your server side CreatePayment call. :slightly_smiling_face:

async function cardPayment(customerId, paymentToken, pennies, rando, orderNumber, email, phoneNumber) {

    const mySecret = await getSecret("SQUARE");
    const url = "https://connect.squareup.com/v2/payments";

    let data = {
        "idempotency_key": rando,
        "amount_money": {
            "amount": pennies,
            "currency": "GBP"
        },

        "source_id": paymentToken,
        "customer_id": customerId,
        "note": "Order Number: " + orderNumber,

        customer_details.seller_keyed_in: true, /// inserted here?

    }

    const headers = {
        "Square-Version": "2023-09-25",
        "Authorization": "Bearer " + mySecret,
        "Content-type": "application/json"
    };

    const request = {
        method: 'POST',
        headers: headers,
        body: JSON.stringify(data)
    };
    return fetch(url, request)

        .then(response => response.json())
        .then(json => console.log(JSON.stringify(json),


        jsonData(json, phoneNumber, email)

           

        ))

        .catch((error) => {
          
           console.log('Oops... ' + error);

           
        });

}

Forgive me. I’m learning this all as I go. I already tried adding it as above but still get the requires verification message.

Yes, it goes there but it will look like:

async function cardPayment(customerId, paymentToken, pennies, rando, orderNumber, email, phoneNumber) {

    const mySecret = await getSecret("SQUARE");
    const url = "https://connect.squareup.com/v2/payments";

    let data = {
        "idempotency_key": rando,
        "amount_money": {
            "amount": pennies,
            "currency": "GBP"
        },

        "source_id": paymentToken,
        "customer_id": customerId,
        "note": "Order Number: " + orderNumber,
        "customer_details": { /// inserted here?
                    "seller_keyed_in": true
             }
    }

    const headers = {
        "Square-Version": "2023-09-25",
        "Authorization": "Bearer " + mySecret,
        "Content-type": "application/json"
    };

    const request = {
        method: 'POST',
        headers: headers,
        body: JSON.stringify(data)
    };
    return fetch(url, request)

        .then(response => response.json())
        .then(json => console.log(JSON.stringify(json),


        jsonData(json, phoneNumber, email)

           

        ))

        .catch((error) => {
          
           console.log('Oops... ' + error);

           
        });

}

:slightly_smiling_face:

Thank you very much! Works grand. :smiley: