Я пытался настроить свой веб-сайт, интегрировав в него форму электронной коммерции. Мне удалось заставить его работать с использованием учетных данных Sandbox, но как только я переключил его на «живой», заменив идентификатор местоположения, идентификатор приложения и токены доступа на оперативные данные, и попытался снять с себя $ 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 $1.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?
Я считаю, что эта проблема происходит, потому что площадь application_id
вы предоставляете при инициализации SqPaymentForm
в index.html
не соответствует тому же приложению, которое выдало токен доступа, который вы предоставляете в process-card.php
,
Приложение, которое пытается зарядить одноразовый номер карты, должно быть тем же приложением, которое изначально создало одноразовый номер.
Я обнаружил, что проблема для меня заключалась в том, что мой файл javascript застрял в кэше с активированным ключом песочницы. Как только я очистил этот кеш, у меня все заработало.