|
22 | 22 |
|
23 | 23 | API_URL = 'https://api.siftscience.com' |
24 | 24 | API3_URL = 'https://api3.siftscience.com' |
| 25 | +API_URL_VERIFICATION = 'https://api.sift.com/v1/verification/' |
| 26 | + |
25 | 27 | DECISION_SOURCES = ['MANUAL_REVIEW', 'AUTOMATED_RULE', 'CHARGEBACK'] |
26 | 28 |
|
27 | 29 |
|
@@ -180,7 +182,6 @@ def track( |
180 | 182 | if include_score_percentiles: |
181 | 183 | field_types = ['SCORE_PERCENTILES'] |
182 | 184 | params['fields'] = ','.join(field_types) |
183 | | - |
184 | 185 | try: |
185 | 186 | response = self.session.post( |
186 | 187 | path, |
@@ -485,7 +486,6 @@ def apply_user_decision(self, user_id, properties, timeout=None): |
485 | 486 |
|
486 | 487 | self._validate_apply_decision_request(properties, user_id) |
487 | 488 | url = self._user_decisions_url(self.account_id, user_id) |
488 | | - |
489 | 489 | try: |
490 | 490 | return Response(self.session.post( |
491 | 491 | url, |
@@ -524,7 +524,6 @@ def apply_order_decision(self, user_id, order_id, properties, timeout=None): |
524 | 524 | self._validate_apply_decision_request(properties, user_id) |
525 | 525 |
|
526 | 526 | url = self._order_apply_decisions_url(self.account_id, user_id, order_id) |
527 | | - |
528 | 527 | try: |
529 | 528 | return Response(self.session.post( |
530 | 529 | url, |
@@ -788,7 +787,6 @@ def update_psp_merchant_profile(self, merchant_id, properties, timeout=None): |
788 | 787 | timeout = self.timeout |
789 | 788 |
|
790 | 789 | url = self._psp_merchant_id_url(self.account_id, merchant_id) |
791 | | - |
792 | 790 | try: |
793 | 791 | return Response(self.session.put( |
794 | 792 | url, |
@@ -854,6 +852,196 @@ def get_a_psp_merchant_profile(self, merchant_id, timeout=None): |
854 | 852 | except requests.exceptions.RequestException as e: |
855 | 853 | raise ApiException(str(e), url) |
856 | 854 |
|
| 855 | + def verification_send(self, properties, timeout=None, version=None): |
| 856 | + """The send call triggers the generation of a OTP code that is stored by Sift and email/sms the code to the user. |
| 857 | + This call is blocking. Check out https://sift.com/developers/docs/python/verification-api/send |
| 858 | + for more information on our send response structure. |
| 859 | +
|
| 860 | + Args: |
| 861 | +
|
| 862 | + properties: |
| 863 | +
|
| 864 | + $user_id: User ID of user being verified, e.g. johndoe123. |
| 865 | + $send_to: The phone / email to send the OTP to. |
| 866 | + $verification_type: The channel used for verification. Should be either $email or $sms. |
| 867 | + $brand_name(optional): Name of the brand of product or service the user interacts with. |
| 868 | + $language(optional): Language of the content of the web site. |
| 869 | + $site_country(optional): Country of the content of the site. |
| 870 | + $event: |
| 871 | + $session_id: The session being verified. See $verification in the Sift Events API documentation. |
| 872 | + $verified_event: The type of the reserved event being verified. |
| 873 | + $reason(optional): The trigger for the verification. See $verification in the Sift Events API documentation. |
| 874 | + $ip(optional): The user's IP address. |
| 875 | + $browser: |
| 876 | + $user_agent: The user agent of the browser that is verifying. Represented by the $browser object. |
| 877 | + Use this field if the client is a browser. |
| 878 | +
|
| 879 | +
|
| 880 | + timeout(optional): Use a custom timeout (in seconds) for this call. |
| 881 | +
|
| 882 | + version(optional): Use a different version of the Sift Science API for this call. |
| 883 | +
|
| 884 | + Returns: |
| 885 | + A sift.client.Response object if the send call succeeded, or raises an ApiException. |
| 886 | + """ |
| 887 | + |
| 888 | + if timeout is None: |
| 889 | + timeout = self.timeout |
| 890 | + |
| 891 | + self._validate_send_request(properties) |
| 892 | + |
| 893 | + url = self._verification_send_url() |
| 894 | + |
| 895 | + try: |
| 896 | + return Response(self.session.post( |
| 897 | + url, |
| 898 | + data=json.dumps(properties), |
| 899 | + auth=requests.auth.HTTPBasicAuth(self.api_key, ''), |
| 900 | + headers={'Content-type': 'application/json', |
| 901 | + 'Accept': '*/*', |
| 902 | + 'User-Agent': self._user_agent()}, |
| 903 | + timeout=timeout)) |
| 904 | + |
| 905 | + except requests.exceptions.RequestException as e: |
| 906 | + raise ApiException(str(e), url) |
| 907 | + |
| 908 | + def _validate_send_request(self, properties): |
| 909 | + """ This method is used to validate arguments passed to the send method. """ |
| 910 | + |
| 911 | + if not isinstance(properties, dict): |
| 912 | + raise TypeError("properties must be a dict") |
| 913 | + elif not properties: |
| 914 | + raise ValueError("properties dictionary may not be empty") |
| 915 | + |
| 916 | + user_id = properties.get('$user_id') |
| 917 | + _assert_non_empty_unicode(user_id, 'user_id', error_cls=ValueError) |
| 918 | + |
| 919 | + send_to = properties.get('$send_to') |
| 920 | + _assert_non_empty_unicode(send_to, 'send_to', error_cls=ValueError) |
| 921 | + |
| 922 | + verification_type = properties.get('$verification_type') |
| 923 | + _assert_non_empty_unicode( |
| 924 | + verification_type, 'verification_type', error_cls=ValueError) |
| 925 | + |
| 926 | + event = properties.get('$event') |
| 927 | + if not isinstance(event, dict): |
| 928 | + raise TypeError("$event must be a dict") |
| 929 | + elif not event: |
| 930 | + raise ValueError("$event dictionary may not be empty") |
| 931 | + |
| 932 | + session_id = event.get('$session_id') |
| 933 | + _assert_non_empty_unicode( |
| 934 | + session_id, 'session_id', error_cls=ValueError) |
| 935 | + |
| 936 | + def verification_resend(self, properties, timeout=None, version=None): |
| 937 | + """A user can ask for a new OTP (one-time password) if they haven’t received the previous one, |
| 938 | + or in case the previous OTP expired. |
| 939 | + This call is blocking. Check out https://sift.com/developers/docs/python/verification-api/resend |
| 940 | + for more information on our send response structure. |
| 941 | +
|
| 942 | + Args: |
| 943 | +
|
| 944 | + properties: |
| 945 | +
|
| 946 | + $user_id: User ID of user being verified, e.g. johndoe123. |
| 947 | + $verified_event(optional): This will be the event type that triggered the verification. |
| 948 | + $verified_entity_id(optional): The ID of the entity impacted by the event being verified. |
| 949 | +
|
| 950 | + timeout(optional): Use a custom timeout (in seconds) for this call. |
| 951 | +
|
| 952 | + version(optional): Use a different version of the Sift Science API for this call. |
| 953 | +
|
| 954 | + Returns: |
| 955 | + A sift.client.Response object if the send call succeeded, or raises an ApiException. |
| 956 | + """ |
| 957 | + |
| 958 | + if timeout is None: |
| 959 | + timeout = self.timeout |
| 960 | + |
| 961 | + self._validate_resend_request(properties) |
| 962 | + |
| 963 | + url = self._verification_resend_url() |
| 964 | + |
| 965 | + try: |
| 966 | + return Response(self.session.post( |
| 967 | + url, |
| 968 | + data=json.dumps(properties), |
| 969 | + auth=requests.auth.HTTPBasicAuth(self.api_key, ''), |
| 970 | + headers={'Content-type': 'application/json', |
| 971 | + 'Accept': '*/*', |
| 972 | + 'User-Agent': self._user_agent()}, |
| 973 | + timeout=timeout)) |
| 974 | + |
| 975 | + except requests.exceptions.RequestException as e: |
| 976 | + raise ApiException(str(e), url) |
| 977 | + |
| 978 | + def _validate_resend_request(self, properties): |
| 979 | + """ This method is used to validate arguments passed to the send method. """ |
| 980 | + |
| 981 | + if not isinstance(properties, dict): |
| 982 | + raise TypeError("properties must be a dict") |
| 983 | + elif not properties: |
| 984 | + raise ValueError("properties dictionary may not be empty") |
| 985 | + |
| 986 | + user_id = properties.get('$user_id') |
| 987 | + _assert_non_empty_unicode(user_id, 'user_id', error_cls=ValueError) |
| 988 | + |
| 989 | + def verification_check(self, properties, timeout=None, version=None): |
| 990 | + """The verification_check call is used for checking the OTP provided by the end user to Sift. |
| 991 | + Sift then compares the OTP, checks rate limits and responds with a decision whether the user should be able to proceed or not. |
| 992 | + This call is blocking. Check out https://sift.com/developers/docs/python/verification-api/check |
| 993 | + for more information on our check response structure. |
| 994 | +
|
| 995 | + Args: |
| 996 | +
|
| 997 | + properties: |
| 998 | + $user_id: User ID of user being verified, e.g. johndoe123. |
| 999 | + $code: The code the user sent to the customer for validation.. |
| 1000 | + $verified_event(optional): This will be the event type that triggered the verification. |
| 1001 | + $verified_entity_id(optional): The ID of the entity impacted by the event being verified. |
| 1002 | +
|
| 1003 | + timeout(optional): Use a custom timeout (in seconds) for this call. |
| 1004 | + version(optional): Use a different version of the Sift Science API for this call. |
| 1005 | +
|
| 1006 | + Returns: |
| 1007 | + A sift.client.Response object if the check call succeeded, or raises |
| 1008 | + an ApiException. |
| 1009 | + """ |
| 1010 | + if timeout is None: |
| 1011 | + timeout = self.timeout |
| 1012 | + |
| 1013 | + self._validate_check_request(properties) |
| 1014 | + |
| 1015 | + url = self._verification_check_url() |
| 1016 | + |
| 1017 | + try: |
| 1018 | + return Response(self.session.post( |
| 1019 | + url, |
| 1020 | + data=json.dumps(properties), |
| 1021 | + auth=requests.auth.HTTPBasicAuth(self.api_key, ''), |
| 1022 | + headers={'Content-type': 'application/json', |
| 1023 | + 'Accept': '*/*', |
| 1024 | + 'User-Agent': self._user_agent()}, |
| 1025 | + timeout=timeout)) |
| 1026 | + |
| 1027 | + except requests.exceptions.RequestException as e: |
| 1028 | + raise ApiException(str(e), url) |
| 1029 | + |
| 1030 | + def _validate_check_request(self, properties): |
| 1031 | + """ This method is used to validate arguments passed to the check method. """ |
| 1032 | + |
| 1033 | + if not isinstance(properties, dict): |
| 1034 | + raise TypeError("properties must be a dict") |
| 1035 | + elif not properties: |
| 1036 | + raise ValueError("properties dictionary may not be empty") |
| 1037 | + |
| 1038 | + user_id = properties.get('$user_id') |
| 1039 | + _assert_non_empty_unicode(user_id, 'user_id', error_cls=ValueError) |
| 1040 | + |
| 1041 | + otp_code = properties.get('$code') |
| 1042 | + if otp_code is None: |
| 1043 | + raise ValueError("code is required") |
| 1044 | + |
857 | 1045 | def _user_agent(self): |
858 | 1046 | return 'SiftScience/v%s sift-python/%s' % (sift.version.API_VERSION, sift.version.VERSION) |
859 | 1047 |
|
@@ -912,6 +1100,14 @@ def _psp_merchant_id_url(self, account_id, merchant_id): |
912 | 1100 | return (self.url + '/v3/accounts/%s/psp_management/merchants/%s' % |
913 | 1101 | (_quote_path(account_id), _quote_path(merchant_id))) |
914 | 1102 |
|
| 1103 | + def _verification_send_url(self): |
| 1104 | + return (API_URL_VERIFICATION + 'send') |
| 1105 | + |
| 1106 | + def _verification_resend_url(self): |
| 1107 | + return (API_URL_VERIFICATION + 'resend') |
| 1108 | + |
| 1109 | + def _verification_check_url(self): |
| 1110 | + return (API_URL_VERIFICATION + 'check') |
915 | 1111 |
|
916 | 1112 | class Response(object): |
917 | 1113 | HTTP_CODES_WITHOUT_BODY = [204, 304] |
|
0 commit comments