1. 程式人生 > 實用技巧 >JIRA對接釘釘群機器人-實現任務的指派通知

JIRA對接釘釘群機器人-實現任務的指派通知

一、前提

Jira Software、釘釘群、RESTful服務、LDAP服務

二、流程圖

三、對接步驟

1、建立專案群,把相關人員拉入群

2、釘釘群的智慧群助手裡新增自定義機器人

3、設定機器人,安全設定裡建議勾選IP地址段,將RESTful服務所在的機器IP填入

4、注意建立完成後的Webhook地址,RESTful服務用這個地址傳送通知訊息,後面步驟要用上

5、RESTful服務新增一個POST介面,並部署到伺服器

 1 @ApiOperation(value = "JIRA網路鉤子")
 2 @PostMapping("/jiraWebHook")
 3 @ResponseBody
4 public Result<Boolean> jiraWebHook(HttpServletRequest request) { 5 BufferedReader br = null; 6 String str, wholeStr = ""; 7 try { 8 br = request.getReader(); 9 10 while ((str = br.readLine()) != null) { 11 wholeStr += str; 12 } 13 log.info("jiraWebHook body: {}", wholeStr);
14 } catch (Exception e) { 15 log.error("jiraWebHook error", e); 16 } finally { 17 if (br != null) { 18 try { 19 br.close(); 20 } catch (Exception e) { 21 } 22 } 23 } 24 return Result.success(JiraWebHookUtil.hook(JSONObject.parseObject(wholeStr, JiraPostData.class
))); 25 }
View Code
  1 @Slf4j
  2 public class JiraWebHookUtil {
  3 
  4     private static final String DING_TALK_ROBOT_URL = "https://oapi.dingtalk.com/robot/send" +
  5             "?access_token=xxxxxx";
  6     private static final String JIRA_BASE_URL = "http://xxx.xxx.xxx.xxx:38080/browse/";
  7     private static RestTemplate restTemplate = new RestTemplate();
  8 
  9     public static boolean hook(JiraPostData postData){
 10         try {
 11             if(postData != null){
 12                 if(StringUtils.equals(postData.getWebhookEvent(), "jira:issue_updated")){
 13                     //更新事件
 14                     List<Item> items = postData.getChangelog().getItems();
 15                     String toUserId = Strings.EMPTY;
 16                     String fromUserId = Strings.EMPTY;
 17                     for(Item item : items){
 18                         if(StringUtils.equals(item.getField(), "assignee")){
 19                             toUserId = item.getTo();
 20                             fromUserId = item.getFrom();
 21                             break;
 22                         }
 23                     }
 24                     if(StringUtils.isNotBlank(toUserId) && StringUtils.isNotBlank(fromUserId)){
 25                         String toMobile = getUserMobile(toUserId);
 26                         String fromMobile = getUserMobile(fromUserId);
 27                         if(StringUtils.isNotBlank(toMobile) && StringUtils.isNotBlank(fromMobile)){
 28                             String issueKey = postData.getIssue().getKey();
 29                             String issueSummary = postData.getIssue().getFields().getSummary();
 30                             DingTalkMarkdownMessage msg = new DingTalkMarkdownMessage();
 31                             msg.setMsgtype("markdown");
 32                             Markdown markdown = new Markdown();
 33                             markdown.setTitle(postData.getIssue().getKey());
 34                             markdown.setText("### @" + fromMobile + " 【轉移任務給】@" + toMobile
 35                                     + "\n>任務編號:[" + issueKey + "](" + JIRA_BASE_URL + issueKey + ")"
 36                                     + "  \n任務標題:" + issueSummary);
 37                             msg.setMarkdown(markdown);
 38                             At at = new At();
 39                             at.setAtMobiles(Arrays.asList(toMobile, fromMobile));
 40                             msg.setAt(at);
 41                             return sendMsgToDingTalk(JSONObject.toJSONString(msg));
 42                         }
 43                     }
 44                 }else if(StringUtils.equals(postData.getWebhookEvent(), "jira:issue_created")){
 45                     //建立事件
 46                     String fromUserId = postData.getUser().getKey();
 47                     String toUserId = postData.getIssue().getFields().getAssignee().getKey();
 48                     if(StringUtils.isNotBlank(toUserId) && StringUtils.isNotBlank(fromUserId)){
 49                         String toMobile = getUserMobile(toUserId);
 50                         String fromMobile = getUserMobile(fromUserId);
 51                         if(StringUtils.isNotBlank(toMobile) && StringUtils.isNotBlank(fromMobile)){
 52                             String issueKey = postData.getIssue().getKey();
 53                             String issueSummary = postData.getIssue().getFields().getSummary();
 54                             DingTalkMarkdownMessage msg = new DingTalkMarkdownMessage();
 55                             msg.setMsgtype("markdown");
 56                             Markdown markdown = new Markdown();
 57                             markdown.setTitle(postData.getIssue().getKey());
 58                             markdown.setText("### @" + fromMobile + " 【指派任務給】@" + toMobile
 59                                     + "\n>任務編號:[" + issueKey + "](" + JIRA_BASE_URL + issueKey + ")"
 60                                     + "  \n任務標題:" + issueSummary);
 61                             msg.setMarkdown(markdown);
 62                             At at = new At();
 63                             at.setAtMobiles(Arrays.asList(toMobile, fromMobile));
 64                             msg.setAt(at);
 65                             return sendMsgToDingTalk(JSONObject.toJSONString(msg));
 66                         }
 67                     }
 68                 }
 69             }
 70 
 71         }catch (Exception e) {
 72             log.error("觸發JIRA網路鉤子失敗", e);
 73         }
 74         return false;
 75     }
 76 
 77     private static boolean sendMsgToDingTalk(String msg){
 78         JSONObject postData = JSONObject.parseObject(msg);
 79         JSONObject result = restTemplate.postForObject(DING_TALK_ROBOT_URL, postData, JSONObject.class);
 80         if(result != null
 81                 && result.getIntValue("errcode") == 0
 82                 && StringUtils.equals(result.getString("errmsg"), "ok")){
 83             return true;
 84         }
 85         return false;
 86     }
 87 
 88     private static String getUserMobile(String userId){
 89         String mobile = Strings.EMPTY;
 90 
 91         Hashtable<String, String> env = new Hashtable<String, String>();
 92         env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
 93         env.put(Context.PROVIDER_URL, "ldap://xxxxxx:389");
 94         env.put(Context.SECURITY_AUTHENTICATION, "simple");
 95         env.put(Context.SECURITY_PRINCIPAL, "cn=xxx,dc=xxx,dc=xxx,dc=com");
 96         env.put(Context.SECURITY_CREDENTIALS, "xxxxxx");
 97         DirContext ctx = null;
 98         try{
 99             ctx = new InitialDirContext(env);
100         }catch(Exception e){
101             log.error("連線LDAP失敗", e);
102         }
103 
104         // 設定過濾條件
105         String filter = "(&(objectClass=top)(objectClass=inetOrgPerson)(cn=" + userId + "))";
106         // 限制要查詢的欄位內容
107         String[] attrPersonArray = {"cn", "mobile"};
108         SearchControls searchControls = new SearchControls();
109         searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
110         // 設定將被返回的Attribute
111         searchControls.setReturningAttributes(attrPersonArray);
112         // 三個引數分別為:
113         // 上下文;
114         // 要搜尋的屬性,如果為空或 null,則返回目標上下文中的所有物件;
115         // 控制搜尋的搜尋控制元件,如果為 null,則使用預設的搜尋控制元件
116         try {
117             NamingEnumeration<SearchResult> answer = ctx.search(
118                     "ou=People,dc=xxx,dc=xxx,dc=xxx", filter, searchControls);
119             // 輸出查到的資料
120             while (answer.hasMore()) {
121                 SearchResult result = answer.next();
122                 Attribute attr = result.getAttributes().get("mobile");
123                 mobile = attr.get().toString();
124                 break;
125             }
126         }catch (Exception e){
127             log.error("查詢LDAP使用者資訊失敗", e);
128         }
129         return mobile;
130     }
131 
132 }
View Code

6、Jira Software配置網路鉤子,使用第5步的介面地址

四、驗證效果