Пожалуйста, помогите мне интегрировать reCaptcha на сайт. При отправке формы возникает ошибка "Ошибка обработки. Ответ не JSON". Я полагаю, что это связано с частью кода, которая проверяет успешность прохождения reCaptcha.
Вот фрагмент кода:
```php
if($responseKeys["success"] && $responseKeys["score"] >= 0.5) {
echo json_encode(array('success' => 'true', 'om_score' => $responseKeys["score"], 'token' => $_POST['token']));
} else {
echo json_encode(array('success' => 'false', 'om_score' => $responseKeys["score"], 'token' => $_POST['token']));
}
```
Если я удаляю эту часть, форма отправляется успешно, но тогда, по всей видимости, функция капчи не работает.
Вот полный код:
```php
<?php
// Файлы phpmailer
require 'phpmailer/PHPMailer.php';
require 'phpmailer/SMTP.php';
require 'phpmailer/Exception.php';
# проверка, что ошибки нет
if (!error_get_last()) {
// Переменные, которые отправляет пользователь
$name = $_POST['name'];
$tel = $_POST['tel'];
$email = $_POST['email'];
$number = $_POST['number'];
$text = $_POST['text'];
$captcha = isset($_POST['token']) ? $_POST['token'] : '';
$secretKey = '***';
$ip = $_SERVER['REMOTE_ADDR'];
$url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secretKey . '&response=' . $captcha;
$response = file_get_contents($url);
$responseKeys = json_decode($response, true);
if($responseKeys["success"] && $responseKeys["score"] >= 0.5) {
echo json_encode(array('success' => 'true', 'om_score' => $responseKeys["score"], 'token' => $captcha));
} else {
echo json_encode(array('success' => 'false', 'om_score' => $responseKeys["score"], 'token' => $captcha));
}
}
```
Можете ли вы подсказать, что не так и как это исправить?
Ваша проблема заключается в том, что вы неправильно обрабатываете ответ от Google reCAPTCHA, поэтому возникает ошибка "Ошибка обработки. Ответ не JSON". Давайте пройдемся по основным шагам для корректной интеграции reCAPTCHA с PHPMailer и убедимся, что все работает хорошо.
### Основные шаги для интеграции
1. **Убедитесь, что вы получили правильные ключи от Google reCAPTCHA**: Вам нужно следить за тем, чтобы вы использовали правильные ключи в своем коде. В вашем случае замените `***` в `$secretKey` на ваш секретный ключ.
2. **Проверка на стороне клиента**: Перед отправкой формы с помощью JavaScript убедитесь, что вы правильно настроили reCAPTCHA, и форма не отправляется без успешной проверки.
Пример JavaScript для инициализации reCAPTCHA v3:
```html
<script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY"></script>
<script>
grecaptcha.ready(function() {
grecaptcha.execute('YOUR_SITE_KEY', {action: 'submit'}).then(function(token) {
document.getElementById('token').value = token;
});
});
</script>
```
3. **Обработка ответа в PHP**: Убедитесь, что вы корректно обрабатываете ответ от reCAPTCHA на сервере.
### Обновленный код
Вот обновленный код с учетом указанных выше рекомендаций:
```php
<?php
require 'phpmailer/PHPMailer.php';
require 'phpmailer/SMTP.php';
require 'phpmailer/Exception.php';
if (!error_get_last()) {
// Переменные, которые отправляет пользователь
$name = $_POST['name'];
$tel = $_POST['tel'];
$email = $_POST['email'];
$number = $_POST['number'];
$text = $_POST['text'];
$captcha = isset($_POST['token']) ? $_POST['token'] : '';
$secretKey = 'YOUR_SECRET_KEY'; // Замените на ваш секретный ключ.
$ip = $_SERVER['REMOTE_ADDR'];
$url = 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secretKey . '&response=' . $captcha;
// Получение ответа от reCAPTCHA
$response = file_get_contents($url);
$responseKeys = json_decode($response, true);
// Проверка успешности и наличия нужного балла
if ($responseKeys['success'] && (isset($responseKeys['score']) && $responseKeys['score'] >= 0.5)) {
// Здесь вы можете отправить почту, так как проверка прошла успешно
// Пример:
// $mail = new PHPMailer();
// Настройка PHPMailer...
// $mail->send();
echo json_encode(array('success' => 'true', 'om_score' => $responseKeys["score"], 'token' => $captcha));
} else {
echo json_encode(array('success' => 'false', 'om_score' => isset($responseKeys['score']) ? $responseKeys['score'] : 'N/A', 'token' => $captcha));
}
}
?>
```
### Примечания
1. Замените `YOUR_SECRET_KEY` на ваш фактический секретный ключ от reCAPTCHA.
2. Убедитесь, что вы правильно добавляете `token` в вашу форму HTML:
```html
<input type="hidden" name="token" id="token">
```
3. Проверяйте наличие поля `score` в ответе от reCAPTCHA, поскольку в более ранних версиях может быть возвращено лишь поле `success`.
Теперь протестируйте свой код, и если будут ошибки, проверьте, какая именно информация возвращается от Google. Это поможет в диагностике возможных проблем.
Проблема в вашем коде заключается в том, что вы не объединяете проверку reCAPTCHA с процессом отправки письма. Вот исправленный вариант:
<?php // Файлы phpmailer require 'phpmailer/PHPMailer.php'; require 'phpmailer/SMTP.php'; require 'phpmailer/Exception.php'; // Инициализация массива данных для ответа $data = []; # проверка, что ошибки нет if (!error_get_last()) { // Проверка reCAPTCHA if(isset($_POST['token'])){ $secretKey = '***'; // Ваш секретный ключ reCAPTCHA $token = $_POST['token']; $url = 'https://www.google.com/recaptcha/api/siteverify'; // Используем cURL вместо file_get_contents для лучшей обработки ошибок $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'secret' => $secretKey, 'response' => $token, 'remoteip' => $_SERVER['REMOTE_ADDR'] )); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); $responseKeys = json_decode($response, true); // Если reCAPTCHA не пройдена, возвращаем ошибку if(!$responseKeys["success"] || $responseKeys["score"] < 0.5) { header('Content-Type: application/json'); echo json_encode([ 'result' => 'error', 'info' => 'Ошибка проверки reCAPTCHA', 'desc' => 'Возможная попытка спама' ]); exit; } } else { header('Content-Type: application/json'); echo json_encode([ 'result' => 'error', 'info' => 'Отсутствует токен reCAPTCHA' ]); exit; } // Переменные, которые отправляет пользователь $name = $_POST['name'] ?? ''; $tel = $_POST['tel'] ?? ''; $email = $_POST['email'] ?? ''; $number = $_POST['number'] ?? ''; $text = $_POST['text'] ?? ''; // Формирование самого письма $title = "Заявка с сайта"; $body = " <h2>Заявка с сайта</h2> <b>Имя:</b> $name<br> <b>Телефон:</b> $tel<br> <b>Почта:</b> $email<br> <b>Количество изделий:</b> $number<br> <b>Сообщение:</b><br>$text "; // Настройки PHPMailer $mail = new PHPMailer\PHPMailer\PHPMailer(); try { $mail->isSMTP(); $mail->CharSet = "UTF-8"; $mail->SMTPAuth = true; //$mail->SMTPDebug = 2; $mail->Debugoutput = function($str, $level) use (&$data) { $data['debug'][] = $str; }; // Настройки вашей почты $mail->Host = 'smtp.yandex.com'; // SMTP сервера вашей почты $mail->Username = '***'; // Логин на почте $mail->Password = '***'; // Пароль на почте $mail->SMTPSecure = 'ssl'; $mail->Port = 465; $mail->setFrom('***', 'Заявка с сайта'); // Адрес самой почты и имя отправителя // Получатель письма $mail->addAddress('***'); // Прикрипление файлов к письму if (!empty($_FILES['file']['name'][0])) { for ($i = 0; $i < count($_FILES['file']['tmp_name']); $i++) { if ($_FILES['file']['error'][$i] === 0) { $mail->addAttachment($_FILES['file']['tmp_name'][$i], $_FILES['file']['name'][$i]); } } } // Отправка сообщения $mail->isHTML(true); $mail->Subject = $title; $mail->Body = $body; // Проверяем отправленность сообщения if ($mail->send()) { $data['result'] = "success"; $data['info'] = "Сообщение успешно отправлено!"; } else { $data['result'] = "error"; $data['info'] = "Сообщение не было отправлено. Ошибка при отправке письма"; $data['desc'] = "Причина ошибки: {$mail->ErrorInfo}"; } } catch (Exception $e) { $data['result'] = "error"; $data['info'] = "Ошибка при отправке письма"; $data['desc'] = $e->getMessage(); } } else { $data['result'] = "error"; $data['info'] = "В коде присутствует ошибка"; $data['desc'] = error_get_last(); } // Отправка результата header('Content-Type: application/json'); echo json_encode($data); ?>
Основные изменения:
Правильная обработка reCAPTCHA:
Использовал cURL вместо file_get_contents для лучшей обработки ошибок
Добавил проверку до обработки формы
При ошибке reCAPTCHA скрипт завершается с ошибкой
Улучшенная обработка ошибок:
Добавил try-catch для обработки исключений PHPMailer
Исправил обработку файлов (используйте $_FILES вместо $file)
JSON ответ:
Теперь скрипт возвращает один JSON ответ, а не несколько
Все сообщения об ошибках стандартизированы
Безопасность:
Добавил проверку наличия токена reCAPTCHA
Использовал оператор объединения ?? для переменных формы
На стороне клиента (HTML/JS):
Убедитесь, что вы правильно реализовали reCAPTCHA v3 на клиентской стороне. Вот пример:
<script src="https://www.google.com/recaptcha/api.js?render=ВАШ_КЛЮЧ_САЙТА"></script> <script> document.querySelector('form').addEventListener('submit', function(e) { e.preventDefault(); grecaptcha.ready(function() { grecaptcha.execute('ВАШ_КЛЮЧ_САЙТА', {action: 'submit'}).then(function(token) { // Добавляем token к данным формы let formData = new FormData(document.querySelector('form')); formData.append('token', token); // Отправка формы fetch('ваш_обработчик.php', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { if(data.result === 'success') { alert('Сообщение отправлено!'); } else { alert('Ошибка: ' + data.info); } }) .catch(error => console.error('Error:', error)); }); }); }); </script>
Замените ВАШ_КЛЮЧ_САЙТА на ваш ключ reCAPTCHA (site key) и ваш_обработчик.php на путь к вашему PHP-скрипту.