# Message Notification Center

## Objective 

Business or system messages can be conveyed quickly while users can receive messages on the UI and handle them conveniently.

## Composition of Message Center

Notification is a basic requirement for systems and there can be a lot of business scenarios where notification is required.

- Synchronous notification: This is an instant notification which, for example, can be utilized by operators to seek help from underwriters.

- Asynchronous notification: This is a delayed notification for time-consuming operations.   

    - Once large amount of data is uploaded, this notification will inform users of the completion.
    - Once batch processing is completed, this notification will inform users of the successful status.

Apart from system-built message centers, solutions also include notification centers, email, SMS, and online chat apps. Compared with other modes, a system message center is often recommended as it will hardly lose any message.

From a system design perspective, there are two different categories:

- Message pusher: This is a trigger point embedded in business transactions to push out messages.  

- Message center: This is a notification center built in the admin console and can be substituted by other modes of notifications.


## UI Operation

**Send Message** supports publicizing announcements or sending messages to others. Basically, there are three types of messages:

*  Announcement

It is a message sent to all users of the system. Everyone, whether they are just navigating on the UI, or have logged in, will see announcements after clicking **Bell** in the upper right corner.

![Send Announcement](./image/monitor/announcement.png)

*  Notification

It is a message sent to chosen users. Users who have been selected will see notifications after clicking **Bell** in the upper right corner of the UI.

If user input "Reminder Time" as a future date or time, the receiver will only receive the alert at that specific point of time.

![Send Notifaction](./image/monitor/notifaction.png)


*  Mandatory Announcement

Different from an announcement that is still displayed in the message box and users might ignore it sometimes, a mandatory announcement will always be dynamically displayed in the top of the UI. It is applicable to scenarios where system administrators want to inform everyone of important messages. 

![Send Mandatory Announcement](./image/msgcenter/mandatory_annoucement.png)

After clicking **View All**, users will see all the announcements and notifications received.

![View All](./image/monitor/messagelist.png)

<div class="docs-note"><span class="docs-admonitions-text">note</span>   

This feature doesn't have authority control and is mostly suitable for administrators. If you want to use this feature for your business, please call our APIs to pass the right parameters.   

</div>


## Development Guidance

#### Overall System Architecture

![overallarchitecture](./image/msgcenter/overallarchitecture1.png) 

#### RabbitMQ1 (Center)

It stores and distributes the original information transferred from business applications.

#### RabbitMQ2 (Pusher)

It stores and distributes messages sent from the message center to be pushed to the terminal.

#### Message Center Application (Platform Pub)

It receives message parameters published by business nodes, generates complete message text, saves messages, counts personal messages of corresponding users, and publishes personal messages of users.

#### WebSocket Application (MSG Pusher)

It pushes messages to the terminal through a valid WebSocket long connection.

#### Message Template Definition

Each product line needs to provide the message server with the message text that needs to be sent in each scenario through the dataTable (MsgCenterMailTemplate). If no custom template is configured, the default template will be used.  

For example, in the scenario where an insurance application form or endorsement (including but not limited to surrender, cancellation, and batch reduction) has been approved, the text of the information to be sent to the mobile phone of the business operator is: **[Operator Name] Hello, [Application Form No./Endorsement No.] of the applicant [Applicant Name]: XXXXXXXXXXXXXXXXXXXXXXXX has been approved. Please pay the fee before [Insurance Commencement/Effective Date] in the amount of [*******].**

Each message needs to define its message template and adopt velocity format specification. The velocity format specification allows the template to contain variables, and the corresponding values can be obtained from the actual input parameters.   

Here is an example: **Hello {handlerName}, {Application Form No./Endorsement No.} of the policyholder {policyHolderName} : {policyNO} has been approved, please pay before {generalTime}, the amount is {amountOfMoney}**.

##### Required parameters

| Variable            | Type                  | Description                                              |
| ------------------- | --------------------- | -------------------------------------------------------- |
| productLine         | String                | Business production lines, such as AH, AUTO, RI, GI, etc |
| sendScene           | String                | Message sending scenario, used to query the corresponding message templates |
| messageSender       | String                | Message sender                     |
| messageReceiverList | List<MessageReceiver/> | Message receiver list. One message may need to be sent to multiple business employees |
| messageType         | String                | Message type, such as SMS, internal message, email, WeChat, etc |
| messageLevel        | String                | Message level, such as important, common, etc |

##### MessageReceiver Fields Description

| Variable            | Type   | Description                                                     |
| ------------------- | ------ | --------------------------------------------------------------- |
| receiverId          | String | ID of the message receiver, that is, userID of the business employee who has logged in to the work platform (required field). Generation method: TenantCode+UserName |
| receiverName        | String | Name of the message recipient                                |
| receiverPhoneNumber | String | Phone number of the message recipient                        |
| receiverWeChat     | String | WeChat ID of the message receiver                                   |

#### Long Connection Management

Business employees involved can log in to WorkList, enter the workbench home page (including the interface of message icon), and then send a connection request to the WebSocket service which authenticates the permission of the request. After the authentication is passed, WebSocket will establish a long connection with it. Then the front-end page will call the restful interface of the message server to obtain the statistics of unread messages and important unread information.

Long connection flowchart is as follows:

​		![websocketLinkmanage](./image/msgcenter/websocketLinkmanage1.png) 

#### Main Flow for Messages

​		![msgcenternode](./image/msgcenter/msgcenternode1.png) 

- #### 	Safety Certification

A long connection between the business UI and the MSG publisher can only be established after the user authentication is passed. Once users pass the authentication, log in to the work platform, their tokens can be retrieved, the WebSocket side can use the tokens for authentication through SSO.

- #### 	Background Integrated Message Center

1. SDK remote call ,  recommended：

   ```
   @Autowired
   private MsgCenterRestfulService msgCenterRestfulService;
       
   MailMessage message = new MailMessage();
   MsgCenterFixedParams msgCenterFixedParams = new MsgCenterFixedParams();
   msgCenterFixedParams.setMessageType(MsgCenterConstants.Msg_Type_Mail);
   msgCenterFixedParams.setMessageLevel(MsgCenterConstants.Msg_Level_Important);
   msgCenterFixedParams.setProductLine(MsgCenterConstants.Msg_Product_Line_Default);
   msgCenterFixedParams.setSendScene(MsgCenterConstants.Msg_Send_Scene_Default);
   msgCenterFixedParams.setMessageCategory(MsgCenterConstants.Msg_Category_Business);
   msgCenterFixedParams.setMessageSender(AppContext.getTenantCode()
   +"-"+AppContext.getCurrentUser().getUserName());
   List<MessageReceiver> receivers = new ArrayList<>();
   MessageReceiver messageReceiver = new MessageReceiver();
   messageReceiver.setReceiverId(AppContext.getTenantCode() + "-" + AppContext.getCurrentUser().getUserName());
   receivers.add(messageReceiver);
   msgCenterFixedParams.setMessageReceiverList(receivers);
   message.setMsgFixedParams(msgCenterFixedParams);
   
   Map<String, Object> mutableParamsMap = new HashMap<>();
   mutableParamsMap.put(MsgCenterConstants.Msg_Message_Body, "New Message");
   message.setMutableParamsMap(mutableParamsMap);
   
   msgCenterRestfulService.sendMailMessage(message);
   ```

   

2. MQ supported,not recommended ( Asynchronous processing, risk of message sending failure )：

```
@Autowired(required = false)
private AppMessageSender appMessageSender;
    
MailMessage message = new MailMessage();
MsgCenterFixedParams msgCenterFixedParams = new MsgCenterFixedParams();
msgCenterFixedParams.setMessageType(MsgCenterConstants.Msg_Type_Mail);
msgCenterFixedParams.setMessageLevel(MsgCenterConstants.Msg_Level_Important);
msgCenterFixedParams.setProductLine(MsgCenterConstants.Msg_Product_Line_Default);
msgCenterFixedParams.setSendScene(MsgCenterConstants.Msg_Send_Scene_Default);
msgCenterFixedParams.setMessageCategory(MsgCenterConstants.Msg_Category_Business);
msgCenterFixedParams.setMessageSender(AppContext.getTenantCode()
+"-"+AppContext.getCurrentUser().getUserName());
List<MessageReceiver> receivers = new ArrayList<>();
MessageReceiver messageReceiver = new MessageReceiver();
messageReceiver.setReceiverId(AppContext.getTenantCode() + "-" + AppContext.getCurrentUser().getUserName());
receivers.add(messageReceiver);
msgCenterFixedParams.setMessageReceiverList(receivers);
message.setMsgFixedParams(msgCenterFixedParams);

Map<String, Object> mutableParamsMap = new HashMap<>();
mutableParamsMap.put(MsgCenterConstants.Msg_Message_Body, "New Message");
message.setMutableParamsMap(mutableParamsMap);

appMessageSender.sendMessage("platform-pub", message);
```

