Skip to content

Commit

Permalink
[feature] identity verification
Browse files Browse the repository at this point in the history
* fixed path params config and added Identity Verification hooks

* added support for fetching checks

* fixed kyc documents tests

---------

Co-authored-by: Iulian Masar <iulian.masar@codegile.com>
  • Loading branch information
iulian03 and Iulian Masar authored Feb 25, 2025
1 parent 83cf8e6 commit d9cdbda
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 10 deletions.
6 changes: 6 additions & 0 deletions mangopay/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@
('CARD_VALIDATION_CREATED', 'card_validation_created', 'Card Validation Created'),
('CARD_VALIDATION_FAILED', 'card_validation_failed', 'Card Validation Failed'),
('CARD_VALIDATION_SUCCEEDED', 'card_validation_succeeded', 'Card Validation Succeeded'),

('IDENTITY_VERIFICATION_VALIDATED', 'identity_verification_validated', 'Identity Verification Validated'),
('IDENTITY_VERIFICATION_FAILED', 'identity_verification_failed', 'Identity Verification Failed'),
('IDENTITY_VERIFICATION_INCONCLUSIVE', 'identity_verification_inconclusive', 'Identity Verification Inconclusive'),
('IDENTITY_VERIFICATION_OUTDATED', 'identity_verification_outdated', 'Identity Verification Outdated'),
('IDENTITY_VERIFICATION_TIMEOUT', 'identity_verification_timeout', 'Identity Verification Timeout')
)

NOTIFICATION_STATUS_CHOICES = Choices(
Expand Down
11 changes: 8 additions & 3 deletions mangopay/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ def parse_result(self, result, model_klass=None):

return pairs

def parse_url(self, meta_url, params=None):
def parse_url(self, meta_url, params=None, path_params=None):
if isinstance(meta_url, dict):
url = meta_url.get(self.identifier)
else:
url = meta_url

# useful when there is a need to pass a path param which should not be part of the object
if path_params:
url = url % path_params

if params:
url = url % params

Expand Down Expand Up @@ -105,9 +109,10 @@ def all(self, handler=None, without_client_id=False, **params):
class InsertQuery(BaseQuery):
identifier = 'INSERT'

def __init__(self, model, idempotency_key=None, **kwargs):
def __init__(self, model, idempotency_key=None, path_params=None, **kwargs):
self.insert_query = kwargs
self.idempotency_key = idempotency_key
self.path_params = path_params
super(InsertQuery, self).__init__(model, 'POST')

def parse_insert(self):
Expand All @@ -126,7 +131,7 @@ def execute(self, handler=None, model_klass=None):

data = self.parse_insert()

url = self.parse_url(self.model._meta.url, self.insert_query)
url = self.parse_url(self.model._meta.url, self.insert_query, self.path_params)

result, data = handler.request(self.method,
url,
Expand Down
51 changes: 51 additions & 0 deletions mangopay/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -2317,3 +2317,54 @@ class Meta:
url = {
SelectQuery.identifier: '/virtual-accounts/availability'
}


class IdentityVerification(BaseModel):
creation_date = DateTimeField(api_name='CreationDate')
hosted_url = CharField(api_name='HostedUrl')
return_url = CharField(api_name='ReturnUrl', required=True)
status = CharField(api_name='Status')

class Meta:
verbose_name = 'identity_verification'
verbose_name_plural = 'identity_verifications'

url = {
InsertQuery.identifier: '/users/%(user_id)s/identity-verifications',
SelectQuery.identifier: '/identity-verifications'
}

def create(self, user_id, idempotency_key=None, **kwargs):
path_params = {'user_id': user_id}
insert = InsertQuery(self, idempotency_key, path_params, **kwargs)
insert.insert_query = self.get_field_dict()
return insert.execute()

def get_checks(self, *args, **kwargs):
kwargs['id'] = self.id
select = SelectQuery(IdentityVerificationCheck, *args, **kwargs)
select.identifier = 'GET_CHECKS'
return select.get("", *args, **kwargs)


class IdentityVerificationCheck(BaseModel):
session_id = CharField(api_name='SessionId')
status = CharField(api_name='Status')
creation_date = DateTimeField(api_name='CreationDate')
last_update = DateTimeField(api_name='LastUpdate')
checks = ListField(api_name='Checks')

class Meta:
verbose_name = 'identity_verification_check'
verbose_name_plural = 'identity_verifications_checks'

url = {
'GET_CHECKS': '/identity-verifications/%(id)s/checks'
}

@classmethod
def get(cls, identity_verification_id, *args, **kwargs):
kwargs['id'] = identity_verification_id
select = SelectQuery(IdentityVerificationCheck, *args, **kwargs)
select.identifier = 'GET_CHECKS'
return select.get("", *args, **kwargs)
50 changes: 50 additions & 0 deletions tests/test_identity_verification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from mangopay.resources import IdentityVerification, IdentityVerificationCheck
from mangopay.utils import timestamp_from_datetime
from tests.test_base import BaseTestLive


class IdentityVerificationTest(BaseTestLive):
_identity_verification = None

def test_create_identity_verification(self):
self.create_new_identity_verification()
self.assertIsNotNone(IdentityVerificationTest._identity_verification)
self.assertIsNotNone(IdentityVerificationTest._identity_verification.return_url)
self.assertIsNotNone(IdentityVerificationTest._identity_verification.hosted_url)
self.assertEqual(IdentityVerificationTest._identity_verification.status, 'PENDING')

def test_get_identity_verification(self):
self.create_new_identity_verification()
fetched = IdentityVerification.get(IdentityVerificationTest._identity_verification.id)

self.assertIsNotNone(fetched)
self.assertEqual(IdentityVerificationTest._identity_verification.hosted_url, fetched.hosted_url)
self.assertEqual(IdentityVerificationTest._identity_verification.return_url, fetched.return_url)
self.assertEqual(IdentityVerificationTest._identity_verification.status, fetched.status)

def test_get_checks(self):
self.create_new_identity_verification()
# can be fetched in 2 ways:

# checks: IdentityVerificationCheck = IdentityVerificationCheck.get(
# IdentityVerificationTest._identity_verification.id)
checks: IdentityVerificationCheck = IdentityVerificationTest._identity_verification.get_checks()

self.assertIsNotNone(checks)
self.assertEqual(checks.status, 'PENDING')
self.assertTrue(timestamp_from_datetime(checks.creation_date) > 0)
self.assertTrue(timestamp_from_datetime(checks.last_update) > 0)
self.assertIsNotNone(checks.checks)

@staticmethod
def create_new_identity_verification():
if IdentityVerificationTest._identity_verification is None:
john = BaseTestLive.get_john()

identity_verification = IdentityVerification()
identity_verification.return_url = "https://example.com"
identity_verification.tag = "created by the Python SDK"

IdentityVerificationTest._identity_verification = IdentityVerification(
**identity_verification.create(john.id))
return IdentityVerificationTest._identity_verification
16 changes: 9 additions & 7 deletions tests/test_kyc_document.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import time

from mangopay.resources import Document
from mangopay.utils import timestamp_from_datetime
from tests.test_base import BaseTestLive


class KYCDocumentTestLive(BaseTestLive):

def test_GetKycDocuments(self):
johns_document = BaseTestLive.get_johns_kyc_document()
documents = Document.all(BeforeDate=timestamp_from_datetime(johns_document.creation_date) + 1000,
AfterDate=timestamp_from_datetime(johns_document.creation_date) - 1000)
current_time = round(time.time())
documents = Document.all(BeforeDate=current_time + 1000,
AfterDate=current_time - 1000)

self.assertTrue(len(documents.data) > 0)

result = Document.all(page=1, per_page=2, Sort='CreationDate:ASC',
BeforeDate=timestamp_from_datetime(johns_document.creation_date) + 1000,
AfterDate=timestamp_from_datetime(johns_document.creation_date) - 1000)
BeforeDate=current_time + 1000,
AfterDate=current_time - 1000)

self.assertTrue(len(result.data) > 0)

result2 = Document.all(page=1, per_page=2, Sort='CreationDate:DESC',
BeforeDate=timestamp_from_datetime(johns_document.creation_date) + 1000,
AfterDate=timestamp_from_datetime(johns_document.creation_date) - 1000)
BeforeDate=current_time + 1000,
AfterDate=current_time - 1000)

self.assertTrue(len(result.data) > 0)
self.assertFalse(result.data[0].id == result2.data[0].id)
Expand Down

0 comments on commit d9cdbda

Please sign in to comment.