|
|
@@ -17,8 +17,8 @@ import org.springframework.web.client.RestTemplate;
|
|
|
|
|
|
import javax.crypto.Mac;
|
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
|
-import java.net.MalformedURLException;
|
|
|
-import java.net.URL;
|
|
|
+import java.net.URI;
|
|
|
+import java.net.URISyntaxException;
|
|
|
import java.net.URLEncoder;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
@@ -27,6 +27,7 @@ import java.util.Map;
|
|
|
* 钉钉机器人客户端
|
|
|
*
|
|
|
* @author Wanxiang Liu
|
|
|
+ * @author Alex Hu
|
|
|
* @version 1.0.0
|
|
|
*/
|
|
|
public class DingTalkRobotClient {
|
|
|
@@ -44,54 +45,51 @@ public class DingTalkRobotClient {
|
|
|
/**
|
|
|
* 钉钉机器人WebHook地址的access_token
|
|
|
*/
|
|
|
- @Value("${dingtalk.robot.access_token}")
|
|
|
+ @Value("${dingtalk.robot.access-token}")
|
|
|
private String accessToken;
|
|
|
|
|
|
/**
|
|
|
* 钉钉机器人是否启用加签,默认false,启用加签需设置secret_token
|
|
|
*/
|
|
|
- @Value("${dingtalk.robot.secret.secret_enabled:false}")
|
|
|
+ @Value("${dingtalk.robot.secret.secret-enabled:false}")
|
|
|
private boolean secretEnable;
|
|
|
|
|
|
/**
|
|
|
* 钉钉机器人WebHook地址的secret_token,群机器人加签用
|
|
|
*/
|
|
|
- @Value("${dingtalk.robot.secret.secret_token:null}")
|
|
|
+ @Value("${dingtalk.robot.secret.secret-token:null}")
|
|
|
private String secretToken;
|
|
|
|
|
|
/**
|
|
|
* Gets default webhook.
|
|
|
+ *
|
|
|
* @return the default webhook
|
|
|
*/
|
|
|
public String getDefaultWebhook() {
|
|
|
- return getWebhook(accessToken);
|
|
|
+ return getWebhook(accessToken, secretToken, secretEnable);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Gets webhook.
|
|
|
+ * 隐含条件,加签功能关闭
|
|
|
+ * 传入accessToken,获取完整的WebHook URL。
|
|
|
+ *
|
|
|
* @param accessToken the access token
|
|
|
* @return the webhook
|
|
|
*/
|
|
|
public String getWebhook(String accessToken) {
|
|
|
- String url = urlPrefix + "?access_token=" + accessToken;
|
|
|
- //若启用加签加上时间戳跟签名串
|
|
|
- if (secretEnable) {
|
|
|
- Long timestamp = System.currentTimeMillis();
|
|
|
- url += "×tamp=" + timestamp
|
|
|
- + "&sign=" + getSign(secretToken, timestamp);
|
|
|
- }
|
|
|
- log.debug(url);
|
|
|
- return url;
|
|
|
+ return getWebhook(accessToken,null,false);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 计算签名
|
|
|
* 参考:https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq/9e91d73c
|
|
|
+ *
|
|
|
* @param secret 密钥,机器人安全设置页面,加签一栏下面显示的SEC开头的字符
|
|
|
- * @param @timestamp
|
|
|
- * @return
|
|
|
+ * @param timestamp 当前时间戳,毫秒级单位
|
|
|
+ * @return 根据时间戳计算后的签名信息
|
|
|
*/
|
|
|
- static String getSign(String secret, Long timestamp) {
|
|
|
+ private static String getSign(String secret, Long timestamp) {
|
|
|
try {
|
|
|
String stringToSign = timestamp + "\n" + secret;
|
|
|
Mac mac = Mac.getInstance("HmacSHA256");
|
|
|
@@ -114,10 +112,10 @@ public class DingTalkRobotClient {
|
|
|
* @return
|
|
|
*/
|
|
|
public DingTalkResponse sendMessageByURL(String url, BaseMessage message) {
|
|
|
- URL actualUrl;
|
|
|
+ URI actualUrl;
|
|
|
try {
|
|
|
- actualUrl = new URL(url);
|
|
|
- } catch (MalformedURLException e) {
|
|
|
+ actualUrl = new URI(url);
|
|
|
+ } catch (URISyntaxException e) {
|
|
|
throw new RuntimeException("URL创建报错!");
|
|
|
}
|
|
|
return sendMessageByURL(actualUrl, message);
|
|
|
@@ -130,23 +128,29 @@ public class DingTalkRobotClient {
|
|
|
* @param message
|
|
|
* @return
|
|
|
*/
|
|
|
- public DingTalkResponse sendMessageByURL(URL url, BaseMessage message) {
|
|
|
+ public DingTalkResponse sendMessageByURL(URI url, BaseMessage message) {
|
|
|
|
|
|
HttpHeaders headers = new HttpHeaders();
|
|
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
HttpEntity<Map> entity = new HttpEntity<>(message.toMessageMap(), headers);
|
|
|
- try {
|
|
|
- DingTalkResponse dingTalkResponse =
|
|
|
- restTemplate.postForObject(url.toURI(), entity, DingTalkResponse.class);
|
|
|
+ DingTalkResponse dingTalkResponse;
|
|
|
|
|
|
- if (!ResponseCodeType.OK.getValue().equals(dingTalkResponse.getErrcode())) {
|
|
|
- throw new DingTalkException(dingTalkResponse.getErrcode(), dingTalkResponse.getErrmsg());
|
|
|
- }
|
|
|
- return dingTalkResponse;
|
|
|
+ try {
|
|
|
+ dingTalkResponse =
|
|
|
+ restTemplate.postForObject(url, entity, DingTalkResponse.class);
|
|
|
} catch (Exception e) {
|
|
|
log.error(e.fillInStackTrace().toString());
|
|
|
- return null;
|
|
|
+ throw new DingTalkException(ResponseCodeType.UNKNOWN.getValue(), e.fillInStackTrace().toString());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 对DingTalkResponse为空情况做异常封装
|
|
|
+ if (dingTalkResponse == null) {
|
|
|
+ throw new DingTalkException(ResponseCodeType.UNKNOWN.getValue(), "请求钉钉报错!");
|
|
|
+ }
|
|
|
+ if (!ResponseCodeType.OK.getValue().equals(dingTalkResponse.getErrcode())) {
|
|
|
+ throw new DingTalkException(dingTalkResponse.getErrcode(), dingTalkResponse.getErrmsg());
|
|
|
}
|
|
|
+ return dingTalkResponse;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -369,4 +373,36 @@ public class DingTalkRobotClient {
|
|
|
public DingTalkResponse sendFeedCardMessage(List<FeedCardMessageItem> feedCardItems) {
|
|
|
return this.sendMessage(new FeedCardMessage(feedCardItems));
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Gets webhook.
|
|
|
+ * access_token、secret_token、secretEnable参数均由外部传入
|
|
|
+ *
|
|
|
+ * @param accessToken the access token
|
|
|
+ * @return the webhook
|
|
|
+ */
|
|
|
+ public String getWebhook(String accessToken, String secretToken, boolean secretEnable) {
|
|
|
+ String url = urlPrefix + "?access_token=" + accessToken;
|
|
|
+ //若启用加签加上时间戳跟签名串
|
|
|
+ if (secretEnable) {
|
|
|
+ Long timestamp = System.currentTimeMillis();
|
|
|
+ url += "×tamp=" + timestamp
|
|
|
+ + "&sign=" + getSign(secretToken, timestamp);
|
|
|
+ }
|
|
|
+ log.debug("The url contains sign is {}", url);
|
|
|
+ return url;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Gets webhook.
|
|
|
+ * 隐含条件,加签功能开启
|
|
|
+ * 传入accessToken和secretToken,获取完整的WebHook URL。
|
|
|
+ *
|
|
|
+ * @param accessToken
|
|
|
+ * @param secretToken
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public String getWebhook(String accessToken, String secretToken) {
|
|
|
+ return getWebhook(accessToken, secretToken, true);
|
|
|
+ }
|
|
|
}
|