• File: wpr-recaptcha-handler.php
  • Full Path: /home/bravrvjk/hpgt.org/wp-content/plugins/royal-elementor-addons/classes/modules/forms/wpr-recaptcha-handler.php
  • Date Modified: 04/10/2026 2:58 PM
  • File size: 3.61 KB
  • MIME-type: text/x-php
  • Charset: utf-8
<?php
namespace WprAddons\Classes\Modules\Forms;

use Elementor\Utils;
use WprAddons\Classes\Utilities;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * WPR Recaptcha Handler - reCAPTCHA v2 and v3 verification
 *
 * @since 3.4.6
 */

class WPR_Recaptcha_Handler {
	public function __construct() {
		add_action( 'wp_ajax_wpr_verify_recaptcha', [ $this, 'wpr_verify_recaptcha' ] );
		add_action( 'wp_ajax_nopriv_wpr_verify_recaptcha', [ $this, 'wpr_verify_recaptcha' ] );
	}

	public function wpr_verify_recaptcha() {
		$recaptcha_response = isset( $_POST['g-recaptcha-response'] ) ? sanitize_text_field( wp_unslash( $_POST['g-recaptcha-response'] ) ) : '';
		$recaptcha_version  = isset( $_POST['recaptcha_version'] ) ? sanitize_text_field( wp_unslash( $_POST['recaptcha_version'] ) ) : 'v3';

		if ( empty( $recaptcha_response ) ) {
			wp_send_json_error( [ 'message' => 'Recaptcha Error' ] );
			return;
		}

		if ( 'v2' === $recaptcha_version ) {
			$is_valid = $this->check_recaptcha_v2( $recaptcha_response );
			if ( $is_valid ) {
				wp_send_json_success( [ 'message' => 'Recaptcha Success' ] );
			} else {
				wp_send_json_error( [ 'message' => 'Recaptcha Error' ] );
			}
			return;
		}

		// v3
		$result = $this->check_recaptcha_v3( $recaptcha_response );
		$score  = isset( $result['score'] ) ? $result['score'] : 0;
		$score_threshold = (float) get_option( 'wpr_recaptcha_v3_score', 0.5 );

		if ( $result['success'] && $score >= $score_threshold ) {
			wp_send_json_success( [
				'message' => 'Recaptcha Success',
				'score'   => $score,
			] );
		} else {
			wp_send_json_error( [
				'message' => 'Recaptcha Error',
				'score'   => $score,
			] );
		}
	}

	/**
	 * Verify reCAPTCHA v2 (checkbox) response. No score returned.
	 *
	 * @param string $recaptcha_response Token from g-recaptcha-response.
	 * @return bool
	 */
	public function check_recaptcha_v2( $recaptcha_response ) {
		$secret_key = get_option( 'wpr_recaptcha_v2_secret_key' );
		if ( empty( $secret_key ) ) {
			return false;
		}

		$remote_ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';

		$response = wp_remote_post(
			'https://www.google.com/recaptcha/api/siteverify',
			[
				'body' => [
					'secret'   => $secret_key,
					'response' => $recaptcha_response,
					'remoteip' => $remote_ip,
				],
			]
		);

		if ( is_wp_error( $response ) ) {
			return false;
		}

		$decoded = json_decode( wp_remote_retrieve_body( $response ), true );
		return ! empty( $decoded['success'] );
	}

	/**
	 * Verify reCAPTCHA v3 response. Returns success and score.
	 *
	 * @param string $recaptcha_response Token from g-recaptcha-response.
	 * @return array{ success: bool, score: float|null }
	 */
	public function check_recaptcha_v3( $recaptcha_response ) {
		$secret_key = get_option( 'wpr_recaptcha_v3_secret_key' );
		if ( empty( $secret_key ) ) {
			return [ 'success' => false, 'score' => null ];
		}

		$remote_ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';

		$response = wp_remote_post(
			'https://www.google.com/recaptcha/api/siteverify',
			[
				'body' => [
					'secret'   => $secret_key,
					'response' => $recaptcha_response,
					'remoteip' => $remote_ip,
				],
			]
		);

		if ( is_wp_error( $response ) ) {
			return [ 'success' => false, 'score' => null ];
		}

		$decoded = json_decode( wp_remote_retrieve_body( $response ), true );
		$success = ! empty( $decoded['success'] );
		$score   = isset( $decoded['score'] ) ? (float) $decoded['score'] : null;

		return [ 'success' => $success, 'score' => $score ];
	}
}

new WPR_Recaptcha_Handler();