Walkthrough
Register a Contract
To create a contract you need to instantiate a RegisterCodeReq object. You will need to insert the App User ID (which identifies the user in TrustFactor services), Username (that is shown to the user and listed in backoffice) and the duration of the code.
The recovery of transaction history depends on the contract’s app user ID. That is, if an application wants the user to continue to have access to the transaction history after the registration of a new contract, then it has to reuse the same app user ID that it he had before.
import com.securityside.trustfactor.client.Client;
import com.securityside.trustfactor.client.ClientBuilder;
import com.securityside.trustfactor.client.request.registercode.RegisterCodeReq;
import com.securityside.trustfactor.util.exception.CryptoException;
public class Main {
public static void main(String[] args) {
ClientBuilder clientBuilder = new ClientBuilder();
clientBuilder.SetPrimaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetSecondaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetPrimaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetSecondaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetTFPub(new PublicKey("craE8nZ9eCjUOFwArwTqfdNuruUrDtCNIQhYBt4vyYQ="));
clientBuilder.SetAppPriv(new PrivateKey("redacted"));
clientBuilder.SetDeeplinkBaseURL("https://open.trustfactor.securityside.com");
Client appClient = clientBuilder.Build();
// Creates a register code request
int duration = 60; // code duration of 60 seconds
RegisterCodeReq request = RegisterCodeReq.builder()
.appUniqueId("appUniqueId")
.appUsername("appUsername")
.codeDuration(duration)
.build();
}
}
After the request is created we need to send it to the TrustFactor services, and we do it by calling the registerCode method in the Client.
import com.securityside.trustfactor.client.Client;
import com.securityside.trustfactor.client.ClientBuilder;
import com.securityside.trustfactor.client.request.registercode.RegisterCodeReq;
import com.securityside.trustfactor.client.request.registercode.RegisterCodeRes;
import com.securityside.trustfactor.util.exception.CryptoException;
public class Main {
public static void main(String[] args) {
ClientBuilder clientBuilder = new ClientBuilder();
clientBuilder.SetPrimaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetSecondaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetPrimaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetSecondaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetTFPub(new PublicKey("craE8nZ9eCjUOFwArwTqfdNuruUrDtCNIQhYBt4vyYQ="));
clientBuilder.SetAppPriv(new PrivateKey("redacted"));
clientBuilder.SetDeeplinkBaseURL("https://open.trustfactor.securityside.com");
Client appClient = clientBuilder.Build();
// Creates a register code request
int duration = 60; // code duration of 60 seconds
RegisterCodeReq request = RegisterCodeReq.builder()
.appUniqueId("appUniqueId")
.appUsername("appUsername")
.codeDuration(duration)
.build();
// Sends a register code request
RegisterCodeRes response = appClient.registerCode(request);
}
}
When we get the RegisterCodeRes response we have two possible flows for the user to complete the registration:
- DeepLink URL
- QR Code
The DeepLink URL is used when the user is in a mobile device and can’t scan the QR Code from their own screen. This allows him to tap a button that redirects him to the mobile application and completes the registration. With the QR Code there are two possible options. Either with the QR Code URL or with the QR Code.
QR Code URL- Made for a custom HTTP client or to obtain the token parameter (which is in the URL) and generate the QR CodeQR Code- Returns a Base64 encoded image with a QR Code that the user should scan in order to complete the registration
Note that for the SDK to obtain the Base64 encoded QR Code it needs to call the TrustFactor Services. Consequently, if the application has a tool to generate the QR Codes it can do so, while saving some network traffic.
The QR Code encodes the registration Deep Link URL. This means that besides being scanned from within the Agent application, it can also be scanned with the device’s native camera, which opens the Agent application directly through the deep link.
Depending on the platform (web or mobile) the user is on, you may want to adjust their registration flow accordingly.
import com.securityside.trustfactor.client.Client;
import com.securityside.trustfactor.client.ClientBuilder;
import com.securityside.trustfactor.client.request.registercode.RegisterCodeReq;
import com.securityside.trustfactor.client.request.registercode.RegisterCodeRes;
import com.securityside.trustfactor.util.exception.CryptoException;
public class Main {
public static void main(String[] args) {
ClientBuilder clientBuilder = new ClientBuilder();
clientBuilder.SetPrimaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetSecondaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetPrimaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetSecondaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetTFPub(new PublicKey("craE8nZ9eCjUOFwArwTqfdNuruUrDtCNIQhYBt4vyYQ="));
clientBuilder.SetAppPriv(new PrivateKey("redacted"));
clientBuilder.SetDeeplinkBaseURL("https://open.trustfactor.securityside.com");
Client appClient = clientBuilder.Build();
// Creates a register code request
int duration = 60; // code duration of 60 seconds
RegisterCodeReq request = RegisterCodeReq.builder()
.appUniqueId("appUniqueId")
.appUsername("appUsername")
.codeDuration(duration)
.build();
// Sends a register code request
RegisterCodeRes response = appClient.registerCode(request);
// Handles the response
int size = 400; // Size in pixels of the qr code
String deeplinkUrl = appClient.generateRegistrationDeeplinkURL(response);
String qrCodeUrl = appClient.generateRegistrationQRCodeURL(response, size);
String qrCode = appClient.getRegistrationQRCode(response, size);
}
}
Require location on registration
The registerCodeV2 method (with RegisterCodeV2Req) additionally supports requiring a precise location during the registration. When the requirePreciseLocation flag is enabled, the generated registration token signals the Agent that the registration must be performed with a precise (GPS) device location.
import com.securityside.trustfactor.client.request.registercode.RegisterCodeV2Req;
import com.securityside.trustfactor.client.request.registercode.RegisterCodeV2Res;
// Creates a register code request requiring a precise location
RegisterCodeV2Req requestV2 = RegisterCodeV2Req.builder()
.appUniqueId("appUniqueId")
.appUsername("appUsername")
.codeDuration(duration)
.requirePreciseLocation(true)
.build();
// Sends the register code request
RegisterCodeV2Res responseV2 = appClient.registerCodeV2(requestV2);
The same Deep Link URL and QR Code methods shown above can be used with the RegisterCodeV2Res response.
Finally, when the user finishes the contract registration the TrustFactor services send a callback to notify the application that the user finished the registration. The callback contains information such as the device key, contract key, app user id and device info.
import com.securityside.trustfactor.callback.CallbackHandler;
import com.securityside.trustfactor.callback.CallbackHandlerBuilder;
import com.securityside.trustfactor.callback.message.Register;
import com.securityside.trustfactor.util.exception.CryptoException;
public class Main {
public static void main(String[] args) {
CallbackHandlerBuilder callbackBuilder = new CallbackHandlerBuilder();
callbackBuilder.SetPrimaryEndpoint("https://applications.trustfactor.app");
callbackBuilder.SetSecondaryEndpoint("https://applications.trustfactor.app");
callbackBuilder.SetPrimaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
callbackBuilder.SetSecondaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
callbackBuilder.SetTFPub(new PublicKey("craE8nZ9eCjUOFwArwTqfdNuruUrDtCNIQhYBt4vyYQ="));
callbackBuilder.SetAppPriv(new PrivateKey("redacted"));
CallbackHandler handler = callbackBuilder.Build();
String data = ""; // received in the request body, HTTP server logic not shown here
Register register = handler.handleRegisterCallback(data);
}
}
Create a Transaction
To create a transaction you first need to instantiate the wanted object such as GenericTransaction for a generic transaction. Keep in mind that there may be several versions of the GenericTransaction class, therefore always use the most recent one to get the latest features.
Old method versions are kept for compatibility reasons and may be deprecated in future SDK versions.
import com.securityside.trustfactor.client.Client;
import com.securityside.trustfactor.client.ClientBuilder;
import com.securityside.trustfactor.model.transaction.creation.v3.Core;
import com.securityside.trustfactor.model.transaction.creation.v3.GenericTransaction;
import com.securityside.trustfactor.model.transaction.creation.v3.auxiliary.Metadata;
import com.securityside.trustfactor.util.exception.CryptoException;
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
ClientBuilder clientBuilder = new ClientBuilder();
clientBuilder.SetPrimaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetSecondaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetPrimaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetSecondaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetTFPub(new PublicKey("craE8nZ9eCjUOFwArwTqfdNuruUrDtCNIQhYBt4vyYQ="));
clientBuilder.SetAppPriv(new PrivateKey("redacted"));
clientBuilder.SetDeeplinkBaseURL("https://open.trustfactor.securityside.com");
Client appClient = clientBuilder.Build();
// Creates a generic transaction
GenericTransaction transaction = GenericTransaction.builder()
.message("Test")
.actionName("Action")
.transactionDuration(30)
.core(Core.builder()
.metadata(Metadata.builder()
.timestamp(1619705292L)
.userAgent("TrustFactor Java SDK")
.channel("Mobile")
.sourceIp("1.2.3.4")
.build())
.build())
.customHeaders(new HashMap<String, String>() {{
put("X-Custom-Header", "Header value");
}})
.build();
}
}
After creating the request object you will need to call an Client method, in this case you will need to use either createTransactionV3WithUserID or createTransactionV3WithKey to create the transaction, respectively with the User ID or the Contract Key. For this example we opted for the createTransactionV3WithUserID.
import com.securityside.trustfactor.client.Client;
import com.securityside.trustfactor.client.ClientBuilder;
import com.securityside.trustfactor.client.request.transaction.CreateTransactionV3WithUserIDRes;
import com.securityside.trustfactor.model.transaction.creation.v3.Core;
import com.securityside.trustfactor.model.transaction.creation.v3.GenericTransaction;
import com.securityside.trustfactor.model.transaction.creation.v3.auxiliary.Metadata;
import com.securityside.trustfactor.util.exception.CryptoException;
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
ClientBuilder clientBuilder = new ClientBuilder();
clientBuilder.SetPrimaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetSecondaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetPrimaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetSecondaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetTFPub(new PublicKey("craE8nZ9eCjUOFwArwTqfdNuruUrDtCNIQhYBt4vyYQ="));
clientBuilder.SetAppPriv(new PrivateKey("redacted"));
clientBuilder.SetDeeplinkBaseURL("https://open.trustfactor.securityside.com");
Client appClient = clientBuilder.Build();
// Creates a generic transaction
GenericTransaction transaction = GenericTransaction.builder()
.message("Test")
.actionName("Action")
.transactionDuration(30)
.core(Core.builder()
.metadata(Metadata.builder()
.timestamp(1619705292L)
.userAgent("TrustFactor Java SDK")
.channel("Mobile")
.sourceIp("1.2.3.4")
.build())
.build())
.customHeaders(new HashMap<String, String>() {{
put("X-Custom-Header", "Header value");
}})
.build();
// Send the create generic transaction
CreateTransactionV3WithUserIDRes response = appClient
.createTransactionV3WithUserID("john.doe", transaction);
}
}
When the generic transaction request is completed a CreateTransactionV3WithUserIDRes response is created, inherited from a generic response class GenericResponse. The response contains the transaction Unique ID, the Contract Key as well as the fields from the GenericResponse presented earlier.
Transactions can also require a precise (GPS) device location on decision, through the requirePreciseLocation flag, and/or a confirmation code, through the requireConfirmationCode flag. When a confirmation code is required, the response also contains a Confirmation Code object with the correct code and the list of options presented to the user on the Agent. The application should display the correct code to the user, so he can select it when deciding the transaction. Check the Transactions in depth chapter for further details on these fields.
Apart from deciding a transaction using a push notification, a transaction deep link url can also be used on mobile. The getTransactionDeeplinkURL can be used when the user is in a mobile device and does not receive a notification for the transaction. This allows him to tap a button that redirects him to the mobile application and decide the transaction.
import com.securityside.trustfactor.client.Client;
import com.securityside.trustfactor.client.ClientBuilder;
import com.securityside.trustfactor.client.request.transaction.CreateTransactionV3WithUserIDRes;
import com.securityside.trustfactor.model.transaction.creation.v3.Core;
import com.securityside.trustfactor.model.transaction.creation.v3.GenericTransaction;
import com.securityside.trustfactor.model.transaction.creation.v3.auxiliary.Metadata;
import com.securityside.trustfactor.util.exception.CryptoException;
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
ClientBuilder clientBuilder = new ClientBuilder();
clientBuilder.SetPrimaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetSecondaryEndpoint("https://applications.trustfactor.app");
clientBuilder.SetPrimaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetSecondaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
clientBuilder.SetTFPub(new PublicKey("craE8nZ9eCjUOFwArwTqfdNuruUrDtCNIQhYBt4vyYQ="));
clientBuilder.SetAppPriv(new PrivateKey("redacted"));
clientBuilder.SetDeeplinkBaseURL("https://open.trustfactor.securityside.com");
Client appClient = clientBuilder.Build();
// Creates a generic transaction
GenericTransaction transaction = GenericTransaction.builder()
.message("Test")
.actionName("Action")
.transactionDuration(30)
.core(Core.builder()
.metadata(Metadata.builder()
.timestamp(1619705292L)
.userAgent("TrustFactor Java SDK")
.channel("Mobile")
.sourceIp("1.2.3.4")
.build())
.build())
.customHeaders(new HashMap<String, String>() {{
put("X-Custom-Header", "Header value");
}})
.build();
// Send the create generic transaction
CreateTransactionV3WithUserIDRes response = appClient
.createTransactionV3WithUserID("john.doe", transaction);
String transactionURL = appClient.getTransactionDeeplinkURL(response);
}
}
When the user decides the transaction or when it expires, TrustFactor services will send a callback to the application notifying its final status.
import com.securityside.trustfactor.callback.CallbackHandler;
import com.securityside.trustfactor.callback.CallbackHandlerBuilder;
import com.securityside.trustfactor.callback.message.Transaction;
import com.securityside.trustfactor.util.exception.CryptoException;
public class Main {
public static void main(String[] args) {
CallbackHandlerBuilder callbackBuilder = new CallbackHandlerBuilder();
callbackBuilder.SetPrimaryEndpoint("https://applications.trustfactor.app");
callbackBuilder.SetSecondaryEndpoint("https://applications.trustfactor.app");
callbackBuilder.SetPrimaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
callbackBuilder.SetSecondaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
callbackBuilder.SetTFPub(new PublicKey("craE8nZ9eCjUOFwArwTqfdNuruUrDtCNIQhYBt4vyYQ="));
callbackBuilder.SetAppPriv(new PrivateKey("redacted"));
CallbackHandler handler = callbackBuilder.Build();
String data = ""; // received in the request body, HTTP server logic not shown here
Transaction transaction = handler.handleTransactionCallback(data);
}
}
Handle SIBS callback
When the application receives this callback it means that SIBS transactions v2 are active, and the user needs an activation code to communicate with the MBWay SDK.
import com.securityside.trustfactor.callback.CallbackHandler;
import com.securityside.trustfactor.callback.CallbackHandlerBuilder;
import com.securityside.trustfactor.model.sibs.GetSIBSRegisterTokenReq;
import com.securityside.trustfactor.util.crypto.Envelope;
import com.securityside.trustfactor.util.exception.CryptoException;
public class Main {
public static void main(String[] args) {
CallbackHandlerBuilder callbackBuilder = new CallbackHandlerBuilder();
callbackBuilder.SetPrimaryEndpoint("https://applications.trustfactor.app");
callbackBuilder.SetSecondaryEndpoint("https://applications.trustfactor.app");
callbackBuilder.SetPrimaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
callbackBuilder.SetSecondaryEndpointPub(new PublicKey("WMIskJyIJo36PO93Qju351cL0CDAuM8KYXTj3hoaYHw="));
callbackBuilder.SetTFPub(new PublicKey("craE8nZ9eCjUOFwArwTqfdNuruUrDtCNIQhYBt4vyYQ="));
callbackBuilder.SetAppPriv(new PrivateKey("redacted"));
CallbackHandler handler = callbackBuilder.Build();
String data = ""; // received in the request body, HTTP server logic not shown here
GetSIBSRegisterTokenReq regCodeRequest = handler.handleGetSIBSRegisterTokenRequest(data);
// Requests SIBS activation code
String seeAtvCodSdk = "see_atv_cod_sdk"; // registration token for SIBS
Envelope envelope = handler.handleGetSIBSRegisterTokenResponse(seeAtvCodSdk);
}
}