npm install npm install nodemon
You will need
- Activated agent access to your Conversations Inbox and an API key (contact tyntec support if you don't have it)
- Your WhatsApp Business Account (WABA) number assigned to your Conversations Inbox by tyntec
- A phone with WhatsApp and a working mobile number as a testing contact
- A testing Microsoft Dynamics account
- A Microsoft Power Apps license in your Dynamics environment
- A Contact in your Microsoft Dynamics with the testing mobile number
- An ngrok account with the binary installed and authorized
- Node.js installed and your favorite text editor or IDE with JavaScript
- Postman
Step One: Extend the data model in your Dynamics
Let's start by creating a data table to hold the message records. You will create a custom table, with custom columns and one lookup column, which is used to relate your messages to specific contacts.
1. Log in to your PowerApps.
2. In the menu on the left, click on Data and then Tables.
3. Click on the + New table. This will bring up a pop-up on your right side.
4. Set the Display name to messagerecord and Name to messagerecord as well. Beware, PowerApps are case sensitive! Then click on Create.
5. Let's add more columns. In your table view, click the + New Column button to add another column to your new table.
6. Set the Display name to Messagebody and the Name to messagebody. Leave the Data type set to Text. Then click Done.
7. Repeat Steps 5 and 6 to create another column with the Display name set to Direction, Name to direction and Data type to Text. Then click Done.
8. Repeat Step 5 and 6 to create another column with the Display name set to Party, Name set to party, Data type set to Lookup and Related table to Contact. Then click Done.
9. Note the full Names of your Message, Messagebody, Party, and Direction entities including the prefix (in our case it was cr1b1). You will need these names in the next step.
Congratulations, your table that will hold all new messages is now ready!
Step Two: Get your integration app ready
For your quick start with integrations, we’ve prepared a sample integration app. Look at what the code does. You will notice that the code is in several directories:
- config/config.js manages your environment variables,
- services/dynamicsConnector.service.js gets an authorization token for the app,
- router/dynamics.router.js handles incoming requests and calls the Dynamics Web API,
- server.js ties the logic together.
Let’s just quickly get your app running in the development style:
1. Clone the api-samples repository and go to the chat-integrations/ms-dynamics folder.
2. Install dependencies (and the nodemon module if you don’t have it yet):
ngrok http 3000
4. Copy .env.example to .env and set environment variables in .env:
- TENANT_ID – your MS tenant ID (Where do I find it?), e.g. ae70ef96-0099-420c-97ba-fa06ca9e2987
- HOST – the domain name of your Dynamics instance, e.g. myinstance.crm4.dynamics.com
- CLIENT_ID – the client ID of your integration app as registered in MS Azure, e.g. ed9da4c8-906d-49ab-b694-ec6c8e8f9871
- USERNAME – your Dynamics username
- PASSWORD – your Dynamics password
5. Modify data table and column names in the file router/dynamics.router.js.
In the constant messageEntity, rename cr1b1_message to the primary name column of your table, cr1b1_direction to your table direction column, and cr1b1_messagebody to your table messagebody column. Then set the cr1b1_party@odata.bind to the name of your lookup column@odata.bind.
In the constant messageRequest, set collection to your table name.
6. And finally, start the app in another terminal:
nodemon server.js
Note: This setup is suitable only for development. For production use, you have to deploy your app properly!
Step Three: Subscribe to your Conversations Inbox
Let's subscribe your integration app to events in the WhatsApp channel of your Conversations Inbox.
1. From the chat-integrations directory, import the CMD.postman_collection.json into Postman.
2. Authorize Postman with your Conversations Inbox API key and your WABA number.
Right-click the collection and select Edit. Then go to Variables and set the apiKey variable to your Conversations Inbox API key. Set also the wabaNumber variable to your WABA number.
3. Let’s set up the webhook!
Open the Set Webhook request and change the URL in the body to the /webhook endpoint on your server.
4. Set the events to “message” and “echo”. This request will subscribe your URL to incoming and outgoing message events.
5. Hit the Send button. You should receive a 2xx status in the response if everything was okay.
Cool! Now your Conversations Inbox knows where to forward your messages.
2. As soon as you send your message, you will see a new table record. You can view active messages in Tables > Views > Active messagerecords.
Your message record should look something like this.
If you don't see some values, add more columns to your view.
3. Voila! All your messages will automatically be copied to your Dynamics.
Congratulations on completing your integration!
More?
With all your messages safely saved in your Dynamics, you could think about improving this integration. Common ways to go further:
-
In your Tables > Dashboards, you can create Dashboards to see analytics of your communication.
We suggest creating a separate view for your new Dynamics Dashboard. Go to Tables > Views > Add View. See also the Microsoft documentation on Dashboards and Views. -
The current integration works for accounts without 2FA. If you want to use 2FA, you need to modify the authentication in dynamicsConnector.service.js. You can find more in the Web API documentation.
-
You may subscribe to more channels in your Conversations Inbox and save messages from several channels. We recommend adding an additional column to your Dynamics table that will store information about the channel through which the messages are transmitted. In the code, you would also need to get the channel information from the channel JID and to add channel information to the constant messageEntity in dynamics.router.js such as:
const messageEntity = { cr1b1_message: messageId, cr1b1_messagebody: message, cr1b1_channel: channel, 'cr1b1_party@odata.bind':`/contacts(${entityContactData.contactid})`, };