5 ) ); $is_down = is_wp_error( $resp ) || wp_remote_retrieve_response_code( $resp ) >= 500; set_transient( 'cfturnstile_cf_status', $is_down ? 'down' : 'up', 2 * MINUTE_IN_SECONDS ); return $is_down; } /** * Render Google reCAPTCHA widget for failsafe mode and enqueue script. * * @param string $unique_id * @return void */ function cfturnstile_render_recaptcha_widget($unique_id = '') { $recaptcha_site_key = trim( (string) get_option('cfturnstile_recaptcha_site_key') ); if ( empty($recaptcha_site_key) ) { return; } $defer = get_option('cfturnstile_defer_scripts', 1) ? array('strategy' => 'defer') : array(); wp_enqueue_script('cfturnstile-recaptcha', 'https://www.google.com/recaptcha/api.js', array(), null, $defer); do_action('cfturnstile_before_field', esc_attr($unique_id)); ?>
'; } /** * Verify Google reCAPTCHA response (used for failsafe) * * @return array $results */ function cfturnstile_verify_recaptcha() { $results = array(); $recaptcha_secret = trim( (string) get_option('cfturnstile_recaptcha_secret_key') ); $recaptcha_response = ''; if ( isset($_POST['g-recaptcha-response']) ) { $recaptcha_response = sanitize_text_field( $_POST['g-recaptcha-response'] ); } if ( empty($recaptcha_secret) || empty($recaptcha_response) ) { $results['success'] = false; $results['error_code'] = empty($recaptcha_secret) ? 'missing-input-secret' : 'missing-input-response'; $recaptcha_resp_obj = (object) array( 'success' => false ); do_action('cfturnstile_after_check', $recaptcha_resp_obj, $results); return $results; } $recaptcha_req = array( 'body' => array( 'secret' => $recaptcha_secret, 'response' => $recaptcha_response, 'remoteip' => cfturnstile_get_ip(), ), ); $recaptcha_verify = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', $recaptcha_req); if ( is_wp_error( $recaptcha_verify ) ) { $results['success'] = false; $results['error_code'] = 'bad-request'; $recaptcha_resp_obj = (object) array( 'success' => false ); do_action('cfturnstile_after_check', $recaptcha_resp_obj, $results); return $results; } $recaptcha_body = wp_remote_retrieve_body( $recaptcha_verify ); $recaptcha_json = json_decode( $recaptcha_body ); $recaptcha_success = ( isset($recaptcha_json->success) && $recaptcha_json->success ); $results['success'] = $recaptcha_success ? true : false; if ( !$recaptcha_success && isset($recaptcha_json->{'error-codes'}) && is_array($recaptcha_json->{'error-codes'}) && !empty($recaptcha_json->{'error-codes'}) ) { $results['error_code'] = $recaptcha_json->{'error-codes'}[0]; } $recaptcha_resp_obj = (object) array( 'success' => $recaptcha_success ? true : false ); do_action('cfturnstile_after_check', $recaptcha_resp_obj, $results); return $results; } /** * Backend failover handler: if Cloudflare siteverify failed, apply configured failsafe. * * @param WP_Error|array $verify The result from wp_remote_post to Cloudflare siteverify * @return array|null Returns results array if handled by failsafe, or null to continue Turnstile path */ function cfturnstile_handle_failover_backend($verify) { if ( ! get_option('cfturnstile_failover') ) { return null; } $is_error = is_wp_error( $verify ); $code = $is_error ? 0 : wp_remote_retrieve_response_code( $verify ); if ( $is_error || $code >= 500 ) { $type = get_option('cfturnstile_failsafe_type', 'allow'); if ( $type === 'recaptcha' ) { return cfturnstile_verify_recaptcha(); } return array('success' => true); } return null; }