User Guide
This user guide assumes that you have already completed the TheM>Getting Started>Quick Start guide and are familiar with TheM class, TheM submodule initialization, and creating/listening for custom events. This guide also assumes that you have already installed the amplifi_mobile_sdk package into your project and placed the following minified libraries in the /lib folder of your project: axios.min.js (Optional - fetch will be used if axios is not present), crypto-js.min.js, lz-string.min.js, moment.min.js, and socket.io.min.js. In addition, you should have completed the Onboarding Guide tutorial in order to create and onboard a user which can be logged into your ampliFi instance.
1. In the src folder of your project (from the Quick Start guide of the TheM Getting Started section), create a new file called user.js
with the following code.
user.js
import ClassTheM from "../node_modules/@PayGearsCorp/amplifi_mobile_sdk/TheM/them.mjs";
import { thisDevice } from "./android-demo-device.js"; //android device emulator for testing
const AMPLIFI_BASE_URL = "PUT_YOUR_INSTANCE_URL_HERE";
const AMPLIFI_CORE_URL = `${AMPLIFI_BASE_URL}core/`;
const DEVICE_TAG = "PUT_YOUR_DEVICE_TAG_HERE"; //Use deviceTag obtained from onboarding tutorial for this device
const _SUPER_SECRET = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
const subClassesToInit = [
"accounts",
//"beneficiaries",
//"cards",
//"cheques",
"common",
//"externalAccounts",
//"fdrs",
//"fundstransfer",
//"fxrates",
//"genericRequests",
//"ious",
//"onboarding",
//"payees",
//"remittance",
//"restrictions",
//"statics",
"user"
];
export const userTutorial = async (subClasses = "") => {
TheM = new ClassTheM({
config: {
AFiInstanceId: "test",
modulesFolder: "",
modulesFolderOnboarding: "",
webworkerFolder: "../TheM/",
baseLibURL: "../demo/lib/",
backEndURL: AMPLIFI_CORE_URL,
socketURL: AMPLIFI_BASE_URL,
user: {
DEFAULT_HOMECOUNTRY: "US"
},
onboarding: {
PRESEGMENTS_ALLOWED: {
"demo_uoiuqwehflkipahgoqq": "GenericClient"
}
}
},
libs: {
}
});
//Emulate user device before initializing TheM submodules
TheM.thisDevice = {
...thisDevice,
TheM,
deviceTag: DEVICE_TAG,
};
//Initialize desired submodules
//Some modules depend on others so must be initialized together
//For instance, most submodules require the "common" subclass to be initialized
await TheM.doInit(subClasses);
//user workflow to try
//Uncomment to run the whole workflow or follow the instructions in the browser
/*
//Prepare for logging in
let _dtsValueString = (new Date()).valueOf().toString();
let { encryptedServerSecret } = await TheM.thisDevice.retrieveLocally("encryptedServerSecret", true);
let serverSecret = CryptoJS.AES.decrypt(encryptedServerSecret, _SUPER_SECRET).toString(CryptoJS.enc.Utf8);
let cryptotext = CryptoJS.AES.encrypt((TheM.thisDevice.deviceTag) + _dtsValueString, serverSecret).toString();
TheM.thisDevice.halfRef = TheM.common.GetRandomSTR(40);
const credentials = {
"dtsValueString": _dtsValueString,
"deviceTag": TheM.thisDevice.deviceTag,
"deviceData": TheM.thisDevice.data,
"channel": TheM.thisDevice.platform,
"dynamicScreensVersion": TheM.thisDevice.dynamicScreensVersion,
"socket": {
halfRef: TheM.thisDevice.halfRef
},
"pushMessToken": TheM.thisDevice.pushMessToken,
"cryptotext": cryptotext
};
await TheM.user.doLogin(credentials);
//After authentication, the locally stored data will be loaded automatically
//Pull user data from the server if it is not fresh enough
await TheM.user.doUpdate();
//Can keep a history of user names if needed
if (TheM.user.name && TheM.user.names.length === 0) {
TheM.user.names.push(TheM.user.name);
}
const payload = {
user: {
addresses: [
{
//AFiUserAddressId: "new", //default AFiUserAddressId is "new" or can assign a unique ID
addressLine1: "456 New Ln.",
addressLine2: "Apt. 1",
city: "Charlotte",
state: "NC",
postalCode: "12345",
countryCode: "US",
country: "US",
isMain: true
}
],
email: "testuser@test.email",
mobile: "5556668888",
}
};
//Editable via event: mobile, email, homecurrency, languageCode, addresses, name, names, sortId, isMetric, entityName, AFiEntityId, segment
console.log(`TheM.user.mobile before details are pushed: ${TheM.user.mobile}`);
//Editable user details can be modified via an event like so
TheM.newEvent("modelBank user details pushed", { payload });
console.log(`TheM.user.mobile after details are pushed: ${TheM.user.mobile}`);
//A new user address instance can be initalized and pushed onto the addresses array like so
TheM.user.addresses.push(TheM.user.getNewTempAddress({
AFiUserAddressId: 'newest',
AFiUserId: 'testaurlx8wfimcrw',
addressLine1: '789 Newer Drive',
addressLine2: null,
city: 'Harrisburg',
countryCode: 'US',
dtsModified: new Date(),
isMain: false,
postalCode: '12345',
state: 'PA',
isSyncedToServer: false
})
);
//User addresses can also be modified via an event like so
TheM.newEvent("modelBank user addresses pushed", {
payload: {
addresses: [
{
AFiUserAddressId: "newest",
addressLine1: "789 Newest Drive",
addressLine2: "Suite 42",
city: "Raleigh",
state: "NC",
postalCode: "12345",
countryCode: "US",
country: "US",
isMain: false
}
]
}
});
console.log(`Pushed a new address using an event: ${JSON.stringify(TheM.user.addresses["newest"])}`);
//Save the modified user locally
TheM.user.doSave();
//This event will cause isSyncedToServer to be set to false
TheM.newEvent("modelBank user details modified", {}); //or "modelBank user addresses modified"
TheM.on("modelBank user refreshed", () => { // Setting a listener that will react to a successful refresh of user data
console.log("All done! Time to log out.");
//Logging out of this user session
TheM.user.doLogout();
}, true);
//Send modified user data to the server, then pull data from server to refresh
if (!TheM.user.isSyncedToServer) {
console.log("Modified data is not yet synced to the server... updating.");
await TheM.user.doUpdate();
}
*/
};
await userTutorial(subClassesToInit.join(" "));
2. The user module expects the client (prospect) to be using some type of device so make sure the android-demo-device.js
file used during onboarding is still in your /src folder.
3. Create a new file in the /demo folder of your project called user.html
with the following code.
user.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<title>ampliFi</title>
<script>
var TheM;
var TheM_config;
</script>
<script src="../lib/socket.io.min.js"></script>
<script src="../lib/lz-string.min.js"></script>
<script src="../lib/moment.min.js"></script>
<script src="../lib/axios.min.js"></script>
<script src="../lib/crypto-js.min.js"></script>
<script type="module" src="/../src/user.js"></script>
<style>
html {
color: white;
background-color: black;
}
</style>
</head>
<body>
<div>
Hit F12 to open the browser console.
Start working with TheM by typing "TheM" into the browser console.
</div>
<br />
<br />
<div>
1. In order to log a user in, we will need to prepare the user credentials using the encryptedServerSecret
stored locally during onboarding. Type the following to retrieve the encryptedServerSecret.
<br /><br />
<code>let { encryptedServerSecret } = await TheM.thisDevice.retrieveLocally("encryptedServerSecret", true);</code>
<br /><br />
Type <code>encryptedServerSecret</code> into the browser console and hit enter to view the encryptedServerSecret
value.
<br /><br />
2. Since we are using an emulated android device to log in, we need to get the cryptotext value like so.
<br /><br />
<code>
let _SUPER_SECRET = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";<br />
let _dtsValueString = (new Date()).valueOf().toString();<br />
let serverSecret = CryptoJS.AES.decrypt(encryptedServerSecret, _SUPER_SECRET).toString(CryptoJS.enc.Utf8);<br />
let cryptotext = CryptoJS.AES.encrypt((TheM.thisDevice.deviceTag) + _dtsValueString, serverSecret).toString();
</code>
<br /><br />
3. Set a socket connection for bidirectional communication.
<br /><br />
<pre><code>TheM.thisDevice.halfRef = TheM.common.GetRandomSTR(40);<br />let manager = new TheM.io.Manager(TheM.config.socketURL + "?halfRef=" + TheM.thisDevice.halfRef, {<br /> autoConnect: false<br />});<br />let socket = manager.socket("/");</code></pre>
<br />
4. Open the socket connection.
<br /><br />
<pre><code>manager.connect(function (data) {<br /> console.log("established real-time comm channel for onboarding");<br /> TheM.thisDevice.isRealTimeCommAvailable = true;<br />});</code></pre>
<br />
5. Log the user in using the deviceTag obtained during onboarding and the newly created cryptotext.
<br /><br />
<pre><code>const credentials = {<br /> "dtsValueString": _dtsValueString,<br /> "deviceTag": "PUT_DEVICE_TAG_HERE",<br /> "deviceData": TheM.thisDevice.data,<br /> "channel": TheM.thisDevice.platform,<br /> "dynamicScreensVersion": TheM.thisDevice.dynamicScreensVersion,<br /> "socket": {<br /> halfRef: TheM.thisDevice.halfRef<br /> },<br /> "pushMessToken": TheM.thisDevice.pushMessToken,<br /> "cryptotext": cryptotext<br />};<br />await TheM.user.doLogin(credentials);</code></pre>
<br />
6.After authentication, the locally stored data will be loaded automatically
<br /><br />
7. Pull user data from the server if it is not fresh enough.
<br /><br />
<code>await TheM.user.doUpdate();</code>
<br /><br />
8. You can keep a history of user names if needed.
<br /><br />
<pre><code>if (TheM.user.name && TheM.user.names.length === 0) {<br /> TheM.user.names.push(TheM.user.name);<br />}</code></pre>
<br />
9. Editable user details can be modified via an event like so. Editable user fields include mobile, email,
homecurrency, languageCode, addresses, name, names, sortId, isMetric, entityName, and AFiEntityId.
<br /><br />
<pre><code>const payload = {<br /> user: {<br /> addresses: [<br /> {<br /> addressLine1: "456 New Ln.",<br /> addressLine2: "Apt. 1",<br /> city: "Charlotte",<br /> state: "NC",<br /> postalCode: "12345",<br /> countryCode: "US",<br /> country: "US",<br /> isMain: true<br /> }<br /> ],<br /> email: "testuser@test.email",<br /> mobile: "5556668888",<br /> }<br />};<br />TheM.newEvent("modelBank user details pushed", { payload });</code></pre>
<br />
10. User addresses can also be modified via an event like so.
<br /><br />
<pre><code>TheM.newEvent("modelBank user addresses pushed", {<br />payload: {<br /> addresses: [<br /> {<br /> AFiUserAddressId: "newest",<br /> addressLine1: "789 Newest Drive",<br /> addressLine2: "Suite 42",<br /> city: "Raleigh",<br /> state: "NC",<br /> postalCode: "12345",<br /> countryCode: "US",<br /> country: "US",<br /> isMain: false<br /> }<br /> ]<br /> }<br />});<br />console.log(`Pushed a new address using an event: ${JSON.stringify(TheM.user.addresses["newest"])}`);</code></pre>
<br />
11. Save the modified user locally.
<br /><br />
<code>
TheM.user.doSave();
</code>
<br /><br />
12. You can set a listener that will react to a successful refresh of user data.
<br /><br />
<pre><code>TheM.on("modelBank user refreshed", () => { <br /> console.log("All done! Time to log out.");<br /> //Logging out of this user session<br /> TheM.user.doLogout();<br />}, true);</code></pre>
13. This event will cause isSyncedToServer to be set to false and will call TheM.user.doUpdate() to sync and
refresh the
modified user data to the server.
<br />
<code>
TheM.newEvent("modelBank user details modified", {}); //or "modelBank user addresses modified"
</code>
<br /><br />
</div>
</body>
</html>
4. Start a server in the root folder of your project.
5. Open a browser and enter the following URL: http://localhost:8000/demo/
6. Click on the link for "user.html" and follow the instructions to log the user in, modify the user data, save and sync the user data, and log out.