diff --git a/pom.xml b/pom.xml index d285d9d6e..cd589a39c 100644 --- a/pom.xml +++ b/pom.xml @@ -25,11 +25,12 @@ 3.8.5 - 3.1.1 + 3.1.4 1.2.1 - 4.8.3.1 - 3.4.1 - 1.7.0 + + 4.8.6.6 + 3.5.0 + 1.10.0 diff --git a/yoti-sdk-api/pom.xml b/yoti-sdk-api/pom.xml index eba17a205..e4e4a6088 100644 --- a/yoti-sdk-api/pom.xml +++ b/yoti-sdk-api/pom.xml @@ -19,7 +19,7 @@ org.bouncycastle - bcpkix-jdk15on + bcpkix-jdk18on com.fasterxml.jackson.core diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/DigitalIdentityClient.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/DigitalIdentityClient.java index 2aa6f5c5c..1690a9835 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/DigitalIdentityClient.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/DigitalIdentityClient.java @@ -4,6 +4,8 @@ import java.security.KeyPair; import java.security.Security; +import com.yoti.api.client.identity.MatchRequest; +import com.yoti.api.client.identity.MatchResult; import com.yoti.api.client.identity.ShareSession; import com.yoti.api.client.identity.ShareSessionQrCode; import com.yoti.api.client.identity.ShareSessionRequest; @@ -54,6 +56,10 @@ public Receipt fetchShareReceipt(String receiptId) throws DigitalIdentityExcepti return identityService.fetchShareReceipt(sdkId, keyPair, receiptId); } + public MatchResult fetchMatch(MatchRequest request) throws DigitalIdentityException { + return identityService.fetchMatch(sdkId, keyPair, request); + } + private KeyPair loadKeyPair(KeyPairSource keyPairSource) throws InitialisationException { try { return keyPairSource.getFromStream(new KeyStreamVisitor()); diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/MatchNotification.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/MatchNotification.java new file mode 100644 index 000000000..26cfe756d --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/MatchNotification.java @@ -0,0 +1,107 @@ +package com.yoti.api.client.identity; + +import static com.yoti.api.client.spi.remote.call.HttpMethod.SUPPORTED_HTTP_METHODS; + +import java.net.URI; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import com.yoti.validation.Validation; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public final class MatchNotification { + + @JsonProperty(Property.URL) + private final String endpoint; + + @JsonProperty(Property.METHOD) + private final String method; + + @JsonProperty(Property.VERIFY_TLS) + private final boolean verifyTls; + + @JsonProperty(Property.HEADERS) + private final Map headers; + + private MatchNotification(Builder builder) { + endpoint = builder.endpoint; + method = builder.method; + verifyTls = builder.verifyTls; + headers = builder.headers; + } + + public String getEndpoint() { + return endpoint; + } + + public String getMethod() { + return method; + } + + public boolean isVerifyTls() { + return verifyTls; + } + + public Map getHeaders() { + return headers; + } + + public static Builder forUrl(URI uri) { + return new Builder(uri); + } + + public static final class Builder { + + private final String endpoint; + private final Map headers; + + private String method; + private boolean verifyTls; + + private Builder(URI uri) { + Validation.notNull(uri, Property.URL); + + endpoint = uri.toString(); + headers = new HashMap<>(); + } + + public Builder withMethod(String method) { + Validation.withinList(method.toUpperCase(Locale.ROOT), SUPPORTED_HTTP_METHODS); + + this.method = method; + return this; + } + + public Builder withVerifyTls(boolean verifyTls) { + this.verifyTls = verifyTls; + return this; + } + + public Builder withHeaders(Map headers) { + this.headers.putAll(headers); + return this; + } + + public Builder withHeader(String key, String value) { + headers.put(key, value); + return this; + } + + public MatchNotification build() { + return new MatchNotification(this); + } + + } + + private static final class Property { + + private static final String URL = "url"; + private static final String METHOD = "method"; + private static final String VERIFY_TLS = "verifyTls"; + private static final String HEADERS = "headers"; + + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/MatchRequest.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/MatchRequest.java new file mode 100644 index 000000000..6dc333ef7 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/MatchRequest.java @@ -0,0 +1,62 @@ +package com.yoti.api.client.identity; + +import com.yoti.validation.Validation; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public final class MatchRequest { + + @JsonProperty(Property.VALUE) + private final String value; + + @JsonProperty(Property.NOTIFICATION) + private final MatchNotification notification; + + private MatchRequest(Builder builder) { + value = builder.value; + notification = builder.notification; + } + + public String getValue() { + return value; + } + + public MatchNotification getNotification() { + return notification; + } + + public static Builder builder(String value) { + return new Builder(value); + } + + public static final class Builder { + + private final String value; + + private MatchNotification notification; + + private Builder(String value) { + Validation.notNullOrEmpty(value, Property.VALUE); + + this.value = value; + } + + public Builder withNotification(MatchNotification notification) { + this.notification = notification; + return this; + } + + public MatchRequest build() { + return new MatchRequest(this); + } + + } + + private static final class Property { + + private static final String VALUE = "value"; + private static final String NOTIFICATION = "notification"; + + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/MatchResult.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/MatchResult.java new file mode 100644 index 000000000..511b1ec3d --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/MatchResult.java @@ -0,0 +1,36 @@ +package com.yoti.api.client.identity; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public final class MatchResult { + + @JsonProperty(Property.ID) + private String id; + + @JsonProperty(Property.RESULT) + private String result; + + public String getId() { + return id; + } + + public String getResult() { + return result; + } + + public void setId(String id) { + this.id = id; + } + + public void setResult(String result) { + this.result = result; + } + + private static final class Property { + + private static final String ID = "id"; + private static final String RESULT = "result"; + + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/UnsignedPathFactory.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/UnsignedPathFactory.java index 6b322cdf2..15ec5eaa6 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/UnsignedPathFactory.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/UnsignedPathFactory.java @@ -15,6 +15,9 @@ public class UnsignedPathFactory { private static final String IDENTITY_SESSION_RECEIPT_RETRIEVAL = "/v2/receipts/%s"; private static final String IDENTITY_SESSION_RECEIPT_KEY_RETRIEVAL = "/v2/wrapped-item-keys/%s"; + // Match + private static final String DIGITAL_ID_MATCH = "/v1/matches"; + // Share V1 private static final String PROFILE = "/profile/%s?appId=%s"; private static final String QR_CODE = "/qrcodes/apps/%s"; @@ -66,6 +69,10 @@ private static String base64ToBase64url(String value) { return value.replace('+', '-').replace('/', '_'); } + public String createIdentityMatchPath() { + return DIGITAL_ID_MATCH; + } + public String createProfilePath(String appId, String connectToken) { return format(PROFILE, connectToken, appId); } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityService.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityService.java index f2d9d6421..b79178c00 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityService.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityService.java @@ -16,6 +16,8 @@ import java.security.KeyPair; import java.util.Optional; +import com.yoti.api.client.identity.MatchRequest; +import com.yoti.api.client.identity.MatchResult; import com.yoti.api.client.identity.ShareSession; import com.yoti.api.client.identity.ShareSessionQrCode; import com.yoti.api.client.identity.ShareSessionRequest; @@ -189,6 +191,30 @@ private ReceiptItemKey fetchShareReceiptKey(String sdkId, KeyPair keyPair, Wrapp } } + public MatchResult fetchMatch(String sdkId, KeyPair keyPair, MatchRequest matchRequest) + throws DigitalIdentityException { + Validation.notNullOrEmpty(sdkId, "SDK ID"); + Validation.notNull(keyPair, "Application Key Pair"); + Validation.notNull(matchRequest, "DID Match request"); + + String path = pathFactory.createIdentityMatchPath(); + + LOG.debug("Requesting digital ID Match for SDK ID '{}' at '{}'", sdkId, path); + + try { + byte[] payload = ResourceMapper.writeValueAsString(matchRequest); + return createSignedRequest(sdkId, keyPair, path, HTTP_POST, payload).execute(MatchResult.class); + } catch (IOException ex) { + throw new DigitalIdentityException("Error while parsing the DID Match request", ex); + } catch (URISyntaxException ex) { + throw new DigitalIdentityException("Error while building the DID Match request", ex); + } catch (GeneralSecurityException ex) { + throw new DigitalIdentityException("Error while signing the DID Match request", ex); + } catch (ResourceException ex) { + throw new DigitalIdentityException("Error while executing the DID Match request", ex); + } + } + SignedRequest createSignedRequest(String sdkId, KeyPair keyPair, String path) throws GeneralSecurityException, UnsupportedEncodingException, URISyntaxException { return createSignedRequest(sdkId, keyPair, path, HTTP_GET, null); diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/DigitalIdentityClientTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/DigitalIdentityClientTest.java index eaeb6abe1..4745cfa7f 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/DigitalIdentityClientTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/DigitalIdentityClientTest.java @@ -13,6 +13,7 @@ import java.io.InputStream; import java.security.KeyPair; +import com.yoti.api.client.identity.MatchRequest; import com.yoti.api.client.identity.ShareSessionRequest; import com.yoti.api.client.spi.remote.KeyStreamVisitor; import com.yoti.api.client.spi.remote.call.identity.DigitalIdentityException; @@ -37,6 +38,7 @@ public class DigitalIdentityClientTest { @Mock(answer = RETURNS_DEEP_STUBS) KeyPair keyPair; @Mock DigitalIdentityService identityService; @Mock ShareSessionRequest shareSessionRequest; + @Mock MatchRequest matchRequest; private KeyPairSource validKeyPairSource; @@ -224,6 +226,28 @@ public void client_FetchShareReceiptException_DigitalIdentityException() throws assertThat(ex.getMessage(), equalTo(exMessage)); } + @Test + public void client_FetchDigitalIdMatchException_DigitalIdentityException() throws IOException { + when(keyPairSource.getFromStream(any(KeyStreamVisitor.class))).thenReturn(keyPair); + + DigitalIdentityClient identityClient = new DigitalIdentityClient( + AN_SDK_ID, + keyPairSource, + identityService + ); + + String exMessage = "Fetch digital identity match error"; + when(identityService.fetchMatch(AN_SDK_ID, keyPair, matchRequest)) + .thenThrow(new DigitalIdentityException(exMessage)); + + DigitalIdentityException ex = assertThrows( + DigitalIdentityException.class, + () -> identityClient.fetchMatch(matchRequest) + ); + + assertThat(ex.getMessage(), equalTo(exMessage)); + } + private static class KeyPairSourceTest implements KeyPairSource { private final String keyPair; diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityServiceTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityServiceTest.java index dd458dfbd..8e3cacdbf 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityServiceTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityServiceTest.java @@ -14,6 +14,8 @@ import java.security.GeneralSecurityException; import java.security.KeyPair; +import com.yoti.api.client.identity.MatchRequest; +import com.yoti.api.client.identity.MatchResult; import com.yoti.api.client.identity.ShareSession; import com.yoti.api.client.identity.ShareSessionRequest; import com.yoti.api.client.spi.remote.call.SignedRequest; @@ -35,6 +37,7 @@ public class DigitalIdentityServiceTest { private static final String SESSION_ID = "aSessionId"; private static final String QR_CODE_ID = "aQrCodeId"; private static final String SESSION_CREATION_PATH = "aSessionCreationPath"; + private static final String DIGITAL_ID_MATCH_PATH = "aDigitalIdMatchPath"; private static final String POST = "POST"; private static final byte[] A_BODY_BYTES = "aBody".getBytes(StandardCharsets.UTF_8); @@ -44,14 +47,19 @@ public class DigitalIdentityServiceTest { @Mock(answer = RETURNS_DEEP_STUBS) SignedRequestBuilder signedRequestBuilder; @Mock SignedRequestBuilderFactory requestBuilderFactory; - @Mock ShareSessionRequest shareSessionRequest; - @Mock SignedRequest signedRequest; @Mock(answer = RETURNS_DEEP_STUBS) KeyPair keyPair; + @Mock SignedRequest signedRequest; + + @Mock ShareSessionRequest shareSessionRequest; @Mock ShareSession shareSession; + @Mock MatchRequest matchRequest; + @Mock MatchResult matchResult; + @Before public void setUp() { when(unsignedPathFactory.createIdentitySessionPath()).thenReturn(SESSION_CREATION_PATH); + when(unsignedPathFactory.createIdentityMatchPath()).thenReturn(DIGITAL_ID_MATCH_PATH); } @Test @@ -277,4 +285,147 @@ public void fetchShareQrCode_NullSessionId_Exception() { assertThat(ex.getMessage(), containsString("QR Code ID")); } + @Test + public void fetchMatch_NullSdkId_Exception() { + IllegalArgumentException ex = assertThrows( + IllegalArgumentException.class, + () -> identityService.fetchMatch(null, keyPair, matchRequest) + ); + + assertThat(ex.getMessage(), containsString("SDK ID")); + } + + @Test + public void fetchMatch_EmptySdkId_Exception() { + IllegalArgumentException ex = assertThrows( + IllegalArgumentException.class, + () -> identityService.fetchMatch("", keyPair, matchRequest) + ); + + assertThat(ex.getMessage(), containsString("SDK ID")); + } + + @Test + public void fetchMatch_NullKeyPair_Exception() { + IllegalArgumentException ex = assertThrows( + IllegalArgumentException.class, + () -> identityService.fetchMatch(SDK_ID, null, matchRequest) + ); + + assertThat(ex.getMessage(), containsString("Application Key Pair")); + } + + @Test + public void fetchMatch_NullMatchRequest_Exception() { + IllegalArgumentException ex = assertThrows( + IllegalArgumentException.class, + () -> identityService.fetchMatch(SDK_ID, keyPair, null) + ); + + assertThat(ex.getMessage(), notNullValue()); + } + + @Test + public void fetchMatch_SerializingWrongPayload_Exception() { + JsonProcessingException causeEx = new JsonProcessingException("serialization error") {}; + + try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { + mapper.when(() -> ResourceMapper.writeValueAsString(matchRequest)).thenThrow(causeEx); + + DigitalIdentityException ex = assertThrows( + DigitalIdentityException.class, + () -> identityService.fetchMatch(SDK_ID, keyPair, matchRequest) + ); + + Throwable cause = ex.getCause(); + assertTrue(cause instanceof JsonProcessingException); + assertThat(cause.getMessage(), containsString("serialization error")); + } + } + + @Test + public void fetchMatch_BuildingRequestWithWrongEndpoint_Exception() throws Exception { + try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { + mapper.when(() -> ResourceMapper.writeValueAsString(matchRequest)).thenReturn(A_BODY_BYTES); + when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); + + String exMessage = "URI wrong format"; + URISyntaxException causeEx = new URISyntaxException("", exMessage); + when(identityService.createSignedRequest(SDK_ID, keyPair, DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) + .thenThrow(causeEx); + + DigitalIdentityException ex = assertThrows( + DigitalIdentityException.class, + () -> identityService.fetchMatch(SDK_ID, keyPair, matchRequest) + ); + + Throwable cause = ex.getCause(); + assertTrue(cause instanceof URISyntaxException); + assertThat(cause.getMessage(), containsString(exMessage)); + } + } + + @Test + public void fetchMatch_BuildingRequestWithWrongQueryParams_Exception() throws Exception { + try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { + mapper.when(() -> ResourceMapper.writeValueAsString(matchRequest)).thenReturn(A_BODY_BYTES); + + when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); + + String exMessage = "Wrong query params format"; + UnsupportedEncodingException causeEx = new UnsupportedEncodingException(exMessage); + when(identityService.createSignedRequest(SDK_ID, keyPair, DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) + .thenThrow(causeEx); + + DigitalIdentityException ex = assertThrows( + DigitalIdentityException.class, + () -> identityService.fetchMatch(SDK_ID, keyPair, matchRequest) + ); + + Throwable cause = ex.getCause(); + assertTrue(cause instanceof UnsupportedEncodingException); + assertThat(cause.getMessage(), containsString(exMessage)); + } + } + + @Test + public void fetchMatch_BuildingRequestWithWrongDigest_Exception() throws Exception { + try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { + mapper.when(() -> ResourceMapper.writeValueAsString(matchRequest)).thenReturn(A_BODY_BYTES); + + when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); + + String exMessage = "Wrong digest"; + GeneralSecurityException causeEx = new GeneralSecurityException(exMessage); + when(identityService.createSignedRequest(SDK_ID, keyPair, DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) + .thenThrow(causeEx); + + DigitalIdentityException ex = assertThrows( + DigitalIdentityException.class, + () -> identityService.fetchMatch(SDK_ID, keyPair, matchRequest) + ); + + Throwable cause = ex.getCause(); + assertTrue(cause instanceof GeneralSecurityException); + assertThat(cause.getMessage(), containsString(exMessage)); + } + } + + @Test + public void fetchMatch_SessionRequest_exception() throws Exception { + try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { + mapper.when(() -> ResourceMapper.writeValueAsString(matchRequest)).thenReturn(A_BODY_BYTES); + + when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); + + when(identityService.createSignedRequest(SDK_ID, keyPair, DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) + .thenReturn(signedRequest); + + when(signedRequest.execute(MatchResult.class)).thenReturn(matchResult); + + MatchResult result = identityService.fetchMatch(SDK_ID, keyPair, matchRequest); + assertSame(matchResult, result); + } + } + } diff --git a/yoti-sdk-parent/pom.xml b/yoti-sdk-parent/pom.xml index d413cb090..e965c874d 100644 --- a/yoti-sdk-parent/pom.xml +++ b/yoti-sdk-parent/pom.xml @@ -24,9 +24,9 @@ - scm:http://github.com/getyoti/yoti-java-sdk.git - scm:http://github.com/getyoti/yoti-java-sdk.git - http://github.com/getyoti/yoti-java-sdk.git + scm:git:https://github.com/getyoti/yoti-java-sdk.git + scm:git:https://github.com/getyoti/yoti-java-sdk.git + https://github.com/getyoti/yoti-java-sdk.git @@ -58,16 +58,6 @@ false false - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - nexus @@ -98,10 +88,10 @@ 8 - 2.0.9 - 1.70 - 2.16.1 - 3.25.3 + 2.0.16 + 1.81 + 2.19.0 + 3.25.8 4.5.14 @@ -112,42 +102,44 @@ 4.13.2 4.11.0 - 2.2 - 3.13.0 + 3.0 + 3.17.0 3.8.5 - 3.11.0 + 3.14.0 - 4.8.3 - 4.8.3.1 - 1.13.0 + + 4.8.6 + 4.8.6.6 + 1.14.0 - 8.4.3 + + 10.0.4 12 - 1.23 + 1.24 java18 1.0 - 3.4.1 - 1.7.0 + 3.5.0 + 1.10.0 - 1.6.13 + 0.8.0 - 3.3.0 + 3.3.1 - 3.6.3 + 3.11.2 8 - 3.1.0 + 3.2.7 - 3.5.0 + 3.9.0 4.3.0 - 0.8.11 + 0.8.13 @@ -156,8 +148,8 @@ org.bouncycastle - bcpkix-jdk15on - ${bouncy.castle.version} + bcpkix-jdk18on + ${bouncycastle.version} com.fasterxml.jackson @@ -228,7 +220,7 @@ org.apache.commons commons-lang3 - ${commons.lang3.version} + ${commons-lang3.version} test @@ -362,14 +354,13 @@ - org.sonatype.plugins - nexus-staging-maven-plugin - ${nexus-staging-maven-plugin.version} + org.sonatype.central + central-publishing-maven-plugin + ${central-publishing-maven-plugin.version} true - ossrh - https://oss.sonatype.org/ - true + central + true @@ -460,8 +451,8 @@ - org.sonatype.plugins - nexus-staging-maven-plugin + org.sonatype.central + central-publishing-maven-plugin diff --git a/yoti-sdk-sandbox/pom.xml b/yoti-sdk-sandbox/pom.xml index 1db785842..f8796b865 100644 --- a/yoti-sdk-sandbox/pom.xml +++ b/yoti-sdk-sandbox/pom.xml @@ -19,7 +19,7 @@ org.bouncycastle - bcpkix-jdk15on + bcpkix-jdk18on com.fasterxml.jackson.core diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxCheck.java index 0e4eca284..aa3954176 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxCheck.java @@ -29,6 +29,7 @@ static abstract class Builder> { protected SandboxRecommendation recommendation; protected List breakdown = new ArrayList<>(); + protected String reportTemplate; public T withRecommendation(SandboxRecommendation recommendation) { this.recommendation = recommendation; @@ -46,6 +47,11 @@ public T withBreakdowns(List breakdowns) { return self(); } + public T withReportTemplate(String reportTemplate) { + this.reportTemplate = reportTemplate; + return self(); + } + protected abstract T self(); public abstract SandboxCheck build(); diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxCheckResult.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxCheckResult.java index ad3d6202d..5a827e1e6 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxCheckResult.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxCheckResult.java @@ -9,12 +9,20 @@ class SandboxCheckResult { @JsonProperty("report") private final SandboxCheckReport report; - SandboxCheckResult(SandboxCheckReport report) { + @JsonProperty("report_template") + private final String reportTemplate; + + SandboxCheckResult(SandboxCheckReport report, String reportTemplate) { this.report = report; + this.reportTemplate = reportTemplate; } public SandboxCheckReport getReport() { return report; } + public String getReportTemplate() { + return reportTemplate; + } + } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheck.java index fd3d40505..6dfdc1b96 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheck.java @@ -30,10 +30,8 @@ protected Builder self() { @Override public SandboxDocumentAuthenticityCheck build() { - notNull(recommendation, "recommendation"); - SandboxCheckReport report = new SandboxCheckReport(recommendation, breakdown); - SandboxCheckResult result = new SandboxCheckResult(report); + SandboxCheckResult result = new SandboxCheckResult(report, reportTemplate); return new SandboxDocumentAuthenticityCheck(result, documentFilter); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheck.java index d3ec8a5a9..e888bdb28 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheck.java @@ -30,10 +30,8 @@ protected Builder self() { @Override public SandboxDocumentFaceMatchCheck build() { - notNull(recommendation, "recommendation"); - SandboxCheckReport report = new SandboxCheckReport(recommendation, breakdown); - SandboxCheckResult result = new SandboxCheckResult(report); + SandboxCheckResult result = new SandboxCheckResult(report, reportTemplate); return new SandboxDocumentFaceMatchCheck(result, documentFilter); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheck.java index 6ba037e6e..4fc3b5ef4 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheck.java @@ -57,10 +57,8 @@ protected Builder self() { @Override public SandboxDocumentTextDataCheck build() { - notNull(recommendation, "recommendation"); - SandboxCheckReport report = new SandboxCheckReport(recommendation, breakdown); - SandboxDocumentTextDataCheckResult result = new SandboxDocumentTextDataCheckResult(report, documentFields); + SandboxDocumentTextDataCheckResult result = new SandboxDocumentTextDataCheckResult(report, reportTemplate, documentFields); return new SandboxDocumentTextDataCheck(result, documentFilter); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheckResult.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheckResult.java index 76ba5c6a5..0b9fdfba2 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheckResult.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheckResult.java @@ -11,8 +11,8 @@ public class SandboxDocumentTextDataCheckResult extends SandboxCheckResult { @JsonProperty("document_fields") private Map documentFields; - SandboxDocumentTextDataCheckResult(SandboxCheckReport report, Map documentFields) { - super(report); + SandboxDocumentTextDataCheckResult(SandboxCheckReport report, String reportTemplate, Map documentFields) { + super(report, reportTemplate); this.documentFields = documentFields; } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheck.java index 6efb6a4c8..c19aabf78 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheck.java @@ -41,10 +41,8 @@ protected Builder self() { @Override public SandboxIdDocumentComparisonCheck build() { - notNull(recommendation, "recommendation"); - SandboxCheckReport report = new SandboxCheckReport(recommendation, breakdown); - SandboxCheckResult result = new SandboxCheckResult(report); + SandboxCheckResult result = new SandboxCheckResult(report, reportTemplate); return new SandboxIdDocumentComparisonCheck(result, secondaryDocumentFilter); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxStaticLivenessCheckBuilder.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxStaticLivenessCheckBuilder.java index 441d0f2ce..ee0db329d 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxStaticLivenessCheckBuilder.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxStaticLivenessCheckBuilder.java @@ -23,10 +23,8 @@ protected SandboxStaticLivenessCheckBuilder self() { @Override public SandboxLivenessCheck build() { - notNull(recommendation, "recommendation"); - SandboxCheckReport report = new SandboxCheckReport(recommendation, breakdown); - SandboxCheckResult result = new SandboxCheckResult(report); + SandboxCheckResult result = new SandboxCheckResult(report, reportTemplate); return new SandboxLivenessCheck(result, DocScanConstants.STATIC, responseDelay); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheck.java index ee58d2663..7e294a5c0 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheck.java @@ -54,10 +54,8 @@ protected Builder self() { @Override public SandboxSupplementaryDocumentTextDataCheck build() { - notNull(recommendation, "recommendation"); - SandboxCheckReport report = new SandboxCheckReport(recommendation, breakdown); - SandboxSupplementaryDocumentTextDataCheckResult result = new SandboxSupplementaryDocumentTextDataCheckResult(report, documentFields); + SandboxSupplementaryDocumentTextDataCheckResult result = new SandboxSupplementaryDocumentTextDataCheckResult(report, reportTemplate, documentFields); return new SandboxSupplementaryDocumentTextDataCheck(result, documentFilter); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheckResult.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheckResult.java index e479a23f4..6771bdaf7 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheckResult.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheckResult.java @@ -11,8 +11,8 @@ public class SandboxSupplementaryDocumentTextDataCheckResult extends SandboxChec @JsonProperty("document_fields") private Map documentFields; - SandboxSupplementaryDocumentTextDataCheckResult(SandboxCheckReport report, Map documentFields) { - super(report); + SandboxSupplementaryDocumentTextDataCheckResult(SandboxCheckReport report, String reportTemplate, Map documentFields) { + super(report, reportTemplate); this.documentFields = documentFields; } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityCheck.java index bea61d0b6..d18804e59 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityCheck.java @@ -29,10 +29,8 @@ protected Builder self() { @Override public SandboxThirdPartyIdentityCheck build() { - notNull(recommendation, "recommendation"); - SandboxCheckReport report = new SandboxCheckReport(recommendation, breakdown); - SandboxCheckResult result = new SandboxCheckResult(report); + SandboxCheckResult result = new SandboxCheckResult(report, reportTemplate); return new SandboxThirdPartyIdentityCheck(result); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxZoomLivenessCheckBuilder.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxZoomLivenessCheckBuilder.java index 262267b95..482804b59 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxZoomLivenessCheckBuilder.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxZoomLivenessCheckBuilder.java @@ -23,10 +23,8 @@ public SandboxZoomLivenessCheckBuilder withResponseDelay(Integer responseDelay) @Override public SandboxLivenessCheck build() { - notNull(recommendation, "recommendation"); - SandboxCheckReport report = new SandboxCheckReport(recommendation, breakdown); - SandboxCheckResult result = new SandboxCheckResult(report); + SandboxCheckResult result = new SandboxCheckResult(report, reportTemplate); return new SandboxLivenessCheck(result, DocScanConstants.ZOOM, responseDelay); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTask.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTask.java index ca31eadcd..c523db6ff 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTask.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTask.java @@ -23,10 +23,17 @@ public class SandboxDocumentTextDataExtractionTask { @JsonProperty("response_delay") private final Integer responseDelay; - SandboxDocumentTextDataExtractionTask(SandboxDocumentTextDataExtractionTaskResult result, SandboxDocumentFilter documentFilter, Integer responseDelay) { + @JsonProperty("result_template") + private final String resultTemplate; + + SandboxDocumentTextDataExtractionTask(SandboxDocumentTextDataExtractionTaskResult result, + SandboxDocumentFilter documentFilter, + Integer responseDelay, + String resultTemplate) { this.result = result; this.documentFilter = documentFilter; this.responseDelay = responseDelay; + this.resultTemplate = resultTemplate; } public static Builder builder() { @@ -45,6 +52,10 @@ public Integer getResponseDelay() { return responseDelay; } + public String getResultTemplate() { + return resultTemplate; + } + /** * Builder for {@link SandboxDocumentTextDataExtractionTask} */ @@ -57,6 +68,7 @@ public static class Builder { private String detectedDocumentType; private SandboxTextExtractionTaskRecommendation recommendation; private Integer responseDelay; + private String resultTemplate; private Builder() {} @@ -106,13 +118,18 @@ public Builder withResponseDelay(Integer responseDelay) { return this; } + public Builder withResultTemplate(String resultTemplate) { + this.resultTemplate = resultTemplate; + return this; + } + public SandboxDocumentTextDataExtractionTask build() { SandboxDocumentTextDataExtractionTaskResult result = new SandboxDocumentTextDataExtractionTaskResult(documentFields, documentIdPhoto, detectedCountry, detectedDocumentType, recommendation); - return new SandboxDocumentTextDataExtractionTask(result, documentFilter, responseDelay); + return new SandboxDocumentTextDataExtractionTask(result, documentFilter, responseDelay, resultTemplate); } } } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTask.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTask.java index beb290b79..feb99e670 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTask.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTask.java @@ -22,12 +22,17 @@ public class SandboxSupplementaryDocTextDataExtractionTask { @JsonProperty("response_delay") private final Integer responseDelay; + @JsonProperty("result_template") + private final String resultTemplate; + SandboxSupplementaryDocTextDataExtractionTask(SandboxSupplementaryDocTextDataExtractionTaskResult result, SandboxDocumentFilter documentFilter, - Integer responseDelay) { + Integer responseDelay, + String resultTemplate) { this.result = result; this.documentFilter = documentFilter; this.responseDelay = responseDelay; + this.resultTemplate = resultTemplate; } public static Builder builder() { @@ -46,6 +51,10 @@ public Integer getResponseDelay() { return responseDelay; } + public String getResultTemplate() { + return resultTemplate; + } + /** * Builder for {@link SandboxSupplementaryDocTextDataExtractionTask} */ @@ -56,6 +65,7 @@ public static class Builder { private String detectedCountry; private SandboxTextExtractionTaskRecommendation recommendation; private Integer responseDelay; + private String resultTemplate; private Builder() {} @@ -94,10 +104,15 @@ public Builder withResponseDelay(Integer responseDelay) { return this; } + public Builder withResultTemplate(String resultTemplate) { + this.resultTemplate = resultTemplate; + return this; + } + public SandboxSupplementaryDocTextDataExtractionTask build() { SandboxSupplementaryDocTextDataExtractionTaskResult result = new SandboxSupplementaryDocTextDataExtractionTaskResult(documentFields, detectedCountry, recommendation); - return new SandboxSupplementaryDocTextDataExtractionTask(result, documentFilter, responseDelay); + return new SandboxSupplementaryDocTextDataExtractionTask(result, documentFilter, responseDelay, resultTemplate); } } } diff --git a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheckTest.java b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheckTest.java index c60c238fa..8974c6c38 100644 --- a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheckTest.java +++ b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheckTest.java @@ -27,17 +27,6 @@ public class SandboxDocumentAuthenticityCheckTest { @Mock SandboxBreakdown sandboxBreakdownMock; @Mock SandboxDocumentFilter sandboxDocumentFilterMock; - @Test - public void builder_shouldThrowExceptionWhenMissingRecommendation() { - try { - SandboxDocumentAuthenticityCheck.builder().build(); - } catch (IllegalArgumentException ex) { - assertThat(ex.getMessage(), containsString("recommendation")); - return; - } - fail("Expected an exception"); - } - @Test public void builder_shouldBuildWithoutDocumentFilter() { SandboxDocumentAuthenticityCheck result = SandboxDocumentAuthenticityCheck.builder() diff --git a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheckTest.java b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheckTest.java index 22ac25b78..2408b1f6a 100644 --- a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheckTest.java +++ b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheckTest.java @@ -21,17 +21,6 @@ public class SandboxDocumentFaceMatchCheckTest { @Mock SandboxRecommendation sandboxRecommendationMock; @Mock SandboxBreakdown sandboxBreakdownMock; - @Test - public void builder_shouldThrowExceptionWhenMissingRecommendation() { - try { - SandboxDocumentFaceMatchCheck.builder().build(); - } catch (IllegalArgumentException ex) { - assertThat(ex.getMessage(), containsString("recommendation")); - return; - } - fail("Expected an exception"); - } - @Test public void builder_shouldBuildCorrectly() { SandboxDocumentFaceMatchCheck result = SandboxDocumentFaceMatchCheck.builder() diff --git a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheckTest.java b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheckTest.java index d8b447874..168c6449c 100644 --- a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheckTest.java +++ b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheckTest.java @@ -33,17 +33,6 @@ public class SandboxDocumentTextDataCheckTest { @Mock SandboxRecommendation sandboxRecommendationMock; @Mock SandboxBreakdown sandboxBreakdownMock; - @Test - public void builder_shouldThrowExceptionForMissingRecommendation() { - try { - SandboxDocumentTextDataCheck.builder().build(); - } catch (IllegalArgumentException ex) { - assertThat(ex.getMessage(), containsString("recommendation")); - return; - } - fail("Expected an exception"); - } - @Test public void builder_shouldInitialiseDocumentFieldsMap() { SandboxDocumentTextDataCheck result = SandboxDocumentTextDataCheck.builder() diff --git a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheckTest.java b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheckTest.java index 213a5595c..daeb3f6f7 100644 --- a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheckTest.java +++ b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheckTest.java @@ -22,17 +22,6 @@ public class SandboxIdDocumentComparisonCheckTest { @Mock SandboxBreakdown sandboxBreakdownMock; @Mock SandboxDocumentFilter secondaryDocumentFilterMock; - @Test - public void builder_shouldThrowExceptionForMissingRecommendation() { - try { - SandboxIdDocumentComparisonCheck.builder().build(); - } catch (IllegalArgumentException ex) { - assertThat(ex.getMessage(), containsString("recommendation")); - return; - } - fail("Expected an exception"); - } - @Test public void builder_shouldBuildCorrectly() { SandboxIdDocumentComparisonCheck result = SandboxIdDocumentComparisonCheck.builder() diff --git a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheckTest.java b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheckTest.java index c1b67d983..441301394 100644 --- a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheckTest.java +++ b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheckTest.java @@ -33,17 +33,6 @@ public class SandboxSupplementaryDocumentTextDataCheckTest { @Mock SandboxRecommendation sandboxRecommendationMock; @Mock SandboxBreakdown sandboxBreakdownMock; - @Test - public void builder_shouldThrowExceptionForMissingRecommendation() { - try { - SandboxSupplementaryDocumentTextDataCheck.builder().build(); - } catch (IllegalArgumentException ex) { - assertThat(ex.getMessage(), containsString("recommendation")); - return; - } - fail("Expected an exception"); - } - @Test public void builder_shouldInitialiseDocumentFieldsMap() { SandboxSupplementaryDocumentTextDataCheck result = SandboxSupplementaryDocumentTextDataCheck.builder() @@ -67,4 +56,4 @@ public void builder_shouldAllowMapForDocumentFields() { assertThat(result.getResult().getDocumentFields(), hasEntry("firstKey", (Object) "firstValue")); assertThat(result.getResult().getDocumentFields(), hasEntry("secondKey", (Object) 100)); } -} \ No newline at end of file +} diff --git a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxZoomLivenessCheckTest.java b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxZoomLivenessCheckTest.java index 9e5d013c1..ee61c401d 100644 --- a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxZoomLivenessCheckTest.java +++ b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/check/SandboxZoomLivenessCheckTest.java @@ -21,17 +21,6 @@ public class SandboxZoomLivenessCheckTest { @Mock SandboxRecommendation sandboxRecommendationMock; @Mock SandboxBreakdown sandboxBreakdownMock; - @Test - public void builder_shouldThrowExceptionForMissingRecommendation() { - try { - SandboxLivenessCheck.forZoomLiveness().build(); - } catch (IllegalArgumentException ex) { - assertThat(ex.getMessage(), containsString("recommendation")); - return; - } - fail("Expected an exception"); - } - @Test public void builder_shouldBuildWithCorrectValues() { SandboxLivenessCheck result = new SandboxZoomLivenessCheckBuilder() diff --git a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTaskTest.java b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTaskTest.java index d8dfc328c..9c6bb8627 100644 --- a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTaskTest.java +++ b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTaskTest.java @@ -105,4 +105,13 @@ public void builder_shouldSetResponseDelay() { assertThat(result.getResponseDelay(), is(10)); } + @Test + public void builder_shouldSetResultTemplate() { + SandboxDocumentTextDataExtractionTask result = SandboxDocumentTextDataExtractionTask.builder() + .withResultTemplate("someResultTemplate") + .build(); + + assertThat(result.getResultTemplate(), is("someResultTemplate")); + } + } diff --git a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTaskTest.java b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTaskTest.java index 93cb6df02..b9fa639e2 100644 --- a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTaskTest.java +++ b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTaskTest.java @@ -90,4 +90,13 @@ public void builder_shouldSetResponseDelay() { assertThat(result.getResponseDelay(), is(10)); } + @Test + public void builder_shouldSetResultTemplate() { + SandboxSupplementaryDocTextDataExtractionTask result = SandboxSupplementaryDocTextDataExtractionTask.builder() + .withResultTemplate("someResultTemplate") + .build(); + + assertThat(result.getResultTemplate(), is("someResultTemplate")); + } + } diff --git a/yoti-sdk-spring-boot-example/README.md b/yoti-sdk-spring-boot-example/README.md index 57accbcde..de237b048 100644 --- a/yoti-sdk-spring-boot-example/README.md +++ b/yoti-sdk-spring-boot-example/README.md @@ -45,6 +45,11 @@ The logic for all the v1 share examples can be found in the `YotiLoginController * Navigate to: * [https://localhost:8443/v2/digital-identity-share](https://localhost:8443/v2/digital-identity-share) to initiate a login using the Yoti share v2 +### Digital Identity Match +* You can run your server-app by executing `java -jar -Dyoti.api.url="https://api.yoti.com/did" target/yoti-sdk-spring-boot-example.jar`. The JVM argument is required to override the default `https://api.yoti.com/api/v1` +* Navigate to: + * [https://localhost:8443/did/](https://localhost:8443/did/) to display the form to initiate a digital ID match + The logic for the v2 share example session creation and receipt can be found respectively in the `IdentitySessionController` and `IdentityLoginController` ## Requirements for running the application diff --git a/yoti-sdk-spring-boot-example/pom.xml b/yoti-sdk-spring-boot-example/pom.xml index fa66ee46e..f280d7c98 100644 --- a/yoti-sdk-spring-boot-example/pom.xml +++ b/yoti-sdk-spring-boot-example/pom.xml @@ -45,12 +45,13 @@ 3.8.5 - 33.0.0-jre + 33.2.1-jre - 4.8.3.1 - 3.4.1 - 1.7.0 - 3.11.0 + + 4.8.6.6 + 3.5.0 + 1.10.0 + 3.14.0 diff --git a/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/DigitalIdController.java b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/DigitalIdController.java new file mode 100644 index 000000000..8b4efa9d6 --- /dev/null +++ b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/DigitalIdController.java @@ -0,0 +1,100 @@ +package com.yoti.api.examples.springboot; + +import java.net.URI; +import java.util.AbstractMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import com.yoti.api.client.DigitalIdentityClient; +import com.yoti.api.client.identity.MatchNotification; +import com.yoti.api.client.identity.MatchRequest; +import com.yoti.api.client.identity.MatchResult; +import com.yoti.api.client.spi.remote.call.ResourceException; +import com.yoti.api.examples.springboot.model.MatchInputForm; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Controller +@RequestMapping("/did") +public class DigitalIdController implements WebMvcConfigurer { + + private final DigitalIdentityClient client; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); + } + + @Autowired + public DigitalIdController(DigitalIdentityClient client) { + this.client = client; + } + + @RequestMapping("/") + public String home(Model model) { + model.addAttribute("matchInputForm", new MatchInputForm()); + return "match-input"; + } + + @PostMapping("/match") + public String match(@ModelAttribute("matchInputForm") MatchInputForm form, Model model) { + MatchNotification.Builder notification = MatchNotification.forUrl(URI.create(form.getEndpoint())) + .withVerifyTls(form.isVerifyTls()) + .withMethod(form.getHttpMethod()); + + List keys = form.getHeaderKeys(); + List values = form.getHeaderValues(); + + Map headers = IntStream.range(0, keys.size()) + .mapToObj(i -> new AbstractMap.SimpleEntry<>( + keys.get(i), + i < values.size() ? values.get(i) : "" + )) + .filter(entry -> entry.getKey() != null && !entry.getKey().isEmpty()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + if (!headers.isEmpty()) { + notification.withHeaders(headers); + } + + MatchRequest.Builder match = MatchRequest.builder(form.getValue()).withNotification(notification.build()); + + MatchResult result = execute(() -> client.fetchMatch(match.build()), model); + + return Optional.ofNullable(result) + .map(r -> { + model.addAttribute("matchId", r.getId()); + model.addAttribute("matchResult", r.getResult()); + + return "match-result"; + }) + .orElse("match-error"); + } + + private static T execute(Supplier supplier, Model model) { + try { + return supplier.get(); + } catch (Exception ex) { + if (ex.getCause() instanceof ResourceException) { + ResourceException resourceEx = (ResourceException) ex.getCause(); + model.addAttribute("jsonError", resourceEx.getResponseBody()); + } else { + model.addAttribute("error", ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage()); + } + + return null; + } + } + +} diff --git a/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/model/MatchInputForm.java b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/model/MatchInputForm.java new file mode 100644 index 000000000..471891c9a --- /dev/null +++ b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/model/MatchInputForm.java @@ -0,0 +1,73 @@ +package com.yoti.api.examples.springboot.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class MatchInputForm { + + private String value; + private String endpoint; + private String httpMethod; + private boolean verifyTls; + private List headerKeys = new ArrayList<>(); + private List headerValues = new ArrayList<>(); + + public MatchInputForm() { + value = "+442532733270"; + endpoint = "https://company.com/callback/did-match"; + httpMethod = "POST"; + verifyTls = true; + headerKeys.add("X-Request-ID"); + headerValues.add(UUID.randomUUID().toString()); + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + public String getHttpMethod() { + return httpMethod; + } + + public void setHttpMethod(String httpMethod) { + this.httpMethod = httpMethod; + } + + public boolean isVerifyTls() { + return verifyTls; + } + + public void setVerifyTls(boolean verifyTls) { + this.verifyTls = verifyTls; + } + + public List getHeaderKeys() { + return headerKeys; + } + + public void setHeaderKeys(List headerKeys) { + this.headerKeys = headerKeys; + } + + public List getHeaderValues() { + return headerValues; + } + + public void setHeaderValues(List headerValues) { + this.headerValues = headerValues; + } + +} diff --git a/yoti-sdk-spring-boot-example/src/main/resources/templates/match-error.html b/yoti-sdk-spring-boot-example/src/main/resources/templates/match-error.html new file mode 100644 index 000000000..7672af2f0 --- /dev/null +++ b/yoti-sdk-spring-boot-example/src/main/resources/templates/match-error.html @@ -0,0 +1,35 @@ + + + + + + Error + + + + + + + + + + + + + Home + Oops, something went wrong. + Error: + + + + + + + + + + + + diff --git a/yoti-sdk-spring-boot-example/src/main/resources/templates/match-input.html b/yoti-sdk-spring-boot-example/src/main/resources/templates/match-input.html new file mode 100644 index 000000000..04e79b9e1 --- /dev/null +++ b/yoti-sdk-spring-boot-example/src/main/resources/templates/match-input.html @@ -0,0 +1,66 @@ + + + + + Run Match + + + + + + + + + + + + Run Digital ID Match + + Enter Match Details: + Value to Match: + + Notification Details: + Notification Endpoint URL: + + HTTP Method (e.g., POST): + + + + Verify TLS + + Headers: + + Header Key 1: + + Header Value 1: + + Header Key 2: + + Header Value 2: + + + + + Run match + + + + + + + + diff --git a/yoti-sdk-spring-boot-example/src/main/resources/templates/match-result.html b/yoti-sdk-spring-boot-example/src/main/resources/templates/match-result.html new file mode 100644 index 000000000..e6c411128 --- /dev/null +++ b/yoti-sdk-spring-boot-example/src/main/resources/templates/match-result.html @@ -0,0 +1,37 @@ + + + + + Match Result + + + + + + + + + + + + + Match Result + + Match ID: ID_HERE + Match Result: RESULT_HERE + + Run + Another Match + + + + + + +
Match ID: ID_HERE
Match Result: RESULT_HERE