Sandbox test payment not working

Hello, I have a problem with the sandbox payment, description below:

When the page loads I have this error:

Then the form loads correctly and When I use one of the test cards you provide:

I get this:

With this error:

I copied and changed stuff from one of your basic templates, here is the code:


var appID = 'sandbox-sq0idb-tdrncM8QaBQ-jRPBX16oFg';
var locationID = 'L4Y2SNXETYZBN';
// Create and initialize a payment form object
var paymentForm = new SqPaymentForm({
  // Initialize the payment form elements
  applicationId: appID,
  locationId: locationID,
  inputClass: 'sq-input',

  // Customize the CSS for SqPaymentForm iframe elements
  inputStyles: [{
    backgroundColor: 'transparent',
    color: '#333333',
    fontFamily: '"Helvetica Neue", "Helvetica", sans-serif',
    fontSize: '16px',
    fontWeight: '400',
    placeholderColor: '#8594A7',
    placeholderFontWeight: '400',
    padding: '16px',
    _webkitFontSmoothing: 'antialiased',
    _mozOsxFontSmoothing: 'grayscale'

  // Initialize the credit card placeholders
  cardNumber: {
    elementId: 'sq-card-number',
    placeholder: '•••• •••• •••• ••••'
  cvv: {
    elementId: 'sq-cvv',
    placeholder: 'CVV'
  expirationDate: {
    elementId: 'sq-expiration-date',
    placeholder: 'MM/YY'
  postalCode: {
    elementId: 'sq-postal-code'

  // SqPaymentForm callback functions
  callbacks: {
    createPaymentRequest: function () {

      var paymentRequestJson = {
        requestShippingAddress: false,
        requestBillingInfo: true,
        shippingContact: {
          familyName: "CUSTOMER LAST NAME",
          givenName: "CUSTOMER FIRST NAME",
          email: "[email protected]",
          country: "USA",
          region: "CA",
          city: "San Francisco",
          addressLines: [
            "1455 Market St #600"
          postalCode: "94103",
          phone: "14255551212"
        currencyCode: "GBP",
        countryCode: "UK",
        total: {
          label: "MERCHANT NAME",
          amount: "1.00",
          pending: false
        lineItems: [{
          label: "Subtotal",
          amount: "1.00",
          pending: false

      return paymentRequestJson;

     * callback function: cardNonceResponseReceived
     * Triggered when: SqPaymentForm completes a card nonce request
    cardNonceResponseReceived: function (errors, nonce, cardData, billingContact, shippingContact) {
      if (errors) {
        var error_html = "";
        for (var i = 0; i < errors.length; i++) {
          error_html += "<li> " + errors[i].message + " </li>";
        document.getElementById("error").innerHTML = error_html;
        document.getElementById('sq-creditcard').disabled = false;

      } else {
        document.getElementById("error").innerHTML = "";

      // Assign the nonce value to the hidden form field
      document.getElementById('card-nonce').value = nonce;

      // POST the nonce form to the payment processing page


     * callback function: unsupportedBrowserDetected
     * Triggered when: the page loads and an unsupported browser is detected
    unsupportedBrowserDetected: function () {

     * callback function: inputEventReceived
     * Triggered when: visitors interact with SqPaymentForm iframe elements.
    inputEventReceived: function (inputEvent) {
      switch (inputEvent.eventType) {
        case 'focusClassAdded':
          /* HANDLE AS DESIRED */
        case 'focusClassRemoved':
          /* HANDLE AS DESIRED */
        case 'errorClassAdded':
          /* HANDLE AS DESIRED */
        case 'errorClassRemoved':
          /* HANDLE AS DESIRED */
        case 'cardBrandChanged':
          /* HANDLE AS DESIRED */
        case 'postalCodeChanged':
          /* HANDLE AS DESIRED */

     * callback function: paymentFormLoaded
     * Triggered when: SqPaymentForm is fully loaded
    paymentFormLoaded: function () {

function onGetCardNonce(event) {

  // Don't submit the form until SqPaymentForm returns with a nonce

  // Request a nonce from the SqPaymentForm object


		// dotenv is used to read from the '.env' file created for credentials
		$dotenv = Dotenv::create(dirname(__FILE__, 2));

		// Pulled from the .env file and upper cased e.g. SANDBOX, PRODUCTION.
		$upper_case_environment = strtoupper(getenv('ENVIRONMENT'));

		// The access token to use in all Connect API requests.
		// Set your environment as *sandbox* if you're just testing things out.
		$access_token =  getenv($upper_case_environment.'_ACCESS_TOKEN');    

		// Initialize the Square client.
		$client = new SquareClient([
			'accessToken' => $access_token,  
			'environment' => getenv('ENVIRONMENT')

		// Helps ensure this code has been reached via form submission
			error_log('Received a non-POST request');
			echo 'Request not allowed';

		// Fail if the card form didn't send a value for `nonce` to the server
		$nonce = $_POST['nonce'];
		if (is_null($nonce)) {
			echo 'Invalid card data';

		$payments_api = $client->getPaymentsApi();

		// To learn more about splitting payments with additional recipients,
		// see the Payments API documentation on our [developer site]
		// (

		$money = new Money();
			// Monetary amounts are specified in the smallest unit of the applicable currency.
			// This amount is in cents. It's also hard-coded for $1.00, which isn't very useful.

			// Every payment you process with the SDK must have a unique idempotency key.
			// If you're unsure whether a particular payment succeeded, you can reattempt
			// it with the same idempotency key without worrying about double charging
			// the buyer.
		$create_payment_request = new CreatePaymentRequest($nonce, uniqid(), $money);

		// The SDK throws an exception if a Connect endpoint responds with anything besides
		// a 200-level HTTP code. This block catches any exceptions that occur from the request.
		try {
			$response = $payments_api->createPayment($create_payment_request);
			// If there was an error with the request we will
			// print them to the browser screen here
			if ($response->isError()) {
				echo 'Api response has Errors';
				$errors = $response->getErrors();
				echo '<ul>';
				foreach ($errors as $error) {
						echo '<li>' . $error->getDetail() . '</li>';
				echo '</ul>';
			echo '<pre>';
			echo '</pre>';
		} catch (ApiException $e) {
			echo 'Caught exception!<br/>';
			echo('<strong>Response body:</strong><br/>');
			echo '<pre>'; var_dump($e->getResponseBody()); echo '</pre>';
			echo '<br/><strong>Context:</strong><br/>';
			echo '<pre>'; var_dump($e->getContext()); echo '</pre>';

Hi @d0tm welcome to the forums! Request not authorized implies an invalid application id. By the sounds of the errors (squareup instead of squareupsandbox), it sounds like you’re loading the production payment form, but using your sandbox application id. Can you be sure you’re linking the form like:

<script type="text/javascript" src="">

instead of