static String lastProcessedTransactionId = "";
public void challengeOOBFlow(
@NonNull D1Task d1Task,
@NonNull FragmentActivity activity,
@NonNull CountDownLatch transactionWaiter) throws D1Exception {
// Implement the interface conforming to the AuthnCallback
D1Authn d1Authn = d1Task.getD1Authn(activity, new AuthnCallback(){
@Override
public void onTransactionDataConfirmation(@NonNull Map<String, String> map, @NonNull AuthnUserConfirmationCallback authnUserConfirmationCallback) {
//Pass the transaction handler that checks the last processed transaction id
try {
transactionHandler(map, transactionWaiter, authnUserConfirmationCallback);
} catch (InterruptedException e) {
//Process the exception
}
}
@NonNull
@Override
public String onBiometricPromptMessage() {
// Provide a message prompt for the authentication prompt. Application can customize the value.
return "Message to be displayed to the user during biometric prompt";
}
});
d1Authn.fetchAuthnRequest(new D1Task.Callback<Void>() {
@Override
public void onSuccess(Void unused) {
// Proceed with subsequent flows after end user verification.
transactionWaiter.countDown();
}
@Override
public void onError(@NonNull D1Exception e) {
// Refer to D1 SDK Integration – Error Management section.
transactionWaiter.countDown();
}
});
}
public synchronized void transactionHandler(
@NonNull Map<String, String> map,
@NonNull CountDownLatch transactionWaiter,
@NonNull AuthnUserConfirmationCallback authnUserConfirmationCallback) throws InterruptedException {
// The 'map' contains the transaction data that is to be authenticated.
//Example Map :
// {
// "acsTransId": "2f37539c-d82e-4929-88db-2f9e72c7fa62",
// "merchantName": "CoffeeHouse2 (Dæmø)",
// "purchaseAmount": "100",
// "purchaseCurrency": "840",
// "purchaseExponent": "2",
// "purchaseDate": "20231017055638"
// }
//Get the current transaction Id and compare to last process transaction id. If same no need to handle the transaction and proceed to cancel the transaction
if(map.get("acsTransId") != lastProcessedTransactionId) {
lastProcessedTransactionId = map.get("acsTransId");
JSONObject json = new JSONObject();
for (Map.Entry<String, String> entry : map.entrySet()) {
try {
json.put(entry.getKey(), entry.getValue());
} catch (JSONException ignored) {}
}
// Application to display the content, prompt end uer either to 'proceed' or to 'deny' the authentication request.
// To proceed: when uer selects proceed
// once proceed, UI will be prompted for authentication based on the selected AuthnType enrolled.
authnUserConfirmationCallback.proceed();
// To cancel: when user selects cancel
authnUserConfirmationCallback.cancel();
} else {
if(transactionWaiter.await(60, TimeUnit.SECONDS)) {
//Mo need to handle the transaction and proceed to cancel the transaction
authnUserConfirmationCallback.cancel();
}
}
}