-
Notifications
You must be signed in to change notification settings - Fork 117
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
380 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
resource(name='pyproject', source='pyproject.toml') | ||
file(name='readme', source='README.md') | ||
|
||
files(sources=['tests/data/*']) | ||
|
||
python_distribution( | ||
name='vonage-verify-v2', | ||
dependencies=[ | ||
':pyproject', | ||
':readme', | ||
'verify_v2/src/vonage_verify_v2', | ||
], | ||
provides=python_artifact(), | ||
generate_setup=False, | ||
repositories=['@pypi'], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# 1.0.0 | ||
- Initial upload |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# Vonage Verify V2 Package | ||
|
||
This package contains the code to use [Vonage's Verify v2 API](https://developer.vonage.com/en/verify/overview) in Python. This package includes methods for working with 2-factor authentication (2FA) messages sent via SMS, Voice, WhatsApp and Email. You can also make Silent Authentication requests with Verify v2 to give your end user a more seamless experience. | ||
|
||
## Usage | ||
|
||
It is recommended to use this as part of the main `vonage` package. The examples below assume you've created an instance of the `vonage.Vonage` class called `vonage_client`. | ||
|
||
|
||
###################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################### | ||
|
||
### Make a Verify Request | ||
|
||
```python | ||
from vonage_verify import VerifyRequest | ||
params = {'number': '1234567890', 'brand': 'Acme Inc.'} | ||
request = VerifyRequest(**params) | ||
response = vonage_client.verify.start_verification(request) | ||
``` | ||
|
||
### Make a PSD2 (Payment Services Directive v2) Request | ||
|
||
```python | ||
from vonage_verify import Psd2Request | ||
params = {'number': '1234567890', 'payee': 'Acme Inc.', 'amount': 99.99} | ||
request = VerifyRequest(**params) | ||
response = vonage_client.verify.start_verification(request) | ||
``` | ||
|
||
### Check a Verification Code | ||
|
||
```python | ||
vonage_client.verify.check_code(request_id='my_request_id', code='1234') | ||
``` | ||
|
||
### Search Verification Requests | ||
|
||
```python | ||
# Search for single request | ||
response = vonage_client.verify.search('my_request_id') | ||
|
||
# Search for multiple requests | ||
response = vonage_client.verify.search(['my_request_id_1', 'my_request_id_2']) | ||
``` | ||
|
||
### Cancel a Verification | ||
|
||
```python | ||
response = vonage_client.verify.cancel_verification('my_request_id') | ||
``` | ||
|
||
### Trigger the Next Workflow Event | ||
|
||
```python | ||
response = vonage_client.verify.trigger_next_event('my_request_id') | ||
``` | ||
|
||
### Request a Network Unblock | ||
|
||
Note: Network Unblock is switched off by default. Contact Sales to enable the Network Unblock API for your account. | ||
|
||
```python | ||
response = vonage_client.verify.request_network_unblock('23410') | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
[project] | ||
name = 'vonage-verify-v2' | ||
version = '1.0.0' | ||
description = 'Vonage verify v2 package' | ||
readme = "README.md" | ||
authors = [{ name = "Vonage", email = "devrel@vonage.com" }] | ||
requires-python = ">=3.8" | ||
dependencies = [ | ||
"vonage-http-client>=1.2.0", | ||
"vonage-utils>=1.0.1", | ||
"pydantic>=2.6.1", | ||
] | ||
classifiers = [ | ||
"Programming Language :: Python", | ||
"Programming Language :: Python :: 3", | ||
"Programming Language :: Python :: 3.8", | ||
"Programming Language :: Python :: 3.9", | ||
"Programming Language :: Python :: 3.10", | ||
"Programming Language :: Python :: 3.11", | ||
"Programming Language :: Python :: 3.12", | ||
"License :: OSI Approved :: Apache Software License", | ||
] | ||
|
||
[project.urls] | ||
homepage = "https://github.com/Vonage/vonage-python-sdk" | ||
|
||
[build-system] | ||
requires = ["setuptools>=61.0", "wheel"] | ||
build-backend = "setuptools.build_meta" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
python_sources() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from .errors import VerifyError | ||
from .enums import VerifyChannel, VerifyLocale | ||
from .requests import ( | ||
VerifyRequest, | ||
SilentAuthWorkflow, | ||
SmsWorkflow, | ||
WhatsappWorkflow, | ||
VoiceWorkflow, | ||
EmailWorkflow, | ||
) | ||
from .responses import ( | ||
StartVerificationResponse, | ||
) | ||
from .verify_v2 import Verify | ||
|
||
__all__ = [ | ||
'Verify', | ||
'VerifyError', | ||
'VerifyChannel', | ||
'VerifyLocale', | ||
'VerifyRequest', | ||
'SilentAuthWorkflow', | ||
'SmsWorkflow', | ||
'WhatsappWorkflow', | ||
'VoiceWorkflow', | ||
'EmailWorkflow', | ||
'StartVerificationResponse', | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
from enum import Enum | ||
|
||
|
||
class VerifyChannel(Enum): | ||
SILENT_AUTH = 'silent_auth' | ||
SMS = 'sms' | ||
WHATSAPP = 'whatsapp' | ||
VOICE = 'voice' | ||
EMAIL = 'email' | ||
|
||
|
||
class VerifyLocale(Enum): | ||
EN_US = 'en-us' | ||
EN_GB = 'en-gb' | ||
ES_ES = 'es-es' | ||
ES_MX = 'es-mx' | ||
ES_US = 'es-us' | ||
IT_IT = 'it-it' | ||
FR_FR = 'fr-fr' | ||
DE_DE = 'de-de' | ||
RU_RU = 'ru-ru' | ||
HI_IN = 'hi-in' | ||
PT_BR = 'pt-br' | ||
PT_PT = 'pt-pt' | ||
ID_ID = 'id-id' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from vonage_utils.errors import VonageError | ||
|
||
|
||
class VerifyError(VonageError): | ||
"""Indicates an error when using the Vonage Verify API.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
from typing import List, Optional, Union | ||
from re import search | ||
|
||
from pydantic import ( | ||
BaseModel, | ||
Field, | ||
field_validator, | ||
model_validator, | ||
) | ||
from vonage_utils.types.phone_number import PhoneNumber | ||
|
||
from .enums import VerifyChannel, VerifyLocale | ||
from .errors import VerifyError | ||
|
||
|
||
class Workflow(BaseModel): | ||
channel: VerifyChannel | ||
to: PhoneNumber | ||
|
||
|
||
class SilentAuthWorkflow(Workflow): | ||
redirect_url: Optional[str] = None | ||
sandbox: Optional[bool] = None | ||
|
||
|
||
class SmsWorkflow(Workflow): | ||
from_: Optional[Union[PhoneNumber, str]] = Field(None, serialization_alias='from') | ||
entity_id: Optional[str] = Field(None, pattern=r'^[0-9]{1,20}$') | ||
content_id: Optional[str] = Field(None, pattern=r'^[0-9]{1,20}$') | ||
app_hash: Optional[str] = Field(None, min_length=11, max_length=11) | ||
|
||
@field_validator('from_') | ||
@classmethod | ||
def check_valid_from_field(cls, v): | ||
if ( | ||
v is not None | ||
and type(v) is not PhoneNumber | ||
and not search(r'^[a-zA-Z0-9]{1,15}$', v) | ||
): | ||
raise VerifyError(f'You must specify a valid "from" value if included.') | ||
|
||
|
||
class WhatsappWorkflow(Workflow): | ||
from_: Union[PhoneNumber, str] = Field(..., serialization_alias='from') | ||
|
||
@field_validator('from_') | ||
@classmethod | ||
def check_valid_sender(cls, v): | ||
if type(v) is not PhoneNumber and not search(r'^[a-zA-Z0-9]{1,15}$', v): | ||
raise VerifyError(f'You must specify a valid "from" value.') | ||
|
||
|
||
class VoiceWorkflow(Workflow): | ||
@model_validator(mode='after') | ||
def remove_from_field_from_voice(self): | ||
self.from_ = None | ||
return self | ||
|
||
|
||
class EmailWorkflow(Workflow): | ||
to: str | ||
from_: Optional[str] = Field(None, serialization_alias='from') | ||
|
||
|
||
class VerifyRequest(BaseModel): | ||
brand: str = Field(..., min_length=1, max_length=16) | ||
workflow: List[Workflow] | ||
locale: Optional[VerifyLocale] = None | ||
channel_timeout: Optional[int] = Field(None, ge=60, le=900) | ||
client_ref: Optional[str] = Field(None, min_length=1, max_length=16) | ||
code_length: Optional[int] = Field(None, ge=4, le=10) | ||
code: Optional[str] = Field(None, pattern=r'^[a-zA-Z0-9]{4,10}$') | ||
|
||
@model_validator(mode='after') | ||
def remove_fields_if_only_silent_auth(self): | ||
if len(self.workflow) == 1 and isinstance(self.workflow[0], SilentAuthWorkflow): | ||
self.locale = None | ||
self.client_ref = None | ||
self.code_length = None | ||
self.code = None | ||
return self |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from typing import Optional | ||
|
||
from pydantic import BaseModel | ||
|
||
|
||
class StartVerificationResponse(BaseModel): | ||
request_id: str | ||
check_url: Optional[str] = None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
from typing import List, Optional, Union | ||
|
||
from pydantic import validate_call | ||
from vonage_http_client.http_client import HttpClient | ||
|
||
from .errors import VerifyError | ||
from .requests import ( | ||
VerifyRequest, | ||
SilentAuthWorkflow, | ||
SmsWorkflow, | ||
WhatsappWorkflow, | ||
VoiceWorkflow, | ||
EmailWorkflow, | ||
) | ||
from .responses import ( | ||
CheckCodeResponse, | ||
StartVerificationResponse, | ||
VerifyControlStatus, | ||
VerifyStatus, | ||
) | ||
|
||
|
||
class Verify: | ||
"""Calls Vonage's Verify V2 API.""" | ||
|
||
def __init__(self, http_client: HttpClient) -> None: | ||
self._http_client = http_client | ||
|
||
@validate_call | ||
def start_verification( | ||
self, verify_request: VerifyRequest | ||
) -> StartVerificationResponse: | ||
"""Start a verification process. | ||
Args: | ||
verify_request (VerifyRequest): The verification request object. | ||
Returns: | ||
StartVerificationResponse: The response object containing the `request_id`. | ||
If requesting Silent Authentication, it will also contain a `check_url` field. | ||
""" | ||
response = self._http_client.post( | ||
self._http_client.api_host, | ||
'/v2/verify', | ||
verify_request.model_dump(by_alias=True, exclude_none=True), | ||
) | ||
|
||
return StartVerificationResponse(**response) | ||
|
||
#################################################################################################### | ||
|
||
#################################################################################################### | ||
|
||
#################################################################################################### | ||
|
||
#################################################################################################### | ||
|
||
@validate_call | ||
def check_code(self, request_id: str, code: str) -> CheckCodeResponse: | ||
"""Check a verification code. | ||
Args: | ||
request_id (str): The request ID. | ||
code (str): The verification code. | ||
Returns: | ||
CheckCodeResponse: The response object containing the verification result. | ||
""" | ||
response = self._http_client.post( | ||
self._http_client.api_host, | ||
'/verify/check/json', | ||
{'request_id': request_id, 'code': code}, | ||
self._auth_type, | ||
self._sent_data_type, | ||
) | ||
self._check_for_error(response) | ||
return CheckCodeResponse(**response) | ||
|
||
@validate_call | ||
def cancel_verification(self, request_id: str) -> VerifyControlStatus: | ||
"""Cancel a verification request. | ||
Args: | ||
request_id (str): The request ID. | ||
Returns: | ||
VerifyControlStatus: The response object containing details of the submitted | ||
verification control. | ||
""" | ||
response = self._http_client.post( | ||
self._http_client.api_host, | ||
'/verify/control/json', | ||
{'request_id': request_id, 'cmd': 'cancel'}, | ||
self._auth_type, | ||
self._sent_data_type, | ||
) | ||
self._check_for_error(response) | ||
|
||
return VerifyControlStatus(**response) | ||
|
||
@validate_call | ||
def trigger_next_workflow(self, request_id: str) -> VerifyControlStatus: | ||
"""Trigger the next workflow event in the verification process. | ||
Args: | ||
request_id (str): The request ID. | ||
Returns: | ||
VerifyControlStatus: The response object containing details of the submitted | ||
verification control. | ||
""" | ||
response = self._http_client.post( | ||
self._http_client.api_host, | ||
'/verify/control/json', | ||
{'request_id': request_id, 'cmd': 'trigger_next_event'}, | ||
self._auth_type, | ||
self._sent_data_type, | ||
) | ||
self._check_for_error(response) | ||
|
||
return VerifyControlStatus(**response) |