|
1 | | -# MaxMind minFraud (WordPress) |
| 1 | +# MaxMind minFraud |
2 | 2 |
|
3 | | -A focused PHP library for the MaxMind minFraud Score API, built for WordPress with `wp_remote_post` and transient caching. No external HTTP dependencies. Drop-in for fraud-scoring at checkout, on signup, or anywhere a 0-99 risk score is useful. |
| 3 | +Score a transaction for fraud risk before you capture the payment. |
4 | 4 |
|
5 | | -## Features |
| 5 | +## What it does |
6 | 6 |
|
7 | | -* 🎯 **One thing well** — wraps the minFraud Score endpoint (the cheapest of MaxMind's three minFraud tiers, returns the 0-99 risk score) |
8 | | -* 💰 **Funds-aware** — surfaces `funds_remaining` / `queries_remaining` from every successful response so you can wire up budget alerts |
9 | | -* 🚦 **Stable error handling** — distinguishes transport / auth / quota failures via `WP_Error` rather than coercing them into a 0 score |
10 | | -* 🪶 **Zero deps** — only PHP and WordPress's HTTP API |
11 | | -* 🔁 **Transient caching** — repeat lookups within a 10-minute window cost zero API calls |
12 | | -* 📦 **Predictable response shape** — getter-friendly Score wrapper that won't break when MaxMind extends the JSON |
| 7 | +MaxMind's minFraud Score takes what you know about an order — the IP, the |
| 8 | +email, the billing address, the payment method — and returns a risk score |
| 9 | +from 0 to 100, informed by what it has seen across everyone else using it. |
13 | 10 |
|
14 | | -## Requirements |
| 11 | +This calls the Score endpoint, hands back a response object, and turns a |
| 12 | +failure into a `WP_Error` rather than an exception, so a checkout can decide |
| 13 | +what to do about it rather than dying. |
| 14 | + |
| 15 | +## Features |
15 | 16 |
|
16 | | -* PHP 7.4 or later |
17 | | -* WordPress 5.0 or later |
18 | | -* MaxMind account + minFraud license key |
| 17 | +* Get a risk score from 0 to 100 for an order |
| 18 | +* Send as much or as little as you have — an IP alone works, more is better |
| 19 | +* Read MaxMind's warnings about fields it could not use |
| 20 | +* Keep an eye on the credits and funds left on the account |
| 21 | +* Get the query id back, for looking a decision up later or disputing it |
| 22 | +* Cache answers, and cache failures briefly so an outage is not amplified |
19 | 23 |
|
20 | 24 | ## Installation |
21 | 25 |
|
22 | 26 | ```bash |
23 | | -composer require arraypress/maxmind-minfraud |
| 27 | +composer require arraypress/wp-maxmind-minfraud |
24 | 28 | ``` |
25 | 29 |
|
26 | 30 | ## Quick start |
27 | 31 |
|
28 | | -```php |
29 | | -use ArrayPress\MaxMind\MinFraud\Client; |
30 | | - |
31 | | -$client = new Client( '123456', 'your-license-key' ); |
32 | | - |
33 | | -$result = $client->check_score( [ |
34 | | - 'device' => [ 'ip_address' => '203.0.113.42' ], |
35 | | - 'email' => [ 'address' => 'alice@example.com' ], |
36 | | - 'billing' => [ |
37 | | - 'country' => 'US', |
38 | | - 'region' => 'CA', |
39 | | - 'city' => 'Los Angeles', |
40 | | - 'postal' => '90210', |
41 | | - ], |
42 | | -] ); |
43 | | - |
44 | | -if ( is_wp_error( $result ) ) { |
45 | | - error_log( 'minFraud failed: ' . $result->get_error_message() ); |
46 | | - return; |
47 | | -} |
48 | | - |
49 | | -if ( $result->is_high_risk() ) { |
50 | | - // 75+ risk score — block / hold the order |
51 | | -} |
52 | | - |
53 | | -$score = $result->get_risk_score(); // 42.5 |
54 | | -$query_id = $result->get_query_id(); // for cross-referencing in MaxMind dashboard |
55 | | -$funds = $result->get_funds_remaining(); // USD remaining on the account |
56 | | -$warnings = $result->get_warnings(); // any non-fatal warnings |
57 | | -``` |
58 | | - |
59 | | -## Configuration |
| 32 | +Score an order and hold the risky ones for review: |
60 | 33 |
|
61 | 34 | ```php |
62 | | -$client = new Client( |
63 | | - 'account-id', |
64 | | - 'license-key', |
65 | | - [ |
66 | | - 'cache_enabled' => true, // default true |
67 | | - 'cache_ttl' => 600, // seconds; default 10 min |
68 | | - 'cache_prefix' => 'mm_', // transient key prefix |
69 | | - ] |
70 | | -); |
71 | | -``` |
72 | | - |
73 | | -## Request payload |
74 | | - |
75 | | -The `check_score()` payload mirrors [MaxMind's spec](https://dev.maxmind.com/minfraud/api-documentation/requests). The minimum is `device.ip_address`, but pass everything you have — minFraud's score quality scales with how much context you give it. |
| 35 | +use ArrayPress\MaxMind\MinFraud\Client; |
76 | 36 |
|
77 | | -Useful fields beyond the basics: |
| 37 | +$client = new Client( $account_id, $license_key ); |
78 | 38 |
|
79 | | -```php |
80 | | -$client->check_score( [ |
81 | | - 'device' => [ |
82 | | - 'ip_address' => '203.0.113.42', |
83 | | - 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', |
84 | | - ], |
85 | | - 'email' => [ 'address' => 'alice@example.com' ], |
86 | | - 'account' => [ 'user_id' => '42' ], |
87 | | - 'billing' => [ 'country' => 'US', 'postal' => '90210' ], |
88 | | - 'shipping' => [ 'country' => 'US', 'postal' => '90210' ], |
89 | | - 'payment' => [ 'processor' => 'stripe' ], |
90 | | - 'event' => [ 'type' => 'purchase' ], |
| 39 | +$score = $client->check_score( [ |
| 40 | + 'device' => [ 'ip_address' => $order->ip ], |
| 41 | + 'email' => [ 'address' => $order->email ], |
| 42 | + 'billing' => [ |
| 43 | + 'country' => $order->billing_country, |
| 44 | + 'postal' => $order->billing_postcode, |
| 45 | + ], |
91 | 46 | ] ); |
92 | | -``` |
93 | 47 |
|
94 | | -## Error handling |
95 | | - |
96 | | -Errors come back as `WP_Error` rather than an empty Score, so you don't accidentally treat an auth failure like a 0 score: |
97 | | - |
98 | | -```php |
99 | | -$result = $client->check_score( $payload ); |
100 | | - |
101 | | -if ( is_wp_error( $result ) ) { |
102 | | - $code = $result->get_error_code(); // 'minfraud_api_error', 'minfraud_bad_response', etc. |
103 | | - $message = $result->get_error_message(); |
104 | | - $data = $result->get_error_data(); // includes HTTP status when relevant |
| 48 | +if ( is_wp_error( $score ) ) { |
| 49 | + return; // Capture anyway; do not lose the sale to an API outage. |
| 50 | +} |
105 | 51 |
|
106 | | - // Fall back to your own rules, log, etc. |
| 52 | +if ( $score->get_risk_score() >= 50 ) { |
| 53 | + $order->flag_for_review( $score->get_query_id() ); |
107 | 54 | } |
108 | 55 | ``` |
109 | 56 |
|
110 | | -Possible error codes: |
| 57 | +The more of the payload you fill in, the better the score. An IP on its own |
| 58 | +is a weak signal. |
111 | 59 |
|
112 | | -* `minfraud_missing_credentials` — account ID / license key not provided |
113 | | -* `minfraud_api_error` — MaxMind returned a non-2xx with an error body |
114 | | -* `minfraud_bad_response` — couldn't decode the JSON |
115 | | -* `http_request_failed` — WordPress transport error (passed through verbatim) |
| 60 | +## What it does not do |
116 | 61 |
|
117 | | -## Why not the official SDK? |
| 62 | +It scores, it does not decide. Where the threshold sits is a business |
| 63 | +question — too low and you turn away real customers, too high and it earns |
| 64 | +nothing — and it is worth reviewing against your own chargebacks rather than |
| 65 | +taking a number from a blog post. |
118 | 66 |
|
119 | | -MaxMind ships an [official PHP SDK](https://github.com/maxmind/minfraud-api-php) that you can absolutely use. This library exists for projects that want a smaller surface area — it's framework-aware (transient cache, `wp_remote_*` transport, no Composer-level Guzzle / PSR-7 deps) and exposes only the Score endpoint, which is what most rule engines actually need. |
| 67 | +## Requirements |
120 | 68 |
|
121 | | -If you need Insights or Factors (subscores for IP location, email reputation, device, etc.), use the official SDK or open an issue. |
| 69 | +* PHP 8.3 or later |
| 70 | +* WordPress 7.1 or later |
| 71 | +* A MaxMind account id and licence key |
122 | 72 |
|
123 | 73 | ## License |
124 | 74 |
|
|
0 commit comments