注册回调,暂时少验证包

This commit is contained in:
jinqiming 2020-11-03 17:36:34 +08:00
parent ee0a0dfbcc
commit 248d87f637
19 changed files with 1319 additions and 3 deletions

View File

@ -0,0 +1,73 @@
package com.snow.web.controller.dingtalk;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2020/11/3 17:11
*/
@RestController
@Slf4j
public class DingTalkCallBack {
/**
* 钉钉回调
* @param signature
* @param timestamp
* @param nonce
* @param body
* @return
*/
@PostMapping(value = "/dingTalkCallBack")
public Object dingCallback(
@RequestParam(value = "signature") String signature,
@RequestParam(value = "timestamp") Long timestamp,
@RequestParam(value = "nonce") String nonce,
@RequestBody(required = false) JSONObject body
) {
String params = "signature:" + signature + " timestamp:" + timestamp + " nonce:" + nonce + " body:" + body;
try {
log.info("begin callback:" + params);
DingTalkEncryptor dingTalkEncryptor = new DingTalkEncryptor(Constant.TOKEN, Constant.ENCODING_AES_KEY, Constant.SUITE_KEY);
// 从post请求的body中获取回调信息的加密数据进行解密处理
String encrypt = body.getString("encrypt");
String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp.toString(), nonce, encrypt);
JSONObject callBackContent = JSON.parseObject(plainText);
// 根据回调事件类型做不同的业务处理
String eventType = callBackContent.getString("EventType");
if (EVENT_CHECK_CREATE_SUITE_URL.equals(eventType)) {
log.info("验证新创建的回调URL有效性: " + plainText);
} else if (EVENT_CHECK_UPADTE_SUITE_URL.equals(eventType)) {
log.info("验证更新回调URL有效性: " + plainText);
} else if (EVENT_SUITE_TICKET.equals(eventType)) {
// suite_ticket用于用签名形式生成accessToken(访问钉钉服务端的凭证)需要保存到应用的db
// 钉钉会定期向本callback url推送suite_ticket新值用以提升安全性
// 应用在获取到新的时值时保存db成功后返回给钉钉success加密串如本demo的return
log.info("应用suite_ticket数据推送: " + plainText);
} else if (EVENT_TMP_AUTH_CODE.equals(eventType)) {
// 本事件应用应该异步进行授权开通企业的初始化目的是尽最大努力快速返回给钉钉服务端用以提升企业管理员开通应用体验
// 即使本接口没有收到数据或者收到事件后处理初始化失败都可以后续再用户试用应用时从前端获取到corpId并拉取授权企业信息进而初始化开通及企业
log.info("企业授权开通应用事件: " + plainText);
} else {
// 其他类型事件处理
}
// 返回success的加密信息表示回调处理成功
return dingTalkEncryptor.getEncryptedMap("success", timestamp, nonce);
} catch (Exception e) {
//失败的情况应用的开发者应该通过告警感知并干预修复
log.error("process callback fail." + params, e);
return "fail";
}
}
}

View File

@ -0,0 +1,126 @@
package com.snow.web.controller.system;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.snow.common.annotation.Log;
import com.snow.common.enums.BusinessType;
import com.snow.system.domain.DingtalkCallBack;
import com.snow.system.service.IDingtalkCallBackService;
import com.snow.common.core.controller.BaseController;
import com.snow.common.core.domain.AjaxResult;
import com.snow.common.utils.poi.ExcelUtil;
import com.snow.common.core.page.TableDataInfo;
/**
* 回调事件Controller
*
* @author qimingjin
* @date 2020-11-02
*/
@Controller
@RequestMapping("/system/back")
public class DingtalkCallBackController extends BaseController
{
private String prefix = "system/back";
@Autowired
private IDingtalkCallBackService dingtalkCallBackService;
@RequiresPermissions("system:back:view")
@GetMapping()
public String back()
{
return prefix + "/back";
}
/**
* 查询回调事件列表
*/
@RequiresPermissions("system:back:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(DingtalkCallBack dingtalkCallBack)
{
startPage();
List<DingtalkCallBack> list = dingtalkCallBackService.selectDingtalkCallBackList(dingtalkCallBack);
return getDataTable(list);
}
/**
* 导出回调事件列表
*/
@RequiresPermissions("system:back:export")
@Log(title = "回调事件", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(DingtalkCallBack dingtalkCallBack)
{
List<DingtalkCallBack> list = dingtalkCallBackService.selectDingtalkCallBackList(dingtalkCallBack);
ExcelUtil<DingtalkCallBack> util = new ExcelUtil<DingtalkCallBack>(DingtalkCallBack.class);
return util.exportExcel(list, "back");
}
/**
* 新增回调事件
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* 新增保存回调事件
*/
@RequiresPermissions("system:back:add")
@Log(title = "回调事件", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(DingtalkCallBack dingtalkCallBack)
{
return toAjax(dingtalkCallBackService.insertDingtalkCallBack(dingtalkCallBack));
}
/**
* 修改回调事件
*/
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap mmap)
{
DingtalkCallBack dingtalkCallBack = dingtalkCallBackService.selectDingtalkCallBackById(id);
mmap.put("dingtalkCallBack", dingtalkCallBack);
return prefix + "/edit";
}
/**
* 修改保存回调事件
*/
@RequiresPermissions("system:back:edit")
@Log(title = "回调事件", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(DingtalkCallBack dingtalkCallBack)
{
return toAjax(dingtalkCallBackService.updateDingtalkCallBack(dingtalkCallBack));
}
/**
* 删除回调事件
*/
@RequiresPermissions("system:back:remove")
@Log(title = "回调事件", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(dingtalkCallBackService.deleteDingtalkCallBackByIds(ids));
}
}

View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('新增回调事件')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-back-add">
<div class="form-group">
<label class="col-sm-3 control-label">回调名称:</label>
<div class="col-sm-8">
<input name="callBackName" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">加解密token</label>
<div class="col-sm-8">
<input name="token" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">数据加密密钥:</label>
<div class="col-sm-8">
<input name="aesKey" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">接收事件回调的url</label>
<div class="col-sm-8">
<input name="url" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">app_key</label>
<div class="col-sm-8">
<input name="appKey" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">app_secret</label>
<div class="col-sm-8">
<input name="appSecret" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">通讯录事件回调:</label>
<div class="col-sm-8" th:with="type=${@dict.getType('address_book')}">
<label th:each="dict : ${type}" class="check-box">
<input name="eventName" type="checkbox" th:value="${dict.dictValue}" th:text="${dict.dictLabel}">
</label>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "system/back"
$("#form-back-add").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-back-add').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('回调事件列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>回调名称:</label>
<input type="text" name="callBackName"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="system:back:add">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="system:back:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="system:back:remove">
<i class="fa fa-remove"></i> 删除
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="system:back:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('system:back:edit')}]];
var removeFlag = [[${@permission.hasPermi('system:back:remove')}]];
var prefix = ctx + "system/back";
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "回调事件",
columns: [{
checkbox: true
},
{
field: 'id',
title: 'ID',
visible: false
},
/* {
field: 'token',
title: 'token'
},
{
field: 'aesKey',
title: '数据加密密钥'
},*/
{
field: 'url',
title: '回调url'
},
{
field: 'callBackName',
title: '回调名称'
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
};
$.table.init(options);
});
</script>
</body>
</html>

View File

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('修改回调事件')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-back-edit" th:object="${dingtalkCallBack}">
<input name="id" th:field="*{id}" type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">回调名称:</label>
<div class="col-sm-8">
<input name="callBackName" th:field="*{callBackName}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">加解密token</label>
<div class="col-sm-8">
<input name="token" th:field="*{token}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">数据加密密钥:</label>
<div class="col-sm-8">
<input name="aesKey" th:field="*{aesKey}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">事件回调url</label>
<div class="col-sm-8">
<input name="url" th:field="*{url}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">app_key</label>
<div class="col-sm-8">
<input name="appKey" th:field="*{appKey}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">app_secret</label>
<div class="col-sm-8">
<input name="appSecret" th:field="*{appSecret}" class="form-control" type="text">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "system/back";
$("#form-back-edit").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-back-edit').serialize());
}
}
</script>
</body>
</html>

View File

@ -11,7 +11,12 @@ public enum DingTalkListenerType {
DEPARTMENT_UPDATE(2, "部门更新"), DEPARTMENT_UPDATE(2, "部门更新"),
DEPARTMENT_DELETED(3, "部门删除"), DEPARTMENT_DELETED(3, "部门删除"),
USER_CREATED(4,"用户创建"); USER_CREATED(4,"用户创建"),
CALL_BACK_REGISTER(10, "回调注册"),
;
private final Integer code; private final Integer code;
private final String info; private final String info;

View File

@ -46,4 +46,9 @@ public class BaseConstantUrl {
* 更新待办 * 更新待办
*/ */
public static final String WORK_RECORD_UPDATE="https://oapi.dingtalk.com/topapi/workrecord/update"; public static final String WORK_RECORD_UPDATE="https://oapi.dingtalk.com/topapi/workrecord/update";
/**
* 注册回调
*/
public static final String REGISTER_CALL_BACK="https://oapi.dingtalk.com/call_back/register_call_back";
} }

View File

@ -0,0 +1,27 @@
package com.snow.dingtalk.listener;
import com.alibaba.fastjson.JSON;
import com.snow.common.utils.spring.SpringUtils;
import com.snow.dingtalk.service.impl.CallBackServiceImpl;
import com.snow.system.domain.DingtalkCallBack;
import com.snow.system.event.SyncEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2020/11/3 17:05
*/
@Component
@Slf4j
public class CallBackService implements ISyncDingTalkInfo {
private CallBackServiceImpl departmentService=SpringUtils.getBean("callBackServiceImpl");
@Override
public void syncDingTalkInfoEvent(SyncEvent syncEvent) {
log.info("调用创建钉钉注册回调传入的原始参数:{}"+JSON.toJSONString(syncEvent));
departmentService.registerCallBack((DingtalkCallBack) syncEvent.getT());
}
}

View File

@ -3,7 +3,6 @@ package com.snow.dingtalk.listener;
import com.snow.common.enums.DingTalkListenerType; import com.snow.common.enums.DingTalkListenerType;
import com.snow.system.event.SyncEvent; import com.snow.system.event.SyncEvent;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/** /**
* @author qimingjin * @author qimingjin
@ -19,12 +18,19 @@ public class SyncDingTalkInfoFactory {
public ISyncDingTalkInfo getSyncDingTalkService(SyncEvent syncEvent){ public ISyncDingTalkInfo getSyncDingTalkService(SyncEvent syncEvent){
Integer eventType = syncEvent.getEventType(); Integer eventType = syncEvent.getEventType();
if(eventType.equals(DingTalkListenerType.DEPARTMENT_CREATE.getCode())){ if(eventType.equals(DingTalkListenerType.DEPARTMENT_CREATE.getCode())){
return new DepartmentCreateEventService(); return new DepartmentCreateEventService();
} }
else if(eventType.equals(DingTalkListenerType.USER_CREATED.getCode())){ else if(eventType.equals(DingTalkListenerType.USER_CREATED.getCode())){
return new UserCreateEventService(); return new UserCreateEventService();
}else { }
else if(eventType.equals(DingTalkListenerType.CALL_BACK_REGISTER.getCode())){
return new CallBackService();
}
else {
throw new RuntimeException("不存在的监听类型"); throw new RuntimeException("不存在的监听类型");
} }

View File

@ -0,0 +1,16 @@
package com.snow.dingtalk.service;
import com.snow.system.domain.DingtalkCallBack;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2020/11/3 11:18
*/
public interface CallBackService {
/**
* 注册事件
*/
void registerCallBack(DingtalkCallBack dingtalkCallBack);
}

View File

@ -0,0 +1,92 @@
package com.snow.dingtalk.service.impl;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import com.alibaba.fastjson.JSON;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiCallBackRegisterCallBackRequest;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.response.OapiCallBackRegisterCallBackResponse;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.snow.common.constant.Constants;
import com.snow.common.utils.StringUtils;
import com.snow.dingtalk.common.BaseConstantUrl;
import com.snow.dingtalk.common.BaseService;
import com.snow.dingtalk.service.CallBackService;
import com.snow.system.domain.DingtalkCallBack;
import com.taobao.api.ApiException;
import org.springframework.stereotype.Service;
import java.util.Arrays;
/**
* @author qimingjin
* @Title:
* @Description:
* @date 2020/11/3 11:19
*/
@Service
public class CallBackServiceImpl extends BaseService implements CallBackService {
public static final String TOKEN="call_back_dingtalk_token";
@Override
public void registerCallBack(DingtalkCallBack dingtalkCallBack) {
DingTalkClient client = new DefaultDingTalkClient(BaseConstantUrl.REGISTER_CALL_BACK);
OapiCallBackRegisterCallBackRequest request = new OapiCallBackRegisterCallBackRequest();
request.setUrl(dingtalkCallBack.getUrl());
request.setAesKey(dingtalkCallBack.getAesKey());
request.setToken(dingtalkCallBack.getToken());
request.setCallBackTag(dingtalkCallBack.getEventNameList());
try {
OapiCallBackRegisterCallBackResponse response = client.execute(request,getCallBackDingTalkToken(dingtalkCallBack));
if(response.getErrcode()==0){
syncDingTalkErrorOperLog(BaseConstantUrl.REGISTER_CALL_BACK,response.getMessage(),"registerCallBack()", JSON.toJSONString(request));
}else {
//记录获取token失败日志
syncDingTalkErrorOperLog(BaseConstantUrl.REGISTER_CALL_BACK,response.getErrmsg(),"registerCallBack()", JSON.toJSONString(request));
}
} catch (ApiException e) {
syncDingTalkErrorOperLog(BaseConstantUrl.REGISTER_CALL_BACK,e.getMessage(),"registerCallBack()", JSON.toJSONString(request));
e.printStackTrace();
}
}
/**
* 获取token
* @return
*/
public String getCallBackDingTalkToken(DingtalkCallBack dingtalkCallBack){
//创建缓存缓存默认是7100S
TimedCache<String, String> timedCache = CacheUtil.newTimedCache(7100);
if(StringUtils.isEmpty(timedCache.get(TOKEN))){
DefaultDingTalkClient client = new DefaultDingTalkClient(BaseConstantUrl.GET_TOKEN_URL);
OapiGettokenRequest request = new OapiGettokenRequest();
request.setAppkey(dingtalkCallBack.getAppKey());
request.setAppsecret(dingtalkCallBack.getAppSecret());
request.setHttpMethod(Constants.GET);
try {
OapiGettokenResponse response = client.execute(request);
if(response.getErrcode()==0){
timedCache.put(TOKEN,response.getAccessToken());
syncDingTalkErrorOperLog(BaseConstantUrl.GET_TOKEN_URL,response.getMessage(),"getCallBackDingTalkToken()", JSON.toJSONString(request));
return response.getAccessToken();
}else {
//记录获取token失败日志
syncDingTalkErrorOperLog(BaseConstantUrl.GET_TOKEN_URL,response.getErrmsg(),"getCallBackDingTalkToken()", JSON.toJSONString(request));
return null;
}
} catch (ApiException e) {
syncDingTalkErrorOperLog(BaseConstantUrl.GET_TOKEN_URL,e.getMessage(),"getCallBackDingTalkToken()",JSON.toJSONString(request));
e.printStackTrace();
}
return null;
}else {
return timedCache.get(TOKEN);
}
}
}

View File

@ -0,0 +1,148 @@
package com.snow.system.domain;
import com.snow.common.annotation.Excel;
import com.snow.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.List;
/**
* 回调事件对象 dingtalk_call_back
*
* @author qimingjin
* @date 2020-11-02
*/
public class DingtalkCallBack extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** ID */
private Long id;
/** 加解密需要用到的tokenISV(服务提供商)推荐使用注册套件时填写的token普通企业可以随机填写 */
@Excel(name = "加解密需要用到的tokenISV(服务提供商)推荐使用注册套件时填写的token普通企业可以随机填写")
private String token;
/** 数据加密密钥。用于回调数据的加密长度固定为43个字符从a-z, A-Z, 0-9共62个字符中选取,您可以随机生成ISV(服务提供商)推荐使用注册套件时填写的EncodingAESKey */
@Excel(name = "数据加密密钥。用于回调数据的加密长度固定为43个字符从a-z, A-Z, 0-9共62个字符中选取,您可以随机生成ISV(服务提供商)推荐使用注册套件时填写的EncodingAESKey")
private String aesKey;
/** 接收事件回调的url必须是公网可以访问的url地址 */
@Excel(name = "接收事件回调的url必须是公网可以访问的url地址")
private String url;
/** app_key */
private String appKey;
/** app_secret */
private String appSecret;
/** 删除表示 */
private Integer delFlag;
/** 回调名称 */
@Excel(name = "回调名称")
private String callBackName;
private List<String> eventNameList;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setToken(String token)
{
this.token = token;
}
public String getToken()
{
return token;
}
public void setAesKey(String aesKey)
{
this.aesKey = aesKey;
}
public String getAesKey()
{
return aesKey;
}
public void setUrl(String url)
{
this.url = url;
}
public String getUrl()
{
return url;
}
public void setAppKey(String appKey)
{
this.appKey = appKey;
}
public String getAppKey()
{
return appKey;
}
public void setAppSecret(String appSecret)
{
this.appSecret = appSecret;
}
public String getAppSecret()
{
return appSecret;
}
public void setDelFlag(Integer delFlag)
{
this.delFlag = delFlag;
}
public Integer getDelFlag()
{
return delFlag;
}
public void setCallBackName(String callBackName)
{
this.callBackName = callBackName;
}
public String getCallBackName()
{
return callBackName;
}
public List<String> getEventNameList() {
return eventNameList;
}
public void setEventNameList(List<String> eventNameList) {
this.eventNameList = eventNameList;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("token", getToken())
.append("aesKey", getAesKey())
.append("url", getUrl())
.append("appKey", getAppKey())
.append("appSecret", getAppSecret())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("callBackName", getCallBackName())
.toString();
}
}

View File

@ -0,0 +1,96 @@
package com.snow.system.domain;
import com.snow.common.annotation.Excel;
import com.snow.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 事件表对象 dingtalk_call_back_event
*
* @author snow
* @date 2020-11-03
*/
public class DingtalkCallBackEvent extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** null */
private Integer id;
/** null */
@Excel(name = "null")
private String eventName;
/** null */
@Excel(name = "null")
private Long callBanckId;
/** null */
@Excel(name = "null")
private String eventDesc;
/** null */
private Long delFlag;
public void setId(Integer id)
{
this.id = id;
}
public Integer getId()
{
return id;
}
public void setEventName(String eventName)
{
this.eventName = eventName;
}
public String getEventName()
{
return eventName;
}
public void setCallBanckId(Long callBanckId)
{
this.callBanckId = callBanckId;
}
public Long getCallBanckId()
{
return callBanckId;
}
public void setEventDesc(String eventDesc)
{
this.eventDesc = eventDesc;
}
public String getEventDesc()
{
return eventDesc;
}
public void setDelFlag(Long delFlag)
{
this.delFlag = delFlag;
}
public Long getDelFlag()
{
return delFlag;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("eventName", getEventName())
.append("callBanckId", getCallBanckId())
.append("eventDesc", getEventDesc())
.append("delFlag", getDelFlag())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateTime", getUpdateTime())
.append("updateBy", getUpdateBy())
.toString();
}
}

View File

@ -0,0 +1,61 @@
package com.snow.system.mapper;
import java.util.List;
import com.snow.system.domain.DingtalkCallBackEvent;
/**
* 事件表Mapper接口
*
* @author snow
* @date 2020-11-03
*/
public interface DingtalkCallBackEventMapper
{
/**
* 查询事件表
*
* @param id 事件表ID
* @return 事件表
*/
public DingtalkCallBackEvent selectDingtalkCallBackEventById(Integer id);
/**
* 查询事件表列表
*
* @param dingtalkCallBackEvent 事件表
* @return 事件表集合
*/
public List<DingtalkCallBackEvent> selectDingtalkCallBackEventList(DingtalkCallBackEvent dingtalkCallBackEvent);
/**
* 新增事件表
*
* @param dingtalkCallBackEvent 事件表
* @return 结果
*/
public int insertDingtalkCallBackEvent(DingtalkCallBackEvent dingtalkCallBackEvent);
/**
* 修改事件表
*
* @param dingtalkCallBackEvent 事件表
* @return 结果
*/
public int updateDingtalkCallBackEvent(DingtalkCallBackEvent dingtalkCallBackEvent);
/**
* 删除事件表
*
* @param id 事件表ID
* @return 结果
*/
public int deleteDingtalkCallBackEventById(Integer id);
/**
* 批量删除事件表
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public int deleteDingtalkCallBackEventByIds(String[] ids);
}

View File

@ -0,0 +1,61 @@
package com.snow.system.mapper;
import java.util.List;
import com.snow.system.domain.DingtalkCallBack;
/**
* 回调事件Mapper接口
*
* @author qimingjin
* @date 2020-11-02
*/
public interface DingtalkCallBackMapper
{
/**
* 查询回调事件
*
* @param id 回调事件ID
* @return 回调事件
*/
public DingtalkCallBack selectDingtalkCallBackById(Long id);
/**
* 查询回调事件列表
*
* @param dingtalkCallBack 回调事件
* @return 回调事件集合
*/
public List<DingtalkCallBack> selectDingtalkCallBackList(DingtalkCallBack dingtalkCallBack);
/**
* 新增回调事件
*
* @param dingtalkCallBack 回调事件
* @return 结果
*/
public int insertDingtalkCallBack(DingtalkCallBack dingtalkCallBack);
/**
* 修改回调事件
*
* @param dingtalkCallBack 回调事件
* @return 结果
*/
public int updateDingtalkCallBack(DingtalkCallBack dingtalkCallBack);
/**
* 删除回调事件
*
* @param id 回调事件ID
* @return 结果
*/
public int deleteDingtalkCallBackById(Long id);
/**
* 批量删除回调事件
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public int deleteDingtalkCallBackByIds(String[] ids);
}

View File

@ -0,0 +1,61 @@
package com.snow.system.service;
import java.util.List;
import com.snow.system.domain.DingtalkCallBack;
/**
* 回调事件Service接口
*
* @author qimingjin
* @date 2020-11-02
*/
public interface IDingtalkCallBackService
{
/**
* 查询回调事件
*
* @param id 回调事件ID
* @return 回调事件
*/
public DingtalkCallBack selectDingtalkCallBackById(Long id);
/**
* 查询回调事件列表
*
* @param dingtalkCallBack 回调事件
* @return 回调事件集合
*/
public List<DingtalkCallBack> selectDingtalkCallBackList(DingtalkCallBack dingtalkCallBack);
/**
* 新增回调事件
*
* @param dingtalkCallBack 回调事件
* @return 结果
*/
public int insertDingtalkCallBack(DingtalkCallBack dingtalkCallBack);
/**
* 修改回调事件
*
* @param dingtalkCallBack 回调事件
* @return 结果
*/
public int updateDingtalkCallBack(DingtalkCallBack dingtalkCallBack);
/**
* 批量删除回调事件
*
* @param ids 需要删除的数据ID
* @return 结果
*/
public int deleteDingtalkCallBackByIds(String ids);
/**
* 删除回调事件信息
*
* @param id 回调事件ID
* @return 结果
*/
public int deleteDingtalkCallBackById(Long id);
}

View File

@ -0,0 +1,125 @@
package com.snow.system.service.impl;
import java.util.List;
import com.snow.common.enums.DingTalkListenerType;
import com.snow.common.utils.DateUtils;
import com.snow.system.domain.DingtalkCallBackEvent;
import com.snow.system.event.SyncEvent;
import com.snow.system.mapper.DingtalkCallBackEventMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import com.snow.system.mapper.DingtalkCallBackMapper;
import com.snow.system.domain.DingtalkCallBack;
import com.snow.system.service.IDingtalkCallBackService;
import com.snow.common.core.text.Convert;
import javax.annotation.Resource;
/**
* 回调事件Service业务层处理
*
* @author qimingjin
* @date 2020-11-02
*/
@Service
public class DingtalkCallBackServiceImpl implements IDingtalkCallBackService
{
@Autowired
private DingtalkCallBackMapper dingtalkCallBackMapper;
@Autowired
private DingtalkCallBackEventMapper dingtalkCallBackEventMapper;
@Autowired
private SysDictDataServiceImpl sysDictDataServiceImpl;
@Resource
private ApplicationContext applicationContext;
/**
* 查询回调事件
*
* @param id 回调事件ID
* @return 回调事件
*/
@Override
public DingtalkCallBack selectDingtalkCallBackById(Long id)
{
return dingtalkCallBackMapper.selectDingtalkCallBackById(id);
}
/**
* 查询回调事件列表
*
* @param dingtalkCallBack 回调事件
* @return 回调事件
*/
@Override
public List<DingtalkCallBack> selectDingtalkCallBackList(DingtalkCallBack dingtalkCallBack)
{
return dingtalkCallBackMapper.selectDingtalkCallBackList(dingtalkCallBack);
}
/**
* 新增回调事件
*
* @param dingtalkCallBack 回调事件
* @return 结果
*/
@Override
public int insertDingtalkCallBack(DingtalkCallBack dingtalkCallBack)
{
dingtalkCallBack.setCreateTime(DateUtils.getNowDate());
DingtalkCallBackEvent dingtalkCallBackEvent=new DingtalkCallBackEvent();
BeanUtils.copyProperties(dingtalkCallBack,dingtalkCallBackEvent);
List<String> eventNameList = dingtalkCallBack.getEventNameList();
int i = dingtalkCallBackMapper.insertDingtalkCallBack(dingtalkCallBack);
eventNameList.forEach(t->{
dingtalkCallBackEvent.setEventName(t);
String addressBook = sysDictDataServiceImpl.selectDictLabel("address_book", t);
dingtalkCallBackEvent.setEventDesc(addressBook);
dingtalkCallBackEvent.setId(i);
dingtalkCallBackEventMapper.insertDingtalkCallBackEvent(dingtalkCallBackEvent);
});
// 同步到dingding
SyncEvent syncEvent = new SyncEvent(dingtalkCallBack, DingTalkListenerType.CALL_BACK_REGISTER.getCode(), dingtalkCallBack);
applicationContext.publishEvent(syncEvent);
return 1;
}
/**
* 修改回调事件
*
* @param dingtalkCallBack 回调事件
* @return 结果
*/
@Override
public int updateDingtalkCallBack(DingtalkCallBack dingtalkCallBack)
{
dingtalkCallBack.setUpdateTime(DateUtils.getNowDate());
return dingtalkCallBackMapper.updateDingtalkCallBack(dingtalkCallBack);
}
/**
* 删除回调事件对象
*
* @param ids 需要删除的数据ID
* @return 结果
*/
@Override
public int deleteDingtalkCallBackByIds(String ids)
{
return dingtalkCallBackMapper.deleteDingtalkCallBackByIds(Convert.toStrArray(ids));
}
/**
* 删除回调事件信息
*
* @param id 回调事件ID
* @return 结果
*/
@Override
public int deleteDingtalkCallBackById(Long id)
{
return dingtalkCallBackMapper.deleteDingtalkCallBackById(id);
}
}

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.snow.system.mapper.DingtalkCallBackEventMapper">
<resultMap type="DingtalkCallBackEvent" id="DingtalkCallBackEventResult">
<result property="id" column="id" />
<result property="eventName" column="event_name" />
<result property="callBanckId" column="call_banck_id" />
<result property="eventDesc" column="event_desc" />
<result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
<result property="updateBy" column="update_by" />
</resultMap>
<sql id="selectDingtalkCallBackEventVo">
select id, event_name, call_banck_id, event_desc, del_flag, create_by, create_time, update_time, update_by from dingtalk_call_back_event
</sql>
<select id="selectDingtalkCallBackEventList" parameterType="DingtalkCallBackEvent" resultMap="DingtalkCallBackEventResult">
<include refid="selectDingtalkCallBackEventVo"/>
<where>
<if test="eventName != null and eventName != ''"> and event_name like concat('%', #{eventName}, '%')</if>
<if test="callBanckId != null "> and call_banck_id = #{callBanckId}</if>
<if test="eventDesc != null and eventDesc != ''"> and event_desc = #{eventDesc}</if>
</where>
</select>
<select id="selectDingtalkCallBackEventById" parameterType="Integer" resultMap="DingtalkCallBackEventResult">
<include refid="selectDingtalkCallBackEventVo"/>
where id = #{id}
</select>
<insert id="insertDingtalkCallBackEvent" parameterType="DingtalkCallBackEvent" useGeneratedKeys="true" keyProperty="id">
insert into dingtalk_call_back_event
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="eventName != null">event_name,</if>
<if test="callBanckId != null">call_banck_id,</if>
<if test="eventDesc != null">event_desc,</if>
<if test="delFlag != null">del_flag,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
<if test="updateBy != null">update_by,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="eventName != null">#{eventName},</if>
<if test="callBanckId != null">#{callBanckId},</if>
<if test="eventDesc != null">#{eventDesc},</if>
<if test="delFlag != null">#{delFlag},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updateBy != null">#{updateBy},</if>
</trim>
</insert>
<update id="updateDingtalkCallBackEvent" parameterType="DingtalkCallBackEvent">
update dingtalk_call_back_event
<trim prefix="SET" suffixOverrides=",">
<if test="eventName != null">event_name = #{eventName},</if>
<if test="callBanckId != null">call_banck_id = #{callBanckId},</if>
<if test="eventDesc != null">event_desc = #{eventDesc},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteDingtalkCallBackEventById" parameterType="Integer">
delete from dingtalk_call_back_event where id = #{id}
</delete>
<delete id="deleteDingtalkCallBackEventByIds" parameterType="String">
delete from dingtalk_call_back_event where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.snow.system.mapper.DingtalkCallBackMapper">
<resultMap type="DingtalkCallBack" id="DingtalkCallBackResult">
<result property="id" column="id" />
<result property="token" column="token" />
<result property="aesKey" column="aes_key" />
<result property="url" column="url" />
<result property="appKey" column="app_key" />
<result property="appSecret" column="app_secret" />
<result property="delFlag" column="del_flag" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="callBackName" column="call_back_name" />
</resultMap>
<sql id="selectDingtalkCallBackVo">
select id, token, aes_key, url, app_key, app_secret, del_flag, create_by, create_time, update_by, update_time, call_back_name from dingtalk_call_back
</sql>
<select id="selectDingtalkCallBackList" parameterType="DingtalkCallBack" resultMap="DingtalkCallBackResult">
<include refid="selectDingtalkCallBackVo"/>
<where>
<if test="callBackName != null and callBackName != ''"> and call_back_name like concat('%', #{callBackName}, '%')</if>
</where>
</select>
<select id="selectDingtalkCallBackById" parameterType="Long" resultMap="DingtalkCallBackResult">
<include refid="selectDingtalkCallBackVo"/>
where id = #{id}
</select>
<insert id="insertDingtalkCallBack" parameterType="DingtalkCallBack" useGeneratedKeys="true" keyProperty="id">
insert into dingtalk_call_back
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="token != null">token,</if>
<if test="aesKey != null">aes_key,</if>
<if test="url != null">url,</if>
<if test="appKey != null">app_key,</if>
<if test="appSecret != null">app_secret,</if>
<if test="delFlag != null">del_flag,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
<if test="callBackName != null">call_back_name,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="token != null">#{token},</if>
<if test="aesKey != null">#{aesKey},</if>
<if test="url != null">#{url},</if>
<if test="appKey != null">#{appKey},</if>
<if test="appSecret != null">#{appSecret},</if>
<if test="delFlag != null">#{delFlag},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="callBackName != null">#{callBackName},</if>
</trim>
</insert>
<update id="updateDingtalkCallBack" parameterType="DingtalkCallBack">
update dingtalk_call_back
<trim prefix="SET" suffixOverrides=",">
<if test="token != null">token = #{token},</if>
<if test="aesKey != null">aes_key = #{aesKey},</if>
<if test="url != null">url = #{url},</if>
<if test="appKey != null">app_key = #{appKey},</if>
<if test="appSecret != null">app_secret = #{appSecret},</if>
<if test="delFlag != null">del_flag = #{delFlag},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="callBackName != null">call_back_name = #{callBackName},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteDingtalkCallBackById" parameterType="Long">
delete from dingtalk_call_back where id = #{id}
</delete>
<delete id="deleteDingtalkCallBackByIds" parameterType="String">
delete from dingtalk_call_back where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>