<dl class="{if $errorField|isset && $errorField == 'recaptchaString'}formError{/if}">
<dt></dt>
<dd>
+ <input type="hidden" name="recaptcha-type" value="invisible">
<div id="recaptchaBucket{$recaptchaBucketID}"></div>
<noscript>
<div style="width: 302px; height: 473px;">
grecaptcha.execute(WCF.recaptcha.mapping['recaptchaBucket{$recaptchaBucketID}']);
return promise.then(function (token) {
return {
- 'g-recaptcha-response': token
+ 'g-recaptcha-response': token,
+ 'recaptcha-type': 'invisible'
};
});
});
<dl class="{if $errorField|isset && $errorField == 'recaptchaString'}formError{/if}">
<dt></dt>
<dd>
+ <input type="hidden" name="recaptcha-type" value="v2">
<div id="recaptchaBucket{$recaptchaBucketID}"></div>
<noscript>
<div style="width: 302px; height: 473px;">
{if $ajaxCaptcha|isset && $ajaxCaptcha}
WCF.System.Captcha.addCallback('{$captchaID}', function() {
return {
- 'g-recaptcha-response': grecaptcha.getResponse(WCF.recaptcha.mapping['recaptchaBucket{$recaptchaBucketID}'])
+ 'g-recaptcha-response': grecaptcha.getResponse(WCF.recaptcha.mapping['recaptchaBucket{$recaptchaBucketID}']),
+ 'type': 'v2'
};
});
{/if}
<dl class="{if $errorField|isset && $errorField == 'recaptchaString'}formError{/if}">
<dt></dt>
<dd>
+ <input type="hidden" name="recaptcha-type" value="invisible">
<div id="recaptchaBucket{$recaptchaBucketID}"></div>
<noscript>
<div style="width: 302px; height: 473px;">
grecaptcha.execute(WCF.recaptcha.mapping['recaptchaBucket{$recaptchaBucketID}']);
return promise.then(function (token) {
return {
- 'g-recaptcha-response': token
+ 'g-recaptcha-response': token,
+ 'recaptcha-type': 'invisible'
};
});
});
<dl class="{if $errorField|isset && $errorField == 'recaptchaString'}formError{/if}">
<dt></dt>
<dd>
+ <input type="hidden" name="recaptcha-type" value="v2">
<div id="recaptchaBucket{$recaptchaBucketID}"></div>
<noscript>
<div style="width: 302px; height: 473px;">
{if $ajaxCaptcha|isset && $ajaxCaptcha}
WCF.System.Captcha.addCallback('{$captchaID}', function() {
return {
- 'g-recaptcha-response': grecaptcha.getResponse(WCF.recaptcha.mapping['recaptchaBucket{$recaptchaBucketID}'])
+ 'g-recaptcha-response': grecaptcha.getResponse(WCF.recaptcha.mapping['recaptchaBucket{$recaptchaBucketID}']),
+ 'type': 'v2'
};
});
{/if}
}
else {
// V2
+ if (isset($_POST['recaptcha-type'])) $this->challenge = $_POST['recaptcha-type'];
if (isset($_POST['g-recaptcha-response'])) $this->response = $_POST['g-recaptcha-response'];
}
}
}
else {
// V2
- RecaptchaHandlerV2::getInstance()->validate($this->response);
+ RecaptchaHandlerV2::getInstance()->validate($this->response, $this->challenge ?: 'v2');
}
}
}
* @param string $response
* @throws UserInputException
*/
- public function validate($response) {
+ public function validate($response, $type = 'v2') {
// fail if response is empty to avoid sending api requests
if (empty($response)) {
throw new UserInputException('recaptchaString', 'false');
}
- $request = new HTTPRequest('https://www.google.com/recaptcha/api/siteverify?secret='.rawurlencode(RECAPTCHA_PRIVATEKEY).'&response='.rawurlencode($response).'&remoteip='.rawurlencode(UserUtil::getIpAddress()), ['timeout' => 10]);
+ if ($type === 'v2') {
+ $key = RECAPTCHA_PRIVATEKEY;
+ }
+ else if ($type === 'invisible') {
+ $key = RECAPTCHA_PRIVATEKEY;
+ }
+ else {
+ throw new \InvalidArgumentException('$type must be either v2 or invisible.');
+ }
+
+ $request = new HTTPRequest('https://www.google.com/recaptcha/api/siteverify?secret='.rawurlencode($key).'&response='.rawurlencode($response).'&remoteip='.rawurlencode(UserUtil::getIpAddress()), ['timeout' => 10]);
try {
$request->execute();