| 
 | 1 | +import base64  | 
 | 2 | +from io import BytesIO  | 
 | 3 | + | 
 | 4 | +import yoti_python_sdk  | 
 | 5 | +from filetype import filetype  | 
 | 6 | +from flask import Flask, Response, render_template, request, send_file, session  | 
 | 7 | +from yoti_python_sdk.doc_scan import (  | 
 | 8 | +    DocScanClient,  | 
 | 9 | +    RequestedDocumentAuthenticityCheckBuilder,  | 
 | 10 | +    RequestedFaceMatchCheckBuilder,  | 
 | 11 | +    RequestedLivenessCheckBuilder,  | 
 | 12 | +    RequestedTextExtractionTaskBuilder,  | 
 | 13 | +    SdkConfigBuilder,  | 
 | 14 | +    SessionSpecBuilder,  | 
 | 15 | +)  | 
 | 16 | +from yoti_python_sdk.doc_scan.exception import DocScanException  | 
 | 17 | + | 
 | 18 | +from .settings import YOTI_APP_BASE_URL, YOTI_CLIENT_SDK_ID, YOTI_KEY_FILE_PATH  | 
 | 19 | + | 
 | 20 | +app = Flask(__name__)  | 
 | 21 | +app.secret_key = "someSecretKey"  | 
 | 22 | + | 
 | 23 | + | 
 | 24 | +def create_session():  | 
 | 25 | +    """  | 
 | 26 | +    Creates a Doc Scan session  | 
 | 27 | +
  | 
 | 28 | +    :return: the create session result  | 
 | 29 | +    :rtype: CreateSessionResult  | 
 | 30 | +    """  | 
 | 31 | +    doc_scan_client = DocScanClient(YOTI_CLIENT_SDK_ID, YOTI_KEY_FILE_PATH)  | 
 | 32 | + | 
 | 33 | +    sdk_config = (  | 
 | 34 | +        SdkConfigBuilder()  | 
 | 35 | +        .with_allows_camera_and_upload()  | 
 | 36 | +        .with_primary_colour("#2d9fff")  | 
 | 37 | +        .with_secondary_colour("#FFFFFF")  | 
 | 38 | +        .with_font_colour("#FFFFFF")  | 
 | 39 | +        .with_locale("en-GB")  | 
 | 40 | +        .with_preset_issuing_country("GBR")  | 
 | 41 | +        .with_success_url("{url}/success".format(url=YOTI_APP_BASE_URL))  | 
 | 42 | +        .with_error_url("{url}/error".format(url=YOTI_APP_BASE_URL))  | 
 | 43 | +        .build()  | 
 | 44 | +    )  | 
 | 45 | + | 
 | 46 | +    session_spec = (  | 
 | 47 | +        SessionSpecBuilder()  | 
 | 48 | +        .with_client_session_token_ttl(600)  | 
 | 49 | +        .with_resources_ttl(90000)  | 
 | 50 | +        .with_user_tracking_id("some-user-tracking-id")  | 
 | 51 | +        .with_requested_check(RequestedDocumentAuthenticityCheckBuilder().build())  | 
 | 52 | +        .with_requested_check(  | 
 | 53 | +            RequestedLivenessCheckBuilder()  | 
 | 54 | +            .for_zoom_liveness()  | 
 | 55 | +            .with_max_retries(1)  | 
 | 56 | +            .build()  | 
 | 57 | +        )  | 
 | 58 | +        .with_requested_check(  | 
 | 59 | +            RequestedFaceMatchCheckBuilder().with_manual_check_fallback().build()  | 
 | 60 | +        )  | 
 | 61 | +        .with_requested_task(  | 
 | 62 | +            RequestedTextExtractionTaskBuilder().with_manual_check_always().build()  | 
 | 63 | +        )  | 
 | 64 | +        .with_sdk_config(sdk_config)  | 
 | 65 | +        .build()  | 
 | 66 | +    )  | 
 | 67 | + | 
 | 68 | +    return doc_scan_client.create_session(session_spec)  | 
 | 69 | + | 
 | 70 | + | 
 | 71 | +@app.route("/")  | 
 | 72 | +def index():  | 
 | 73 | +    try:  | 
 | 74 | +        result = create_session()  | 
 | 75 | +    except DocScanException as e:  | 
 | 76 | +        return render_template("error.html", error=e.text)  | 
 | 77 | + | 
 | 78 | +    session["doc_scan_session_id"] = result.session_id  | 
 | 79 | + | 
 | 80 | +    iframe_url = "{base_url}/web/index.html?sessionID={session_id}&sessionToken={session_token}".format(  | 
 | 81 | +        base_url=yoti_python_sdk.YOTI_DOC_SCAN_API_URL,  | 
 | 82 | +        session_id=result.session_id,  | 
 | 83 | +        session_token=result.client_session_token,  | 
 | 84 | +    )  | 
 | 85 | + | 
 | 86 | +    return render_template("index.html", iframe_url=iframe_url)  | 
 | 87 | + | 
 | 88 | + | 
 | 89 | +@app.route("/success")  | 
 | 90 | +def success():  | 
 | 91 | +    doc_scan_client = DocScanClient(YOTI_CLIENT_SDK_ID, YOTI_KEY_FILE_PATH)  | 
 | 92 | + | 
 | 93 | +    session_id = session.get("doc_scan_session_id", None)  | 
 | 94 | + | 
 | 95 | +    try:  | 
 | 96 | +        session_result = doc_scan_client.get_session(session_id)  | 
 | 97 | +    except DocScanException as e:  | 
 | 98 | +        return render_template("error.html", error=e.text)  | 
 | 99 | + | 
 | 100 | +    return render_template("success.html", session_result=session_result)  | 
 | 101 | + | 
 | 102 | + | 
 | 103 | +@app.route("/error")  | 
 | 104 | +def error():  | 
 | 105 | +    error_message = "An unknown error occurred"  | 
 | 106 | + | 
 | 107 | +    if request.args.get("yotiErrorCode", None) is not None:  | 
 | 108 | +        error_message = "Error Code: {}".format(request.args.get("yotiErrorCode"))  | 
 | 109 | + | 
 | 110 | +    return render_template("error.html", error=error_message)  | 
 | 111 | + | 
 | 112 | + | 
 | 113 | +@app.route("/media")  | 
 | 114 | +def media():  | 
 | 115 | +    media_id = request.args.get("mediaId", None)  | 
 | 116 | +    if media_id is None:  | 
 | 117 | +        return Response(status=404)  | 
 | 118 | + | 
 | 119 | +    doc_scan_client = DocScanClient(YOTI_CLIENT_SDK_ID, YOTI_KEY_FILE_PATH)  | 
 | 120 | + | 
 | 121 | +    base64_req = request.args.get("base64", "0")  | 
 | 122 | + | 
 | 123 | +    session_id = session.get("doc_scan_session_id", None)  | 
 | 124 | +    if session_id is None:  | 
 | 125 | +        return Response("No session ID available", status=404)  | 
 | 126 | + | 
 | 127 | +    try:  | 
 | 128 | +        retrieved_media = doc_scan_client.get_media_content(session_id, media_id)  | 
 | 129 | +    except DocScanException as e:  | 
 | 130 | +        return render_template("error.html", error=e.text)  | 
 | 131 | + | 
 | 132 | +    if base64_req == "1" and retrieved_media.mime_type == "application/octet-stream":  | 
 | 133 | +        decoded = base64.b64decode(retrieved_media.content)  | 
 | 134 | +        info = filetype.guess(decoded)  | 
 | 135 | + | 
 | 136 | +        buffer = BytesIO()  | 
 | 137 | +        buffer.write(decoded)  | 
 | 138 | +        buffer.seek(0)  | 
 | 139 | + | 
 | 140 | +        return send_file(  | 
 | 141 | +            buffer,  | 
 | 142 | +            attachment_filename="media." + info.extension,  | 
 | 143 | +            mimetype=info.mime,  | 
 | 144 | +            as_attachment=True,  | 
 | 145 | +        )  | 
 | 146 | + | 
 | 147 | +    return Response(  | 
 | 148 | +        retrieved_media.content, content_type=retrieved_media.mime_type, status=200  | 
 | 149 | +    )  | 
 | 150 | + | 
 | 151 | + | 
 | 152 | +if __name__ == "__main__":  | 
 | 153 | +    app.run()  | 
0 commit comments