|  |  |  | 
|---|
|  |  |  | import com.dingtalk.api.request.OapiRobotSendRequest; | 
|---|
|  |  |  | import com.dingtalk.api.response.OapiRobotSendResponse; | 
|---|
|  |  |  | import com.taobao.api.ApiException; | 
|---|
|  |  |  | import lombok.extern.slf4j.Slf4j; | 
|---|
|  |  |  | import org.apache.commons.codec.binary.Base64; | 
|---|
|  |  |  | import org.springframework.beans.factory.annotation.Value; | 
|---|
|  |  |  | import org.springframework.core.env.Environment; | 
|---|
|  |  |  | import org.springframework.stereotype.Component; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import javax.crypto.Mac; | 
|---|
|  |  |  | 
|---|
|  |  |  | import java.security.InvalidKeyException; | 
|---|
|  |  |  | import java.security.NoSuchAlgorithmException; | 
|---|
|  |  |  | import java.util.Collections; | 
|---|
|  |  |  | import java.util.HashMap; | 
|---|
|  |  |  | import java.util.Map; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * @author ZhuBaoMin | 
|---|
|  |  |  | 
|---|
|  |  |  | * @LastEditTime 2024-07-31 9:20 | 
|---|
|  |  |  | * @Description 钉钉客户端工具类 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Slf4j | 
|---|
|  |  |  | @Component | 
|---|
|  |  |  | public class DingTalk { | 
|---|
|  |  |  | private static final String dingTalkConfigPriFix = "dingtalk"; | 
|---|
|  |  |  | private static final Map<String, Option> optionsMap = new HashMap(); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | class Option{ | 
|---|
|  |  |  | public Boolean enable ; | 
|---|
|  |  |  | public String robotUrl ; | 
|---|
|  |  |  | public String robotAccessToken ; | 
|---|
|  |  |  | public String secret ; | 
|---|
|  |  |  | public Boolean atAll ; | 
|---|
|  |  |  | public String mobile ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | /* | 
|---|
|  |  |  | @Value("${dingtalk.robot.url}") | 
|---|
|  |  |  | private String URL; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Value("${dingtalk.mobile}") | 
|---|
|  |  |  | private String MOBILE; | 
|---|
|  |  |  | */ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | public void sendMessage(String message) { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | Long timestamp = System.currentTimeMillis(); | 
|---|
|  |  |  | String secret = SECRET; | 
|---|
|  |  |  | String stringToSign = timestamp + "\n" + secret; | 
|---|
|  |  |  | Mac mac = Mac.getInstance("HmacSHA256"); | 
|---|
|  |  |  | mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256")); | 
|---|
|  |  |  | byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); | 
|---|
|  |  |  | String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8"); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //sign字段和timestamp字段必须拼接到请求URL上,否则会出现 310000 的错误信息 | 
|---|
|  |  |  | DingTalkClient client = new DefaultDingTalkClient( URL + "?sign=" + sign + "×tamp=" + timestamp); | 
|---|
|  |  |  | OapiRobotSendRequest req = new OapiRobotSendRequest(); | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 发送文本消息 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | //定义文本内容 | 
|---|
|  |  |  | OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text(); | 
|---|
|  |  |  | text.setContent(message); | 
|---|
|  |  |  | //定义 @对象 | 
|---|
|  |  |  | OapiRobotSendRequest.At at = new OapiRobotSendRequest.At(); | 
|---|
|  |  |  | if(AT_ALL) { | 
|---|
|  |  |  | at.setIsAtAll(true); | 
|---|
|  |  |  | }else { | 
|---|
|  |  |  | at.setAtMobiles(Collections.singletonList(MOBILE)); | 
|---|
|  |  |  | private Option getOptions(String orgTag, Environment env){ | 
|---|
|  |  |  | Option vo = null ; | 
|---|
|  |  |  | try{ | 
|---|
|  |  |  | vo = optionsMap.get(orgTag); | 
|---|
|  |  |  | if(vo == null){ | 
|---|
|  |  |  | vo = new Option(); | 
|---|
|  |  |  | String enableStr = env.getProperty(dingTalkConfigPriFix + "." + orgTag + ".enable"); | 
|---|
|  |  |  | if(enableStr != null && !enableStr.trim().equals("")){ | 
|---|
|  |  |  | vo.enable = Boolean.valueOf(enableStr); | 
|---|
|  |  |  | }else{ | 
|---|
|  |  |  | vo.enable = true ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | vo.robotUrl = env.getProperty(dingTalkConfigPriFix + "." + orgTag + ".robot.url"); | 
|---|
|  |  |  | vo.robotAccessToken = env.getProperty(dingTalkConfigPriFix + "." + orgTag + ".robot.access-token"); | 
|---|
|  |  |  | vo.secret = env.getProperty(dingTalkConfigPriFix + "." + orgTag + ".robot.secret"); | 
|---|
|  |  |  | String atAllStr = env.getProperty(dingTalkConfigPriFix + "." + orgTag + ".at-all"); | 
|---|
|  |  |  | if(atAllStr != null && !atAllStr.trim().equals("")){ | 
|---|
|  |  |  | vo.atAll = Boolean.valueOf(atAllStr); | 
|---|
|  |  |  | }else{ | 
|---|
|  |  |  | vo.atAll = true ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | vo.mobile = env.getProperty(dingTalkConfigPriFix + "." + orgTag + ".mobile"); | 
|---|
|  |  |  | optionsMap.put(orgTag, vo) ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | //设置消息类型 | 
|---|
|  |  |  | req.setMsgtype("text"); | 
|---|
|  |  |  | req.setText(text); | 
|---|
|  |  |  | req.setAt(at); | 
|---|
|  |  |  | OapiRobotSendResponse rsp = client.execute(req, CUSTOM_ROBOT_TOKEN); | 
|---|
|  |  |  | System.out.println(rsp.getBody()); | 
|---|
|  |  |  | } catch (ApiException e) { | 
|---|
|  |  |  | e.printStackTrace(); | 
|---|
|  |  |  | } catch (UnsupportedEncodingException e) { | 
|---|
|  |  |  | throw new RuntimeException(e); | 
|---|
|  |  |  | } catch (NoSuchAlgorithmException e) { | 
|---|
|  |  |  | throw new RuntimeException(e); | 
|---|
|  |  |  | } catch (InvalidKeyException e) { | 
|---|
|  |  |  | throw new RuntimeException(e); | 
|---|
|  |  |  | }catch (Exception e){ | 
|---|
|  |  |  | vo = null ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | return vo ; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 向钉钉群发送消息 | 
|---|
|  |  |  | * @param orgTag | 
|---|
|  |  |  | * @param env | 
|---|
|  |  |  | * @param message | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | public void sendMessage(String orgTag, Environment env, String message) { | 
|---|
|  |  |  | if(orgTag == null || orgTag.trim().equals("")){ | 
|---|
|  |  |  | log.error("钉钉发送消息异常,机构标签为空"); | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if(env == null){ | 
|---|
|  |  |  | log.error("钉钉发送消息异常,Spring环境为空"); | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if(message == null || message.trim().equals("")){ | 
|---|
|  |  |  | log.error("钉钉发送消息异常,消息为空"); | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | Option vo = this.getOptions(orgTag.trim(), env) ; | 
|---|
|  |  |  | if(vo == null){ | 
|---|
|  |  |  | log.error("钉钉发送消息异常,钉钉配置错误"); | 
|---|
|  |  |  | return; | 
|---|
|  |  |  | } | 
|---|
|  |  |  | if(vo.enable){ | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | Long timestamp = System.currentTimeMillis() ; | 
|---|
|  |  |  | String stringToSign = timestamp + "\n" + vo.secret; | 
|---|
|  |  |  | Mac mac = Mac.getInstance("HmacSHA256"); | 
|---|
|  |  |  | mac.init(new SecretKeySpec(vo.secret.getBytes("UTF-8"), "HmacSHA256")); | 
|---|
|  |  |  | byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8")); | 
|---|
|  |  |  | String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8"); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //定义文本内容 | 
|---|
|  |  |  | OapiRobotSendRequest.Text text = new OapiRobotSendRequest.Text(); | 
|---|
|  |  |  | text.setContent(message); | 
|---|
|  |  |  | //定义 @对象 | 
|---|
|  |  |  | OapiRobotSendRequest.At at = new OapiRobotSendRequest.At(); | 
|---|
|  |  |  | if(vo.atAll) { | 
|---|
|  |  |  | at.setIsAtAll(true); | 
|---|
|  |  |  | }else { | 
|---|
|  |  |  | at.setAtMobiles(Collections.singletonList(vo.mobile)); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | OapiRobotSendRequest req = new OapiRobotSendRequest(); | 
|---|
|  |  |  | //设置消息类型 | 
|---|
|  |  |  | req.setMsgtype("text"); | 
|---|
|  |  |  | req.setText(text); | 
|---|
|  |  |  | req.setAt(at); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | //sign字段和timestamp字段必须拼接到请求URL上,否则会出现 310000 的错误信息 | 
|---|
|  |  |  | DingTalkClient client = new DefaultDingTalkClient( vo.robotUrl + "?sign=" + sign + "×tamp=" + timestamp); | 
|---|
|  |  |  | OapiRobotSendResponse rsp = client.execute(req, vo.robotAccessToken); | 
|---|
|  |  |  | log.info(rsp.getBody()); | 
|---|
|  |  |  | } catch (ApiException e) { | 
|---|
|  |  |  | log.error("钉钉发送消息异常", e); | 
|---|
|  |  |  | //e.printStackTrace(); | 
|---|
|  |  |  | } catch (UnsupportedEncodingException e) { | 
|---|
|  |  |  | log.error("钉钉发送消息异常", e); | 
|---|
|  |  |  | //e.printStackTrace(); | 
|---|
|  |  |  | } catch (NoSuchAlgorithmException e) { | 
|---|
|  |  |  | log.error("钉钉发送消息异常", e); | 
|---|
|  |  |  | //e.printStackTrace(); | 
|---|
|  |  |  | } catch (InvalidKeyException e) { | 
|---|
|  |  |  | log.error("钉钉发送消息异常", e); | 
|---|
|  |  |  | //e.printStackTrace(); | 
|---|
|  |  |  | } catch (Exception e){ | 
|---|
|  |  |  | log.error("钉钉发送消息异常", e); | 
|---|
|  |  |  | //e.printStackTrace(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|