配置自定义消息供第三方调用
系统环境配置
1、执行sql
id 主键保证表中唯一,appid和代码中传入和appid一致,name 名称
sql示例:
INSERT INTO ECOLOGY_BIZ_EC(ID,APPID,NAME) VALUES('1','b5797216-f297-4c1d-9692-d183f6e95214','NC系统');
2、刷新OAsql缓存
chrome浏览器访问 OA地址/commcache/cacheMonitor.jsp界面,点击重启加载配置
3、web.xml修改
将EMFilter添加在SessionFilter之前(已经有了不需要再做修改)
<filter>
<filter-name>EMFilter</filter-name>
<filter-class>com.cloudstore.dev.api.service.EMFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EMFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>SessionFilter</filter-name>
<filter-class>com.cloudstore.dev.api.service.SessionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>SessionFilter</filter-name>
<url-pattern>/page/interfaces/*.jsp</url-pattern>
</filter-mapping>
4、RSA-0.0.1-SNAPSHOT.jar
在ecology系统代码目录中找到ecology/WEB-INF/lib/RSA-0.0.1-SNAPSHOT.jar 文件引入到第三方系统项目资源目录下。
配置消息来源
新建消息来源,生成消息code,用于发消息时传入,作为一类消息的标识
新建消息类型
如果消息需要推送到企业微信、钉钉、云之家,需要将新建的消息类型在EM后台做关联
外部系统java调用示例
package com.weavernorth.test;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import weaver.general.TimeUtil;
import weaver.rsa.security.RSA;
public class TestSendMsg {
public static void main(String[] args) {
try {
testRestful("http://27.191.191.64:8088"); // OA地址
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
}
}
/**
* APPID 指定一个UUID (请记住是指定一个UUID,作为第三方系统的唯一标识)
*/
private static final String APPID = "b5797216-f297-4c1d-9692-d183f6e95214";
/**
* 发送消息,参数封装
*
* @return
*/
public static Map<String, String> sendCustomMessageSingle() {
Map<String, String> map = new HashMap<>();
// 消息来源,新建消息来源获取code 请查看文档消息来源部分
map.put("code", "1172");
// userIdList参数 userIdList 接收人OA系统id
// lastNameList 接收人姓名(任选一个填入即可,以逗号分隔)
map.put("userIdList", "1");
// 接收人登录名
// map.put("loginIdList","zhangsan,wangwu" );
// 接收人编号
map.put("workCodeList", "WS01640,WS01641");
map.put("lastNameList", "张三,王五"); // 接收人姓名
// creater的值 创建人OA系统id
map.put("creater", "1");
/// 创建人登录名
// map.put("creater","zhangsan");
/// 创建人编号 /
// map.put("creater","WS01640");
//创建人姓名(对应接收人所传入的形式)
// map.put("creater","张三");
map.put("title", "OA测试消息提醒" + TimeUtil.getCurrentTimeString());
map.put("context", "这是消息内容" + TimeUtil.getCurrentTimeString());
map.put("linkUrl", "http://www.baidu.com");
map.put("linkMobileUrl", "http://www.baidu.com");
// map.put("targetId","559|id22"); //消息来源code +“|”+业务id 消息需要打上已处理标记
// map.put("bizState","0"); //0 表示消息初始状态是待处理 消息需要打上已处理标记
return map;
}
/**
* 将消息打上已处理标记,参数封装
*
* @return
*/
public static Map<String, String> alterCustomMessageSingle() {
Map<String, String> map = new HashMap<>();
// map.put("code","559"); //消息来源code(传了代表,code也要做为修改时where后面的条件)
map.put("targetId", "1172|id1");// 修改消息状态时所依据的条件,在消息发送时也需要插入,字符串拼接方式为业务id前加消息来源的“code|"
map.put("bizState", "1");// 待处理 0 已处理 1 已同意 2 已拒绝 3 已删除 27 已暂停 34 已撤销 35
map.put("userIdList", "1,3"); // 接收人OA系统id
// map.put("loginIdList","zhangsan,wangwu" ); //接收人登录名
// map.put("workCodeList","WS01640,WS01641"); //接收人编号
// map.put("lastNameList","张三,王五" ); //接收人姓名
return map;
}
/**
* 删除消息,参数封装
*
* @return
*/
public static Map<String, String> deleteCustomMessageSingle() {
Map<String, String> map = new HashMap<>();
// map.put("code","559"); //消息来源code(传了代表,code也要做为修改时where后面的条件)
map.put("targetId", "559|id22");// 修改消息状态时所依据的条件,在消息发送时也需要插入,字符串拼接方式为业务id前加消息来源的“code|"
map.put("bizState", "1");// 待处理 0 已处理 1 已同意 2 已拒绝 3 已删除 27 已暂停 34 已撤销 35
map.put("userIdList", "1,3"); // 接收人OA系统id
// map.put("loginIdList","zhangsan,wangwu" ); //接收人登录名
// map.put("workCodeList","WS01640,WS01641"); //接收人编号
// map.put("lastNameList","张三,王五" ); //接收人姓名
return map;
}
/**
* 通过获取到的token请求发消息,修改消息,删除消息接口
*
* @param address OA地址
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public static String testRestful(String address) throws NoSuchAlgorithmException, KeyManagementException {
Map<String, String> heads = new HashMap<>();
Map<String, Object> datas = testGetoken(address);
// ECOLOGY返回的token
String token = (String) (datas.get("token"));
// 封装参数到请求头
heads.put("appid", APPID);
heads.put("token", token);
heads.put("skipsession", "1");
// 调用ECOLOGY系统发消息接口,消息推送接口返回为true,代表消息成功加入缓存,实际消息是否发送成功,请查看OA后台消息推送日志,和EM消息日志
String data = post(address + "/api/ec/dev/message/sendCustomMessageSingle", sendCustomMessageSingle(), heads);
// 调用ECOLOGY系统修改消息接口,将消息打上已处理标记
// String data = post(address + "/api/ec/dev/message/alterCustomMessageSingle",alterCustomMessageSingle(), heads);
// 调用ECOLOGY系统删除消息接口,将消息删除
// String data = post(address + "/api/ec/dev/message/deleteCustomMessageSingle",deleteCustomMessageSingle(), heads);
System.out.println("testRestful:" + data);
return data;
}
/**
* 通过注册返回的OA系统公钥和秘钥获取token
*
* @param address OA地址
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public static Map<String, Object> testGetoken(String address)
throws NoSuchAlgorithmException, KeyManagementException {
Map<String, String> heads = new HashMap<>();
// 注册接口返回的secrit私钥和spk公钥可以在第一次调用后,第三方系统保存起来,之后调用可以不用再调用这个注册接口
Map<String, Object> datas = testRegist(address);
System.out.println(">>>>>>>获取公钥返回数据>>>>>>>" + datas);
// ECOLOGY返回的系统公钥
String spk = (String) (datas.get("spk"));
RSA rsa = new RSA();
// 对秘钥进行加密传输,防止篡改数据
String secret = rsa.encrypt(null, (String) (datas.get("secrit")), null, "utf-8", spk, false);
// 封装参数到请求头
heads.put("appid", APPID);
heads.put("secret", secret);
// 调用ECOLOGY系统接口进行注册
String data = post(address + "/api/ec/dev/auth/applytoken", null, heads);
System.out.println("=====获取token的返回数据=====" + data);
return JSONObject.parseObject(data, new TypeReference<Map<String, Object>>() {
});
}
/**
* 注册第三方系统到OA系统,第一次用APPID获取到公钥spk和私钥secret,第三方系统可以保存,下次不用在请求注册接口
*
* @param address OA地址
* @return
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public static Map<String, Object> testRegist(String address)
throws NoSuchAlgorithmException, KeyManagementException {
Map<String, String> heads = new HashMap<>();
// 获取当前异构系统RSA加密的公钥
String cpk = new RSA().getRSA_PUB();
// 封装参数到请求头
heads.put("appid", APPID);
heads.put("cpk", cpk);
// 调用ECOLOGY系统接口进行注册
String data = post(address + "/api/ec/dev/auth/regist", null, heads);
System.out.println("=====testRegist=====" + data);
return JSONObject.parseObject(data, new TypeReference<Map<String, Object>>() {
});
}
/**
* 此方法仅供参考,第三方系统可采用自己的方式调用http接口
*
* @param path 请求路径
* @param data 请求参数
* @return
*/
public static String post(String path, Map<String, String> params, Map<String, String> data) {
try {
String str = "";
// if (params != null) {
// StringBuilder stringBuilder = new StringBuilder("?");
// for (Map.Entry<String, String> entry : params.entrySet()) {
// stringBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
// }
// if (stringBuilder.length() > 1)
// path += stringBuilder.substring(0, stringBuilder.length() - 1);
// }
URL url = new URL(path);
// 打开和url之间的连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// PrintWriter out = null;
// 请求参数 编码为 utf-8
// 请求方式
conn.setRequestMethod("POST");
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
if (data != null)
for (Map.Entry<String, String> entry : data.entrySet())
conn.setRequestProperty(entry.getKey(), entry.getValue());
// 设置是否向httpUrlConnection输出,设置是否从httpUrlConnection读入,此外发送post请求必须设置这两个
// 最常用的Http请求无非是get和post,get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet,
// post与get的 不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。
conn.setDoOutput(true);
conn.setDoInput(true);
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
if (params != null)
out.write(mapToStr(params));
// 缓冲数据
out.flush();
out.close();
// 获取URLConnection对象对应的输入流
InputStream is = conn.getInputStream();
// 构造一个字符流缓存
BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));
String result = "";
while ((str = br.readLine()) != null) {
result = str;
}
// 关闭流
is.close();
// 断开连接,最好写上,disconnect是在底层tcp socket链接空闲时才切断。如果正在被其他线程使用就不切断。
// 固定多线程的话,如果不disconnect,链接会增多,直到收发不出信息。写上disconnect后正常一些。
conn.disconnect();
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 将Map转换成字符串参数,用于POST GET 请求
*
* @param map
* @return
*/
public static String mapToStr(Map<String, String> map) {
StringBuilder stringBuilder = new StringBuilder();
if (map != null) {
for (Map.Entry<String, String> entry : map.entrySet()) {
stringBuilder.append(entry.getKey());
if (entry.getValue() != null)
stringBuilder.append("=").append(entry.getValue());
stringBuilder.append("&");
}
}
if (stringBuilder.length() > 0)
return stringBuilder.substring(0, stringBuilder.length() - 1);
return null;
}
}
OA内部调用实例
新建消息
import com.cloudstore.dev.api.bean.MessageBean;
import com.cloudstore.dev.api.bean.MessageType;
import com.cloudstore.dev.api.util.Util_Message;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
MessageType messageType = MessageType.newInstance(121); // 消息来源(见文档第四点补充 必填)
Set<String> userIdList = new HashSet<>(); // 接收人id 必填
String title = "标题"; // 标题
String context = "内容"; // 内容
String linkUrl = "PC端链接"; // PC端链接
String linkMobileUrl = "移动端链接"; // 移动端链接
try {
MessageBean messageBean = Util_Message.createMessage(messageType, userIdList, title, context, linkUrl, linkMobileUrl);
messageBean.setCreater(1);// 创建人id
//message.setBizState("0");// 需要修改消息为已处理等状态时传入,表示消息最初状态为待处理
//messageBean.setTargetId("121|22"); //消息来源code +“|”+业务id需要修改消息为已处理等状态时传入
Util_Message.store(messageBean);
} catch (IOException e) {
e.printStackTrace();
}
修改消息
import com.cloudstore.dev.api.bean.MessageBean;
import com.cloudstore.dev.api.bean.MessageType;
import com.cloudstore.dev.api.util.Util_Message;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
try {
MessageBean messageBean = Util_Message.createMessage();
messageBean.setUserList(new HashSet<>());//接收人id
messageBean.setTargetId("121|22"); targetId code +“|”+业务id删除消息时所依据的条件
//bizState 业务状态 待处理 0 已处理 1 已同意 2 已拒绝 3 已删除 27 已暂停 34 已撤销 35
messageBean.setBizState("bizState");
//消息来源code(传了代表code也做为修改时的条件,默认不传)
//messageBean.setMessageType(MessageType.newInstance(121));
Util_Message.updateBizState(messageBean);
} catch (Exception e) {
e.printStackTrace();
}
删除消息
import com.cloudstore.dev.api.bean.MessageBean;
import com.cloudstore.dev.api.bean.MessageType;
import com.cloudstore.dev.api.util.Util_Message;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
try {
MessageBean messageBean = Util_Message.createMessage();
//接收人id
messageBean.setUserList(new HashSet<>());
//code + “|” + 业务id
messageBean.setTargetId("121|22");
//消息来源code(传了代表code也做为删除时的条件,默认不传)
//messageBean.setMessageType(MessageType.newInstance(121));
Util_Message.delMessageTargetid(messageBean);
} catch (Exception e) {
e.printStackTrace();
}