site_key() ); } /** * Returns the class the provider's own script looks for. * * v3 draws nothing, so there is no widget to mark. * * @return string An empty string. */ public function widget_class(): string { return ''; } /** * Returns the request field the answer arrives in. */ public function response_field(): string { return self::FIELD; } /** * Returns the score a submission must reach. * * @return float The threshold, between 0 and 1. */ public function threshold(): float { return min( 1.0, max( 0.0, (float) Settings::get( 'recaptcha_threshold', 0.5 ) ) ); } /** * Refuses a token whose score is below the threshold. * * @param array $body Decoded response. * * @return WP_Error|null The reason it failed, or null when it passed. */ protected function inspect( array $body ): ?WP_Error { /* * The action names what the token was minted for. Without checking it, a * token solved on any other v3 widget on the same site — a login form, a * comment box, a third-party plugin's — is accepted here, because they all * verify against the same secret. Absent means the site key is a v2 one, so * there is nothing to compare. */ $action = strtolower( trim( (string) ( $body['action'] ?? '' ) ) ); if ( '' !== $action && self::ACTION !== $action ) { return new WP_Error( 'formpilot_captcha_action', __( 'The spam check rejected this submission.', 'devplugins-custom-form-builder' ) ); } // A response without a score is a v2 key answering a v3 request. Treating // that as a pass is right: the checkbox was solved. $score = isset( $body['score'] ) ? (float) $body['score'] : 1.0; if ( $score >= $this->threshold() ) { return null; } return new WP_Error( 'formpilot_captcha_score', __( 'The spam check rejected this submission.', 'devplugins-custom-form-builder' ), array( 'score' => $score ) ); } /** * Returns the endpoint the answer is checked against. */ protected function verify_url(): string { return 'https://www.google.com/recaptcha/api/siteverify'; } /** * Returns the private key. */ protected function secret(): string { return Settings::text( 'recaptcha_secret' ); } }