From 72da723f29891b2f10934975ea0adae7ecc5d98d Mon Sep 17 00:00:00 2001 From: Gregory Oschwald Date: Wed, 7 May 2025 13:42:13 -0700 Subject: [PATCH] Add new matchesPostal phone output --- CHANGELOG.md | 3 ++ .../com/maxmind/minfraud/response/Phone.java | 33 +++++++++++++++++++ .../response/FactorsResponseTest.java | 4 +++ .../response/InsightsResponseTest.java | 13 ++++++++ .../maxmind/minfraud/response/PhoneTest.java | 3 ++ .../test-data/insights-response.json | 2 ++ 6 files changed, 58 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12e5b547..1317e1af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ CHANGELOG 3.7.0 ------------------ +* Added support for the `/billing_phone/matches_postal` and + `/shipping_phone/matches_postal` outputs. These are available as the + `matchesPostal` method on `com.maxmind.minfraud.response.Phone`. * Added `CRYPTOMUS` to the `Payment.Processor` enum. 3.6.0 (2025-02-10) diff --git a/src/main/java/com/maxmind/minfraud/response/Phone.java b/src/main/java/com/maxmind/minfraud/response/Phone.java index bea753bf..fa85a6d1 100644 --- a/src/main/java/com/maxmind/minfraud/response/Phone.java +++ b/src/main/java/com/maxmind/minfraud/response/Phone.java @@ -9,27 +9,49 @@ public final class Phone extends AbstractModel { private final String country; private final Boolean isVoip; + private final Boolean matchesPostal; private final String networkOperator; private final String numberType; /** * @param country The ISO 3166-2 country code for the phone number. * @param isVoip Whether the number is VoIP. + * @param matchesPostal Whether the phone number matches the postal code. * @param networkOperator The network operator associated with the phone number. * @param numberType The type of the phone number. */ public Phone( @JsonProperty("country") String country, @JsonProperty("is_voip") Boolean isVoip, + @JsonProperty("matches_postal") Boolean matchesPostal, @JsonProperty("network_operator") String networkOperator, @JsonProperty("number_type") String numberType ) { this.country = country; this.isVoip = isVoip; + this.matchesPostal = matchesPostal; this.networkOperator = networkOperator; this.numberType = numberType; } + /** + * @param country The ISO 3166-2 country code for the phone number. + * @param isVoip Whether the number is VoIP. + * @param networkOperator The network operator associated with the phone number. + * @param numberType The type of the phone number. + * + * @deprecated use other constructor instead. + */ + @Deprecated + public Phone( + String country, + Boolean isVoip, + String networkOperator, + String numberType + ) { + this(country, isVoip, null, networkOperator, numberType); + } + /** * Constructor for {@code Phone}. */ @@ -56,6 +78,17 @@ public Boolean isVoip() { return isVoip; } + /** + * @return This is {@code true} if the phone number's prefix is commonly associated with the + * postal code. It is {@code false} if the prefix is not associated with the postal code. + * It is non-{@code null} only when the phone number is in the US, the number prefix is + * in our database, and the postal code and country are provided in the request. + */ + @JsonProperty("matches_postal") + public Boolean matchesPostal() { + return matchesPostal; + } + /** * @return The name of the original network operator associated with the phone number. This * field does not reflect phone numbers that have been ported from the original operator to diff --git a/src/test/java/com/maxmind/minfraud/response/FactorsResponseTest.java b/src/test/java/com/maxmind/minfraud/response/FactorsResponseTest.java index 0326da99..36b2c967 100644 --- a/src/test/java/com/maxmind/minfraud/response/FactorsResponseTest.java +++ b/src/test/java/com/maxmind/minfraud/response/FactorsResponseTest.java @@ -20,9 +20,11 @@ public void testFactors() throws Exception { .startObject() .startObjectField("billing_phone") .put("is_voip", false) + .put("matches_postal", true) .end() .startObjectField("shipping_phone") .put("is_voip", true) + .put("matches_postal", false) .end() .startObjectField("subscores") .put("avs_result", 0.01) @@ -66,7 +68,9 @@ public void testFactors() throws Exception { ); assertTrue(factors.getShippingPhone().isVoip(), "correct shipping phone isVoip"); + assertFalse(factors.getShippingPhone().matchesPostal(), "correct shipping phone matchesPostal"); assertFalse(factors.getBillingPhone().isVoip(), "correct billing phone isVoip"); + assertTrue(factors.getBillingPhone().matchesPostal(), "correct billing phone matchesPostal"); assertEquals( Double.valueOf(0.01), diff --git a/src/test/java/com/maxmind/minfraud/response/InsightsResponseTest.java b/src/test/java/com/maxmind/minfraud/response/InsightsResponseTest.java index b0138bac..23b73e30 100644 --- a/src/test/java/com/maxmind/minfraud/response/InsightsResponseTest.java +++ b/src/test/java/com/maxmind/minfraud/response/InsightsResponseTest.java @@ -45,12 +45,14 @@ public void testInsights() throws Exception { .end() .startObjectField("shipping_phone") .put("is_voip", true) + .put("matches_postal", false) .end() .startObjectField("billing_address") .put("is_in_ip_country", true) .end() .startObjectField("billing_phone") .put("is_voip", false) + .put("matches_postal", true) .end() .put("funds_remaining", 1.20) .put("queries_remaining", 123) @@ -78,16 +80,27 @@ public void testInsights() throws Exception { ); assertTrue(insights.getCreditCard().isBusiness(), "correct credit card is business"); assertTrue(insights.getCreditCard().isPrepaid(), "correct credit card prepaid"); + assertTrue( insights.getShippingAddress().isInIpCountry(), "correct shipping address is in IP country" ); assertTrue(insights.getShippingPhone().isVoip(), "correct shipping phone isVoip"); + assertFalse( + insights.getShippingPhone().matchesPostal(), + "correct shipping phone matchesPostal" + ); + assertTrue( insights.getBillingAddress().isInIpCountry(), "correct billing address is in IP country" ); assertFalse(insights.getBillingPhone().isVoip(), "correct billing phone isVoip"); + assertTrue( + insights.getBillingPhone().matchesPostal(), + "correct billing phone matchesPostal" + ); + assertEquals( Double.valueOf(1.20), insights.getFundsRemaining(), diff --git a/src/test/java/com/maxmind/minfraud/response/PhoneTest.java b/src/test/java/com/maxmind/minfraud/response/PhoneTest.java index a8cf3fa9..decc4193 100644 --- a/src/test/java/com/maxmind/minfraud/response/PhoneTest.java +++ b/src/test/java/com/maxmind/minfraud/response/PhoneTest.java @@ -1,6 +1,7 @@ package com.maxmind.minfraud.response; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import com.fasterxml.jackson.jr.ob.JSON; @@ -17,6 +18,7 @@ public void testPhone() throws Exception { .startObject() .put("country", "US") .put("is_voip", true) + .put("matches_postal", false) .put("network_operator", "Operator") .put("number_type", "fixed") .end() @@ -25,6 +27,7 @@ public void testPhone() throws Exception { assertEquals("US", phone.getCountry()); assertTrue(phone.isVoip()); + assertFalse(phone.matchesPostal()); assertEquals("Operator", phone.getNetworkOperator()); assertEquals("fixed", phone.getNumberType()); } diff --git a/src/test/resources/test-data/insights-response.json b/src/test/resources/test-data/insights-response.json index a87dfef7..0302c7bc 100644 --- a/src/test/resources/test-data/insights-response.json +++ b/src/test/resources/test-data/insights-response.json @@ -135,6 +135,7 @@ "billing_phone": { "country": "US", "is_voip": false, + "matches_postal": true, "network_operator": "Verizon/1", "number_type": "fixed" }, @@ -185,6 +186,7 @@ "shipping_phone": { "country": "CA", "is_voip": true, + "matches_postal": false, "network_operator": "Telus Mobility-SVR/2", "number_type": "mobile" },