Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for new phone outputs #146

Merged
merged 2 commits into from
Jun 27, 2024
Merged
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
5 changes: 5 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ History
``ip_address`` parameter optional. Now the ``tag`` and at least one of the
following parameters must be supplied: ``ip_address``, ``maxmind_id``,
``minfraud_id``, ``transaction_id``.
* Added ``billing_phone`` and ``shipping_phone`` properties to the minFraud
Insights and Factors response models. These contain objects with information
about the respective phone numbers. Please see `our developer
site <https://dev.maxmind.com/minfraud/api-documentation/responses/>`_ for
more information.

2.10.0 (2024-04-16)
+++++++++++++++++++
Expand Down
92 changes: 92 additions & 0 deletions minfraud/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,58 @@ class ShippingAddress:
}


@_inflate_to_namedtuple
class Phone:
"""Information about the billing or shipping phone number.

.. attribute:: country

The two-character ISO 3166-1 country code for the country associated with
the phone number.

:type: str | None

.. attribute:: is_voip

This property is ``True`` if the phone number is a Voice over Internet
Protocol (VoIP) number allocated by a regulator. The property is
``False`` when the number is not VoIP. If the phone number was not
provided or we do not have data for it, the property will be ``None``.

:type: bool | None

.. attribute:: network_operator

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 another, nor does it identify mobile
virtual network operators.

:type: str | None

.. attribute:: number_type

One of the following values: fixed or mobile. Additional values may be
added in the future.

:type: str | None

"""

country: Optional[str]
is_voip: Optional[bool]
network_operator: Optional[str]
number_type: Optional[str]

__slots__ = ()
_fields = {
"country": None,
"is_voip": None,
"network_operator": None,
"number_type": None,
}


@_inflate_to_namedtuple
class ServiceWarning:
"""Warning from the web service.
Expand Down Expand Up @@ -1110,11 +1162,27 @@ class Factors:

:type: BillingAddress

.. attribute:: billing_phone

A :class:`.Phone` object containing minFraud data related to the billing
phone used in the transaction.

:type: Phone

.. attribute:: shipping_address

A :class:`.ShippingAddress` object containing
minFraud data related to the shipping address used in the transaction.

:type: ShippingAddress

.. attribute:: shipping_phone

A :class:`.Phone` object containing minFraud data related to the shipping
phone used in the transaction.

:type: Phone

.. attribute:: subscores

A :class:`.Subscores` object containing scores for many of the
Expand All @@ -1123,6 +1191,7 @@ class Factors:
"""

billing_address: BillingAddress
billing_phone: Phone
credit_card: CreditCard
disposition: Disposition
funds_remaining: float
Expand All @@ -1133,12 +1202,14 @@ class Factors:
queries_remaining: int
risk_score: float
shipping_address: ShippingAddress
shipping_phone: Phone
subscores: Subscores
warnings: Tuple[ServiceWarning, ...]

__slots__ = ()
_fields = {
"billing_address": BillingAddress,
"billing_phone": Phone,
"credit_card": CreditCard,
"disposition": Disposition,
"funds_remaining": None,
Expand All @@ -1149,6 +1220,7 @@ class Factors:
"queries_remaining": None,
"risk_score": None,
"shipping_address": ShippingAddress,
"shipping_phone": Phone,
"subscores": Subscores,
"warnings": _create_warnings,
}
Expand Down Expand Up @@ -1241,13 +1313,30 @@ class Insights:

:type: BillingAddress

.. attribute:: billing_phone

A :class:`.Phone` object containing minFraud data related to the billing
phone used in the transaction.

:type: Phone

.. attribute:: shipping_address

A :class:`.ShippingAddress` object containing
minFraud data related to the shipping address used in the transaction.

:type: ShippingAddress

.. attribute:: shipping_phone

A :class:`.Phone` object containing minFraud data related to the shipping
phone used in the transaction.

:type: Phone
"""

billing_address: BillingAddress
billing_phone: Phone
credit_card: CreditCard
device: Device
disposition: Disposition
Expand All @@ -1258,11 +1347,13 @@ class Insights:
queries_remaining: int
risk_score: float
shipping_address: ShippingAddress
shipping_phone: Phone
warnings: Tuple[ServiceWarning, ...]

__slots__ = ()
_fields = {
"billing_address": BillingAddress,
"billing_phone": Phone,
"credit_card": CreditCard,
"device": Device,
"disposition": Disposition,
Expand All @@ -1273,6 +1364,7 @@ class Insights:
"queries_remaining": None,
"risk_score": None,
"shipping_address": ShippingAddress,
"shipping_phone": Phone,
"warnings": _create_warnings,
}

Expand Down
12 changes: 12 additions & 0 deletions tests/data/factors-response.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@
"distance_to_ip_location": 5465,
"is_in_ip_country": false
},
"billing_phone": {
"country": "US",
"is_voip": true,
"network_operator": "Verizon/1",
"number_type": "fixed"
},
"credit_card": {
"issuer": {
"name": "Bank of No Hope",
Expand Down Expand Up @@ -159,6 +165,12 @@
"latitude": 35.704729,
"longitude": -97.568619
},
"shipping_phone": {
"country": "CA",
"is_voip": true,
"network_operator": "Telus Mobility-SVR/2",
"number_type": "mobile"
},
"subscores": {
"avs_result": 0.01,
"billing_address": 0.02,
Expand Down
12 changes: 12 additions & 0 deletions tests/data/insights-response.json
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@
"distance_to_ip_location": 5465,
"is_in_ip_country": false
},
"billing_phone": {
"country": "US",
"is_voip": true,
"network_operator": "Verizon/1",
"number_type": "fixed"
},
"credit_card": {
"issuer": {
"name": "Bank of No Hope",
Expand Down Expand Up @@ -159,6 +165,12 @@
"latitude": 35.704729,
"longitude": -97.568619
},
"shipping_phone": {
"country": "CA",
"is_voip": true,
"network_operator": "Telus Mobility-SVR/2",
"number_type": "mobile"
},
"warnings": [
{
"code": "INPUT_INVALID",
Expand Down
19 changes: 19 additions & 0 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,21 @@ def test_issuer(self):
self.assertEqual(phone, issuer.phone_number)
self.assertEqual(True, issuer.matches_provided_phone_number)

def test_phone(self):
phone = Phone(
{
"country": "US",
"is_voip": True,
"network_operator": "Verizon/1",
"number_type": "fixed",
}
)

self.assertEqual("US", phone.country)
self.assertEqual(True, phone.is_voip)
self.assertEqual("Verizon/1", phone.network_operator)
self.assertEqual("fixed", phone.number_type)

def test_warning(self):
code = "INVALID_INPUT"
msg = "Input invalid"
Expand Down Expand Up @@ -327,7 +342,9 @@ def factors_response(self):
"device": {"id": "b643d445-18b2-4b9d-bad4-c9c4366e402a"},
"email": {"domain": {"first_seen": "2014-02-23"}, "is_free": True},
"shipping_address": {"is_in_ip_country": True},
"shipping_phone": {"is_voip": True},
"billing_address": {"is_in_ip_country": True},
"billing_phone": {"is_voip": True},
"funds_remaining": 10.01,
"queries_remaining": 123,
"risk_score": 0.01,
Expand Down Expand Up @@ -367,8 +384,10 @@ def check_insights_data(self, insights, uuid):
self.assertEqual("reject", insights.disposition.action)
self.assertEqual(True, insights.email.is_free)
self.assertEqual("2014-02-23", insights.email.domain.first_seen)
self.assertEqual(True, insights.shipping_phone.is_voip)
self.assertEqual(True, insights.shipping_address.is_in_ip_country)
self.assertEqual(True, insights.billing_address.is_in_ip_country)
self.assertEqual(True, insights.billing_phone.is_voip)
self.assertEqual(uuid, insights.id)
self.assertEqual(10.01, insights.funds_remaining)
self.assertEqual(123, insights.queries_remaining)
Expand Down
Loading