Skip to content

Commit 20051fd

Browse files
committed
start adding verify v2
1 parent 2b68284 commit 20051fd

File tree

11 files changed

+380
-0
lines changed

11 files changed

+380
-0
lines changed

verify_v2/BUILD

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
resource(name='pyproject', source='pyproject.toml')
2+
file(name='readme', source='README.md')
3+
4+
files(sources=['tests/data/*'])
5+
6+
python_distribution(
7+
name='vonage-verify-v2',
8+
dependencies=[
9+
':pyproject',
10+
':readme',
11+
'verify_v2/src/vonage_verify_v2',
12+
],
13+
provides=python_artifact(),
14+
generate_setup=False,
15+
repositories=['@pypi'],
16+
)

verify_v2/CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# 1.0.0
2+
- Initial upload

verify_v2/README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Vonage Verify V2 Package
2+
3+
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.
4+
5+
## Usage
6+
7+
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`.
8+
9+
10+
######################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
11+
12+
### Make a Verify Request
13+
14+
```python
15+
from vonage_verify import VerifyRequest
16+
params = {'number': '1234567890', 'brand': 'Acme Inc.'}
17+
request = VerifyRequest(**params)
18+
response = vonage_client.verify.start_verification(request)
19+
```
20+
21+
### Make a PSD2 (Payment Services Directive v2) Request
22+
23+
```python
24+
from vonage_verify import Psd2Request
25+
params = {'number': '1234567890', 'payee': 'Acme Inc.', 'amount': 99.99}
26+
request = VerifyRequest(**params)
27+
response = vonage_client.verify.start_verification(request)
28+
```
29+
30+
### Check a Verification Code
31+
32+
```python
33+
vonage_client.verify.check_code(request_id='my_request_id', code='1234')
34+
```
35+
36+
### Search Verification Requests
37+
38+
```python
39+
# Search for single request
40+
response = vonage_client.verify.search('my_request_id')
41+
42+
# Search for multiple requests
43+
response = vonage_client.verify.search(['my_request_id_1', 'my_request_id_2'])
44+
```
45+
46+
### Cancel a Verification
47+
48+
```python
49+
response = vonage_client.verify.cancel_verification('my_request_id')
50+
```
51+
52+
### Trigger the Next Workflow Event
53+
54+
```python
55+
response = vonage_client.verify.trigger_next_event('my_request_id')
56+
```
57+
58+
### Request a Network Unblock
59+
60+
Note: Network Unblock is switched off by default. Contact Sales to enable the Network Unblock API for your account.
61+
62+
```python
63+
response = vonage_client.verify.request_network_unblock('23410')
64+
```

verify_v2/pyproject.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[project]
2+
name = 'vonage-verify-v2'
3+
version = '1.0.0'
4+
description = 'Vonage verify v2 package'
5+
readme = "README.md"
6+
authors = [{ name = "Vonage", email = "[email protected]" }]
7+
requires-python = ">=3.8"
8+
dependencies = [
9+
"vonage-http-client>=1.2.0",
10+
"vonage-utils>=1.0.1",
11+
"pydantic>=2.6.1",
12+
]
13+
classifiers = [
14+
"Programming Language :: Python",
15+
"Programming Language :: Python :: 3",
16+
"Programming Language :: Python :: 3.8",
17+
"Programming Language :: Python :: 3.9",
18+
"Programming Language :: Python :: 3.10",
19+
"Programming Language :: Python :: 3.11",
20+
"Programming Language :: Python :: 3.12",
21+
"License :: OSI Approved :: Apache Software License",
22+
]
23+
24+
[project.urls]
25+
homepage = "https://github.com/Vonage/vonage-python-sdk"
26+
27+
[build-system]
28+
requires = ["setuptools>=61.0", "wheel"]
29+
build-backend = "setuptools.build_meta"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
python_sources()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from .errors import VerifyError
2+
from .enums import VerifyChannel, VerifyLocale
3+
from .requests import (
4+
VerifyRequest,
5+
SilentAuthWorkflow,
6+
SmsWorkflow,
7+
WhatsappWorkflow,
8+
VoiceWorkflow,
9+
EmailWorkflow,
10+
)
11+
from .responses import (
12+
StartVerificationResponse,
13+
)
14+
from .verify_v2 import Verify
15+
16+
__all__ = [
17+
'Verify',
18+
'VerifyError',
19+
'VerifyChannel',
20+
'VerifyLocale',
21+
'VerifyRequest',
22+
'SilentAuthWorkflow',
23+
'SmsWorkflow',
24+
'WhatsappWorkflow',
25+
'VoiceWorkflow',
26+
'EmailWorkflow',
27+
'StartVerificationResponse',
28+
]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from enum import Enum
2+
3+
4+
class VerifyChannel(Enum):
5+
SILENT_AUTH = 'silent_auth'
6+
SMS = 'sms'
7+
WHATSAPP = 'whatsapp'
8+
VOICE = 'voice'
9+
EMAIL = 'email'
10+
11+
12+
class VerifyLocale(Enum):
13+
EN_US = 'en-us'
14+
EN_GB = 'en-gb'
15+
ES_ES = 'es-es'
16+
ES_MX = 'es-mx'
17+
ES_US = 'es-us'
18+
IT_IT = 'it-it'
19+
FR_FR = 'fr-fr'
20+
DE_DE = 'de-de'
21+
RU_RU = 'ru-ru'
22+
HI_IN = 'hi-in'
23+
PT_BR = 'pt-br'
24+
PT_PT = 'pt-pt'
25+
ID_ID = 'id-id'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from vonage_utils.errors import VonageError
2+
3+
4+
class VerifyError(VonageError):
5+
"""Indicates an error when using the Vonage Verify API."""
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from typing import List, Optional, Union
2+
from re import search
3+
4+
from pydantic import (
5+
BaseModel,
6+
Field,
7+
field_validator,
8+
model_validator,
9+
)
10+
from vonage_utils.types.phone_number import PhoneNumber
11+
12+
from .enums import VerifyChannel, VerifyLocale
13+
from .errors import VerifyError
14+
15+
16+
class Workflow(BaseModel):
17+
channel: VerifyChannel
18+
to: PhoneNumber
19+
20+
21+
class SilentAuthWorkflow(Workflow):
22+
redirect_url: Optional[str] = None
23+
sandbox: Optional[bool] = None
24+
25+
26+
class SmsWorkflow(Workflow):
27+
from_: Optional[Union[PhoneNumber, str]] = Field(None, serialization_alias='from')
28+
entity_id: Optional[str] = Field(None, pattern=r'^[0-9]{1,20}$')
29+
content_id: Optional[str] = Field(None, pattern=r'^[0-9]{1,20}$')
30+
app_hash: Optional[str] = Field(None, min_length=11, max_length=11)
31+
32+
@field_validator('from_')
33+
@classmethod
34+
def check_valid_from_field(cls, v):
35+
if (
36+
v is not None
37+
and type(v) is not PhoneNumber
38+
and not search(r'^[a-zA-Z0-9]{1,15}$', v)
39+
):
40+
raise VerifyError(f'You must specify a valid "from" value if included.')
41+
42+
43+
class WhatsappWorkflow(Workflow):
44+
from_: Union[PhoneNumber, str] = Field(..., serialization_alias='from')
45+
46+
@field_validator('from_')
47+
@classmethod
48+
def check_valid_sender(cls, v):
49+
if type(v) is not PhoneNumber and not search(r'^[a-zA-Z0-9]{1,15}$', v):
50+
raise VerifyError(f'You must specify a valid "from" value.')
51+
52+
53+
class VoiceWorkflow(Workflow):
54+
@model_validator(mode='after')
55+
def remove_from_field_from_voice(self):
56+
self.from_ = None
57+
return self
58+
59+
60+
class EmailWorkflow(Workflow):
61+
to: str
62+
from_: Optional[str] = Field(None, serialization_alias='from')
63+
64+
65+
class VerifyRequest(BaseModel):
66+
brand: str = Field(..., min_length=1, max_length=16)
67+
workflow: List[Workflow]
68+
locale: Optional[VerifyLocale] = None
69+
channel_timeout: Optional[int] = Field(None, ge=60, le=900)
70+
client_ref: Optional[str] = Field(None, min_length=1, max_length=16)
71+
code_length: Optional[int] = Field(None, ge=4, le=10)
72+
code: Optional[str] = Field(None, pattern=r'^[a-zA-Z0-9]{4,10}$')
73+
74+
@model_validator(mode='after')
75+
def remove_fields_if_only_silent_auth(self):
76+
if len(self.workflow) == 1 and isinstance(self.workflow[0], SilentAuthWorkflow):
77+
self.locale = None
78+
self.client_ref = None
79+
self.code_length = None
80+
self.code = None
81+
return self
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from typing import Optional
2+
3+
from pydantic import BaseModel
4+
5+
6+
class StartVerificationResponse(BaseModel):
7+
request_id: str
8+
check_url: Optional[str] = None

0 commit comments

Comments
 (0)