From 5fb59c5ba91035412253e992f37599baf7f26a9f Mon Sep 17 00:00:00 2001 From: William Storey Date: Tue, 16 Sep 2025 21:33:55 +0000 Subject: [PATCH 1/3] Add credit_application and fund_transfer event types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add credit_application and fund_transfer to the /event/type validation enum and corresponding test cases. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- HISTORY.rst | 2 ++ src/minfraud/validation.py | 2 ++ tests/test_validation.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index 2470852..68f8016 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -9,6 +9,8 @@ History * Setuptools has been replaced with the uv build backend for building the package. * Added ``securepay`` to the ``/payment/processor`` validation. +* Added ``credit_application`` and ``fund_transfer`` to the ``/event/type`` + validation. 3.1.0 (2025-05-23) ++++++++++++++++++ diff --git a/src/minfraud/validation.py b/src/minfraud/validation.py index 76ef668..51ad232 100644 --- a/src/minfraud/validation.py +++ b/src/minfraud/validation.py @@ -285,7 +285,9 @@ def _credit_card_token(s: str) -> str: [ "account_creation", "account_login", + "credit_application", "email_change", + "fund_transfer", "password_reset", "payout_change", "purchase", diff --git a/tests/test_validation.py b/tests/test_validation.py index 206d753..fdcd321 100644 --- a/tests/test_validation.py +++ b/tests/test_validation.py @@ -324,7 +324,9 @@ def test_type(self) -> None: for good in ( "account_creation", "account_login", + "credit_application", "email_change", + "fund_transfer", "password_reset", "payout_change", "purchase", From 2aa733bab9ce03bcf48ce98ad4458dfeb8ac85ac Mon Sep 17 00:00:00 2001 From: William Storey Date: Tue, 16 Sep 2025 21:39:35 +0000 Subject: [PATCH 2/3] Add /event/party field with agent and customer values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new /event/party enum field to specify which party is submitting the transaction. Valid values are "agent" and "customer". The field is positioned first in the event object. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- HISTORY.rst | 2 ++ README.rst | 1 + src/minfraud/validation.py | 3 +++ tests/data/full-transaction-request.json | 1 + tests/test_validation.py | 6 ++++++ 5 files changed, 13 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index 68f8016..72188b6 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -11,6 +11,8 @@ History * Added ``securepay`` to the ``/payment/processor`` validation. * Added ``credit_application`` and ``fund_transfer`` to the ``/event/type`` validation. +* Added the input ``/event/party``. This is the party submitting the + transaction. 3.1.0 (2025-05-23) ++++++++++++++++++ diff --git a/README.rst b/README.rst index 7dd93cc..65599c2 100644 --- a/README.rst +++ b/README.rst @@ -156,6 +156,7 @@ Score, Insights and Factors Example >>> 'user_agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36' >>> }, >>> 'event': { + >>> 'party': 'customer', >>> 'shop_id': 's2123', >>> 'type': 'purchase', >>> 'transaction_id': 'txn3134133', diff --git a/src/minfraud/validation.py b/src/minfraud/validation.py index 51ad232..c229428 100644 --- a/src/minfraud/validation.py +++ b/src/minfraud/validation.py @@ -281,6 +281,8 @@ def _credit_card_token(s: str) -> str: ) +_event_party = In(["agent", "customer"]) + _event_type = In( [ "account_creation", @@ -348,6 +350,7 @@ def _uri(s: str) -> str: "domain": _hostname, }, "event": { + "party": _event_party, "shop_id": str, "time": _rfc3339_datetime, "type": _event_type, diff --git a/tests/data/full-transaction-request.json b/tests/data/full-transaction-request.json index 73df585..ee02605 100644 --- a/tests/data/full-transaction-request.json +++ b/tests/data/full-transaction-request.json @@ -1,5 +1,6 @@ { "event": { + "party": "customer", "transaction_id": "txn3134133", "shop_id": "s2123", "time": "2014-04-12T23:20:50.052+00:00", diff --git a/tests/test_validation.py b/tests/test_validation.py index fdcd321..18a0c6f 100644 --- a/tests/test_validation.py +++ b/tests/test_validation.py @@ -308,6 +308,12 @@ def test_domain(self) -> None: class TestEvent(ValidationBase, unittest.TestCase): + def test_party(self) -> None: + for good in ("agent", "customer"): + self.check_transaction({"event": {"party": good}}) + for bad in ("bad", 1, ""): + self.check_invalid_transaction({"event": {"party": bad}}) + def test_transaction(self) -> None: self.check_transaction_str_type("event", "transaction_id") From e37fafca0bc5ecfcd1f6c112c50a8a4de3d15f8d Mon Sep 17 00:00:00 2001 From: William Storey Date: Tue, 16 Sep 2025 21:44:57 +0000 Subject: [PATCH 3/3] Add /payment/method field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new /payment/method enum field to specify the payment method associated with the transaction. Valid values are bank_debit, bank_redirect, bank_transfer, buy_now_pay_later, card, crypto, digital_wallet, gift_card, real_time_payment, and rewards. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- HISTORY.rst | 2 ++ README.rst | 1 + src/minfraud/validation.py | 16 ++++++++++++++++ tests/data/full-transaction-request.json | 1 + tests/test_validation.py | 17 +++++++++++++++++ 5 files changed, 37 insertions(+) diff --git a/HISTORY.rst b/HISTORY.rst index 72188b6..905d3e4 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -13,6 +13,8 @@ History validation. * Added the input ``/event/party``. This is the party submitting the transaction. +* Added the input ``/payment/method``. This is the payment method associated + with the transaction. 3.1.0 (2025-05-23) ++++++++++++++++++ diff --git a/README.rst b/README.rst index 65599c2..92c58c6 100644 --- a/README.rst +++ b/README.rst @@ -210,6 +210,7 @@ Score, Insights and Factors Example >>> 'payment': { >>> 'decline_code': 'invalid number', >>> 'was_authorized': False, + >>> 'method': 'card', >>> 'processor': 'stripe' >>> }, >>> 'shopping_cart': [{ diff --git a/src/minfraud/validation.py b/src/minfraud/validation.py index c229428..6dc9be9 100644 --- a/src/minfraud/validation.py +++ b/src/minfraud/validation.py @@ -98,6 +98,21 @@ def _hostname(hostname: str) -> str: _shipping_address["delivery_speed"] = _delivery_speed +_payment_method = In( + [ + "bank_debit", + "bank_redirect", + "bank_transfer", + "buy_now_pay_later", + "card", + "crypto", + "digital_wallet", + "gift_card", + "real_time_payment", + "rewards", + ], +) + _payment_processor = In( [ "adyen", @@ -320,6 +335,7 @@ def _uri(s: str) -> str: }, "billing": _address, "payment": { + "method": _payment_method, "processor": _payment_processor, "was_authorized": bool, "decline_code": str, diff --git a/tests/data/full-transaction-request.json b/tests/data/full-transaction-request.json index ee02605..c49b508 100644 --- a/tests/data/full-transaction-request.json +++ b/tests/data/full-transaction-request.json @@ -42,6 +42,7 @@ "delivery_speed": "same_day" }, "payment": { + "method": "card", "processor": "stripe", "was_authorized": false, "decline_code": "invalid number" diff --git a/tests/test_validation.py b/tests/test_validation.py index 18a0c6f..0d31a53 100644 --- a/tests/test_validation.py +++ b/tests/test_validation.py @@ -378,6 +378,23 @@ def test_referrer_uri(self) -> None: class TestPayment(ValidationBase, unittest.TestCase): + def test_method(self) -> None: + for good in ( + "bank_debit", + "bank_redirect", + "bank_transfer", + "buy_now_pay_later", + "card", + "crypto", + "digital_wallet", + "gift_card", + "real_time_payment", + "rewards", + ): + self.check_transaction({"payment": {"method": good}}) + for bad in ("bad", 1, ""): + self.check_invalid_transaction({"payment": {"method": bad}}) + def test_processor(self) -> None: for good in ("adyen", "stripe"): self.check_transaction({"payment": {"processor": good}})