Skip to content

Commit 9ab7827

Browse files
committed
Added V3 as copy of V2
1 parent e9bbdd1 commit 9ab7827

File tree

5 files changed

+490
-0
lines changed

5 files changed

+490
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.uid2.client;
2+
3+
public class IdentityMapV3Client {
4+
/**
5+
* @param uid2BaseUrl The <a href="https://unifiedid.com/docs/getting-started/gs-environments">UID2 Base URL</a>
6+
* @param clientApiKey Your client API key
7+
* @param base64SecretKey Your client secret key
8+
*/
9+
public IdentityMapV3Client(String uid2BaseUrl, String clientApiKey, String base64SecretKey) {
10+
identityMapHelper = new IdentityMapV3Helper(base64SecretKey);
11+
uid2ClientHelper = new Uid2ClientHelper(uid2BaseUrl, clientApiKey);
12+
}
13+
14+
/**
15+
* @param identityMapInput represents the input required for <a href="https://unifiedid.com/docs/endpoints/post-identity-map">/identity/map</a>
16+
* @return an IdentityMapResponse instance
17+
* @throws Uid2Exception if the response did not contain a "success" status, or the response code was not 200, or there was an error communicating with the provided UID2 Base URL
18+
*/
19+
public IdentityMapV3Response generateIdentityMap(IdentityMapV3Input identityMapInput) {
20+
EnvelopeV2 envelope = identityMapHelper.createEnvelopeForIdentityMapRequest(identityMapInput);
21+
22+
String responseString = uid2ClientHelper.makeRequest(envelope, "/v2/identity/map");
23+
return identityMapHelper.createIdentityMapResponse(responseString, envelope, identityMapInput);
24+
}
25+
26+
private final IdentityMapV3Helper identityMapHelper;
27+
private final Uid2ClientHelper uid2ClientHelper;
28+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.uid2.client;
2+
3+
import com.google.gson.Gson;
4+
5+
import java.nio.charset.StandardCharsets;
6+
7+
public class IdentityMapV3Helper {
8+
/**
9+
* @param base64SecretKey your UID2 client secret
10+
*/
11+
public IdentityMapV3Helper(String base64SecretKey) {uid2Helper = new Uid2Helper(base64SecretKey);}
12+
13+
/**
14+
* @param identityMapInput represents the input required for <a href="https://unifiedid.com/docs/endpoints/post-identity-map">/identity/map</a>
15+
* @return an EnvelopeV2 instance to use in the POST body of <a href="https://unifiedid.com/docs/endpoints/post-identity-map">/identity/map</a>
16+
*/
17+
public EnvelopeV2 createEnvelopeForIdentityMapRequest(IdentityMapV3Input identityMapInput) {
18+
byte[] jsonBytes = new Gson().toJson(identityMapInput).getBytes(StandardCharsets.UTF_8);
19+
return uid2Helper.createEnvelopeV2(jsonBytes);
20+
}
21+
22+
23+
/**
24+
* @param responseString the response body returned by a call to <a href="https://unifiedid.com/docs/endpoints/post-identity-map">/identity/map</a>
25+
* @param envelope the EnvelopeV2 instance returned by {@link #createEnvelopeForIdentityMapRequest}
26+
* @param identityMapInput the same instance that was passed to {@link #createEnvelopeForIdentityMapRequest}.
27+
* @return an IdentityMapResponse instance
28+
*/
29+
public IdentityMapV3Response createIdentityMapResponse(String responseString, EnvelopeV2 envelope, IdentityMapV3Input identityMapInput) {
30+
String decryptedResponseString = uid2Helper.decrypt(responseString, envelope.getNonce());
31+
return new IdentityMapV3Response(decryptedResponseString, identityMapInput);
32+
}
33+
34+
Uid2Helper uid2Helper;
35+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.uid2.client;
2+
3+
import com.google.gson.annotations.SerializedName;
4+
5+
import java.util.ArrayList;
6+
import java.util.Collections;
7+
import java.util.HashMap;
8+
import java.util.List;
9+
10+
public class IdentityMapV3Input {
11+
/**
12+
* @param emails a list of normalized or unnormalized email addresses
13+
* @return a IdentityMapInput instance, to be used in {@link IdentityMapHelper#createEnvelopeForIdentityMapRequest}
14+
*/
15+
public static IdentityMapV3Input fromEmails(Iterable<String> emails) {
16+
return new IdentityMapV3Input(IdentityType.Email, emails, false);
17+
}
18+
19+
/**
20+
* @param phones a <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#phone-number-normalization">normalized</a> phone number
21+
* @return an IdentityMapInput instance
22+
*/
23+
public static IdentityMapV3Input fromPhones(Iterable<String> phones) {
24+
return new IdentityMapV3Input(IdentityType.Phone, phones, false);
25+
}
26+
27+
/**
28+
* @param hashedEmails a <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#email-address-normalization">normalized</a> and <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#email-address-hash-encoding">hashed</a> email address
29+
* @return an IdentityMapInput instance
30+
*/
31+
public static IdentityMapV3Input fromHashedEmails(Iterable<String> hashedEmails) {
32+
return new IdentityMapV3Input(IdentityType.Email, hashedEmails, true);
33+
}
34+
35+
/**
36+
* @param hashedPhones a <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#phone-number-normalization">normalized</a> and <a href="https://unifiedid.com/docs/getting-started/gs-normalization-encoding#phone-number-hash-encoding">hashed</a> phone number
37+
* @return an IdentityMapInput instance
38+
*/
39+
public static IdentityMapV3Input fromHashedPhones(Iterable<String> hashedPhones) {
40+
return new IdentityMapV3Input(IdentityType.Phone, hashedPhones, true);
41+
}
42+
43+
private IdentityMapV3Input(IdentityType identityType, Iterable<String> emailsOrPhones, boolean alreadyHashed) {
44+
if (identityType == IdentityType.Email) {
45+
hashedNormalizedEmails = new ArrayList<>();
46+
for (String email : emailsOrPhones) {
47+
if (alreadyHashed) {
48+
hashedNormalizedEmails.add(email);
49+
} else {
50+
String hashedEmail = InputUtil.normalizeAndHashEmail(email);
51+
hashedNormalizedEmails.add(hashedEmail);
52+
addHashedToRawDiiMapping(hashedEmail, email);
53+
}
54+
}
55+
} else { //phone
56+
hashedNormalizedPhones = new ArrayList<>();
57+
for (String phone : emailsOrPhones) {
58+
if (alreadyHashed) {
59+
hashedNormalizedPhones.add(phone);
60+
} else {
61+
if (!InputUtil.isPhoneNumberNormalized(phone)) {
62+
throw new IllegalArgumentException("phone number is not normalized: " + phone);
63+
}
64+
65+
String hashedNormalizedPhone = InputUtil.getBase64EncodedHash(phone);
66+
addHashedToRawDiiMapping(hashedNormalizedPhone, phone);
67+
hashedNormalizedPhones.add(hashedNormalizedPhone);
68+
}
69+
}
70+
}
71+
}
72+
73+
private void addHashedToRawDiiMapping(String hashedDii, String rawDii) {
74+
hashedDiiToRawDiis.computeIfAbsent(hashedDii, k -> new ArrayList<>()).add(rawDii);
75+
}
76+
77+
78+
List<String> getRawDiis(String identifier) {
79+
final boolean wasInputAlreadyHashed = hashedDiiToRawDiis.isEmpty();
80+
if (wasInputAlreadyHashed)
81+
return Collections.singletonList(identifier);
82+
return hashedDiiToRawDiis.get(identifier);
83+
}
84+
85+
@SerializedName("email_hash")
86+
private List<String> hashedNormalizedEmails;
87+
@SerializedName("phone_hash")
88+
private List<String> hashedNormalizedPhones;
89+
90+
private final transient HashMap<String, List<String>> hashedDiiToRawDiis = new HashMap<>();
91+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package com.uid2.client;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.JsonElement;
5+
import com.google.gson.JsonObject;
6+
import com.google.gson.annotations.SerializedName;
7+
8+
import java.util.Collections;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
12+
public class IdentityMapV3Response {
13+
IdentityMapV3Response(String response, IdentityMapV3Input identityMapInput) {
14+
JsonObject responseJson = new Gson().fromJson(response, JsonObject.class);
15+
status = responseJson.get("status").getAsString();
16+
17+
if (!isSuccess()) {
18+
throw new Uid2Exception("Got unexpected identity map status: " + status);
19+
}
20+
21+
Gson gson = new Gson();
22+
JsonObject body = getBodyAsJson(responseJson);
23+
24+
Iterable<JsonElement> mapped = getJsonArray(body, "mapped");
25+
for (JsonElement identity : mapped) {
26+
List<String> rawDiis = getRawDiis(identity, identityMapInput);
27+
MappedIdentity mappedIdentity = gson.fromJson(identity, MappedIdentity.class);
28+
for (String rawDii : rawDiis) {
29+
mappedIdentities.put(rawDii, mappedIdentity);
30+
}
31+
}
32+
33+
Iterable<JsonElement> unmapped = getJsonArray(body, "unmapped");
34+
for (JsonElement identity : unmapped) {
35+
List<String> rawDiis = getRawDiis(identity, identityMapInput);
36+
UnmappedIdentity unmappedIdentity = gson.fromJson(identity, UnmappedIdentity.class);
37+
for (String rawDii : rawDiis) {
38+
unmappedIdentities.put(rawDii, unmappedIdentity);
39+
}
40+
}
41+
}
42+
43+
private static Iterable<JsonElement> getJsonArray(JsonObject body, String header) {
44+
JsonElement jsonElement = body.get(header);
45+
if (jsonElement == null) {
46+
return Collections.emptyList();
47+
}
48+
return jsonElement.getAsJsonArray();
49+
}
50+
51+
private List<String> getRawDiis(JsonElement identity, IdentityMapV3Input identityMapInput) {
52+
String identifier = identity.getAsJsonObject().get("identifier").getAsString();
53+
return identityMapInput.getRawDiis(identifier);
54+
}
55+
56+
public boolean isSuccess() {
57+
return "success".equals(status);
58+
}
59+
static JsonObject getBodyAsJson(JsonObject jsonResponse) {
60+
return jsonResponse.get("body").getAsJsonObject();
61+
}
62+
63+
static public class MappedIdentity {
64+
public MappedIdentity(String rawUid, String bucketId) {
65+
this.rawUid = rawUid;
66+
this.bucketId = bucketId;
67+
}
68+
69+
public String getRawUid() {return rawUid;}
70+
public String getBucketId() {return bucketId;}
71+
72+
@SerializedName("advertising_id")
73+
private final String rawUid;
74+
@SerializedName("bucket_id")
75+
private final String bucketId;
76+
}
77+
78+
static public class UnmappedIdentity {
79+
public UnmappedIdentity(String reason) {
80+
this.reason = reason;
81+
}
82+
83+
public String getReason() {return reason;}
84+
85+
private final String reason;
86+
}
87+
88+
public HashMap<String, MappedIdentity> getMappedIdentities() {
89+
return mappedIdentities;
90+
}
91+
92+
public HashMap<String, UnmappedIdentity> getUnmappedIdentities() {
93+
return unmappedIdentities;
94+
}
95+
96+
private final String status;
97+
private final HashMap<String, MappedIdentity> mappedIdentities = new HashMap<>();
98+
private final HashMap<String, UnmappedIdentity> unmappedIdentities = new HashMap<>();
99+
}

0 commit comments

Comments
 (0)