Skip to content

v2.14.5

Latest

Choose a tag to compare

@mehmet-yoti mehmet-yoti released this 16 Dec 15:13
eab6d64

Static Liveness Check Implementation

Overview

This implementation adds support for Static Liveness Check to the Yoti Python SDK, enabling identity verification using a single static image instead of the ZOOM liveness method which requires multiple frames and facemap data.

Features Added

1. Session Creation (Request Side)

Create STATIC Liveness Check

from yoti_python_sdk.doc_scan import RequestedLivenessCheckBuilder

# Build a STATIC liveness check
liveness_check = (
    RequestedLivenessCheckBuilder()
    .for_static_liveness()
    .with_max_retries(3)
    .with_manual_check_never()
    .build()
)

Generated JSON:

{
  "type": "LIVENESS",
  "config": {
    "liveness_type": "STATIC",
    "manual_check": "NEVER",
    "max_retries": 3
  }
}

2. Session Retrieval (Response Side)

Access STATIC Liveness Resources

from yoti_python_sdk.doc_scan import DocScanClient

client = DocScanClient(sdk_id, key_file_path)
session_result = client.get_session(session_id)

# Get all STATIC liveness resources
static_resources = session_result.resources.static_liveness_resources

for resource in static_resources:
    print(f"Resource ID: {resource.id}")
    print(f"Liveness Type: {resource.liveness_type}")
    
    # Access the image and media
    if resource.image and resource.image.media:
        media_id = resource.image.media.id
        media_type = resource.image.media.type
        created = resource.image.media.created
        
        print(f"Media ID: {media_id}")
        print(f"Media Type: {media_type}")

3. Media Content Retrieval

Download STATIC Liveness Image

# Get the first STATIC liveness resource
static_liveness = session_result.resources.static_liveness_resources[0]

# Extract media ID
media_id = static_liveness.image.media.id

# Retrieve the actual image content
media_content = client.get_media_content(session_id, media_id)

# Access the image bytes and MIME type
image_bytes = media_content.content
mime_type = media_content.mime_type  # e.g., "image/jpeg" or "image/png"

# Save to file
with open(f"liveness_image.{mime_type.split('/')[-1]}", "wb") as f:
    f.write(image_bytes)

Run Tests

# Run STATIC liveness tests only
pytest yoti_python_sdk/tests/doc_scan/session/create/check/test_liveness_check.py -v
pytest yoti_python_sdk/tests/doc_scan/session/retrieve/test_static_liveness_resource.py -v

# Run all doc_scan tests
pytest yoti_python_sdk/tests/doc_scan/ -v

Example Application

The Flask example application (examples/doc_scan/) now displays Static Liveness resources on the success page:

  • Shows resource ID and liveness type
  • Displays the static liveness image
  • Provides media ID for reference
  • Uses collapsible accordion UI similar to ZOOM liveness

Backward Compatibility

Fully backward compatible - All existing code using ZOOM liveness continues to work without any changes:

# Existing ZOOM liveness code still works
zoom_check = RequestedLivenessCheckBuilder().for_zoom_liveness().build()
zoom_resources = session_result.resources.zoom_liveness_resources

# New STATIC liveness code
static_check = RequestedLivenessCheckBuilder().for_static_liveness().build()
static_resources = session_result.resources.static_liveness_resources

Acceptance Criteria

All three acceptance criteria have been met:

  1. Add support for requesting a liveness check type STATIC

    • Implemented via for_static_liveness() builder method
    • Supports manual_check parameter (defaults to "NEVER")
  2. Add support for retrieving the updated liveness check response

    • Created StaticLivenessResourceResponse class
    • Added static_liveness_resources filter property
    • Parses image and media objects correctly
  3. Ensure that the SDKs support retrieving the media for the STATIC liveness check

    • Media ID accessible via resource.image.media.id
    • Existing get_media_content() method works seamlessly
    • Example application displays the image

For Existing Implementations

No changes required! Your existing ZOOM liveness code will continue to work. You can optionally add STATIC liveness support:

# Add STATIC liveness alongside existing ZOOM liveness
session_spec = (
    SessionSpecBuilder()
    .with_requested_check(
        RequestedLivenessCheckBuilder()
        .for_zoom_liveness()  # Existing
        .with_max_retries(1)
        .build()
    )
    .with_requested_check(
        RequestedLivenessCheckBuilder()
        .for_static_liveness()  # New
        .with_max_retries(3)
        .with_manual_check_never()
        .build()
    )
    # ... other configuration
    .build()
)