INVALID_REQUEST_ERROR(nonce 问题)从沙箱切换到实时时

INVALID_REQUEST_ERROR (nonce issue) when switching from sandbox to live

我一直在尝试设置我的网站,将电子商务表单集成到网站中。我设法使用 Sandbox 凭据让它工作,但一旦我将它切换到 "live",替换实时数据的位置 ID、应用程序 ID 和访问令牌,并试图向自己收取 1.00 美元,我开始收到以下信息错误:

Caught exception!
Response body:
object(stdClass)[6]
  public 'errors' => 
    array (size=1)
      0 => 
        object(stdClass)[7]
          public 'category' => string 'INVALID_REQUEST_ERROR' (length=21)
          public 'code' => string 'NOT_FOUND' (length=9)
          public 'detail' => string 'Resource not found.' (length=19)
          public 'field' => string 'card_nonce' (length=10)

Response headers:
array (size=12)
  0 => string 'HTTP/1.1 404 Not Found' (length=22)
  'Content-Type' => string 'application/json' (length=16)
  'Vary' => string 'Accept-Encoding' (length=15)
  'X-Content-Type-Options' => string 'nosniff' (length=7)
  'X-Download-Options' => string 'noopen' (length=6)
  'X-Frame-Options' => string 'SAMEORIGIN' (length=10)
  'X-Permitted-Cross-Domain-Policies' => string 'none' (length=4)
  'X-Xss-Protection' => string '1; mode=block' (length=13)
  'Date' => string 'Sun, 12 Jun 2016 22:20:11 GMT' (length=29)
  'Content-Length' => string '121' (length=3)
  'Keep-Alive' => string 'timeout=60' (length=10)
  'Strict-Transport-Security' => string 'max-age=631152000' (length=17)

但是,自从我在上一页收到随机数接收警报后,我知道随机数已创建。

这里是 index.html:

<html>
<head>
  <title>My Payment Form</title>
  <script type="text/javascript" src="https://js.squareup.com/v2/paymentform"></script>
  <script type="text/javascript">
    var sqPaymentForm = new SqPaymentForm({

      // Replace this value with your application's ID (available from the merchant dashboard).
      // If you're just testing things out, replace this with your _Sandbox_ application ID,
      // which is also available there.
      applicationId: 'xxxxxxxxxxxxxxx', //for public posting purposes
      inputClass: 'sq-input',
      cardNumber: {
        elementId: 'sq-card-number',
        placeholder: "0000 0000 0000 0000"
      },
      cvv: {
        elementId: 'sq-cvv',
        placeholder: 'CVV'
      },
      expirationDate: {
        elementId: 'sq-expiration-date',
        placeholder: 'MM/YY'
      },
      postalCode: {
        elementId: 'sq-postal-code',
        placeholder: 'Postal Code'
      },
      inputStyles: [

        // Because this object provides no value for mediaMaxWidth or mediaMinWidth,
        // these styles apply for screens of all sizes, unless overridden by another
        // input style below.
        {
          fontSize: '14px',
          padding: '3px'
        },

        // These styles are applied to inputs ONLY when the screen width is 400px
        // or smaller. Note that because it doesn't specify a value for padding,
        // the padding value in the previous object is preserved.
        {
          mediaMaxWidth: '400px',
          fontSize: '18px',
        }
      ],
      callbacks: {
        cardNonceResponseReceived: function(errors, nonce, cardData) {
          if (errors) {
            var errorDiv = document.getElementById('errors');
            errorDiv.innerHTML = "";
            errors.forEach(function(error) {
              var p = document.createElement('p');
              p.innerHTML = error.message;
              errorDiv.appendChild(p);
            });
          } else {
            // This alert is for debugging purposes only.
            alert('Nonce received! ' + nonce + ' ' + JSON.stringify(cardData));

            // Assign the value of the nonce to a hidden form element
            var nonceField = document.getElementById('card-nonce');
            nonceField.value = nonce;

            // Submit the form
            document.getElementById('form').submit();
          }
        },
        unsupportedBrowserDetected: function() {
          // Alert the buyer that their browser is not supported
        }
      }
    });
    function submitButtonClick() {
      event.preventDefault();
      sqPaymentForm.requestCardNonce();
    }
  </script>
  <style type="text/css">
    .sq-input {
      border: 1px solid #CCCCCC;
      margin-bottom: 10px;
      padding: 1px;
    }
    .sq-input--focus {
      outline-width: 5px;
      outline-color: #70ACE9;
      outline-offset: -1px;
      outline-style: auto;
    }
    .sq-input--error {
      outline-width: 5px;
      outline-color: #FF9393;
      outline-offset: 0px;
      outline-style: auto;
    }
  </style>
</head>
<body>

  <h1>My Payment Form</h1>

  <form id="form" novalidate action="process-card.php" method="post">
    <label>Credit Card</label>
    <div id="sq-card-number"></div>
    <label>CVV</label>
    <div id="sq-cvv"></div>
    <label>Expiration Date</label>
    <div id="sq-expiration-date"></div>
    <label>Postal Code</label>
    <div id="sq-postal-code"></div>
    <input type="hidden" id="card-nonce" name="nonce">
    <input type="submit" onClick="submitButtonClick()" id="card-nonce">
  </form>

  <div id="errors"></div>
</body>
</html>

这是过程-card.php:

    <?php

require 'vendor/autoload.php';

# Replace these values. You probably want to start with your Sandbox credentials
# to start: https://docs.connect.squareup.com/articles/using-sandbox/

# The ID of the business location to associate processed payments with.
# If you're testing things out, use a sandbox location ID.
#
# See [Retrieve your business's locations](https://docs.connect.squareup.com/articles/getting-started/#retrievemerchantprofile)
# for an easy way to get your business's location IDs.
$location_id = 'xxxxxxxxxx';  //for public posting purposes

# The access token to use in all Connect API requests. Use your *sandbox* access
# token if you're just testing things out.
$access_token = 'xxxxxxxxx'; //for public posting purposes

# Helps ensure this code has been reached via form submission
if ($_SERVER['REQUEST_METHOD'] != 'POST') {
  error_log("Received a non-POST request");
  echo "Request not allowed";
  http_response_code(405);
  return;
}

# 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";
  http_response_code(422);
  return;
}

$transaction_api = new \SquareConnect\Api\TransactionApi();

$request_body = array (

  "card_nonce" => $nonce,

  # Monetary amounts are specified in the smallest unit of the applicable currency.
  # This amount is in cents. It's also hard-coded for .00, which isn't very useful.
  "amount_money" => array (
    "amount" => 100,
    "currency" => "CAD"
  ),

  # 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.
  "idempotency_key" => uniqid()
);

# 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 {
  $result = $transaction_api->charge($access_token, $location_id, $request_body);
  echo "<pre>";
  print_r($result);
  echo "</pre>";
} catch (\SquareConnect\ApiException $e) {
  echo "Caught exception!<br/>";
  print_r("<strong>Response body:</strong><br/>");
  echo "<pre>"; var_dump($e->getResponseBody()); echo "</pre>";
  echo "<br/><strong>Response headers:</strong><br/>";
  echo "<pre>"; var_dump($e->getResponseHeaders()); echo "</pre>";
}

您是否在 Square 注册了多个应用程序?

我认为出现此问题是因为您在 index.html 中初始化 SqPaymentForm 时提供的 Square application_id 与发布您在中提供的访问令牌的应用程序不对应process-card.php.

尝试对卡随机数进行收费的应用程序必须与首先生成随机数的应用程序相同。

我发现对我来说问题是我的 javascript 文件卡在缓存中,沙箱密钥已激活。一旦我清除了缓存,它就对我有用了。