diff --git a/quote-handler.php b/quote-handler.php
index 37d1cd0..802729c 100644
--- a/quote-handler.php
+++ b/quote-handler.php
@@ -375,6 +375,60 @@ if (!checkRateLimit()) {
sendResponse(false, 'Too many requests. Please try again later.');
}
+// reCAPTCHA Verification
+require_once '.recaptcha-config.php';
+
+function validateRecaptcha($token) {
+ if (!RECAPTCHA_ENABLED) {
+ // Skip validation if reCAPTCHA is disabled (test keys)
+ error_log("reCAPTCHA validation skipped - test keys in use");
+ return true;
+ }
+
+ if (empty($token)) {
+ return false;
+ }
+
+ $secretKey = RECAPTCHA_SECRET_KEY;
+ $verifyURL = 'https://www.google.com/recaptcha/api/siteverify';
+
+ $data = [
+ 'secret' => $secretKey,
+ 'response' => $token,
+ 'remoteip' => $_SERVER['REMOTE_ADDR']
+ ];
+
+ $options = [
+ 'http' => [
+ 'header' => "Content-type: application/x-www-form-urlencoded\r\n",
+ 'method' => 'POST',
+ 'content' => http_build_query($data)
+ ]
+ ];
+
+ $context = stream_context_create($options);
+ $result = file_get_contents($verifyURL, false, $context);
+
+ if ($result === false) {
+ error_log('reCAPTCHA verification request failed');
+ return false;
+ }
+
+ $resultJson = json_decode($result, true);
+
+ if ($resultJson['success'] && isset($resultJson['score'])) {
+ return $resultJson['score'] >= RECAPTCHA_THRESHOLD;
+ }
+
+ return false;
+}
+
+// Verify reCAPTCHA
+$recaptchaResponse = $_POST['recaptcha_response'] ?? '';
+if (!validateRecaptcha($recaptchaResponse)) {
+ sendResponse(false, 'Security verification failed. Please try again.');
+}
+
// Spam protection - honeypot field
if (isset($_POST['website']) && !empty($_POST['website'])) {
sendResponse(false, 'Spam detected');
diff --git a/quote.php b/quote.php
index 8908650..dcbda5f 100644
--- a/quote.php
+++ b/quote.php
@@ -503,6 +503,8 @@ $canonical_url = "https://ukdataservices.co.uk/quote";
$_SESSION['form_start_time'] = time();
?>
+
+