Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,42 @@ with additional error codes based on the client's checks. When adding a new
[`RequestMethod`](./src/ReCaptcha/RequestMethod.php) ensure that it returns the
`ReCaptcha::E_CONNECTION_FAILED` and `ReCaptcha::E_BAD_RESPONSE` where
appropriate.

## Public API compatibility

The 1.x line treats the following classes and interfaces as public API:
`ReCaptcha`, `RequestMethod`, `Response`, `RequestParameters`,
`RequestMethod\Post`, `RequestMethod\CurlPost`, and
`RequestMethod\SocketPost`, plus the request wrapper classes
`RequestMethod\Curl` and `RequestMethod\Socket`.

Changes that narrow those APIs, such as adding native scalar parameter types,
adding native return types to existing public methods, making public non-final
classes `readonly` or `final`, removing public classes, or removing existing
constructor argument forms, should be reserved for a major release.

The `RequestMethod::submit()` interface intentionally keeps its 1.x-compatible
native signature. Implementations are still expected to return the body of the
reCAPTCHA response as a string.

### 1.5.1 Compatibility Focus

Release 1.5.1 restores 1.4.x compatibility and keeps the 1.5.0 reliability fixes.

- Restored 1.x public API contracts by removing narrowing type hints and `readonly` modifiers from public non-final DTOs.
- Kept custom `RequestMethod` implementations working without native return types.
- Kept legacy input handling for compatibility.
- Fixed deprecated `curl_close()` usage for PHP 8.5+.
- Kept the cURL handle cleanup, HTTP/1.1 handling, and TLS verification changes.

### BC Testing

The test suite covers the backward compatibility cases below:

- `testLegacyRequestMethodImplementationWithoutReturnTypeCanBeUsed()`: Custom implementations without strict return types.
- `testNonStringRequestMethodResponseReturnsBadResponse()`: Non-string responses from custom implementations.
- `testScalarResponseIsAccepted()`: Scalar inputs such as integers in `verify()`.
- `testZeroAsStringIsValidResponse()`: The "0" response token.
- `testVerifyReturnsErrorOnNullResponse()`: Null input handling.

These tests document expected 1.x behavior.
19 changes: 19 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,25 @@ a good idea to run them locally before submission to avoid getting things
bounced back. That said, tests can be a little daunting so feel free to submit
your PR and ask for help.

### Backward Compatibility Testing

Changes to public APIs must preserve backward compatibility within the 1.x
release line. When changes affect public methods, parameters, or return types,
include tests for:

1. Legacy implementation support. If interface contracts change, verify that old
implementations still work without modification.
2. Type coercion scenarios. Verify that null, scalar, and non-standard inputs
behave as they did in 1.4.x.
3. Custom `RequestMethod` implementations. Verify that user-provided
implementations continue to work without return type declarations.

See the BC-focused tests in [`ReCaptchaTest.php`](./tests/ReCaptcha/ReCaptchaTest.php):
- `testLegacyRequestMethodImplementationWithoutReturnTypeCanBeUsed()`
- `testNonStringRequestMethodResponseReturnsBadResponse()`
- `testScalarResponseIsAccepted()`
- `testZeroAsStringIsValidResponse()`

## Code reviews

All submissions, including submissions by project members, require review.
Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ and v3.
- reCAPTCHA: https://cloud.google.com/security/products/recaptcha
- This repo: https://github.com/google/recaptcha
- Hosted demo: https://recaptcha-demo.appspot.com/
- Version: 1.5.0
- Version: 1.5.1
- License: BSD, see [LICENSE](LICENSE)

> [!IMPORTANT]
Expand Down Expand Up @@ -76,7 +76,7 @@ This library comes in when you need to verify the user's response. On the PHP
side you need the response from the reCAPTCHA service and secret key from your
credentials. Instantiate the `ReCaptcha` class with your secret key, specify any
additional validation rules, and then call `verify()` with the reCAPTCHA
response (usually in `$_POST[\ReCaptcha\ReCaptcha::USER_TOKEN_PARAMETER]` or the
response (usually in `$_POST[\ReCaptcha\ReCaptcha::RESPONSE_KEY]` or the
response from `grecaptcha.execute()` in JS which is in `$gRecaptchaResponse` in
the example) and user's IP address. For example:

Expand Down Expand Up @@ -169,6 +169,11 @@ $recaptcha = new \ReCaptcha\ReCaptcha($secret, new \ReCaptcha\RequestMethod\Sock

For more details on usage and structure, see [ARCHITECTURE](ARCHITECTURE.md).

The 1.x line preserves compatibility for the public request and response APIs.
See [Public API compatibility](ARCHITECTURE.md#public-api-compatibility) for
details on which API changes require a major release.


### Examples

You can see examples of each reCAPTCHA type in [examples/](examples/). You can
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@
},
"extra": {
"branch-alias": {
"dev-main": "1.4.x-dev"
"dev-main": "1.5.x-dev"
}
},
"scripts": {
"lint": "vendor/bin/php-cs-fixer -vvv check --using-cache=no",
"lint-fix": "vendor/bin/php-cs-fixer -vvv fix --using-cache=no",
"phpstan": "vendor/bin/phpstan",
"test": "XDEBUG_MODE=coverage vendor/bin/phpunit",
"test": "@php -d xdebug.mode=coverage vendor/bin/phpunit",
"serve-examples": "@php -S localhost:8080 -t examples"
},
"config": {
Expand Down
74 changes: 37 additions & 37 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions examples/recaptcha-request-curl.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@
<h2><kbd>POST</kbd> data</h2>
<kbd><pre><?php echo htmlspecialchars(print_r($_POST, true), ENT_QUOTES | ENT_HTML5, 'UTF-8'); ?></pre></kbd>
<?php
// If the form submission includes the "g-captcha-response" field
// If the form submission includes the "g-recaptcha-response" field
// Create an instance of the service using your secret and the CurlPost request method.
/** @var string $secret */
$recaptcha = new ReCaptcha($secret, new CurlPost());

// Make the call to verify the response and also pass the user's IP address
/** @var string $serverName */
$serverName = $_SERVER['SERVER_NAME'];
$serverName = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? '';

/** @var string $responseKey */
$responseKey = $_POST[ReCaptcha::RESPONSE_KEY];
Expand Down
4 changes: 2 additions & 2 deletions examples/recaptcha-request-post.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,14 @@
<h2><kbd>POST</kbd> data</h2>
<kbd><pre><?php echo htmlspecialchars(print_r($_POST, true), ENT_QUOTES | ENT_HTML5, 'UTF-8'); ?></pre></kbd>
<?php
// If the form submission includes the "g-captcha-response" field
// If the form submission includes the "g-recaptcha-response" field
// Create an instance of the service using your secret and the Post request method.
/** @var string $secret */
$recaptcha = new ReCaptcha($secret, new Post());

// Make the call to verify the response and also pass the user's IP address
/** @var string $serverName */
$serverName = $_SERVER['SERVER_NAME'];
$serverName = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? '';

/** @var string $responseKey */
$responseKey = $_POST[ReCaptcha::RESPONSE_KEY];
Expand Down
Loading
Loading