From f621b07b46d7d615865881bcac501b0d2a63eaf2 Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Tue, 20 Jan 2026 09:01:46 -0800 Subject: [PATCH 1/3] Add anonymizer property to IpAddress model Expose the GeoIP2 Insights anonymizer data in the minFraud IpAddress model. This was previously available in the underlying GeoIP2 library (since 3.3.0) but not exposed in minFraud responses. Co-Authored-By: Claude Opus 4.5 --- CHANGELOG.md | 5 +++ src/MinFraud/Model/IpAddress.php | 14 ++++++++ .../Test/MinFraud/Model/InsightsTest.php | 32 +++++++++++++++++++ tests/data/minfraud/factors-response.json | 10 ++++++ tests/data/minfraud/insights-response.json | 10 ++++++ 5 files changed, 71 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 829c3e4c..4252c395 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ CHANGELOG 3.6.0 ------------------ +* Added the `anonymizer` property to `MaxMind\MinFraud\Model\IpAddress`. This + contains anonymizer data from the GeoIP2 Insights response, including VPN + detection confidence, provider name, and network last seen date. This was + previously available in the GeoIP2 library but not exposed in minFraud + responses. * Added `banquest`, `summit_payments`, and `yaadpay` to the payment processor validation. diff --git a/src/MinFraud/Model/IpAddress.php b/src/MinFraud/Model/IpAddress.php index 4c4ea43b..3c671688 100644 --- a/src/MinFraud/Model/IpAddress.php +++ b/src/MinFraud/Model/IpAddress.php @@ -5,6 +5,7 @@ namespace MaxMind\MinFraud\Model; use GeoIp2\Model\Insights; +use GeoIp2\Record\Anonymizer; use GeoIp2\Record\City; use GeoIp2\Record\Continent; use GeoIp2\Record\Country; @@ -18,6 +19,13 @@ */ class IpAddress implements \JsonSerializable { + /** + * @var Anonymizer data for the anonymizer status of the requested IP + * address. This object contains information about whether + * the IP address belongs to an anonymous network. + */ + public readonly Anonymizer $anonymizer; + /** * @var City city data for the requested IP address */ @@ -123,6 +131,7 @@ public function __construct(?array $response, array $locales = ['en']) $this->representedCountry = $insights->representedCountry; $this->subdivisions = $insights->subdivisions; $this->traits = $insights->traits; + $this->anonymizer = $insights->anonymizer; $this->location = new GeoIp2Location($response['location'] ?? []); $this->risk = $response['risk'] ?? null; @@ -143,6 +152,11 @@ public function jsonSerialize(): ?array { $js = []; + $anonymizer = $this->anonymizer->jsonSerialize(); + if (!empty($anonymizer)) { + $js['anonymizer'] = $anonymizer; + } + $city = $this->city->jsonSerialize(); if (!empty($city)) { $js['city'] = $city; diff --git a/tests/MaxMind/Test/MinFraud/Model/InsightsTest.php b/tests/MaxMind/Test/MinFraud/Model/InsightsTest.php index 9b788764..a5046383 100644 --- a/tests/MaxMind/Test/MinFraud/Model/InsightsTest.php +++ b/tests/MaxMind/Test/MinFraud/Model/InsightsTest.php @@ -124,6 +124,38 @@ public function testInsightsProperties(): void 'correct mobile network code' ); + // Test anonymizer object + foreach ([ + 'isAnonymous', + 'isAnonymousVpn', + 'isHostingProvider', + 'isPublicProxy', + 'isTorExitNode', + ] as $property) { + $this->assertTrue( + $insights->ipAddress->anonymizer->{$property}, + "anonymizer {$property} is true" + ); + } + + $this->assertSame( + $array['ip_address']['anonymizer']['confidence'], + $insights->ipAddress->anonymizer->confidence, + 'correct anonymizer confidence' + ); + + $this->assertSame( + $array['ip_address']['anonymizer']['provider_name'], + $insights->ipAddress->anonymizer->providerName, + 'correct anonymizer provider name' + ); + + $this->assertSame( + $array['ip_address']['anonymizer']['network_last_seen'], + $insights->ipAddress->anonymizer->networkLastSeen, + 'correct anonymizer network last seen' + ); + $this->assertSame( $array['billing_phone']['country'], $insights->billingPhone->country, diff --git a/tests/data/minfraud/factors-response.json b/tests/data/minfraud/factors-response.json index 0e951022..dea20485 100644 --- a/tests/data/minfraud/factors-response.json +++ b/tests/data/minfraud/factors-response.json @@ -111,6 +111,16 @@ "network": "152.216.7.0/24", "organization": "STONEHOUSE office network", "user_type": "government" + }, + "anonymizer": { + "confidence": 99, + "is_anonymous": true, + "is_anonymous_vpn": true, + "is_hosting_provider": true, + "is_public_proxy": true, + "is_tor_exit_node": true, + "network_last_seen": "2025-01-15", + "provider_name": "TestVPN" } }, "billing_address": { diff --git a/tests/data/minfraud/insights-response.json b/tests/data/minfraud/insights-response.json index ca420943..6af029e0 100644 --- a/tests/data/minfraud/insights-response.json +++ b/tests/data/minfraud/insights-response.json @@ -111,6 +111,16 @@ "network": "152.216.7.0/24", "organization": "STONEHOUSE office network", "user_type": "government" + }, + "anonymizer": { + "confidence": 99, + "is_anonymous": true, + "is_anonymous_vpn": true, + "is_hosting_provider": true, + "is_public_proxy": true, + "is_tor_exit_node": true, + "network_last_seen": "2025-01-15", + "provider_name": "TestVPN" } }, "billing_address": { From 287e19a7caba8de9afd06a5993040a88c682d38e Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Tue, 20 Jan 2026 09:42:05 -0800 Subject: [PATCH 2/3] Set release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4252c395..78767fb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ CHANGELOG ========= -3.6.0 +3.6.0 (2026-01-20) ------------------ * Added the `anonymizer` property to `MaxMind\MinFraud\Model\IpAddress`. This From 71520b75fd6016f2100ab394e2b982cad382462e Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Tue, 20 Jan 2026 09:42:27 -0800 Subject: [PATCH 3/3] Update for v3.6.0 --- README.md | 2 +- src/MinFraud/ServiceClient.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5b299c54..4392e5b3 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ You should now have the file `composer.phar` in your project directory. Run in your project root: ``` -php composer.phar require maxmind/minfraud:^3.5.0 +php composer.phar require maxmind/minfraud:^3.6.0 ``` You should now have the files `composer.json` and `composer.lock` as well as diff --git a/src/MinFraud/ServiceClient.php b/src/MinFraud/ServiceClient.php index 87e973a8..f1e2ce02 100644 --- a/src/MinFraud/ServiceClient.php +++ b/src/MinFraud/ServiceClient.php @@ -9,7 +9,7 @@ abstract class ServiceClient { - public const VERSION = 'v3.5.0'; + public const VERSION = 'v3.6.0'; /** * @var Client