telesign 2.2.2__tar.gz → 2.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {telesign-2.2.2 → telesign-2.2.4}/LICENSE.txt +7 -7
- {telesign-2.2.2/telesign.egg-info → telesign-2.2.4}/PKG-INFO +9 -9
- {telesign-2.2.2 → telesign-2.2.4}/README.rst +8 -8
- telesign-2.2.4/examples/intelligence/1_get_risk_score_and_related_insights.py +29 -0
- {telesign-2.2.2 → telesign-2.2.4}/setup.py +1 -1
- telesign-2.2.4/telesign/intelligence.py +39 -0
- telesign-2.2.4/telesign/phoneid.py +28 -0
- {telesign-2.2.2 → telesign-2.2.4}/telesign/rest.py +70 -36
- {telesign-2.2.2 → telesign-2.2.4}/telesign/util.py +6 -0
- {telesign-2.2.2 → telesign-2.2.4/telesign.egg-info}/PKG-INFO +9 -9
- {telesign-2.2.2 → telesign-2.2.4}/telesign.egg-info/SOURCES.txt +3 -0
- telesign-2.2.4/tests/test_phoneid.py +48 -0
- {telesign-2.2.2 → telesign-2.2.4}/tests/test_rest.py +68 -0
- telesign-2.2.2/telesign/phoneid.py +0 -54
- {telesign-2.2.2 → telesign-2.2.4}/MANIFEST.in +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/examples/appverify/1_get_status_by_external_id.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/examples/messaging/1_send_message.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/examples/messaging/2_send_message_with_verification_code.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/examples/phoneid/1_check_phone_type_to_block_voip.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/examples/phoneid/2_cleansing.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/examples/score/1_check_phone_number_risk_level.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/examples/voice/1_send_voice_call.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/examples/voice/2_send_voice_call_with_verification_code.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/examples/voice/3_send_voice_call_french.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/setup.cfg +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/telesign/__init__.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/telesign/appverify.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/telesign/messaging.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/telesign/score.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/telesign/voice.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/telesign.egg-info/dependency_links.txt +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/telesign.egg-info/requires.txt +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/telesign.egg-info/top_level.txt +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/tests/__init__.py +0 -0
- {telesign-2.2.2 → telesign-2.2.4}/tests/test_util.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
Copyright (c)
|
|
1
|
+
Copyright (c) 2023 Telesign Corp.
|
|
2
2
|
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
-
this software and associated documentation files (the "Software"), to deal
|
|
5
|
-
the Software without restriction, including without limitation the rights
|
|
6
|
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
-
of the Software, and to permit persons to whom the Software is
|
|
8
|
-
so, subject to the following conditions:
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
9
|
|
|
10
10
|
The above copyright notice and this permission notice shall be included in all
|
|
11
11
|
copies or substantial portions of the Software.
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 1.1
|
|
2
2
|
Name: telesign
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.4
|
|
4
4
|
Summary: TeleSign SDK
|
|
5
5
|
Home-page: https://github.com/telesign/python_telesign
|
|
6
6
|
Author: TeleSign Corp.
|
|
7
7
|
Author-email: support@telesign.com
|
|
8
8
|
License: MIT
|
|
9
9
|
Description: .. image:: https://raw.github.com/TeleSign/python_telesign/master/python_banner.jpg
|
|
10
|
-
|
|
10
|
+
:target: https://standard.telesign.com
|
|
11
11
|
|
|
12
12
|
.. image:: https://img.shields.io/travis/TeleSign/python_telesign.svg
|
|
13
|
-
|
|
13
|
+
:target: https://travis-ci.org/TeleSign/python_telesign
|
|
14
14
|
|
|
15
15
|
.. image:: https://img.shields.io/codecov/c/github/TeleSign/python_telesign.svg
|
|
16
|
-
|
|
16
|
+
:target: https://codecov.io/gh/TeleSign/python_telesign
|
|
17
17
|
|
|
18
18
|
.. image:: https://img.shields.io/pypi/v/telesign.svg
|
|
19
|
-
|
|
19
|
+
:target: https://pypi.python.org/pypi/telesign
|
|
20
20
|
|
|
21
21
|
.. image:: https://img.shields.io/pypi/l/telesign.svg
|
|
22
|
-
|
|
22
|
+
:target: https://github.com/TeleSign/python_telesign/blob/master/LICENSE
|
|
23
23
|
|
|
24
24
|
===================
|
|
25
25
|
TeleSign Python SDK
|
|
@@ -36,7 +36,7 @@ Description: .. image:: https://raw.github.com/TeleSign/python_telesign/master/p
|
|
|
36
36
|
-------------
|
|
37
37
|
|
|
38
38
|
Code documentation is included in the SDK. Complete documentation, quick start guides and reference material
|
|
39
|
-
for the TeleSign API is available within the `TeleSign
|
|
39
|
+
for the TeleSign API is available within the `TeleSign Standard Documentation <https://standard.telesign.com/>`_.
|
|
40
40
|
|
|
41
41
|
Installation
|
|
42
42
|
------------
|
|
@@ -88,14 +88,14 @@ Description: .. image:: https://raw.github.com/TeleSign/python_telesign/master/p
|
|
|
88
88
|
print(response.json)
|
|
89
89
|
|
|
90
90
|
.. code-block:: javascript
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
{'reference_id': 'DGFDF6E11AB86303ASDFD425BE00000657',
|
|
93
93
|
'status': {'code': 103,
|
|
94
94
|
'description': 'Call in progress',
|
|
95
95
|
'updated_on': '2016-12-12T00:39:58.325559Z'}}
|
|
96
96
|
|
|
97
97
|
For more examples, see the `examples <https://github.com/TeleSign/python_telesign/tree/master/examples>`_ folder or
|
|
98
|
-
visit the `TeleSign
|
|
98
|
+
visit the `TeleSign Standard Documentation <https://standard.telesign.com/>`_.
|
|
99
99
|
|
|
100
100
|
Keywords: telesign,sms,voice,mobile,authentication,identity,messaging
|
|
101
101
|
Platform: UNKNOWN
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
.. image:: https://raw.github.com/TeleSign/python_telesign/master/python_banner.jpg
|
|
2
|
-
|
|
2
|
+
:target: https://standard.telesign.com
|
|
3
3
|
|
|
4
4
|
.. image:: https://img.shields.io/travis/TeleSign/python_telesign.svg
|
|
5
|
-
|
|
5
|
+
:target: https://travis-ci.org/TeleSign/python_telesign
|
|
6
6
|
|
|
7
7
|
.. image:: https://img.shields.io/codecov/c/github/TeleSign/python_telesign.svg
|
|
8
|
-
|
|
8
|
+
:target: https://codecov.io/gh/TeleSign/python_telesign
|
|
9
9
|
|
|
10
10
|
.. image:: https://img.shields.io/pypi/v/telesign.svg
|
|
11
|
-
|
|
11
|
+
:target: https://pypi.python.org/pypi/telesign
|
|
12
12
|
|
|
13
13
|
.. image:: https://img.shields.io/pypi/l/telesign.svg
|
|
14
|
-
|
|
14
|
+
:target: https://github.com/TeleSign/python_telesign/blob/master/LICENSE
|
|
15
15
|
|
|
16
16
|
===================
|
|
17
17
|
TeleSign Python SDK
|
|
@@ -28,7 +28,7 @@ Documentation
|
|
|
28
28
|
-------------
|
|
29
29
|
|
|
30
30
|
Code documentation is included in the SDK. Complete documentation, quick start guides and reference material
|
|
31
|
-
for the TeleSign API is available within the `TeleSign
|
|
31
|
+
for the TeleSign API is available within the `TeleSign Standard Documentation <https://standard.telesign.com/>`_.
|
|
32
32
|
|
|
33
33
|
Installation
|
|
34
34
|
------------
|
|
@@ -80,11 +80,11 @@ Here is a basic code example with the JSON response.
|
|
|
80
80
|
print(response.json)
|
|
81
81
|
|
|
82
82
|
.. code-block:: javascript
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
{'reference_id': 'DGFDF6E11AB86303ASDFD425BE00000657',
|
|
85
85
|
'status': {'code': 103,
|
|
86
86
|
'description': 'Call in progress',
|
|
87
87
|
'updated_on': '2016-12-12T00:39:58.325559Z'}}
|
|
88
88
|
|
|
89
89
|
For more examples, see the `examples <https://github.com/TeleSign/python_telesign/tree/master/examples>`_ folder or
|
|
90
|
-
visit the `TeleSign
|
|
90
|
+
visit the `TeleSign Standard Documentation <https://standard.telesign.com/>`_.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Example code that makes requests to intelligence API."""
|
|
2
|
+
from __future__ import print_function
|
|
3
|
+
from telesign.intelligence import IntelligenceClient
|
|
4
|
+
|
|
5
|
+
customer_1 = "your_customer_id-44ZA-47B5-95B9-ACXM9B1E5CAA"
|
|
6
|
+
api_key_1 = "your_api_key_or_password"
|
|
7
|
+
|
|
8
|
+
phone_number = "15555551212"
|
|
9
|
+
account_lifecycle_event = "create"
|
|
10
|
+
|
|
11
|
+
body = {
|
|
12
|
+
"contact_details": {"email": "ghopper@gmail.com", "phone_number": "15555551212"},
|
|
13
|
+
"external_id": "REG432538",
|
|
14
|
+
"account_lifecycle_event": "create",
|
|
15
|
+
"ip": "1.1.1.1",
|
|
16
|
+
"device_id": "2e4fa042234d",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
client = IntelligenceClient(customer_1, api_key_1)
|
|
20
|
+
response = client.intelligence(body)
|
|
21
|
+
|
|
22
|
+
if response.ok:
|
|
23
|
+
print(
|
|
24
|
+
"Phone number {} has a '{}' risk level and the score is '{}'.".format(
|
|
25
|
+
response.json["phone_details"]["numbering"]["original"]["phone_number"],
|
|
26
|
+
response.json["risk"]["level"],
|
|
27
|
+
response.json["risk"]["score"],
|
|
28
|
+
)
|
|
29
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Client to make requests to intelligence API."""
|
|
2
|
+
from __future__ import unicode_literals
|
|
3
|
+
|
|
4
|
+
from telesign.rest import RestClient
|
|
5
|
+
from telesign.util import AuthMethod
|
|
6
|
+
|
|
7
|
+
INTELLIGENCE_BASE_URL = "https://detect.telesign.com"
|
|
8
|
+
INTELLIGENCE_ENDPOINT_PATH = "/intelligence"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class IntelligenceClient(RestClient):
|
|
12
|
+
"""
|
|
13
|
+
It is critical today to evaluate fraud risk throughout the entire customer journey.
|
|
14
|
+
|
|
15
|
+
Telesign Intelligence makes it easy to understand the risk and the reason behind it with tailored scoring models
|
|
16
|
+
and comprehensive reason codes.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, customer_id, api_key, **kwargs):
|
|
20
|
+
super(IntelligenceClient, self).__init__(
|
|
21
|
+
customer_id=customer_id,
|
|
22
|
+
api_key=api_key,
|
|
23
|
+
rest_endpoint=INTELLIGENCE_BASE_URL,
|
|
24
|
+
auth_method=AuthMethod.BASIC.value,
|
|
25
|
+
**kwargs
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
def intelligence(self, params):
|
|
29
|
+
"""
|
|
30
|
+
Telesign Intelligence is like a credit check for digital profiles.
|
|
31
|
+
|
|
32
|
+
You submit a phone number, IP, and email to the service, the individual
|
|
33
|
+
identifiers are each evaluated, and then a score is returned telling you how risky
|
|
34
|
+
that user is. You decide whether to proceed based on the score.
|
|
35
|
+
|
|
36
|
+
See https://developer.telesign.com/enterprise/docs/intelligence-overview
|
|
37
|
+
for detailed API documentation.
|
|
38
|
+
"""
|
|
39
|
+
return self.post(INTELLIGENCE_ENDPOINT_PATH, body=params, query_params=None)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from __future__ import unicode_literals
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
from telesign.rest import RestClient
|
|
6
|
+
|
|
7
|
+
PHONEID_RESOURCE = "/v1/phoneid/{phone_number}"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PhoneIdClient(RestClient):
|
|
11
|
+
"""
|
|
12
|
+
A set of APIs that deliver deep phone number data attributes that help optimize the end user
|
|
13
|
+
verification process and evaluate risk.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, customer_id, api_key, **kwargs):
|
|
17
|
+
super(PhoneIdClient, self).__init__(customer_id, api_key, **kwargs)
|
|
18
|
+
|
|
19
|
+
def phoneid(self, phone_number, **params):
|
|
20
|
+
"""
|
|
21
|
+
The PhoneID API provides a cleansed phone number, phone type, and telecom carrier information to determine the
|
|
22
|
+
best communication method - SMS or voice.
|
|
23
|
+
|
|
24
|
+
See https://developer.telesign.com/docs/phoneid-api for detailed API documentation.
|
|
25
|
+
"""
|
|
26
|
+
return self.post(PHONEID_RESOURCE.format(phone_number=phone_number),
|
|
27
|
+
json_fields=params,
|
|
28
|
+
**params)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import unicode_literals
|
|
2
2
|
|
|
3
|
-
from requests import post
|
|
4
3
|
import hmac
|
|
5
4
|
import uuid
|
|
6
5
|
from base64 import b64encode, b64decode
|
|
@@ -9,8 +8,10 @@ from hashlib import sha256
|
|
|
9
8
|
from platform import python_version
|
|
10
9
|
|
|
11
10
|
import requests
|
|
11
|
+
import json
|
|
12
12
|
|
|
13
13
|
import telesign
|
|
14
|
+
from telesign.util import AuthMethod
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class RestClient(requests.models.RequestEncodingMixin):
|
|
@@ -51,7 +52,8 @@ class RestClient(requests.models.RequestEncodingMixin):
|
|
|
51
52
|
api_key,
|
|
52
53
|
rest_endpoint='https://rest-api.telesign.com',
|
|
53
54
|
proxies=None,
|
|
54
|
-
timeout=10
|
|
55
|
+
timeout=10,
|
|
56
|
+
auth_method=None):
|
|
55
57
|
"""
|
|
56
58
|
TeleSign RestClient useful for making generic RESTful requests against our API.
|
|
57
59
|
|
|
@@ -73,6 +75,8 @@ class RestClient(requests.models.RequestEncodingMixin):
|
|
|
73
75
|
|
|
74
76
|
self.timeout = timeout
|
|
75
77
|
|
|
78
|
+
self.auth_method = auth_method
|
|
79
|
+
|
|
76
80
|
@staticmethod
|
|
77
81
|
def generate_telesign_headers(customer_id,
|
|
78
82
|
api_key,
|
|
@@ -82,7 +86,8 @@ class RestClient(requests.models.RequestEncodingMixin):
|
|
|
82
86
|
date_rfc2616=None,
|
|
83
87
|
nonce=None,
|
|
84
88
|
user_agent=None,
|
|
85
|
-
content_type=None
|
|
89
|
+
content_type=None,
|
|
90
|
+
auth_method=None):
|
|
86
91
|
"""
|
|
87
92
|
Generates the TeleSign REST API headers used to authenticate requests.
|
|
88
93
|
|
|
@@ -101,6 +106,7 @@ class RestClient(requests.models.RequestEncodingMixin):
|
|
|
101
106
|
:param nonce: A unique cryptographic nonce for the request, as a string.
|
|
102
107
|
:param user_agent: (optional) User Agent associated with the request, as a string.
|
|
103
108
|
:param content_type: (optional) ContentType of the request, as a string.
|
|
109
|
+
:param auth_method: (optional) Authentication type ex: Basic, HMAC etc
|
|
104
110
|
:return: The TeleSign authentication headers.
|
|
105
111
|
"""
|
|
106
112
|
if date_rfc2616 is None:
|
|
@@ -112,31 +118,39 @@ class RestClient(requests.models.RequestEncodingMixin):
|
|
|
112
118
|
if not content_type:
|
|
113
119
|
content_type = "application/x-www-form-urlencoded" if method_name in ("POST", "PUT") else ""
|
|
114
120
|
|
|
115
|
-
auth_method
|
|
121
|
+
# Default auth_method is Digest if not explicitly specified
|
|
122
|
+
if auth_method == AuthMethod.BASIC:
|
|
123
|
+
usr_apikey = "{customer_id}:{api_key}".format(customer_id=customer_id,
|
|
124
|
+
api_key=api_key)
|
|
125
|
+
b64val = b64encode(usr_apikey.encode())
|
|
126
|
+
authorization = "{auth_method} {b64val}".format(auth_method=AuthMethod.BASIC,
|
|
127
|
+
b64val=b64val.decode())
|
|
128
|
+
else:
|
|
129
|
+
auth_method = AuthMethod.HMAC_SHA256
|
|
116
130
|
|
|
117
|
-
|
|
131
|
+
string_to_sign_builder = ["{method}".format(method=method_name)]
|
|
118
132
|
|
|
119
|
-
|
|
133
|
+
string_to_sign_builder.append("\n{content_type}".format(content_type=content_type))
|
|
120
134
|
|
|
121
|
-
|
|
135
|
+
string_to_sign_builder.append("\n{date}".format(date=date_rfc2616))
|
|
122
136
|
|
|
123
|
-
|
|
137
|
+
string_to_sign_builder.append("\nx-ts-auth-method:{auth_method}".format(auth_method=auth_method))
|
|
124
138
|
|
|
125
|
-
|
|
139
|
+
string_to_sign_builder.append("\nx-ts-nonce:{nonce}".format(nonce=nonce))
|
|
126
140
|
|
|
127
|
-
|
|
128
|
-
|
|
141
|
+
if content_type and url_encoded_fields:
|
|
142
|
+
string_to_sign_builder.append("\n{fields}".format(fields=url_encoded_fields))
|
|
129
143
|
|
|
130
|
-
|
|
144
|
+
string_to_sign_builder.append("\n{resource}".format(resource=resource))
|
|
131
145
|
|
|
132
|
-
|
|
146
|
+
string_to_sign = "".join(string_to_sign_builder)
|
|
133
147
|
|
|
134
|
-
|
|
135
|
-
|
|
148
|
+
signer = hmac.new(b64decode(api_key), string_to_sign.encode("utf-8"), sha256)
|
|
149
|
+
signature = b64encode(signer.digest()).decode("utf-8")
|
|
136
150
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
151
|
+
authorization = "TSA {customer_id}:{signature}".format(
|
|
152
|
+
customer_id=customer_id,
|
|
153
|
+
signature=signature)
|
|
140
154
|
|
|
141
155
|
headers = {
|
|
142
156
|
"Authorization": authorization,
|
|
@@ -151,69 +165,89 @@ class RestClient(requests.models.RequestEncodingMixin):
|
|
|
151
165
|
|
|
152
166
|
return headers
|
|
153
167
|
|
|
154
|
-
def post(self, resource, **
|
|
168
|
+
def post(self, resource, body=None, json_fields=None, **query_params):
|
|
155
169
|
"""
|
|
156
170
|
Generic TeleSign REST API POST handler.
|
|
157
171
|
|
|
158
172
|
:param resource: The partial resource URI to perform the request against, as a string.
|
|
159
|
-
:param
|
|
173
|
+
:param body: (optional) A dictionary sent as a part of request body.
|
|
174
|
+
:param query_params: query_params to perform the POST request with, as a dictionary.
|
|
160
175
|
:return: The RestClient Response object.
|
|
161
176
|
"""
|
|
162
|
-
return self._execute(self.session.post, 'POST', resource, **
|
|
177
|
+
return self._execute(self.session.post, 'POST', resource, body, json_fields, **query_params)
|
|
163
178
|
|
|
164
|
-
def get(self, resource, **
|
|
179
|
+
def get(self, resource, body=None, json_fields=None, **query_params):
|
|
165
180
|
"""
|
|
166
181
|
Generic TeleSign REST API GET handler.
|
|
167
182
|
|
|
168
183
|
:param resource: The partial resource URI to perform the request against, as a string.
|
|
169
|
-
:param
|
|
184
|
+
:param body: (optional) A dictionary sent as a part of request body.
|
|
185
|
+
:param query_params: query_params to perform the GET request with, as a dictionary.
|
|
170
186
|
:return: The RestClient Response object.
|
|
171
187
|
"""
|
|
172
|
-
return self._execute(self.session.get, 'GET', resource, **
|
|
188
|
+
return self._execute(self.session.get, 'GET', resource, body, json_fields, **query_params)
|
|
173
189
|
|
|
174
|
-
def put(self, resource, **
|
|
190
|
+
def put(self, resource, body=None, json_fields=None, **query_params):
|
|
175
191
|
"""
|
|
176
192
|
Generic TeleSign REST API PUT handler.
|
|
177
193
|
|
|
178
194
|
:param resource: The partial resource URI to perform the request against, as a string.
|
|
179
|
-
:param
|
|
195
|
+
:param body: (optional) A dictionary sent as a part of request body.
|
|
196
|
+
:param query_params: query_params to perform the PUT request with, as a dictionary.
|
|
180
197
|
:return: The RestClient Response object.
|
|
181
198
|
"""
|
|
182
|
-
return self._execute(self.session.put, 'PUT', resource, **
|
|
199
|
+
return self._execute(self.session.put, 'PUT', resource, body, json_fields, **query_params)
|
|
183
200
|
|
|
184
|
-
def delete(self, resource, **
|
|
201
|
+
def delete(self, resource, body=None, json_fields=None, **query_params):
|
|
185
202
|
"""
|
|
186
203
|
Generic TeleSign REST API DELETE handler.
|
|
187
204
|
|
|
188
205
|
:param resource: The partial resource URI to perform the request against, as a string.
|
|
189
|
-
:param
|
|
206
|
+
:param body: (optional) A dictionary sent as a part of request body.
|
|
207
|
+
:param query_params: query_params to perform the DELETE request with, as a dictionary.
|
|
190
208
|
:return: The RestClient Response object.
|
|
191
209
|
"""
|
|
192
|
-
return self._execute(self.session.delete, 'DELETE', resource, **
|
|
210
|
+
return self._execute(self.session.delete, 'DELETE', resource, body, json_fields, **query_params)
|
|
193
211
|
|
|
194
|
-
def _execute(self, method_function, method_name, resource, **
|
|
212
|
+
def _execute(self, method_function, method_name, resource, body=None, json_fields=None, **query_params):
|
|
195
213
|
"""
|
|
196
214
|
Generic TeleSign REST API request handler.
|
|
197
215
|
|
|
198
216
|
:param method_function: The Requests HTTP request function to perform the request.
|
|
199
217
|
:param method_name: The HTTP method name, as an upper case string.
|
|
200
218
|
:param resource: The partial resource URI to perform the request against, as a string.
|
|
201
|
-
:param
|
|
219
|
+
:param body: (optional) A dictionary sent as a part of request body.
|
|
220
|
+
:param query_params: query_params to perform the HTTP request with, as a dictionary.
|
|
202
221
|
:return: The RestClient Response object.
|
|
203
222
|
"""
|
|
204
223
|
resource_uri = "{api_host}{resource}".format(api_host=self.api_host, resource=resource)
|
|
205
224
|
|
|
206
|
-
url_encoded_fields = self._encode_params(
|
|
225
|
+
url_encoded_fields = self._encode_params(query_params)
|
|
226
|
+
if json_fields:
|
|
227
|
+
fields = json.dumps(json_fields)
|
|
228
|
+
url_encoded_fields = fields
|
|
229
|
+
|
|
230
|
+
if body or json_fields:
|
|
231
|
+
content_type = "application/json"
|
|
232
|
+
else:
|
|
233
|
+
content_type = None # set later
|
|
207
234
|
|
|
208
235
|
headers = RestClient.generate_telesign_headers(self.customer_id,
|
|
209
236
|
self.api_key,
|
|
210
237
|
method_name,
|
|
211
238
|
resource,
|
|
212
239
|
url_encoded_fields,
|
|
213
|
-
user_agent=self.user_agent
|
|
214
|
-
|
|
240
|
+
user_agent=self.user_agent,
|
|
241
|
+
content_type=content_type,
|
|
242
|
+
auth_method=self.auth_method)
|
|
215
243
|
if method_name in ['POST', 'PUT']:
|
|
216
|
-
payload = {
|
|
244
|
+
payload = {}
|
|
245
|
+
if body:
|
|
246
|
+
payload['json'] = body
|
|
247
|
+
if query_params:
|
|
248
|
+
payload['data'] = url_encoded_fields
|
|
249
|
+
if json_fields:
|
|
250
|
+
payload = {'data': url_encoded_fields}
|
|
217
251
|
else:
|
|
218
252
|
payload = {'params': url_encoded_fields}
|
|
219
253
|
|
|
@@ -4,6 +4,7 @@ from hmac import HMAC
|
|
|
4
4
|
from base64 import b64decode, b64encode
|
|
5
5
|
from hashlib import sha256
|
|
6
6
|
from random import SystemRandom
|
|
7
|
+
from enum import Enum
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
def to_utc_rfc3339(a_datetime):
|
|
@@ -40,3 +41,8 @@ def verify_telesign_callback_signature(api_key, signature, json_str):
|
|
|
40
41
|
signatures_equal = False
|
|
41
42
|
|
|
42
43
|
return signatures_equal
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class AuthMethod(Enum):
|
|
47
|
+
BASIC = "Basic"
|
|
48
|
+
HMAC_SHA256 = "HMAC-SHA256"
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 1.1
|
|
2
2
|
Name: telesign
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.4
|
|
4
4
|
Summary: TeleSign SDK
|
|
5
5
|
Home-page: https://github.com/telesign/python_telesign
|
|
6
6
|
Author: TeleSign Corp.
|
|
7
7
|
Author-email: support@telesign.com
|
|
8
8
|
License: MIT
|
|
9
9
|
Description: .. image:: https://raw.github.com/TeleSign/python_telesign/master/python_banner.jpg
|
|
10
|
-
|
|
10
|
+
:target: https://standard.telesign.com
|
|
11
11
|
|
|
12
12
|
.. image:: https://img.shields.io/travis/TeleSign/python_telesign.svg
|
|
13
|
-
|
|
13
|
+
:target: https://travis-ci.org/TeleSign/python_telesign
|
|
14
14
|
|
|
15
15
|
.. image:: https://img.shields.io/codecov/c/github/TeleSign/python_telesign.svg
|
|
16
|
-
|
|
16
|
+
:target: https://codecov.io/gh/TeleSign/python_telesign
|
|
17
17
|
|
|
18
18
|
.. image:: https://img.shields.io/pypi/v/telesign.svg
|
|
19
|
-
|
|
19
|
+
:target: https://pypi.python.org/pypi/telesign
|
|
20
20
|
|
|
21
21
|
.. image:: https://img.shields.io/pypi/l/telesign.svg
|
|
22
|
-
|
|
22
|
+
:target: https://github.com/TeleSign/python_telesign/blob/master/LICENSE
|
|
23
23
|
|
|
24
24
|
===================
|
|
25
25
|
TeleSign Python SDK
|
|
@@ -36,7 +36,7 @@ Description: .. image:: https://raw.github.com/TeleSign/python_telesign/master/p
|
|
|
36
36
|
-------------
|
|
37
37
|
|
|
38
38
|
Code documentation is included in the SDK. Complete documentation, quick start guides and reference material
|
|
39
|
-
for the TeleSign API is available within the `TeleSign
|
|
39
|
+
for the TeleSign API is available within the `TeleSign Standard Documentation <https://standard.telesign.com/>`_.
|
|
40
40
|
|
|
41
41
|
Installation
|
|
42
42
|
------------
|
|
@@ -88,14 +88,14 @@ Description: .. image:: https://raw.github.com/TeleSign/python_telesign/master/p
|
|
|
88
88
|
print(response.json)
|
|
89
89
|
|
|
90
90
|
.. code-block:: javascript
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
{'reference_id': 'DGFDF6E11AB86303ASDFD425BE00000657',
|
|
93
93
|
'status': {'code': 103,
|
|
94
94
|
'description': 'Call in progress',
|
|
95
95
|
'updated_on': '2016-12-12T00:39:58.325559Z'}}
|
|
96
96
|
|
|
97
97
|
For more examples, see the `examples <https://github.com/TeleSign/python_telesign/tree/master/examples>`_ folder or
|
|
98
|
-
visit the `TeleSign
|
|
98
|
+
visit the `TeleSign Standard Documentation <https://standard.telesign.com/>`_.
|
|
99
99
|
|
|
100
100
|
Keywords: telesign,sms,voice,mobile,authentication,identity,messaging
|
|
101
101
|
Platform: UNKNOWN
|
|
@@ -4,6 +4,7 @@ README.rst
|
|
|
4
4
|
setup.cfg
|
|
5
5
|
setup.py
|
|
6
6
|
examples/appverify/1_get_status_by_external_id.py
|
|
7
|
+
examples/intelligence/1_get_risk_score_and_related_insights.py
|
|
7
8
|
examples/messaging/1_send_message.py
|
|
8
9
|
examples/messaging/2_send_message_with_verification_code.py
|
|
9
10
|
examples/phoneid/1_check_phone_type_to_block_voip.py
|
|
@@ -14,6 +15,7 @@ examples/voice/2_send_voice_call_with_verification_code.py
|
|
|
14
15
|
examples/voice/3_send_voice_call_french.py
|
|
15
16
|
telesign/__init__.py
|
|
16
17
|
telesign/appverify.py
|
|
18
|
+
telesign/intelligence.py
|
|
17
19
|
telesign/messaging.py
|
|
18
20
|
telesign/phoneid.py
|
|
19
21
|
telesign/rest.py
|
|
@@ -26,5 +28,6 @@ telesign.egg-info/dependency_links.txt
|
|
|
26
28
|
telesign.egg-info/requires.txt
|
|
27
29
|
telesign.egg-info/top_level.txt
|
|
28
30
|
tests/__init__.py
|
|
31
|
+
tests/test_phoneid.py
|
|
29
32
|
tests/test_rest.py
|
|
30
33
|
tests/test_util.py
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from __future__ import unicode_literals
|
|
2
|
+
import os
|
|
3
|
+
from unittest import TestCase
|
|
4
|
+
from telesign.phoneid import PhoneIdClient
|
|
5
|
+
|
|
6
|
+
class TestPhoneId(TestCase):
|
|
7
|
+
def setUp(self):
|
|
8
|
+
self.customer_id = os.getenv('CUSTOMER_ID', 'FFFFFFFF-EEEE-DDDD-1234-AB1234567890')
|
|
9
|
+
self.api_key = os.getenv('API_KEY', 'EXAMPLE----TE8sTgg45yusumoN6BYsBVkh+yRJ5czgsnCehZaOYldPJdmFh6NeX8kunZ2zU1YWaUw/0wV6xfw==')
|
|
10
|
+
self.phone_number_test = "11234567890"
|
|
11
|
+
|
|
12
|
+
def test_phoneid_constructor(self):
|
|
13
|
+
|
|
14
|
+
client = PhoneIdClient(self.customer_id,
|
|
15
|
+
self.api_key)
|
|
16
|
+
|
|
17
|
+
self.assertEqual(client.customer_id, self.customer_id)
|
|
18
|
+
self.assertEqual(client.api_key, self.api_key)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_phoneid_pid_contact(self):
|
|
22
|
+
|
|
23
|
+
client = PhoneIdClient(self.customer_id, self.api_key)
|
|
24
|
+
content_type_expected = 'application/json'
|
|
25
|
+
status_code_expected = 200
|
|
26
|
+
|
|
27
|
+
payload = {
|
|
28
|
+
"addons": {
|
|
29
|
+
"contact": {}
|
|
30
|
+
},
|
|
31
|
+
"phone_number": self.phone_number_test
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
response = client.phoneid(**payload)
|
|
35
|
+
|
|
36
|
+
self.assertEqual(response.headers.get('Content-Type'), content_type_expected, "Content-Type args do not match expected")
|
|
37
|
+
self.assertEqual(response.status_code, status_code_expected, "Status code args do not match expected")
|
|
38
|
+
|
|
39
|
+
def test_phoneid_pid(self):
|
|
40
|
+
|
|
41
|
+
client = PhoneIdClient(self.customer_id, self.api_key)
|
|
42
|
+
content_type_expected = 'application/json'
|
|
43
|
+
status_code_expected = 200
|
|
44
|
+
|
|
45
|
+
response = client.phoneid(self.phone_number_test)
|
|
46
|
+
|
|
47
|
+
self.assertEqual(response.headers.get('Content-Type'), content_type_expected, "Content-Type args do not match expected")
|
|
48
|
+
self.assertEqual(response.status_code, status_code_expected, "Status code args do not match expected")
|
|
@@ -6,6 +6,7 @@ from unittest import TestCase
|
|
|
6
6
|
from uuid import UUID
|
|
7
7
|
|
|
8
8
|
from telesign.rest import RestClient
|
|
9
|
+
from telesign.util import AuthMethod
|
|
9
10
|
|
|
10
11
|
if sys.version_info < (3, 3):
|
|
11
12
|
from mock import Mock, patch
|
|
@@ -104,6 +105,29 @@ class TestRest(TestCase):
|
|
|
104
105
|
|
|
105
106
|
self.assertEqual(expected_authorization_header, actual_headers['Authorization'])
|
|
106
107
|
|
|
108
|
+
def test_generate_telesign_headers_with_post_basic_authentication(self):
|
|
109
|
+
method_name = 'POST'
|
|
110
|
+
date_rfc2616 = 'Wed, 14 Dec 2016 18:20:12 GMT'
|
|
111
|
+
nonce = 'A1592C6F-E384-4CDB-BC42-C3AB970369E9'
|
|
112
|
+
resource = '/v1/resource'
|
|
113
|
+
|
|
114
|
+
expected_authorization_header = ('Basic RkZGRkZGRkYtRUVFRS1ERERELTEyMzQtQUIxMjM'
|
|
115
|
+
'0NTY3ODkwOkVYQU1QTEUtLS0tVEU4c1RnZzQ1eXVzdW1vTjZCWXNCVmto'
|
|
116
|
+
'K3lSSjVjemdzbkNlaFphT1lsZFBKZG1GaDZOZVg4a3VuWjJ6VTFZV2FV'
|
|
117
|
+
'dy8wd1Y2eGZ3PT0=')
|
|
118
|
+
|
|
119
|
+
actual_headers = RestClient.generate_telesign_headers(self.customer_id,
|
|
120
|
+
self.api_key,
|
|
121
|
+
method_name,
|
|
122
|
+
resource,
|
|
123
|
+
'',
|
|
124
|
+
date_rfc2616=date_rfc2616,
|
|
125
|
+
nonce=nonce,
|
|
126
|
+
user_agent='unit_test',
|
|
127
|
+
auth_method=AuthMethod.BASIC.value)
|
|
128
|
+
|
|
129
|
+
self.assertEqual(expected_authorization_header, actual_headers['Authorization'])
|
|
130
|
+
|
|
107
131
|
def test_generate_telesign_headers_default_date_and_nonce(self):
|
|
108
132
|
method_name = 'GET'
|
|
109
133
|
resource = '/v1/resource'
|
|
@@ -144,6 +168,28 @@ class TestRest(TestCase):
|
|
|
144
168
|
self.assertEqual(post_kwargs, expected_post_kwargs,
|
|
145
169
|
"client.session.post.call_args kwargs do not match expected")
|
|
146
170
|
|
|
171
|
+
@patch('telesign.rest.RestClient.generate_telesign_headers', return_value={})
|
|
172
|
+
def test_post_body(self, mock_generate_telesign_headers):
|
|
173
|
+
test_host = 'https://test.com'
|
|
174
|
+
test_resource = '/test/resource'
|
|
175
|
+
test_params = {'test': '123_\u03ff_test'}
|
|
176
|
+
|
|
177
|
+
client = RestClient(self.customer_id, self.api_key, rest_endpoint=test_host)
|
|
178
|
+
client.session.post = Mock()
|
|
179
|
+
|
|
180
|
+
expected_post_args = (u'https://test.com/test/resource',)
|
|
181
|
+
expected_post_kwargs = {'headers': {}, 'json': test_params, 'timeout': client.timeout}
|
|
182
|
+
|
|
183
|
+
client.post(test_resource, body=test_params)
|
|
184
|
+
|
|
185
|
+
self.assertEqual(client.session.post.call_count, 1, "client.session.post not called")
|
|
186
|
+
|
|
187
|
+
post_args, post_kwargs = client.session.post.call_args
|
|
188
|
+
self.assertEqual(post_args, expected_post_args,
|
|
189
|
+
"client.session.post.call_args args do not match expected")
|
|
190
|
+
self.assertEqual(post_kwargs, expected_post_kwargs,
|
|
191
|
+
"client.session.post.call_args kwargs do not match expected")
|
|
192
|
+
|
|
147
193
|
@patch('telesign.rest.RestClient.generate_telesign_headers', return_value={})
|
|
148
194
|
def test_get(self, mock_generate_telesign_headers):
|
|
149
195
|
test_host = 'https://test.com'
|
|
@@ -209,3 +255,25 @@ class TestRest(TestCase):
|
|
|
209
255
|
"client.session.delete.call_args args do not match expected")
|
|
210
256
|
self.assertEqual(delete_kwargs, expected_delete_kwargs,
|
|
211
257
|
"client.session.delete.call_args kwargs do not match expected")
|
|
258
|
+
|
|
259
|
+
@patch('telesign.rest.RestClient.generate_telesign_headers', return_value={})
|
|
260
|
+
def test_post_basic_auth(self, mock_generate_telesign_headers):
|
|
261
|
+
test_host = 'https://test.com'
|
|
262
|
+
test_resource = '/test/resource'
|
|
263
|
+
test_params = {'test': '123_\u03ff_test'}
|
|
264
|
+
|
|
265
|
+
client = RestClient(self.customer_id, self.api_key, rest_endpoint=test_host, auth_method=AuthMethod.BASIC.value)
|
|
266
|
+
client.session.post = Mock()
|
|
267
|
+
|
|
268
|
+
expected_post_args = (u'https://test.com/test/resource',)
|
|
269
|
+
expected_post_kwargs = {'headers': {}, 'data': 'test=123_%CF%BF_test', 'timeout': client.timeout}
|
|
270
|
+
|
|
271
|
+
client.post(test_resource, **test_params)
|
|
272
|
+
|
|
273
|
+
self.assertEqual(client.session.post.call_count, 1, "client.session.post not called")
|
|
274
|
+
|
|
275
|
+
post_args, post_kwargs = client.session.post.call_args
|
|
276
|
+
self.assertEqual(post_args, expected_post_args,
|
|
277
|
+
"client.session.post.call_args args do not match expected")
|
|
278
|
+
self.assertEqual(post_kwargs, expected_post_kwargs,
|
|
279
|
+
"client.session.post.call_args kwargs do not match expected")
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
from __future__ import unicode_literals
|
|
2
|
-
|
|
3
|
-
import json
|
|
4
|
-
|
|
5
|
-
from telesign.rest import RestClient
|
|
6
|
-
|
|
7
|
-
PHONEID_RESOURCE = "/v1/phoneid/{phone_number}"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class PhoneIdClient(RestClient):
|
|
11
|
-
"""
|
|
12
|
-
A set of APIs that deliver deep phone number data attributes that help optimize the end user
|
|
13
|
-
verification process and evaluate risk.
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
def __init__(self, customer_id, api_key, **kwargs):
|
|
17
|
-
super(PhoneIdClient, self).__init__(customer_id, api_key, **kwargs)
|
|
18
|
-
|
|
19
|
-
def phoneid(self, phone_number, **params):
|
|
20
|
-
"""
|
|
21
|
-
The PhoneID API provides a cleansed phone number, phone type, and telecom carrier information to determine the
|
|
22
|
-
best communication method - SMS or voice.
|
|
23
|
-
|
|
24
|
-
See https://developer.telesign.com/docs/phoneid-api for detailed API documentation.
|
|
25
|
-
"""
|
|
26
|
-
return self.post(PHONEID_RESOURCE.format(phone_number=phone_number),
|
|
27
|
-
**params)
|
|
28
|
-
|
|
29
|
-
def _execute(self, method_function, method_name, resource, **params):
|
|
30
|
-
resource_uri = "{api_host}{resource}".format(api_host=self.api_host, resource=resource)
|
|
31
|
-
|
|
32
|
-
json_fields = json.dumps(params)
|
|
33
|
-
|
|
34
|
-
content_type = "application/json" if method_name in ("POST", "PUT") else ""
|
|
35
|
-
|
|
36
|
-
headers = self.generate_telesign_headers(self.customer_id,
|
|
37
|
-
self.api_key,
|
|
38
|
-
method_name,
|
|
39
|
-
resource,
|
|
40
|
-
json_fields,
|
|
41
|
-
user_agent=self.user_agent,
|
|
42
|
-
content_type=content_type)
|
|
43
|
-
|
|
44
|
-
if method_name in ['POST', 'PUT']:
|
|
45
|
-
payload = {'data': json_fields}
|
|
46
|
-
else:
|
|
47
|
-
payload = {'params': json_fields}
|
|
48
|
-
|
|
49
|
-
response = self.Response(method_function(resource_uri,
|
|
50
|
-
headers=headers,
|
|
51
|
-
timeout=self.timeout,
|
|
52
|
-
**payload))
|
|
53
|
-
|
|
54
|
-
return response
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{telesign-2.2.2 → telesign-2.2.4}/examples/messaging/2_send_message_with_verification_code.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{telesign-2.2.2 → telesign-2.2.4}/examples/voice/2_send_voice_call_with_verification_code.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|