泛微E9消息接口说明

配置自定义消息供第三方调用

系统环境配置

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,用于发消息时传入,作为一类消息的标识

image-20210521220644944

image-20210521220711963

image-20210521220844974

新建消息类型

image-20210521220954226

image-20210521221031119image-20210521221046481

如果消息需要推送到企业微信、钉钉、云之家,需要将新建的消息类型在EM后台做关联

file_1587520109000.png

外部系统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();
}
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
泛微e9后端接口的创建流程主要包括以下几个步骤。 1.需求分析:根据实际业务需求,确定需要创建的后端接口的功能和目标,明确接口的输入参数、输出结果以及具体的业务逻辑。 2.接口设计:根据需求分析的结果,设计接口的名称、URL、请求方法(如GET、POST)、参数列表和返回结果的数据格式等。需要注意的是,接口的设计应该符合RESTful风格,并尽量遵循统一的命名规范。 3.编码实现:根据接口设计的结果,使用泛微e9的开发工具,如Flowline或者编写自定义Java代码,实现接口的具体功能。在编码过程中,需要考虑接口的安全性、性能优化以及异常处理等问题。 4.接口测试:编码完成后,进行接口的单元测试和集成测试,保证接口的功能正确性和稳定性。可以使用Postman等工具,发送不同类型的请求,验证接口的输入输出与预期是否一致。 5.文档编写:编写接口的详细文档,包括接口说明、参数列表、返回结果的结构和格式、示例请求和响应等内容。这些文档将被用于后续接口使用和维护的参考。 6.部署发布:将编码完成的接口部署到泛微e9的服务器或云平台上,并进行发布。确保接口可以在生产环境中正常访问和使用。 7.监控与维护:上线后,对接口进行监控和维护,定期检查接口的性能和稳定性,并及时修复接口中的bug和问题,保证接口的正常运行。 通过以上步骤的执行,可以成功创建一个泛微e9后端接口,实现业务需求并提供高质量的服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值