|
15 | 15 | import com.mparticle.commerce.Product; |
16 | 16 | import com.mparticle.commerce.Promotion; |
17 | 17 | import com.mparticle.commerce.TransactionAttributes; |
| 18 | +import com.mparticle.identity.AliasRequest; |
18 | 19 | import com.mparticle.identity.IdentityApi.SingleUserIdentificationCallback; |
19 | 20 | import com.mparticle.identity.IdentityApiRequest; |
20 | 21 | import com.mparticle.identity.MParticleUser; |
@@ -98,6 +99,12 @@ public class MParticleJSInterface { |
98 | 99 | protected static final String IDENTITY = "Identity"; |
99 | 100 | protected static final String TYPE = "Type"; |
100 | 101 |
|
| 102 | + // Alias (Identity) keys - accept multiple JS naming conventions |
| 103 | + private static final String ALIAS_SOURCE_MPID = "source_mpid"; |
| 104 | + private static final String ALIAS_DESTINATION_MPID = "destination_mpid"; |
| 105 | + private static final String ALIAS_START_TIME_MS = "start_unixtime_ms"; |
| 106 | + private static final String ALIAS_END_TIME_MS = "end_unixtime_ms"; |
| 107 | + |
101 | 108 | public MParticleJSInterface() { |
102 | 109 | Product.setEqualityComparator(new Product.EqualityComparator() { |
103 | 110 | @Override |
@@ -168,6 +175,61 @@ public void modify(String json) { |
168 | 175 | MParticle.getInstance().Identity().modify(request); |
169 | 176 | } |
170 | 177 |
|
| 178 | + /** |
| 179 | + * Initiate an Identity Alias request. |
| 180 | + * |
| 181 | + * Expects JSON containing: |
| 182 | + * - source mpid |
| 183 | + * - destination mpid (if omitted, will default to current user's mpid when available) |
| 184 | + * - start/end times (unix time; accepts ms or seconds) |
| 185 | + * |
| 186 | + * Returns true if the request passed validation and was queued. |
| 187 | + */ |
| 188 | + @JavascriptInterface |
| 189 | + public boolean aliasUsers(String json) { |
| 190 | + try { |
| 191 | + JSONObject jsonObject = new JSONObject(json); |
| 192 | + |
| 193 | + long sourceMpid = getFlexibleLong(jsonObject, |
| 194 | + "sourceMpid", "sourceMPID", ALIAS_SOURCE_MPID, "source_mpid", "source_mpid" |
| 195 | + ); |
| 196 | + long destinationMpid = getFlexibleLong(jsonObject, |
| 197 | + "destinationMpid", "destinationMPID", ALIAS_DESTINATION_MPID, "destination_mpid", "destination_mpid" |
| 198 | + ); |
| 199 | + |
| 200 | + if (destinationMpid == 0) { |
| 201 | + MParticleUser currentUser = MParticle.getInstance().Identity().getCurrentUser(); |
| 202 | + if (currentUser != null) { |
| 203 | + destinationMpid = currentUser.getId(); |
| 204 | + } |
| 205 | + } |
| 206 | + |
| 207 | + long startTime = getFlexibleLong(jsonObject, |
| 208 | + "startTime", "start_time", "startTimeMs", "start_time_ms", ALIAS_START_TIME_MS |
| 209 | + ); |
| 210 | + long endTime = getFlexibleLong(jsonObject, |
| 211 | + "endTime", "end_time", "endTimeMs", "end_time_ms", ALIAS_END_TIME_MS |
| 212 | + ); |
| 213 | + |
| 214 | + startTime = maybeSecondsToMs(startTime); |
| 215 | + endTime = maybeSecondsToMs(endTime); |
| 216 | + |
| 217 | + AliasRequest request = AliasRequest.builder() |
| 218 | + .sourceMpid(sourceMpid) |
| 219 | + .destinationMpid(destinationMpid) |
| 220 | + .startTime(startTime) |
| 221 | + .endTime(endTime) |
| 222 | + .build(); |
| 223 | + |
| 224 | + return MParticle.getInstance().Identity().aliasUsers(request); |
| 225 | + } catch (JSONException jse) { |
| 226 | + Logger.warning(String.format(errorMsg, jse.getMessage())); |
| 227 | + } catch (Exception ex) { |
| 228 | + Logger.warning(String.format(errorMsg, ex.getMessage())); |
| 229 | + } |
| 230 | + return false; |
| 231 | + } |
| 232 | + |
171 | 233 | @JavascriptInterface |
172 | 234 | public void logEvent(String json) { |
173 | 235 | try { |
@@ -837,4 +899,41 @@ static String getBridgeName(String workspaceToken) { |
837 | 899 | bridgeName.append("_v2"); |
838 | 900 | return bridgeName.toString(); |
839 | 901 | } |
| 902 | + |
| 903 | + private static long getFlexibleLong(JSONObject jsonObject, String... keys) { |
| 904 | + if (jsonObject == null || keys == null) { |
| 905 | + return 0; |
| 906 | + } |
| 907 | + for (String key : keys) { |
| 908 | + if (MPUtility.isEmpty(key) || !jsonObject.has(key)) { |
| 909 | + continue; |
| 910 | + } |
| 911 | + Object value = jsonObject.opt(key); |
| 912 | + if (value == null || value == JSONObject.NULL) { |
| 913 | + continue; |
| 914 | + } |
| 915 | + if (value instanceof Number) { |
| 916 | + return ((Number) value).longValue(); |
| 917 | + } |
| 918 | + if (value instanceof String) { |
| 919 | + try { |
| 920 | + return Long.parseLong((String) value); |
| 921 | + } catch (NumberFormatException ignore) { |
| 922 | + // continue |
| 923 | + } |
| 924 | + } |
| 925 | + } |
| 926 | + return 0; |
| 927 | + } |
| 928 | + |
| 929 | + /** |
| 930 | + * If the value looks like seconds-since-epoch (10 digits), convert to milliseconds. |
| 931 | + * This avoids accidentally scaling small relative values. |
| 932 | + */ |
| 933 | + private static long maybeSecondsToMs(long unixTime) { |
| 934 | + if (unixTime > 1000000000L && unixTime < 10000000000L) { |
| 935 | + return unixTime * 1000L; |
| 936 | + } |
| 937 | + return unixTime; |
| 938 | + } |
840 | 939 | } |
0 commit comments