Skip to content

Commit 089e474

Browse files
[API-7343] Enable scores percentiles in the scores api. (#100)
Enable scores percentiles in the scores api
1 parent f8bd37f commit 089e474

2 files changed

Lines changed: 61 additions & 5 deletions

File tree

sift/client.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,7 @@ def track(
180180
params['force_workflow_run'] = 'true'
181181

182182
if include_score_percentiles:
183-
field_types = ['SCORE_PERCENTILES']
184-
params['fields'] = ','.join(field_types)
183+
params['fields'] = 'SCORE_PERCENTILES'
185184
try:
186185
response = self.session.post(
187186
path,
@@ -193,7 +192,7 @@ def track(
193192
except requests.exceptions.RequestException as e:
194193
raise ApiException(str(e), path)
195194

196-
def score(self, user_id, timeout=None, abuse_types=None, version=None):
195+
def score(self, user_id, timeout=None, abuse_types=None, version=None, include_score_percentiles=False):
197196
"""Retrieves a user's fraud score from the Sift Science API.
198197
This call is blocking. Check out https://siftscience.com/resources/references/score_api.html
199198
for more information on our Score response structure.
@@ -210,6 +209,9 @@ def score(self, user_id, timeout=None, abuse_types=None, version=None):
210209
211210
version(optional): Use a different version of the Sift Science API for this call.
212211
212+
include_score_percentiles(optional) : Whether to add new parameter in the query parameter.
213+
if include_score_percentiles is true then add a new parameter called fields in the query parameter
214+
213215
Returns:
214216
A sift.client.Response object if the score call succeeded, or raises
215217
an ApiException.
@@ -227,6 +229,9 @@ def score(self, user_id, timeout=None, abuse_types=None, version=None):
227229
if abuse_types:
228230
params['abuse_types'] = ','.join(abuse_types)
229231

232+
if include_score_percentiles:
233+
params['fields'] = 'SCORE_PERCENTILES'
234+
230235
url = self._score_url(user_id, version)
231236

232237
try:
@@ -239,7 +244,7 @@ def score(self, user_id, timeout=None, abuse_types=None, version=None):
239244
except requests.exceptions.RequestException as e:
240245
raise ApiException(str(e), url)
241246

242-
def get_user_score(self, user_id, timeout=None, abuse_types=None):
247+
def get_user_score(self, user_id, timeout=None, abuse_types=None, include_score_percentiles=False):
243248
"""Fetches the latest score(s) computed for the specified user and abuse types from the Sift Science API.
244249
As opposed to client.score() and client.rescore_user(), this *does not* compute a new score for the user; it
245250
simply fetches the latest score(s) which have computed. These scores may be arbitrarily old.
@@ -256,6 +261,9 @@ def get_user_score(self, user_id, timeout=None, abuse_types=None):
256261
should be returned (if scores were requested). If not specified, a score will
257262
be returned for every abuse_type to which you are subscribed.
258263
264+
include_score_percentiles(optional) : Whether to add new parameter in the query parameter.
265+
if include_score_percentiles is true then add a new parameter called fields in the query parameter
266+
259267
Returns:
260268
A sift.client.Response object if the score call succeeded, or raises
261269
an ApiException.
@@ -271,6 +279,9 @@ def get_user_score(self, user_id, timeout=None, abuse_types=None):
271279
if abuse_types:
272280
params['abuse_types'] = ','.join(abuse_types)
273281

282+
if include_score_percentiles:
283+
params['fields'] = 'SCORE_PERCENTILES'
284+
274285
try:
275286
response = self.session.get(
276287
url,

tests/test_client.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1411,7 +1411,7 @@ def test_update_psp_merchant_profile(self):
14111411
self.assertIsInstance(response, sift.client.Response)
14121412
assert ('address' in response.body)
14131413

1414-
def test_with__include_score_percentiles_ok(self):
1414+
def test_with_include_score_percentiles_ok(self):
14151415
event = '$transaction'
14161416
mock_response = mock.Mock()
14171417
mock_response.content = '{"status": 0, "error_message": "OK"}'
@@ -1453,6 +1453,51 @@ def test_include_score_percentiles_as_false_ok(self):
14531453
assert (response.api_status == 0)
14541454
assert (response.api_error_message == "OK")
14551455

1456+
def test_score_api_include_score_percentiles_ok(self):
1457+
mock_response = mock.Mock()
1458+
mock_response.content = score_response_json()
1459+
mock_response.json.return_value = json.loads(mock_response.content)
1460+
mock_response.status_code = 200
1461+
mock_response.headers = response_with_data_header()
1462+
with mock.patch.object(self.sift_client.session, 'get') as mock_get:
1463+
mock_get.return_value = mock_response
1464+
response = self.sift_client.score(user_id='12345', include_score_percentiles=True)
1465+
mock_get.assert_called_with(
1466+
'https://api.siftscience.com/v205/score/12345',
1467+
params={'api_key': self.test_key, 'fields': 'SCORE_PERCENTILES'},
1468+
headers=mock.ANY,
1469+
timeout=mock.ANY)
1470+
self.assertIsInstance(response, sift.client.Response)
1471+
assert (response.is_ok())
1472+
assert (response.api_error_message == "OK")
1473+
assert (response.body['score'] == 0.85)
1474+
assert (response.body['scores']['content_abuse']['score'] == 0.14)
1475+
assert (response.body['scores']['payment_abuse']['score'] == 0.97)
1476+
1477+
def test_get_user_score_include_score_percentiles_ok(self):
1478+
"""Test the GET /{version}/users/{userId}/score API, i.e. client.get_user_score()
1479+
"""
1480+
test_timeout = 5
1481+
mock_response = mock.Mock()
1482+
mock_response.content = USER_SCORE_RESPONSE_JSON
1483+
mock_response.json.return_value = json.loads(mock_response.content)
1484+
mock_response.status_code = 200
1485+
mock_response.headers = response_with_data_header()
1486+
with mock.patch.object(self.sift_client.session, 'get') as mock_get:
1487+
mock_get.return_value = mock_response
1488+
response = self.sift_client.get_user_score(user_id='12345', timeout=test_timeout, include_score_percentiles=True)
1489+
mock_get.assert_called_with(
1490+
'https://api.siftscience.com/v205/users/12345/score',
1491+
params={'api_key': self.test_key, 'fields': 'SCORE_PERCENTILES'},
1492+
headers=mock.ANY,
1493+
timeout=test_timeout)
1494+
self.assertIsInstance(response, sift.client.Response)
1495+
assert (response.is_ok())
1496+
assert (response.api_error_message == "OK")
1497+
assert (response.body['entity_id'] == '12345')
1498+
assert (response.body['scores']['content_abuse']['score'] == 0.14)
1499+
assert (response.body['scores']['payment_abuse']['score'] == 0.97)
1500+
assert ('latest_decisions' in response.body)
14561501

14571502
def main():
14581503
unittest.main()

0 commit comments

Comments
 (0)