Status | NOT STARTED |
Owner | |
---|---|
Contributors | |
Due date |
|
Tickets | Epic: SAF-1404 - BO: Genesys integration Backlog
|
On this page |
Terms
Name | Description |
---|---|
Customer | The Safibank mobile app user. |
Agent | The backoffice agent. |
Conversation | Here refers to the chat between a customer and a backoffice agent. |
ACD | Automatic communication distribution is a system that intelligently routes interactions based on agent availability, caller input, agent skill levels, volume of interactions, time of day, agent groups, trunk line, costs, priority, or other variables. |
Queue | An ACD queue is a workgroup queue that is set up to deliver ACD calls. ACD calls are routed to the appropriate Workgroup based on caller input. All members of that Workgroup (call agents) are expected to have a core set of skills required to handle any call on that queue. |
Inbound message | A message sent to Genesys. |
Outbound message | A message sent by Genesys. |
Message receipt | Acknowledge a message is received. A message receipt is also an inbound or outbound message, used to tell the message producer the current status of the message. |
Realm is an embedded, object-oriented database that lets you build real-time, always-on applications. |
Background
We don’t want customer’s app to interact with Genesys cloud directly. We also want to make sure the conversations between customer mobile app and Genesys cloud are monitored for security purpose.
Architecture overview
The only way to chime in on a conversation between mobile app and Genesys cloud, is using Open Messaging.
Open messaging is a lightweight integration that facilitates messaging with third-party systems and external messaging services. With open messaging you can leverage Genesys Cloud's asynchronous ACD capabilities to route inbound open messages to the right queues and agents.
Here the Middleware stands for Backoffice’s genesys-gateway.
Simply put:
Backoffice (more precisely, genesys-gateway) will provide a webhook to receive outbound messages from Genesys Cloud.
Backoffice will use Genesys SDK to push an inbound message to Genesys Cloud.
Mobile apps will not communicate with Backoffice directly, but instead there will be Realm as middleman.
Implementation
Prerequisites
The first step in setting up open messaging is to create an integration. There are two ways to create an integration:
Create from Genesys Cloud Admin UI.
Send a request to POST /api/v2/conversations/messaging/integrations/open.
Brave:
{ "name": "Open Messaging Integration for Brave environment", // required "outboundNotificationWebhookUrl": "https://api.smallog.tech/genesys-gateway/webhook/conversations/outbound/messages", // required, webhook URL // required, Genesys uses this token to compute a signature for a request and then include the signature in X-Hub-Signature-256 header in the request to webhook. "outboundNotificationWebhookSignatureSecretToken": "OUTBOUND_NOTIFICATION_WEBHOOK_SIGNATURE_SECRET_TOKEN", "webhookHeaders": { // optional "YOUR-HEADER-KEY-1": "YOUR-HEADER-VALUE-1", "YOUR-HEADER-KEY-2": "YOUR-HEADER-VALUE-2", ... } }
Tangled:
{ "name": "Open Messaging Integration for tangled environment", // required "outboundNotificationWebhookUrl": "https://api.sfdvwork.xyz/genesys-gateway/webhook/conversations/outbound/messages", // required, webhook URL "outboundNotificationWebhookSignatureSecretToken": "OUTBOUND_NOTIFICATION_WEBHOOK_SIGNATURE_SECRET_TOKEN", // required, see description above. "webhookHeaders": { // optional "YOUR-HEADER-KEY-1": "YOUR-HEADER-VALUE-1", "YOUR-HEADER-KEY-2": "YOUR-HEADER-VALUE-2", ... } }
The token is used to encrypt the request to webhook. Genesys cloud uses this token to generate a signature for the request, and puts both token and signature in http request’s headers. In webhook, we’ll verify and ensure the request is not tampered.
To add Realm SDK in the application (https://www.mongodb.com/docs/realm/sdk/kotlin/quick-start/#quick-start---kotlin-sdk ), we have to:
add plugin
id("io.realm.kotlin") version "1.6.1"
in gradleadd
io.realm.kotlin:library-sync
andorg.jetbrains.kotlinx:kotlinx-coroutines-core
as dependencies
Generate OAuth token
In order to call Genesys Cloud APIs, we must generate a token for the calls.
Genesys provides SDK so we can use directly. See ph.safibank.genesysgateway.client
.GenesysClient
in genesys-gateway.
Process inbound messages
Since mobile app will send (or exactly speaking, sync between realms) the chat messages to Realm, for Backoffice we need to consume the messages from Realm then forward to Genesys Cloud using Genesys RESTful APIs.
1. Consume messages from Realm
To receive any updates on chat messages in Realm, refer to https://www.mongodb.com/docs/realm/sdk/kotlin/realm-database/react-to-changes/#register-a-realmobject-change-listener .
2. Convert a Realm message to Genesys inbound message
3. Send the inbound message to Genesys Cloud
We can use either of the two ways to push an inbound message to Genesys Cloud:
ConversationsApi.postConversationsMessagesInboundOpen
(Recommended)
If this is the first message of a conversation, which means the customer starts a new conversation, we need to store the customerId-conversationId combination (and timestamp) in database.
There should be a composite index on ‘customerId’ and timestamp columns.
Nice-to-have: An Ably message should be able to indicate whether it’s the first message of a conversation or not. CC Andre Laksmana (Unlicensed)
More sample inbound messages can be found here.
{ "id": "<Open Message ID>", "channel": { "platform": "Open", "type": "Private", "messageId": "<External Service Message ID>", // should be able to use a random UUID "to": { "id": "<Integration ID>" }, "from": { "nickname": "Messaging User", "id": "messaging-user@externalservice.com", // this should be the customer id "idType": "email", "image": "https://externalservice.com/profiles/messaging-user.png", "firstName": "Messaging", "lastName": "User" }, "time": "2021-01-21T16:47:07.592Z" }, "type": "Text", "text": "Inbound message", "direction": "Inbound" }
Process outbound messages
1. Webhook
SAF-1901 - Create webhook to receive Genesys outbound messages Ready for Testing
To receive any conversation (outbound) messages from Genesys Cloud, we need to provide a RESTful API in genesys-gateway as the webhook.
POST /genesys/webhook/conversations/outbound/messages
The sample message payloads can be found here.
{ "id": "<Messaging Platform Message ID>", "channel": { "platform": "Open", "type": "Private", "to": { "id": "messaging-user@externalservice.com", // the customer id "idType": "email" }, "from": { "id": "<Integration ID>" }, "time": "2021-01-21T16:47:07.592Z" }, "type": "Text", "text": "Outbound message text!", "direction": "Outbound" }
2. Validate an outbound message
To validate if a message is really from Genesys Cloud, we need to get the signature from the X-Hub-Signature-256
request header, then compare with the SHA value of message:
Javascript code sample:
const crypto = require('crypto'); // integration - the integration object // normalizedMessage - the NormalizedMessage payload // request - webhook request object const normalizedMessage = request.data; const signature = request.headers['X-Hub-Signature-256']; const secretToken = integration.outboundNotificationWebhookSignatureSecretToken; const messageHash = crypto.createHmac('sha256', secretToken) .update(JSON.stringify(normalizedMessage)) .digest('base64'); if (`sha256=${messageHash}` !== signature) { throw new Error("Webhook Validation Failed! Throw this away."); } else { processMessages(normalizedMessage); }
3. Construct a Realm message and sync with customer’s mobile
To be determined for the message format.
To sync any updates with mobile apps, refer to https://www.mongodb.com/docs/realm/sdk/kotlin/realm-database/create/create-a-new-object/#create-a-new-object---kotlin-sdk or https://www.mongodb.com/docs/realm/sdk/kotlin/realm-database/update/upsert-an-object/#upsert-an-object---kotlin-sdk .
Acknowledge a message
Refer to Message receipts for more details. A message receipt is also an inbound or outbound message.
When an outbound message is received by the customer’s mobile app, we will push an inbound message receipt to Genesys Cloud to notify that the message is delivered successfully.
When an inbound message is accepted by Genesys Cloud, we will get a message receipt from webhook, saying the inbound message is delivered.
Conversation history API)
Can mobile app retrieve from Realm ?
Since we have stored customerId-conversationId combinations in database, and there is an index on ‘customerId' column, it should be very fast to query the conversationIds for a given customer.
1. Query the conversations for a given customer and time period
GET /genesys/{customerId}/conversations?from=2023-01-20&to=2023-01-25 // suppose time is in +8 timezone
We get the conversation ids by querying database.
2. Construct the conversation history
Now we are able to get the conversations one by one using:
GET /api/v2/conversations/messages/{conversationId}
, its response contains all of the messages of a conversation.
To be determined for the response. Andre Laksmana (Unlicensed)
If there are a lot of conversation ids, it would be very slow to load all of the conversations for these ids.
Issue of onboarding conversations
A customer who is onboarding, may want to chat with a Backoffice agent to get help because s/he meets with problems during onboarding. After onboarded, s/he also wants to be able to see his/her previous conversations.
In order to achieve this, the customer’s mobile app must tell Backoffice the formal customer id after onboarded.
The process would be like this:
A customer is onboarding but meets with problems.
The customer chats with a Backoffice agent.
The customer’s mobile app creates a temporary customer id since at this moment the customer is not a regular customer and doesn’t have a formal customer id.
Backoffice (genesys-gateway) queries Genesys Cloud to find the conversation using the message id, and store the customerId-conversationId combination into database.
After the customer completes the onboarding, the customer’s mobile app send the temporary customer id and new formal customer id to Backoffice(either by Ably message or RESTful API).
Backoffice (genesys-gateway) updates the customerId-conversationId combination in database.
Message formats
Type | From | To | Format |
---|---|---|---|
Inbound | Mobile app | Ably | |
Inbound | genesys-gateway | Genesys | |
Outbound | Genesys | genesys-gateway | |
Outbound | genesys-gateway | Ably | |
Outbound | Ably | Mobile app |
Resources
Attachments:
image-20230206-025458.png (image/png)
MobileApp-GenesysGateway.png (image/png)