1.参考钉钉开发文档
钉钉开发文档:https://ding-doc.dingtalk.com/doc#/serverapi2/pgoxpy
2.开始设计思路
因为是在管理后台上进行添加,在手机钉钉端进行显示,后台同样也需要显示,所以做了两个controller,但只调用一个service
- 后台展示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);
}
}
- 手机端调用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次。
超出以上限制次数后,接口返回成功,但用户无法接收到。详细的限制说明,请参考“工作通知消息的限制”。
该接口是异步发送消息,接口返回成功并不表示用户一定会收到消息,需要通过“查询工作通知消息的发送结果”接口查询是否给用户发送成功。
消息类型和样例可参考消息类型文档。
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;
}
}