Skip to content

Commit bc7eb6e

Browse files
authored
Merge pull request #329 from getyoti/RELEASE-3.5.0
Release 3.5.0
2 parents e611275 + be3a930 commit bc7eb6e

File tree

23 files changed

+784
-322
lines changed

23 files changed

+784
-322
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,13 @@ If you are using Maven, you need to add the following dependency:
101101
<dependency>
102102
<groupId>com.yoti</groupId>
103103
<artifactId>yoti-sdk-api</artifactId>
104-
<version>3.4.0</version>
104+
<version>3.5.0</version>
105105
</dependency>
106106
```
107107

108108
If you are using Gradle, here is the dependency to add:
109109

110-
`compile group: 'com.yoti', name: 'yoti-sdk-api', version: '3.4.0'`
110+
`compile group: 'com.yoti', name: 'yoti-sdk-api', version: '3.5.0'`
111111

112112
You will find all classes packaged under `com.yoti.api`
113113

examples/doc-scan/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
<dependency>
5252
<groupId>com.yoti</groupId>
5353
<artifactId>yoti-sdk-api</artifactId>
54-
<version>3.4.0</version>
54+
<version>3.5.0</version>
5555
</dependency>
5656
</dependencies>
5757

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<groupId>com.yoti</groupId>
66
<artifactId>yoti-sdk</artifactId>
77
<packaging>pom</packaging>
8-
<version>3.4.0</version>
8+
<version>3.5.0</version>
99
<name>Yoti SDK</name>
1010
<description>Java SDK for simple integration with the Yoti platform</description>
1111
<url>https://github.com/getyoti/yoti-java-sdk</url>

yoti-sdk-api/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<parent>
1212
<groupId>com.yoti</groupId>
1313
<artifactId>yoti-sdk-parent</artifactId>
14-
<version>3.4.0</version>
14+
<version>3.5.0</version>
1515
<relativePath>../yoti-sdk-parent</relativePath>
1616
</parent>
1717

yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/ReceiptFetcher.java

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
import java.security.KeyPair;
66
import java.security.PrivateKey;
77
import java.util.Base64;
8+
import java.util.Optional;
89

910
import com.yoti.api.client.ActivityFailureException;
1011
import com.yoti.api.client.ProfileException;
12+
import com.yoti.api.client.spi.remote.call.ProfileResponse;
1113
import com.yoti.api.client.spi.remote.call.ProfileService;
1214
import com.yoti.api.client.spi.remote.call.Receipt;
1315
import com.yoti.api.client.spi.remote.util.DecryptionHelper;
@@ -31,29 +33,37 @@ public static ReceiptFetcher newInstance() {
3133

3234
public Receipt fetch(String encryptedConnectToken, KeyPair keyPair, String appId) throws ProfileException {
3335
LOG.debug("Decrypting connect token: '{}'", encryptedConnectToken);
36+
3437
String connectToken = decryptConnectToken(encryptedConnectToken, keyPair.getPrivate());
3538
LOG.debug("Connect token decrypted: '{}'", connectToken);
36-
Receipt receipt = profileService.getReceipt(keyPair, appId, connectToken);
37-
validateReceipt(receipt, connectToken);
38-
return receipt;
39+
40+
ProfileResponse profile = profileService.getProfile(keyPair, appId, connectToken);
41+
validateReceipt(profile, connectToken);
42+
return profile.getReceipt();
3943
}
4044

4145
private String decryptConnectToken(String encryptedConnectToken, PrivateKey privateKey) throws ProfileException {
4246
try {
4347
byte[] byteValue = Base64.getUrlDecoder().decode(encryptedConnectToken);
4448
byte[] decryptedToken = DecryptionHelper.decryptAsymmetric(byteValue, privateKey);
4549
return new String(decryptedToken, DEFAULT_CHARSET);
46-
} catch (Exception e) {
47-
throw new ProfileException("Cannot decrypt connect token", e);
50+
} catch (Exception ex) {
51+
throw new ProfileException("Cannot decrypt connect token", ex);
4852
}
4953
}
5054

51-
private void validateReceipt(Receipt receipt, String connectToken) throws ProfileException {
52-
if (receipt == null) {
53-
throw new ProfileException("No receipt for '" + connectToken + "' was found");
54-
}
55-
if (receipt.getOutcome() == null || !receipt.getOutcome().isSuccessful()) {
56-
throw new ActivityFailureException("Sharing activity unsuccessful for " + receipt.getDisplayReceiptId());
55+
private void validateReceipt(ProfileResponse profile, String connectToken) throws ProfileException {
56+
Receipt receipt = Optional.ofNullable(profile)
57+
.map(ProfileResponse::getReceipt)
58+
.orElseThrow(() -> new ProfileException("No profile for '" + connectToken + "' was found"));
59+
60+
if (!receipt.hasOutcome(Receipt.Outcome.SUCCESS)) {
61+
throw new ActivityFailureException(
62+
String.format("Sharing activity unsuccessful for %s%s",
63+
receipt.getDisplayReceiptId(),
64+
Optional.ofNullable(profile.getError()).map(e -> String.format(" - %s", e)).orElse("")
65+
)
66+
);
5767
}
5868
}
5969

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.yoti.api.client.spi.remote.call;
2+
3+
import java.util.Objects;
4+
5+
import com.fasterxml.jackson.annotation.JsonProperty;
6+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
7+
8+
@JsonDeserialize(builder = ErrorDetails.Builder.class)
9+
public final class ErrorDetails {
10+
11+
private final String code;
12+
private final String description;
13+
14+
private ErrorDetails(Builder builder) {
15+
this.code = builder.code;
16+
this.description = builder.description;
17+
}
18+
19+
public static Builder builder() {
20+
return new Builder();
21+
}
22+
23+
public String getCode() {
24+
return code;
25+
}
26+
27+
public String getDescription() {
28+
return description;
29+
}
30+
31+
@Override
32+
public boolean equals(Object o) {
33+
if (this == o) {
34+
return true;
35+
}
36+
if (o == null || getClass() != o.getClass()) {
37+
return false;
38+
}
39+
40+
ErrorDetails that = (ErrorDetails) o;
41+
return Objects.equals(code, that.code) && Objects.equals(description, that.description);
42+
}
43+
44+
@Override
45+
public int hashCode() {
46+
return Objects.hash(code, description);
47+
}
48+
49+
@Override
50+
public String toString() {
51+
return String.format("Error[code='%s', description='%s']", code, description);
52+
}
53+
54+
public static final class Builder {
55+
56+
private String code;
57+
private String description;
58+
59+
private Builder() { }
60+
61+
@JsonProperty(Property.ERROR_CODE)
62+
public Builder code(String code) {
63+
this.code = code;
64+
return this;
65+
}
66+
67+
@JsonProperty(Property.DESCRIPTION)
68+
public Builder description(String description) {
69+
this.description = description;
70+
return this;
71+
}
72+
73+
public ErrorDetails build() {
74+
return new ErrorDetails(this);
75+
}
76+
77+
}
78+
79+
private static final class Property {
80+
81+
private static final String ERROR_CODE = "error_code";
82+
private static final String DESCRIPTION = "description";
83+
84+
private Property() { }
85+
86+
}
87+
88+
}
Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
package com.yoti.api.client.spi.remote.call;
22

3+
import java.util.Objects;
4+
35
import com.fasterxml.jackson.annotation.JsonProperty;
46

5-
class ProfileResponse {
7+
public class ProfileResponse {
68

7-
@JsonProperty("session_data")
9+
@JsonProperty(Property.SESSION_DATA)
810
private String sessionData;
911

10-
@JsonProperty("receipt")
12+
@JsonProperty(Property.RECEIPT)
1113
private Receipt receipt;
1214

13-
public ProfileResponse(){}
15+
@JsonProperty(Property.ERROR_DETAILS)
16+
private ErrorDetails error;
17+
18+
public ProfileResponse() { }
1419

15-
private ProfileResponse(String sessionData, Receipt receipt){
20+
private ProfileResponse(String sessionData, Receipt receipt, ErrorDetails error) {
1621
this.sessionData = sessionData;
1722
this.receipt = receipt;
23+
this.error = error;
1824
}
1925

2026
public String getSessionData() {
@@ -33,28 +39,39 @@ public void setReceipt(Receipt receipt) {
3339
this.receipt = receipt;
3440
}
3541

42+
public ErrorDetails getError() {
43+
return error;
44+
}
45+
46+
public void setError(ErrorDetails error) {
47+
this.error = error;
48+
}
49+
3650
@Override
3751
public boolean equals(Object o) {
38-
if (this == o) return true;
39-
if (!(o instanceof ProfileResponse)) return false;
52+
if (this == o) {
53+
return true;
54+
}
55+
if (o == null || getClass() != o.getClass()) {
56+
return false;
57+
}
4058

4159
ProfileResponse that = (ProfileResponse) o;
42-
43-
if (!sessionData.equals(that.sessionData)) return false;
44-
return receipt.equals(that.receipt);
45-
60+
return Objects.equals(sessionData, that.sessionData)
61+
&& Objects.equals(receipt, that.receipt)
62+
&& Objects.equals(error, that.error);
4663
}
4764

4865
@Override
4966
public int hashCode() {
50-
int result = sessionData.hashCode();
51-
result = 31 * result + receipt.hashCode();
52-
return result;
67+
return Objects.hash(sessionData, receipt, error);
5368
}
5469

5570
public static class ProfileResponseBuilder {
71+
5672
private String sessionData;
5773
private Receipt receipt;
74+
private ErrorDetails error;
5875

5976
public ProfileResponseBuilder setSessionData(String sessionData) {
6077
this.sessionData = sessionData;
@@ -66,9 +83,36 @@ public ProfileResponseBuilder setReceipt(Receipt receipt) {
6683
return this;
6784
}
6885

86+
public ProfileResponseBuilder setError(ErrorDetails error) {
87+
this.error = error;
88+
return this;
89+
}
90+
91+
/**
92+
* ProfileResponse Builder build
93+
*
94+
* @return The response Profile
95+
* @deprecated Use {@link #build()} instead.
96+
*/
97+
@Deprecated
6998
public ProfileResponse createProfileResonse() {
70-
return new ProfileResponse(sessionData, receipt);
99+
return new ProfileResponse(sessionData, receipt, error);
71100
}
101+
102+
public ProfileResponse build() {
103+
return new ProfileResponse(sessionData, receipt, error);
104+
}
105+
106+
}
107+
108+
private static final class Property {
109+
110+
private static final String SESSION_DATA = "session_data";
111+
private static final String RECEIPT = "receipt";
112+
private static final String ERROR_DETAILS = "error_details";
113+
114+
private Property() { }
115+
72116
}
73117

74118
}

yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileService.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,18 @@ public static ProfileService newInstance() {
5050
}
5151

5252
public Receipt getReceipt(KeyPair keyPair, String appId, String connectToken) throws ProfileException {
53+
return getProfile(keyPair, appId, connectToken).getReceipt();
54+
}
55+
56+
public ProfileResponse getProfile(KeyPair keyPair, String appId, String connectToken) throws ProfileException {
5357
notNull(keyPair, "Key pair");
5458
notNull(appId, "Application id");
5559
notNull(connectToken, "Connect token");
5660

5761
String path = unsignedPathFactory.createProfilePath(appId, connectToken);
5862

5963
try {
60-
String authKey = Base64.getEncoder()
61-
.encodeToString(keyPair.getPublic().getEncoded());
64+
String authKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
6265

6366
SignedRequest signedRequest = createSignedRequest(keyPair, path, authKey);
6467
return fetchReceipt(signedRequest);
@@ -67,21 +70,20 @@ public Receipt getReceipt(KeyPair keyPair, String appId, String connectToken) th
6770
}
6871
}
6972

70-
private Receipt fetchReceipt(SignedRequest signedRequest) throws IOException, ProfileException {
73+
private ProfileResponse fetchReceipt(SignedRequest signedRequest) throws IOException, ProfileException {
7174
LOG.info("Fetching profile from resource at '{}'", signedRequest.getUri());
75+
7276
try {
73-
ProfileResponse response = signedRequest.execute(ProfileResponse.class);
74-
return response.getReceipt();
75-
} catch (ResourceException re) {
76-
int responseCode = re.getResponseCode();
77+
return signedRequest.execute(ProfileResponse.class);
78+
} catch (ResourceException ex) {
79+
int responseCode = ex.getResponseCode();
7780
switch (responseCode) {
7881
case HTTP_INTERNAL_ERROR:
79-
throw new ProfileException("Error completing sharing: " + re.getResponseBody(), re);
82+
throw new ProfileException("Error completing sharing: " + ex.getResponseBody(), ex);
8083
case HTTP_NOT_FOUND:
81-
throw new ProfileException("Profile not found. This can be due to a used or expired token. Details: "
82-
+ re.getResponseBody(), re);
84+
throw new ProfileException("Profile not found. This can be due to a used or expired token. Details: " + ex.getResponseBody(), ex);
8385
default:
84-
throw new ProfileException("Unexpected response: " + responseCode + " " + re.getResponseBody(), re);
86+
throw new ProfileException("Unexpected response: " + responseCode + " " + ex.getResponseBody(), ex);
8587
}
8688
}
8789
}

0 commit comments

Comments
 (0)