1.参考钉钉开发文档

钉钉开发文档:https://ding-doc.dingtalk.com/doc#/serverapi2/pgoxpy

2.开始设计思路

因为是在管理后台上进行添加,在手机钉钉端进行显示,后台同样也需要显示,所以做了两个controller,但只调用一个service

  1. 后台展示controller
package com.eastcom.info.controller;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.eastcom.common.controller.BaseController;
import com.eastcom.common.spring.BeanConverter;
import com.eastcom.common.utils.R;
import com.eastcom.common.validator.group.Insert;
import com.eastcom.info.domain.InfoPublishCheckDO;
import com.eastcom.info.domain.InfoPublishCreateVO;
import com.eastcom.info.domain.InfoPublishDO;
import com.eastcom.info.service.InfoPublishService;
import com.taobao.api.ApiException;

import java.util.List;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestParam;
import com.alibaba.fastjson.JSONObject;
import com.eastcom.common.utils.PageUtils;
import com.eastcom.common.utils.Query;
import io.swagger.annotations.ApiOperation;

@Controller
@RequestMapping("/info/ddinfo")
public class InfoPublishController extends BaseController {
	@Autowired
	private InfoPublishService service;
	
	@Autowired
	private BeanConverter beanConverter;
	
	
	@GetMapping()
	@RequiresPermissions("info:ddinfo:ddinfo")
	String Ddinfo(Model model){
	    model.addAttribute(session_user_flag, JSONObject.toJSON(getUser()).toString());
	    return "info/infoPublishList";
	}
	
	@ResponseBody
	@GetMapping("/list")
	@RequiresPermissions("info:ddinfo:ddinfo")
	@ApiOperation(value = "获取信息列表", notes = "offset,limit分页参数", tags = { "" })
	public PageUtils list(@RequestParam Map<String, Object> params ,Integer offset , Integer limit){
		//查询列表数据
        Query query = new Query(params);
		List<InfoPublishDO> ddinfoList = service.list(query);
		int total = service.count(query);
		PageUtils pageUtils = new PageUtils(ddinfoList, total);
		return pageUtils;
	}
	


	
	@GetMapping("/add")
	@RequiresPermissions("info:ddinfo:add")
	String add(){
	    return "info/infoPublishAdd";
	}
	
	/*
	 * 发布工作通知
	 */
	@ResponseBody
	@PostMapping("/save")
	@ApiOperation(value = "发布信息", notes = "infoContent等必填,createTime(形如2020-03-05)等选填", tags = { "" })
	public R createInfo(@Validated(Insert.class) InfoPublishCreateVO iv ,HttpServletRequest request, BindingResult result) throws ApiException, Exception {
		validate(result);
		InfoPublishDO ip = new InfoPublishDO();
		beanConverter.convert(iv, ip);
		ip.setCreateUserid(getUser().getName());
		return service.createInfo(ip,request);
	}
	
	/*
	 * 查询工作通知消息的发送进度
	 */
	
	@PostMapping("/checkInfo")
	@ResponseBody
	@ApiOperation(value = "查询工作通知消息的发送进度", notes = "id+createUserid+taskId等必填", tags = { "" })
	public R checkInfo(@RequestBody InfoPublishCheckDO ic, HttpServletRequest request) throws ApiException {
		InfoPublishDO ip = new InfoPublishDO();
		beanConverter.convert(ic, ip);
		
		getUser().setDingid("393630295226781623");
		String dd = getUser().getDingid();
		ic.setCreateUserid(dd);
		
		return service.checkInfo(ip, request);
	}
	
}
  1. 手机端调用controller
package com.eastcom.info.controller;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.eastcom.common.controller.BaseController;
import com.eastcom.common.utils.R;
import com.eastcom.info.domain.InfoPublishDO;
import com.eastcom.info.service.InfoPublishService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Controller
@RequestMapping("/info/ddinfo")
@Api(tags = "info-个人工作台-通知公告")
public class InfoPublishDdController extends BaseController {
	@Autowired
	private InfoPublishService service;
	

	//获取工作通知列表
	@PostMapping("/getInfoList")
	@ResponseBody
	@ApiOperation(value = "获取工作通知列表", notes = "", tags = { "" })
	public R getInfoList(@RequestBody InfoPublishDO data, HttpServletRequest request) {		
		return R.ok().put("data", service.getInfoList(data, request));
	}
	
	
	@PostMapping("/getInfo")
	@ResponseBody
	@ApiOperation(value = "获取单个信息详情", notes = "id", tags = { "" })
	public R getInfo(@RequestBody Map<String, String> map, HttpServletRequest request) {
		InfoPublishDO data = service.getInfo(map.get("id"));
		return R.ok().put("data", data);
	}
}

3.被调用的service层

package com.eastcom.info.service;

import javax.servlet.http.HttpServletRequest;

import com.eastcom.common.utils.R;
import com.eastcom.info.domain.InfoPublishDO;
import com.taobao.api.ApiException;

import java.util.List;
import java.util.Map;

public interface InfoPublishService {

	// 发布信息
	public R createInfo(InfoPublishDO ip, HttpServletRequest request) throws ApiException, Exception;

	// 获取信息
	public InfoPublishDO getInfo(String id);

	//获取全部通知
	public List<InfoPublishDO> getInfoList(InfoPublishDO data, HttpServletRequest request);
	
	//获取全部通知
	public List<InfoPublishDO> list(Map<String, Object> map);

	public int count(Map<String, Object> map);

	R checkInfo(InfoPublishDO ip, HttpServletRequest request) throws ApiException;

}

4.serviceImpl层

package com.eastcom.info.service.impl;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.dingtalk.api.request.OapiMessageCorpconversationGetsendprogressRequest;
import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
import com.dingtalk.api.response.OapiMessageCorpconversationGetsendprogressResponse;
import com.eastcom.common.utils.R;
import com.eastcom.info.dao.InfoPublishDao;
import com.eastcom.info.domain.InfoPublishDO;
import com.eastcom.info.service.InfoPublishService;
import com.eastcom.system.service.DdService;
import com.taobao.api.ApiException;

@Service
public class InfoPublishServiceImpl implements InfoPublishService {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private InfoPublishDao dao;

	@Autowired
	private DdService ddService;

	@Value("${dd.agentId}")
	private Long agentId;

	private static final String CREATE_INFO_URL = "https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2";
	private static final String CHECK_INFO_URL = "https://oapi.dingtalk.com/topapi/message/corpconversation/getsendprogress";



	@Override
	public List<InfoPublishDO> list(Map<String, Object> map) {
		return dao.list(map);
	}

	@Override
	public int count(Map<String, Object> map) {
		return dao.count(map);
	}
	
	@Override
	public InfoPublishDO getInfo(String id) {
		// TODO Auto-generated method stub
		return dao.getInfo(id);
	}

	/*信息发布逻辑:
	1,先入库,成功返回任务id
	2,推送DD,
	*/
	@Override
	public R createInfo(InfoPublishDO ip, HttpServletRequest request) throws ApiException, Exception {
		if(StringUtils.isEmpty(agentId)){
			return R.error("钉钉应用未配置");
		}
		dao.createInfoPublish(ip);
		DingTalkClient client = new DefaultDingTalkClient(CREATE_INFO_URL);

		OapiMessageCorpconversationAsyncsendV2Request req = new OapiMessageCorpconversationAsyncsendV2Request();
		// 传入的是员工的钉钉号
		/*req.setUseridList("393630295226781623"); */
		// 申请的应用AgentId
		req.setAgentId(agentId);
		// true为全体员工
		req.setToAllUser(true);
		OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
		// 消息类型
		msg.setOa(new OapiMessageCorpconversationAsyncsendV2Request.OA());
		msg.getOa().setMessageUrl(ddService.getHomeUrl(request)+"#/pages/mywork/notice/notice_detail?id="+ip.getId());
		msg.getOa().setHead(new OapiMessageCorpconversationAsyncsendV2Request.Head());
		msg.getOa().getHead().setText("head");
		msg.getOa().setBody(new OapiMessageCorpconversationAsyncsendV2Request.Body());
		msg.getOa().getBody().setTitle(ip.getInfoTitle());
		msg.getOa().getBody().setContent(ip.getInfoContent().substring(0,25)+"......");
		msg.getOa().getBody().setAuthor(ip.getCreateUserid());
		msg.setMsgtype("oa");
		req.setMsg(msg);
		

		try {
			OapiMessageCorpconversationAsyncsendV2Response response = client.execute(req, ddService.getAccessToken());
				logger.debug(req.getMsg());
			JSONObject res = JSON.parseObject(req.getMsg());
			ip.setTaskId((Long) res.get("task_id"));
			return R.ok();
		} catch (ApiException e) {
			logger.error(e.getMessage());
			return R.error(e.getMessage());
		}
	}

	/*
	 * 查询工作通知消息的发送进度
	 */
	@Override
	public R checkInfo(InfoPublishDO ip, HttpServletRequest request) throws ApiException {
		DingTalkClient client = new DefaultDingTalkClient(CHECK_INFO_URL);
		OapiMessageCorpconversationGetsendprogressRequest res  = new OapiMessageCorpconversationGetsendprogressRequest();
		res.setAgentId(agentId);
		res.setTaskId(ip.getTaskId());
		
		try {
			OapiMessageCorpconversationGetsendprogressResponse response = client.execute(res, ddService.getAccessToken());
			return R.ok();
		} catch (ApiException e) {
			logger.error(e.getMessage());
			return R.error(e.getMessage());
		}
	}

	@Override
	public List<InfoPublishDO> getInfoList(InfoPublishDO data, HttpServletRequest request) {
		// TODO Auto-generated method stub
		return dao.getInfoList(data);
	}

}

注意事项

发送工作通知消息需要注意以下事项:

同一个应用相同消息的内容同一个用户一天只能接收一次。
同一个应用给同一个用户发送消息,企业内部开发方式一天不得超过500次。
通过设置to_all_user参数全员推送消息,一天最多3次。
超出以上限制次数后,接口返回成功,但用户无法接收到。详细的限制说明,请参考“工作通知消息的限制”。
该接口是异步发送消息,接口返回成功并不表示用户一定会收到消息,需要通过“查询工作通知消息的发送结果”接口查询是否给用户发送成功。
消息类型和样例可参考消息类型文档。

钉钉工作台发送自定义通知java 钉钉工作通知api_钉钉工作台发送自定义通知java

5.三个实体类

package com.eastcom.info.domain;

import java.io.Serializable;

import javax.validation.constraints.NotNull;

import com.eastcom.common.validator.group.Insert;

public class InfoPublishCheckDO implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private String id;
	//信息内容
	@NotNull(message = "信息内容不能为空", groups = Insert.class)
	private String infoContent;
	
	private String infoTitle;
	//发起人
	private String createUserid;
	//创建时间
	private String createTime;
	//创建的发送任务id
	private Long taskId;


	public Long getTaskId() {
		return taskId;
	}
	public void setTaskId(Long taskId) {
		this.taskId = taskId;
	}
	public String getId() {
		return id;
	}
	public String getInfoTitle() {
		return infoTitle;
	}
	public void setInfoTitle(String infoTitle) {
		this.infoTitle = infoTitle;
	}
	public void setId(String id) {
		this.id = id;
	}
	
	public String getInfoContent() {
		return infoContent;
	}
	public void setInfoContent(String infoContent) {
		this.infoContent = infoContent;
	}
	
	public String getCreateUserid() {
		return createUserid;
	}
	public void setCreateUserid(String createUserid) {
		this.createUserid = createUserid;
	}
	public String getCreateTime() {
		return createTime;
	}
	public void setCreateTime(String createTime) {
		this.createTime = createTime;
	}
	
	
	
	
}
package com.eastcom.info.domain;

import java.io.Serializable;

import javax.validation.constraints.NotNull;

import com.eastcom.common.validator.group.Insert;

public class InfoPublishCreateVO implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private String id;
	//信息内容
	@NotNull(message = "信息内容不能为空", groups = Insert.class)
	private String infoContent;
	
	private String infoTitle;
	//发起人
	private String createUserid;
	//创建时间
	private String createTime;
	//private String[] deliverUserIds;
	
	public String getId() {
		return id;
	}
	public String getInfoTitle() {
		return infoTitle;
	}
	public void setInfoTitle(String infoTitle) {
		this.infoTitle = infoTitle;
	}
	public void setId(String id) {
		this.id = id;
	}
	
	public String getInfoContent() {
		return infoContent;
	}
	public void setInfoContent(String infoContent) {
		this.infoContent = infoContent;
	}
	
	public String getCreateUserid() {
		return createUserid;
	}
	public void setCreateUserid(String createUserid) {
		this.createUserid = createUserid;
	}
	public String getCreateTime() {
		return createTime;
	}
	public void setCreateTime(String createTime) {
		this.createTime = createTime;
	}
	
	
	
	
}
package com.eastcom.info.domain;

import java.io.Serializable;

import javax.validation.constraints.NotNull;

import com.eastcom.common.validator.group.Insert;

public class InfoPublishDO implements Serializable {
	private static final long serialVersionUID = 1L;

	private String id;
	// 信息内容
	@NotNull(message = "信息内容不能为空", groups = Insert.class)
	private String infoContent;

	private String infoTitle;
	// 发起人
	private String createUserid;
	// 创建时间
	private String createTime;
	// 创建的发送任务id
	private Long taskId;

	public Long getTaskId() {
		return taskId;
	}

	public void setTaskId(Long taskId) {
		this.taskId = taskId;
	}

	// 任务执行状态,0=未开始,1=处理中,2=处理完毕
	private String status;

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getId() {
		return id;
	}

	public String getInfoTitle() {
		return infoTitle;
	}

	public void setInfoTitle(String infoTitle) {
		this.infoTitle = infoTitle;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getInfoContent() {
		return infoContent;
	}

	public void setInfoContent(String infoContent) {
		this.infoContent = infoContent;
	}

	public String getCreateUserid() {
		return createUserid;
	}

	public void setCreateUserid(String createUserid) {
		this.createUserid = createUserid;
	}

	public String getCreateTime() {
		return createTime;
	}

	public void setCreateTime(String createTime) {
		this.createTime = createTime;
	}

}