1. 消息集成

1.1. 概述

实现协同平台和业务系统的消息互通:

  • 发送消息

    发送系统消息,外部系统可以调用接口向协同用户发送消息。通过消息的链接可单点登录到业务系统进行处理。

  • 消息通道扩展

    即PC消息、M1/M3消息推送等这都属于其中一种通道,根据实际需要可以扩展其他通道,监听系统消息,发送到邮件、IM或业务系统。

  • 短信接口

    通过短信插件,可以通过短信发送系统通知消息。

1.2. 消息组件(第三方系统发送消息到平台)

第三方系统可以通过消息通道接收协同平台的消息,也可以使用下面两种方式向协同用户发送消息:

  • 远程:调用web service,使用消息服务发送消息

  • 本地:开发插件,使用消息组件接口发送。

平台开发手册.消息集成.消息组件(第三方系统发送消息到平台).

1.2.1. 应用范围

  • 系统内用户发起、处理某些业务时,需要告知或提醒另外一些用户的时候需要用到系统消息组件

  • 系统在线呼叫,需要用到系统消息组件

1.2.2. 开发规范

下面主要介绍本地的消息接口

注入消息接口 userMessageManager

例如:

<bean class="com.seeyon.apps.collaboration.manager.impl.ColManagerImpl"> 
    <property name="userMessageManager" ref="userMessageManager" /> 
</bean>

private UserMessageManager userMessageManager;

public UserMessageManager getUserMessageManager(){
    return this.userMessageManager;
}
public void setUserMessageManager(UserMessageManager userMessageManager){
    this.userMessageManager = userMessageManager;
}

private  void sendMessage(){
    userMessageManager.sendSystemMessage(msgContent, ApplicationCategoryEnum.taskManage, userId.longValue(), msgReceivers, new Object[] {1});
}

接口说明:

几种接口形式:
/** 
  * 发送系统消息,发送给单个接收者
  * @param content  消息体 
  * @param messageCategroy 消息所属应用分类 在com.seeyon.ctp.common.constants.ApplicationCategoryEnum中定义 
  * @param senderId  发送者ID 
  * @param receiver  接收者 
  * @param messageFilterArgs  消息转移的参数,与对应的UserMessageFilter对应 
  * @see com.seeyon.ctp.common.constants.ApplicationCategoryEnum 
  * @throws MessageException 
  */ 
void sendSystemMessage(MessageContent content, 
    ApplicationCategoryEnum messageCategroy, long senderId, 
    MessageReceiver receiver, Object... messageFilterArgs) throws MessageException; 

/** 
  * 发送系统消息,发送给多个接收者
  * @param content  消息体 
  * @param messageCategroy 
  *                       消息所属应用分类 
  *                     在com.seeyon.ctp.common.constants.ApplicationCategoryEnum中定义 
  * @param senderId  发送者ID 
  * @param receivers  接收者 
  * @param messageFilterArgs  消息转移的参数,与对应的UserMessageFilter对应 
  * @see com.seeyon.ctp.common.constants.ApplicationCategoryEnum 
  * @throws MessageException 
  */ 
  void sendSystemMessage(MessageContent content, 
    ApplicationCategoryEnum messageCategroy, long senderId, 
    Collection  receivers,  Object...  messageFilterArgs)  throws 
        MessageException; 

/** 
  * 发送系统消息,使用指定的时间发送给多个接收者
  * @param content   消息体 
  * @param messageCategroy 
  *                       消息所属应用分类 
  *                       在com.seeyon.ctp.common.constants.ApplicationCategoryEnum中定义 
  *                       如果是插件,需要在插件定义文件中配置applicationCategory属性 
  * @param senderId  发送者ID 
  * @param creationDate  发送时间 
  * @param receivers  接收者 
  * @param messageFilterArgs  消息转移的参数,与对应的UserMessageFilter对应 
  * @see com.seeyon.ctp.common.constants.ApplicationCategoryEnum 
  * @throws MessageException 
  */ 
void sendSystemMessage(MessageContent content, int messageCategroy, 
    long senderId, Date creationDate, 
    Collection receivers, Object... messageFilterArgs) 
    throws MessageException;

接口使用注意事项:

  • 如果MessageContent相同,接收者为多人的情况下,禁止通过for-each 方式调用sendSystemMessage方法发送消息 ;而应该使用多接收者的接口。
  • 如果MessageContent的Subject是动态的,比如:处理协同的状态,通过消息定义来解决。

接口参数说明:

MessageContent 构造消息体

MessageContent 消息体,主要封装国际化key以及参数。国际化内容放在各插件的中的国际化文件中,不需要在消息组件中的国际化文件中增加。

几种构造方法说明:

方式一: new MessageContent(String key, Object... param)

方式二:MessageContent.get(String key, Object... param)

方式三:new MessageContent() .add(String key, Object... params)……

例如:
MessageContent messageContent = new MessageContent() 
      .add("col.send", subject, sender.getName()) 
      .add("col.agent") 
      .setBody(bodyContent, bodyType, bodyCreateDate);

设置正文,主要用于email的正文:MessageContent.setBody(String bodyContent, String bodyType, Date bodyCreateDate)

设置重要程度:1普通,2重要,3非常重 要:MessageContent.setImportantLevel(Integer)

MessageReceiver 消息接收者

MessageReceiver 消息接收者,主要封装关联主体对象id、接收人Id、链接类型及链接参数

几种构造方法说明:

  • 每个接收者的链接地址都不一样,通过for-each单个构造 MessageReceiver MessageReceiver.get(Long referenceId, long receiverId, String linkType, String... linkParam)
  • 一个接收者,但没有连接 MessageReceiver MessageReceiver.get(Long referenceId, long receiverId)
  • 多个接收者,一样的链接 List get(Long referenceId, List receiverIds, String linkType, String... linkParam)
  • 多个接收者,都没有链接 List get(Long referenceId, List receiverIds)

1.3. 消息通道(第三方系统接收平台消息)

当第三方系统(sms,email,rtx,gke)需要接收协同平台消息时,可以使用消息展现通道。

只需实现一个消息接口, 系统就可以把外部的应用集成进来,在集成端可以接收系统 的所有消息,如在线消息,协同,会议,计划等,在系统启动前和用户个人设置中均可以配置。

1.3.1. 接口说明

接口名称:interface MessagePipeline

必须实现的方法如下:

方法定义 返回值 备注
getName() String 消息展现通道的系统标示,注意不要重复,有数字字母 下划线构成,如:pc,sms,email,rtx,gke getShowName() string 消息展现通道的显示名称 isAvailability() boolean 该通道是否可用,可以控制是否需要消息展现
isAllowSetting(User currentUser) String 是否允许用户在“个人设置-消息提示设置”中进行配 置; 如:短信提示,需要后台管理员授权,并且设置了个人 的手机号码,人员是当前登录者,允许配置返回 null, 否则返回提示信息(注意国际化)
getAllowSettingCategory() List 得到哪些应用类别可以配置(参考 ApplicationCategoryEnum), 如果采用系统默认, 请直接返回 null 如果不允许配置请参考 isAllowSetting(User currentUser)
invoke(Message[] messages) void 在此方法中处理消息,把消息集成到外系统 getSortId() int 排序号,从 0 开始
isDefaultSend() boolean 默认是否发送,如果为 false,则个人需要在“个人设 置-消息提示设置”中进行配置
isShowSetting() boolean 如果 isDefaultSend 设置为false,则个人需要设置为true

注册到系统

<bean id="rtxMessagePipeline" class="com.seeyon.v3x.plugin.rtx.message.RTXMessagePipeline"/>

系统启动时显示:

[main] INFO MessagePipelineManagerImpl:68 - 加载消息展现通道:[pc, email, rtx]

则代表pc、email和rtx三个消息通道实现加载成功。

代码示例

以 RTX 消息展现为例:

public class RTXMessagePipeline implements MessagePipeline {
    // 处理消息
    public void invoke(Message[] messages) {
        for (Message message: messages) {
            try {
                String remoteURL = message.getRemoteURL();
                String userName = message.getReceiverMember().getLoginName();
                RTXNotifyValueBean value = new RTXNotifyValueBean();
                String content = message.getContent();
                value.title = message.getSenderMember().getName();
                // ...
                rtxSendNotifyManager.sendNotify(value);
            } catch (Throwable e) {
                log.error("", e);
            }
        }
    }
    // 该通道是否可用
    public boolean isAvailability() {
        return SystemEnvironment.hasPlugin("rtx");
    }
    // 消息展现通道的系统标示
    public String getName() {
        return "rtx";
    }
    // 默认是否发送
    public boolean isDefaultSend() {
        return false;
    }
    // 排序号
    public int getSortId() {
        return 6;
    }
}

1.4. 短信接口

二次开发时客户可能指定具体短信网关,这样我们需要支持此短信网关来发短信,可以只采用普通方式发短信息, 实现 平台普通短信接口即可,短信插件被启用时加载到系统。 例如:UFMOBILE,短信王 如果客户想使用消息回调,打开链接,必须开启移动应用插件,就是实现 wappush 接口的,必须开启移动应用插 件,并且短信网关必须支持 wap 方式,只实现 wap 短信接口不能支持普通短信方式.

例如:中国移动 CMPP3,金迪,分众 短信接口使用情况如下:

短信插件启用:

1 实现了“普通短信接口”,则系统启动时加载.

2 只实现了“支持 wap 方式接口”,并且移动应用插件未启用,则系统启动时不加载.

3 实现了“普通短信接口”,并且也实现了“支持 wap 方式接口”,并且移动应用插件未启用,则支持普通短信 插件功能,不支持 wap 方式。

1.4.1. 接口说明

接口名称: interface AdapterMobileMessageManger

普通短信接口 interface AdapterMobileWapPushManager 支持 wap 方式接口,wappush url 不能为空,即消息回调地址不能为空,如果同时实现了普通短信接口,则实现普通短信功能。

1.4.2. 支持wap

/**
* 检测Wappush适配器是否可用
*/
public boolean isAvailability();
/**
* 短信网关的名称
*/
public String getName();
/**
* 发送Wappush消息
* @param messageId
* 消息的唯一标示
* @param srcPhone
* 短信的发送方手机号码
* @param destPhone
* 短信的接收方手机号码
* @param content
* 短信内容
* @param wappushURL
* wap push的url,如果为null,说明不发送wappush,采用普通短信
* @return true 发送成功
*/
public boolean sendMessage(int messageId, String srcPhone, String destPhone, String content,
    String wappushURL);
/**
* 发送Wappush消息
* @param messageId
* 消息的唯一标示
* @param srcPhone
* 短信的发送方手机号码
* @param destPhone
* 短信的接收方手机号码
* @param content
* 短信内容
* @param wappushURL
* wap push的url,如果为null,说明不发送wappush,如果同时实现了AdapterMobileMessageManger 采用普通短信
* @return true 发送成功
*/
public boolean sendMessage(int messageId, String srcPhone, Collection destPhone,
    String content, String wappushURL);
/**
* 是否支持群发
*
* @return true 支持
*/
public boolean isSupportQueueSend();

1.4.3. 普通方式

/**
* 检测短信适配器是否可用
* @return
*/
public boolean isAvailability();
/**
* 短信网关名称
* @return
*/
public String getName();
/**
* 发送短消息
*
* @param messageId
* 消息的唯一标示
* @param srcPhone
* 短信的发送方手机号码
* @param destPhone
* 短信的接收方手机号码
* @param content
* 短信内容
* @return true 发送成功
*/
public boolean sendMessage(int messageId, String srcPhone, String destPhone,
String content);
/**
* 发送短消息
*
* @param messageId
* 消息的唯一标示
* @param srcPhone
* 短信的发送方手机号码
* @param destPhone
* 短信的接收方手机号码
* @param content
* 短信内容
* @return true 发送成功
*/
public boolean sendMessage(int messageId, String srcPhone, Collection
    destPhone,
    String content);
/**
* 是否支持群发
* @return true 支持
*/
public boolean isSupportQueueSend();
/**
* 是否支持收短信
* @return
*/
public boolean isSupportRecive();
/**
* 从手机端返回到协同平台系统*
* @return
*/
public List recive();

1.4.4. 注册到系统

插 件 配 置 文 件 sms.xml , 在 这 个 文 件 中 找 到 smsAdapterManager.xml,spring Bean 在这里配置

<bean id="adapterMobileMessageManagerShortMessageKing"
    class="com.seeyon.v3x.mobile.adapter.king.AdapterMobileMessageManagerShortMessageKingImpl"/>

短信网关需要的配置参数统一在 sms.properties 里配置 如:

#M 短信王 的用户名

mobile.kingname =

#M 短信王 的密码

mobile.kingpassword =

系统启动日志:

MobileMessageManagerImpl:852 - 启动手机短信收发线程[短信王短信, ?]

代表短信接口启动成功

1.4.5. 代码示例

以短信王为例:

public class AdapterMobileMessageManagerShortMessageKingImpl implements
    AdapterMobileMessageManger {
    //标识名称
    public String getName() {
        return "短信王短信";
    }
    //单个短信发送
    public boolean sendMessage(int messageId, String srcPhone,
        String destPhone, String content) {
        //短信的内容不超过 60个字,小灵通号不超过 40个字。
        Sender sender = new Sender(kingName, kingPassword);
        String result = sender.massSend(destPhone, content, "", "");
        String success = getParameters(result).get("success");
        if (Strings.isBlank(success)) {
            return false;
        }
        String[] str = success.split(",");
        boolean successSend = false;
        for (int i = 0; i < str.length; i++) {
            if (str[i].equals(destPhone)) {
                successSend = true;
            }
        }
        return successSend;
    }
    //接收短信
    public List < MobileReciver > recive() {
        Sender sender = new Sender(kingName, kingPassword);
        String str = sender.readSms();
        String string = null;
        String srcphonenum = null;
        String srcPhone = null;
        String content = null;
        if (str.indexOf("&msg=") != str.indexOf("&dst=")) {
            string = str.substring(str.indexOf("&msg"), str.indexOf("&dst"));
            content = string.substring(string.indexOf("=") + 1);
        }
        if (str.indexOf("&src=") != str.indexOf("&msg=")) {
            srcphonenum = str.substring(str.indexOf("&src="), str.indexOf("&msg="));
            if (srcphonenum != null) {
                srcPhone = srcphonenum.substring(srcphonenum.indexOf("=") + 1);
            }
        }
        List < MobileReciver > list = new ArrayList < MobileReciver > ();
        if (content != null && srcPhone != null) {
            MobileReciver reciver = new MobileReciver();
            reciver.setContent(content);
            reciver.setSrcPhone(srcPhone);
            list.add(reciver);
        }
        return list;
    }
}

results matching ""

    No results matching ""