Skip to content

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.

py -m http.server 8000

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.