All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wultra.app.onboardingserver.provider.zenid.ZenidDocumentVerificationProvider Maven / Gradle / Ivy

The newest version!
/*
 * PowerAuth Enrollment Server
 * Copyright (C) 2021 Wultra s.r.o.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 */
package com.wultra.app.onboardingserver.provider.zenid;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wultra.app.enrollmentserver.model.enumeration.CardSide;
import com.wultra.app.enrollmentserver.model.enumeration.DocumentType;
import com.wultra.app.enrollmentserver.model.enumeration.DocumentVerificationStatus;
import com.wultra.app.enrollmentserver.model.integration.*;
import com.wultra.app.onboardingserver.api.errorhandling.DocumentVerificationException;
import com.wultra.app.onboardingserver.api.provider.DocumentVerificationProvider;
import com.wultra.app.onboardingserver.common.database.DocumentVerificationRepository;
import com.wultra.app.onboardingserver.common.database.entity.DocumentResultEntity;
import com.wultra.app.onboardingserver.common.database.entity.DocumentVerificationEntity;
import com.wultra.app.onboardingserver.common.errorhandling.RemoteCommunicationException;
import com.wultra.app.onboardingserver.provider.zenid.model.api.*;
import com.wultra.core.rest.client.base.RestClientException;
import jakarta.annotation.Nullable;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * Implementation of the {@link DocumentVerificationProvider} with ZenID.
 *
 * @author Lukas Lukovsky, [email protected]
 */
@ConditionalOnProperty(value = "enrollment-server-onboarding.document-verification.provider", havingValue = "zenid")
@Component
@Slf4j
public class ZenidDocumentVerificationProvider implements DocumentVerificationProvider {

    private static final String SDK_INIT_RESPONSE = "zenid-sdk-init-response";
    private static final String SDK_INIT_TOKEN = "sdk-init-token";

    private static final String INTERNAL_SERVER_ERROR = "InternalServerError";
    private static final String LICENSE_INVALID = "License invalid";

    private final ZenidConfigProps zenidConfigProps;

    private final ObjectMapper objectMapper;

    private final DocumentVerificationRepository documentVerificationRepository;

    private final ZenidRestApiService zenidApiService;

    /**
     * Service constructor.
     *
     * @param zenidConfigProps               ZenID configuration properties.
     * @param objectMapper                   Object mapper.
     * @param documentVerificationRepository Document verification repository.
     * @param zenidApiService                ZenID API service.
     */
    @Autowired
    public ZenidDocumentVerificationProvider(
            ZenidConfigProps zenidConfigProps,
            @Qualifier("objectMapperZenid")
            ObjectMapper objectMapper,
            DocumentVerificationRepository documentVerificationRepository,
            ZenidRestApiService zenidApiService) {
        this.zenidConfigProps = zenidConfigProps;
        this.objectMapper = objectMapper;
        this.documentVerificationRepository = documentVerificationRepository;
        this.zenidApiService = zenidApiService;
    }

    @Override
    public DocumentsSubmitResult checkDocumentUpload(OwnerId id, DocumentVerificationEntity document) throws RemoteCommunicationException, DocumentVerificationException {
        DocumentsSubmitResult result = new DocumentsSubmitResult();
        ResponseEntity responseEntity;

        try {
            responseEntity = zenidApiService.syncSample(document.getUploadId());
        } catch (RestClientException e) {
            throw new RemoteCommunicationException(
                    String.format("Unable to check %s upload in ZenID due to a REST call failure, statusCode=%s, responseBody='%s', %s",
                            document, e.getStatusCode(), e.getResponse(), id),
                    e);
        } catch (Exception e) {
            throw new RemoteCommunicationException(
                    String.format("Unexpected error when checking %s upload in ZenID, %s", document, id), e);
        }

        final ZenidWebUploadSampleResponse response = responseEntity.getBody();
        if (response == null) {
            throw new RemoteCommunicationException(String.format("Missing response body when checking %s upload in ZenID, %s", document, id));
        }

        if (!responseEntity.getStatusCode().is2xxSuccessful()) {
            throw new DocumentVerificationException(
                    String.format("Failed to check %s upload in ZenID, statusCode=%s, responseBody='%s', %s",
                            document, responseEntity.getStatusCode(), response, id));
        }
        handleLicenceError(response.getErrorCode(), response.getErrorText());

        DocumentSubmitResult documentSubmitResult =
                createDocumentSubmitResult(id, document.getUploadId(), document.toString(), response);
        if (response.getMinedData() != null) {
            checkForMinedPhoto(id, document.getUploadId(), result, response.getMinedData());
        }

        if (zenidConfigProps.isAdditionalDocSubmitValidationsEnabled() && response.getMinedData() != null) {
            checkAdditionalValidations(id, document.getType(), document.getSide(), documentSubmitResult, response.getMinedData());
        }

        result.setResults(List.of(documentSubmitResult));

        return result;
    }

    @Override
    public DocumentsSubmitResult submitDocuments(OwnerId id, List documents) throws RemoteCommunicationException, DocumentVerificationException {
        DocumentsSubmitResult result = new DocumentsSubmitResult();

        for (SubmittedDocument document : documents) {
            ResponseEntity responseEntity;

            try {
                responseEntity = zenidApiService.uploadSample(id, document);
            } catch (RestClientException e) {
                throw new RemoteCommunicationException(
                        String.format("Failed REST call to submit documents to ZenID, statusCode=%s, responseBody='%s', %s",
                                e.getStatusCode(), e.getResponse(), id),
                        e);
            } catch (Exception e) {
                throw new RemoteCommunicationException(String.format("Unexpected error when submitting documents to ZenID, %s", id), e);
            }

            final ZenidWebUploadSampleResponse response = responseEntity.getBody();
            if (response == null) {
                throw new RemoteCommunicationException(String.format("Missing response body when submitting documents to ZenID, %s", id));
            }

            if (!responseEntity.getStatusCode().is2xxSuccessful()) {
                throw new DocumentVerificationException(
                        String.format("Failed to submit documents to ZenID, statusCode=%s, responseBody='%s', %s",
                                responseEntity.getStatusCode(), response, id));
            }
            handleLicenceError(response.getErrorCode(), response.getErrorText());

            DocumentSubmitResult documentSubmitResult =
                    createDocumentSubmitResult(id, document.getDocumentId(), document.toString(), response);
            if (response.getMinedData() != null) {
                checkForMinedPhoto(id, document.getDocumentId(), result, response.getMinedData());
            }
            if (zenidConfigProps.isAdditionalDocSubmitValidationsEnabled() && response.getMinedData() != null) {
                checkAdditionalValidations(id, document.getType(), document.getSide(), documentSubmitResult, response.getMinedData());
            }
            result.getResults().add(documentSubmitResult);
        }
        return result;
    }

    @Override
    public boolean shouldStoreSelfie() {
        return true;
    }

    @Override
    public DocumentsVerificationResult verifyDocuments(OwnerId id, List uploadIds) throws RemoteCommunicationException, DocumentVerificationException {
        ResponseEntity responseEntity;
        try {
            responseEntity = zenidApiService.investigateSamples(uploadIds);
        } catch (RestClientException e) {
            throw new RemoteCommunicationException(
                    String.format("Failed REST call to verify documents %s in ZenID, statusCode=%s, responseBody='%s', %s",
                            uploadIds, e.getStatusCode(), e.getResponse(), id),
                    e);
        } catch (Exception e) {
            throw new RemoteCommunicationException(String.format("Unexpected error when verifying documents %s in ZenID", uploadIds), e);
        }

        final ZenidWebInvestigateResponse response = responseEntity.getBody();
        if (response == null) {
            throw new RemoteCommunicationException(String.format("Missing response body when verifying documents %s in ZenID, %s", uploadIds, id));
        }

        if (!responseEntity.getStatusCode().is2xxSuccessful()) {
            throw new DocumentVerificationException(
                    String.format("Failed to verify documents %s in ZenID, statusCode=%s, responseBody='%s', %s", uploadIds, responseEntity.getStatusCode(), response, id));
        }
        handleLicenceError(response.getErrorCode(), response.getErrorText());

        return toResult(id, response, uploadIds);
    }

    @Override
    public DocumentsVerificationResult getVerificationResult(OwnerId id, String verificationId) throws RemoteCommunicationException, DocumentVerificationException {
        ResponseEntity responseEntity;
        try {
            responseEntity = zenidApiService.getInvestigation(verificationId);
        } catch (RestClientException e) {
            throw new RemoteCommunicationException(
                    String.format("Failed REST call to get a verification result for verificationId=%s from ZenID, statusCode=%s, responseBody='%s', %s", verificationId, e.getStatusCode(), e.getResponse(), id), e);
        } catch (Exception e) {
            throw new RemoteCommunicationException("Unexpected error when getting a verification result for verificationId=" + verificationId, e);
        }

        final ZenidWebInvestigateResponse response = responseEntity.getBody();
        if (response == null) {
            throw new RemoteCommunicationException(
                    String.format("Unexpected error when getting a verification result for verificationId=%s from ZenID, %s", verificationId, id));
        }

        if (!responseEntity.getStatusCode().is2xxSuccessful()) {
            throw new DocumentVerificationException(
                    String.format("Failed to get a verification result for verificationId=%s from ZenID, statusCode=%s, responseBody='%s', %s",
                            verificationId, responseEntity.getStatusCode(), response, id));
        }
        handleLicenceError(response.getErrorCode(), response.getErrorText());

        List uploadIds = documentVerificationRepository.findAllUploadIds(verificationId);
        return toResult(id, response, uploadIds);
    }

    @Override
    public Image getPhoto(String photoId) throws RemoteCommunicationException, DocumentVerificationException {
        ResponseEntity responseEntity;
        try {
            responseEntity = zenidApiService.getImage(photoId);
        } catch (RestClientException e) {
            throw new RemoteCommunicationException(
                    String.format("Failed REST call to get a photoId=%s from ZenID, statusCode=%s, responseBody='%s'", photoId, e.getStatusCode(), e.getResponse()),
                    e);
        } catch (Exception e) {
            throw new RemoteCommunicationException(String.format("Unexpected error when getting a photo=%s from ZenID", photoId), e);
        }

        if (responseEntity.getBody() == null) {
            throw new RemoteCommunicationException(String.format("Missing response body when getting a photoId=%s from ZenID", photoId));
        }

        if (!responseEntity.getStatusCode().is2xxSuccessful()) {
            throw new DocumentVerificationException(String.format("Failed to get a photo photoId=%s from ZenID, statusCode=%s, hasBody=%s",
                    photoId, responseEntity.getStatusCode(), responseEntity.hasBody()));
        }

        String filename = getContentDispositionFilename(responseEntity.getHeaders());

        return Image.builder()
                .data(responseEntity.getBody())
                .filename(filename)
                .build();
    }

    @Override
    public void cleanupDocuments(OwnerId id, List uploadIds) throws RemoteCommunicationException, DocumentVerificationException {
        for (String uploadId : uploadIds) {
            ResponseEntity responseEntity;
            try {
                responseEntity = zenidApiService.deleteSample(uploadId);
            } catch (RestClientException e) {
                throw new RemoteCommunicationException(
                        String.format("Failed REST call to cleanup documents from ZenID, statusCode=%s, responseBody='%s', %s",
                            e.getStatusCode(), e.getResponse(), id),
                        e);
            } catch (Exception e) {
                throw new RemoteCommunicationException("Unexpected error when cleaning up documents from ZenID, " + id, e);
            }

            final ZenidWebDeleteSampleResponse response = responseEntity.getBody();
            if (response == null) {
                throw new RemoteCommunicationException("Missing response body when cleaning up documents from ZenID, " + id);
            }

            if (!responseEntity.getStatusCode().is2xxSuccessful()) {
                throw new DocumentVerificationException(
                        String.format("Failed to cleanup a document uploadId=%s from ZenID, statusCode=%s, responseBody='%s', %s",
                                uploadId, responseEntity.getStatusCode(), response, id));
            }
            handleLicenceError(response.getErrorCode(), response.getErrorText());

            if (ZenidWebDeleteSampleResponse.ErrorCodeEnum.UNKNOWN_SAMPLE_ID.equals(response.getErrorCode())) {
                logger.info("Cleanup of an unknown document with uploadId={}", uploadId);
            } else if (response.getErrorCode() != null) {
                throw new DocumentVerificationException(
                        String.format("Failed to cleanup uploadId=%s from ZenID, errorCode=%s, errorText=%s",
                                uploadId, response.getErrorCode(), response.getErrorText()));
            }
        }
        logger.info("{} Cleaned up uploaded documents {} from ZenID.", id, uploadIds);
    }

    @Override
    public List parseRejectionReasons(DocumentResultEntity docResult) throws DocumentVerificationException {
        if (docResult.getVerificationResult() == null) {
            logger.warn("Missing the verification result in {} to parse rejected errors from", docResult);
            return Collections.emptyList();
        }
        final List validations;
        try {
            validations = objectMapper.readValue(docResult.getVerificationResult(), new TypeReference<>() { });
        } catch (JsonProcessingException e) {
            throw new DocumentVerificationException("Unexpected error when parsing verification result data from " + docResult, e);
        }

        final List errors = new ArrayList<>();
        if (validations != null) {
            validations.forEach(validation -> {
                if (Boolean.TRUE.equals(validation.getOk())) {
                    return;
                }
                validation.getIssues().forEach(issue -> errors.add(issue.getIssueDescription()));
            });
        }

        return errors;
    }

    @Override
    public VerificationSdkInfo initVerificationSdk(OwnerId id, Map initAttributes) throws RemoteCommunicationException, DocumentVerificationException {
        Validate.isTrue(initAttributes.containsKey(SDK_INIT_TOKEN), "Missing initialization token for ZenID SDK");
        String token = initAttributes.get(SDK_INIT_TOKEN);

        ResponseEntity responseEntity;
        try {
            responseEntity = zenidApiService.initSdk(token);
        } catch (RestClientException e) {
            throw new RemoteCommunicationException(
                    String.format("Failed REST call to init ZenID SDK, statusCode=%s, responseBody='%s', %s", e.getStatusCode(), e.getResponse(), id),
                    e);
        } catch (Exception e) {
            throw new RemoteCommunicationException("Unexpected error when initializing ZenID SDK, " + id, e);
        }

        final ZenidWebInitSdkResponse response = responseEntity.getBody();
        if (response == null) {
            throw new RemoteCommunicationException("Missing response body when initializing ZenID SDK, " + id);
        }

        if (!responseEntity.getStatusCode().is2xxSuccessful()) {
            throw new DocumentVerificationException(
                    String.format("Failed to initialize ZenID SDK, statusCode=%s, responseBody='%s', %s",
                        responseEntity.getStatusCode(), response, id));
        }

        VerificationSdkInfo verificationSdkInfo = new VerificationSdkInfo();
        verificationSdkInfo.getAttributes().put(SDK_INIT_RESPONSE, response.getResponse());
        return verificationSdkInfo;
    }

    private DocumentSubmitResult createDocumentSubmitResult(OwnerId id,
                                                            String documentId,
                                                            String uploadContext,
                                                            ZenidWebUploadSampleResponse response)
            throws DocumentVerificationException {
        DocumentSubmitResult documentSubmitResult = new DocumentSubmitResult();
        documentSubmitResult.setDocumentId(documentId);
        documentSubmitResult.setUploadId(response.getSampleID());

        if (response.getMinedData() != null) {
            String extractedData = toExtractedData(id, response.getMinedData());
            documentSubmitResult.setExtractedData(extractedData);
        }

        final ZenidWebUploadSampleResponse.StateEnum state = response.getState();
        if (state == ZenidWebUploadSampleResponse.StateEnum.DONE) {
            logger.debug("Document upload of {} is done in ZenID, {}", uploadContext, id);
            if (documentSubmitResult.getExtractedData() == null) {
                logger.info("No data extracted from {} in ZenID, defaulting to empty json data, {}", uploadContext, id);
                documentSubmitResult.setExtractedData(DocumentSubmitResult.NO_DATA_EXTRACTED);
            }
        } else if (state == ZenidWebUploadSampleResponse.StateEnum.NOT_DONE) {
            logger.debug("Document upload of {} is still in progress in ZenID, {}", uploadContext, id);
        } else if (state == ZenidWebUploadSampleResponse.StateEnum.REJECTED) {
            logger.debug("Document upload of {} is rejected in ZenID, {}, {}", uploadContext, response.getErrorText(), id);
            documentSubmitResult.setRejectReason(response.getErrorText());
        } else {
            throw new DocumentVerificationException(String.format("Document upload of %s failed in ZenID: %s, %s", uploadContext, state, id));
        }

        if (response.getErrorCode() != null) {
            documentSubmitResult.setErrorDetail("ZenID error: " + response.getErrorCode() +
                    (response.getErrorText() != null ? ", " + response.getErrorText() : ""));
        }
        return documentSubmitResult;
    }

    private void checkAdditionalValidations(OwnerId id,
                                            DocumentType documentType,
                                            CardSide cardSide,
                                            DocumentSubmitResult documentSubmitResult,
                                            ZenidSharedMineAllResult minedData) {
        if (DocumentType.SELFIE_PHOTO.equals(documentType)) {
            logger.debug("Not performing additional validations for selfie photo");
            return;
        }
        DocumentType zenIdDocType = minedData.getDocumentRole() == null ?
                null : toDocumentType(minedData.getDocumentRole());
        if (documentType != zenIdDocType) {
            logger.info("Received different document type {} ({}) than expected {} from ZenID, {}",
                    zenIdDocType, minedData.getDocumentRole(), documentType, id);
            documentSubmitResult.setRejectReason(
                    String.format("Different document type %s than expected %s", zenIdDocType, documentType)
            );
        }
        if (documentSubmitResult.getRejectReason() == null) {
            CardSide zenIdCardSide = minedData.getPageCode() == null ?
                    null : toCardSide(minedData.getPageCode());
            if (zenIdCardSide == null && cardSide != null) {
                documentSubmitResult.setRejectReason(String.format("Not recognized document side %s", cardSide));
            } else if (zenIdCardSide != null && cardSide != null && cardSide != zenIdCardSide) {
                documentSubmitResult.setRejectReason(
                        String.format("Different document side %s than expected %s", zenIdCardSide, cardSide)
                );
            }
        }        
    }
    
    private void checkForMinedPhoto(OwnerId id,
                                    String documentId,
                                    DocumentsSubmitResult result,
                                    ZenidSharedMineAllResult minedData) {
        // Photo hash of the person is optionally present at /MinedData/Photo/ImageData/ImageHash
        ZenidSharedMinedPhoto photo = minedData.getPhoto();
        if (photo != null && photo.getImageData() != null && photo.getImageData().getImageHash() != null) {
            logger.info("Extracted a photoId from submitted documentId={} to ZenID, {}", documentId, id);
            result.setExtractedPhotoId(photo.getImageData().getImageHash().getAsText());
        }
    }

    private String getContentDispositionFilename(HttpHeaders headers) {
        String filename = headers.getContentDisposition().getFilename();
        if (filename == null) {
            MediaType contentType = headers.getContentType();
            if (contentType != null) {
                filename = "unknown." + contentType.getSubtype().toLowerCase();
            } else {
                throw new IllegalStateException("Unable to resolve filename");
            }
        }
        return filename;
    }

    private DocumentsVerificationResult toResult(OwnerId id, ZenidWebInvestigateResponse response, List knownSampleIds)
            throws DocumentVerificationException {
        DocumentsVerificationResult result = new DocumentsVerificationResult();
        result.setVerificationId(String.valueOf(response.getInvestigationID()));

        if (response.getErrorCode() != null) {
            result.setErrorDetail("ZenID error: " + response.getErrorCode() +
                    (response.getErrorText() != null ? ", " + response.getErrorText() : ""));
        } else {
            Map> sampleIdsValidations = new HashMap<>();
            // Only sampleIds with failed validations are in the response, prefill with all known sampleIds
            knownSampleIds.forEach(sampleId -> sampleIdsValidations.put(sampleId, new ArrayList<>()));
            List globalValidations = new ArrayList<>();
            for (ZenidWebInvestigationValidatorResponse validatorResult : response.getValidatorResults()) {
                if (validatorResult.getIssues().isEmpty()) {
                    // no issues - some kind of global validation
                    ZenidWebInvestigationValidatorResponse validationData = copyOf(validatorResult);
                    globalValidations.add(validationData);
                } else {
                    for (ZenidWebInvestigationIssueResponse issueItem : validatorResult.getIssues()) {
                        if (issueItem.getSampleID() == null) {
                            // missing sampleId - some kind of global validation
                            ZenidWebInvestigationValidatorResponse validationData = copyOf(validatorResult);
                            validationData.addIssuesItem(issueItem);
                            globalValidations.add(validationData);
                        } else {
                            // with sampleId - validation on a specific document
                            ZenidWebInvestigationValidatorResponse validationData = copyOf(validatorResult);
                            validationData.addIssuesItem(issueItem);
                            sampleIdsValidations.computeIfAbsent(issueItem.getSampleID(), sampleId -> new ArrayList<>())
                                    .add(validationData);
                        }
                    }
                }
            }

            List verificationResults = new ArrayList<>();

            String extractedData = toExtractedData(id, response.getMinedData());
            for (var entry : sampleIdsValidations.entrySet()) {
                // TODO Consider using an object instead of simple array (call for a standard json)
                List validations = new ArrayList<>(entry.getValue());

                final DocumentVerificationResult verificationResult = new DocumentVerificationResult();
                verificationResult.setExtractedData(extractedData);
                verificationResult.setUploadId(entry.getKey());

                // Find a first failed validation, use its description as the rejected reason for the document
                Optional failedValidation = validations.stream()
                        .filter(validation -> !Boolean.TRUE.equals(validation.getOk()))
                        // Sort the validations by difference between the actual score and the accepted score value
                        .max(Comparator.comparingInt((value -> value.getAcceptScore() - value.getScore())));
                if (failedValidation.isPresent()) {
                    final String rejectReason = failedValidation.get().getIssues().get(0).getIssueDescription();
                    logger.debug("Document rejected in ZenID, {}, {}", rejectReason, id);
                    verificationResult.setRejectReason(rejectReason);
                }

                validations.addAll(globalValidations);
                String verificationResultData;
                try {
                    verificationResultData = objectMapper.writeValueAsString(validations);
                } catch (JsonProcessingException e) {
                    throw new DocumentVerificationException("Unexpected error when processing verification result data, " + id, e);
                }

                verificationResult.setVerificationResult(verificationResultData);
                verificationResults.add(verificationResult);
            }
            result.setResults(verificationResults);
        }

        // TODO compute verification score
        // result.setVerificationScore();

        DocumentVerificationStatus verificationStatus = toStatus(response.getState());
        if (result.getResults() != null) {
            // Check the results if there is no rejected validation
            Optional optionalFailedVerification = result.getResults()
                    .stream()
                    .filter(value -> StringUtils.isNotBlank(value.getRejectReason()))
                    .findAny();
            if (optionalFailedVerification.isPresent()) {
                verificationStatus = DocumentVerificationStatus.REJECTED;
                result.setRejectReason(optionalFailedVerification.get().getRejectReason());
            }
        }
        result.setStatus(verificationStatus);
        return result;
    }

    private ZenidWebInvestigationValidatorResponse copyOf(ZenidWebInvestigationValidatorResponse value) {
        ZenidWebInvestigationValidatorResponse result = new ZenidWebInvestigationValidatorResponse();
        result.setAcceptScore(value.getAcceptScore());
        result.setCode(value.getCode());
        result.setName(value.getName());
        result.setScore(value.getScore());
        result.setOk(value.getOk());
        return result;
    }

    private String toExtractedData(OwnerId id, ZenidSharedMineAllResult minedData) throws DocumentVerificationException {
        try {
            return objectMapper.writeValueAsString(minedData);
        } catch (JsonProcessingException e) {
            throw new DocumentVerificationException("Unexpected error when processing extracted data, " + id, e);
        }
    }

    private DocumentVerificationStatus toStatus(ZenidWebInvestigateResponse.StateEnum stateEnum) {
        return switch (stateEnum) {
            case DONE, ARCHIVED -> DocumentVerificationStatus.ACCEPTED;
            case ERROR -> DocumentVerificationStatus.FAILED;
            case NOT_DONE, OPERATOR -> DocumentVerificationStatus.IN_PROGRESS;
            case REJECTED -> DocumentVerificationStatus.REJECTED;
        };
    }

    private DocumentType toDocumentType(ZenidSharedMineAllResult.DocumentRoleEnum documentRoleEnum) {
        return switch (documentRoleEnum) {
            case DRV -> DocumentType.DRIVING_LICENSE;
            case IDC -> DocumentType.ID_CARD;
            case PAS -> DocumentType.PASSPORT;
            default -> DocumentType.UNKNOWN;
        };
    }

    @Nullable
    private CardSide toCardSide(@Nullable ZenidSharedMineAllResult.PageCodeEnum pageCodeEnum) {
        if (pageCodeEnum == null) {
            return null;
        }
        return switch (pageCodeEnum) {
            case F -> CardSide.FRONT;
            case B -> CardSide.BACK;
        };
    }

    private static void handleLicenceError(final Enum errorCode, final String errorText) throws RemoteCommunicationException {
        if (errorCode != null && INTERNAL_SERVER_ERROR.equals(errorCode.name()) && StringUtils.startsWithIgnoreCase(errorText, LICENSE_INVALID)) {
            throw new RemoteCommunicationException("Out of ZenID licence: " + errorText);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy