From c9658c3bf848534a720b16c45efaf9df41f93636 Mon Sep 17 00:00:00 2001 From: chenweiwei Date: Tue, 11 Jun 2024 17:58:39 +0800 Subject: [PATCH] 1:钉钉代码优化 --- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/constant/DingtalkConstant.java | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/constant/Env.java | 65 ----------------------------------------------------------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/controller/DingtalkController.java | 41 +++++++++++++++++++++++++---------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/auth/AuthHelper.java | 180 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/department/DepartmentHelper.java | 62 -------------------------------------------------------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/eventchange/eventChangeHelper.java | 80 -------------------------------------------------------------------------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/media/MediaHelper.java | 53 ----------------------------------------------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/ConversationMessageDelivery.java | 16 ---------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/ImageMessage.java | 17 ----------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/LightAppMessageDelivery.java | 15 --------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/LinkMessage.java | 22 ---------------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/Message.java | 6 ------ zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/MessageDelivery.java | 15 --------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/MessageHelper.java | 43 ------------------------------------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/OAMessage.java | 69 --------------------------------------------------------------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/TextMessage.java | 17 ----------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/user/User.java | 43 ------------------------------------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/user/UserHelper.java | 143 ----------------------------------------------------------------------------------------------------------------------------------------------- zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/service/DingtalkService.java | 13 +++++++++++++ zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/service/impl/DingtalkServiceImpl.java | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 20 files changed, 187 insertions(+), 862 deletions(-) create mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/constant/DingtalkConstant.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/constant/Env.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/auth/AuthHelper.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/department/DepartmentHelper.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/eventchange/eventChangeHelper.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/media/MediaHelper.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/ConversationMessageDelivery.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/ImageMessage.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/LightAppMessageDelivery.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/LinkMessage.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/Message.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/MessageDelivery.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/MessageHelper.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/OAMessage.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/TextMessage.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/user/User.java delete mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/user/UserHelper.java create mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/service/DingtalkService.java create mode 100644 zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/service/impl/DingtalkServiceImpl.java diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/constant/DingtalkConstant.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/constant/DingtalkConstant.java new file mode 100644 index 0000000..bedac5e --- /dev/null +++ b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/constant/DingtalkConstant.java @@ -0,0 +1,70 @@ +package com.chinagas.modules.schsf.constant; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@ConfigurationProperties(prefix = "dingtalk") +@Component +@Data +public class DingtalkConstant { + + /** + * 企业corpid + */ + private String corpId; + + /** + * 应用agentId + */ + private String agentId; + + /** + * 应用的appkey + */ + private String appKey; + + /** + * 应用的appsecret + */ + private String appSecret; + + /** + * 回调host + */ + private String callbackUrlHost; + + /** + * 加解密需要用到的token,企业可以随机填写。如 "123456" + */ + private String token; + + /** + * 数据加密密钥。用于回调数据的加密,长度固定为43个字符,从a-z, A-Z, 0-9共62个字符中选取,您可以随机生成 + */ + private String encodingAesKey; + + /** + * DING API地址 + */ + private String oapiHost; + + /** + * 删除企业回调接口url + */ + private String deleteCallback; + + /** + * 注册企业回调接口url + */ + private String registerCallback; + + /** + * 企业应用后台地址,用户管理后台免登使用 + */ + private String oaBackgroundUrl; + + private String ssoSecret; + + +} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/constant/Env.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/constant/Env.java deleted file mode 100644 index f43c97c..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/constant/Env.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.chinagas.modules.schsf.constant; - - -/** - * 企业应用接入时的常量定义 - */ -public class Env { - - /** - * 企业corpid - */ - public static final String CORP_ID = "dingf2f9115915afcb54a39a90f97fcb1e09"; - - /** - * 应用agentId - */ - public static final String AGENT_ID = "3129896987"; - - /** - * 应用的appkey - */ - public static final String APP_KEY = "dingplin6zezdw81rqjd"; - - /** - * 应用的appsecret - */ - public static final String APP_SECRET = "urDzarTDCpo6A7nJfPiGUJRTGY8O-JO0pvDl0O6wm3Eih6zL92hDdThIdmeKUh2C"; - - /** - * 回调host - */ - public static final String CALLBACK_URL_HOST = ""; - - /** - * 加解密需要用到的token,企业可以随机填写。如 "123456" - */ - public static final String TOKEN = "123456"; - - /** - * 数据加密密钥。用于回调数据的加密,长度固定为43个字符,从a-z, A-Z, 0-9共62个字符中选取,您可以随机生成 - */ - public static final String ENCODING_AES_KEY = "abcdefghijabcdefghijabcdefghijabcdefghij123"; - - /** - * DING API地址 - */ - public static final String OAPI_HOST = "https://oapi.dingtalk.com"; - - /** - * 删除企业回调接口url - */ - public static final String DELETE_CALLBACK = "https://oapi.dingtalk.com/call_back/delete_call_back"; - - /** - * 注册企业回调接口url - */ - public static final String REGISTER_CALLBACK = "https://oapi.dingtalk.com/call_back/register_call_back"; - - /** - * 企业应用后台地址,用户管理后台免登使用 - */ - public static final String OA_BACKGROUND_URL = ""; - - public static final String SSO_Secret = ""; -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/controller/DingtalkController.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/controller/DingtalkController.java index 85b1d29..ea1a3e3 100644 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/controller/DingtalkController.java +++ b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/controller/DingtalkController.java @@ -1,10 +1,11 @@ package com.chinagas.modules.schsf.controller; import com.chinagas.common.core.domain.AjaxResult; -import com.chinagas.modules.schsf.constant.Env; +import com.chinagas.modules.schsf.constant.DingtalkConstant; import com.chinagas.modules.schsf.exception.OApiException; -import com.chinagas.modules.schsf.openApi.auth.AuthHelper; +import com.chinagas.modules.schsf.service.DingtalkService; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -15,34 +16,42 @@ import java.util.HashMap; @RequestMapping("/dingtalk") @Slf4j public class DingtalkController { + @Autowired + private DingtalkService dingtalkService; + + @Autowired + private DingtalkConstant dingtalkConstant; @GetMapping("/getConfig") public AjaxResult getConfig(String url) throws OApiException { - log.info("getConfig:{}",1); - String appKey = Env.APP_KEY; - String agentId = Env.AGENT_ID; - String corpId = Env.CORP_ID; + log.info("getConfig:{}", 1); + String appKey = dingtalkConstant.getAppKey(); + String agentId = dingtalkConstant.getAgentId(); + String corpId = dingtalkConstant.getCorpId(); long timeStamp = System.currentTimeMillis(); String nonceStr = "nonceStr"; + // 获取access token - String accessToken = AuthHelper.getAccessToken(timeStamp); + String accessToken = dingtalkService.getAccessToken(timeStamp); System.out.println("成功获取access token: " + accessToken); + + // 获取jsapi ticket - String ticket = AuthHelper.getJsapiTicket(accessToken,timeStamp); - System.out.println("成功获取jsapi ticket: "+ticket); + String ticket = dingtalkService.getJsapiTicket(accessToken, timeStamp); + System.out.println("成功获取jsapi ticket: " + ticket); // 获取签名 // String url = "http://www.dingtalk.com"; - String signature = AuthHelper.sign(ticket, nonceStr, timeStamp, url); + String signature = dingtalkService.getSign(ticket, nonceStr, timeStamp, url); System.out.println("成功签名: " + signature); HashMap objectObjectHashMap = new HashMap<>(); - objectObjectHashMap.put("appKey",appKey); - objectObjectHashMap.put("agentId",agentId); - objectObjectHashMap.put("corpId",corpId); - objectObjectHashMap.put("timeStamp",timeStamp); - objectObjectHashMap.put("nonceStr",nonceStr); - objectObjectHashMap.put("signature",signature); + objectObjectHashMap.put("appKey", appKey); + objectObjectHashMap.put("agentId", agentId); + objectObjectHashMap.put("corpId", corpId); + objectObjectHashMap.put("timeStamp", timeStamp); + objectObjectHashMap.put("nonceStr", nonceStr); + objectObjectHashMap.put("signature", signature); System.out.println(objectObjectHashMap); return AjaxResult.success(objectObjectHashMap); } diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/auth/AuthHelper.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/auth/AuthHelper.java deleted file mode 100644 index bdac3dd..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/auth/AuthHelper.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.chinagas.modules.schsf.openApi.auth; - -import com.chinagas.modules.schsf.constant.Env; -import com.chinagas.modules.schsf.exception.OApiException; -import com.chinagas.modules.schsf.utils.FileUtils; -import com.chinagas.modules.schsf.utils.HttpHelper; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.dingtalk.oapi.lib.aes.DingTalkJsApiSingnature; -import com.dingtalk.open.client.ServiceFactory; -import com.dingtalk.open.client.api.model.corp.JsapiTicket; -import com.dingtalk.open.client.api.service.corp.CorpConnectionService; -import com.dingtalk.open.client.api.service.corp.JsapiService; - -import javax.servlet.http.HttpServletRequest; -import java.net.URLDecoder; -import java.util.HashMap; -import java.util.Map; - -/** - * AccessToken和jsticket的获取封装 - */ -public class AuthHelper { - - /** - * 调整到1小时50分钟 - */ - public static final long cacheTime = 1000 * 60 * 55 * 2; - - /** - * 在此方法中,为了避免频繁获取access_token, - * 在距离上一次获取access_token时间在两个小时之内的情况, - * 将直接从持久化存储中读取access_token - *

- * 因为access_token和jsapi_ticket的过期时间都是7200秒 - * 所以在获取access_token的同时也去获取了jsapi_ticket - * 注:jsapi_ticket是在前端页面JSAPI做权限验证配置的时候需要使用的 - * 具体信息请查看开发者文档--权限验证配置 - */ - public static String getAccessToken(Long timeStamp) throws OApiException { - long curTime = timeStamp == null ? System.currentTimeMillis() : timeStamp; - JSONObject accessTokenValue = (JSONObject) FileUtils.getValue("accesstoken", Env.APP_KEY); - String accToken = ""; - JSONObject jsontemp = new JSONObject(); - if (accessTokenValue == null || curTime - accessTokenValue.getLong("begin_time") >= cacheTime) { - try { - ServiceFactory serviceFactory = ServiceFactory.getInstance(); - CorpConnectionService corpConnectionService = serviceFactory.getOpenService(CorpConnectionService.class); - accToken = corpConnectionService.getCorpToken(Env.APP_KEY, Env.APP_SECRET); - // save accessToken - JSONObject jsonAccess = new JSONObject(); - jsontemp.clear(); - jsontemp.put("access_token", accToken); - jsontemp.put("begin_time", curTime); - jsonAccess.put(Env.APP_KEY, jsontemp); - //真实项目中最好保存到数据库中 - FileUtils.write2File(jsonAccess, "accesstoken"); - - } catch (Exception e) { - e.printStackTrace(); - } - } else { - return accessTokenValue.getString("access_token"); - } - return accToken; - } - - /** - * 获取JSTicket, 用于js的签名计算 - * 正常的情况下,jsapi_ticket的有效期为7200秒,所以开发者需要在某个地方设计一个定时器,定期去更新jsapi_ticket - */ - public static String getJsapiTicket(String accessToken,Long timeStamp) throws OApiException { - JSONObject jsTicketValue = (JSONObject) FileUtils.getValue("jsticket", Env.APP_KEY); - long curTime =timeStamp==null? System.currentTimeMillis():timeStamp; - String jsTicket = ""; - - if (jsTicketValue == null || curTime - - jsTicketValue.getLong("begin_time") >= cacheTime) { - ServiceFactory serviceFactory; - try { - serviceFactory = ServiceFactory.getInstance(); - JsapiService jsapiService = serviceFactory.getOpenService(JsapiService.class); - - JsapiTicket JsapiTicket = jsapiService.getJsapiTicket(accessToken, "jsapi"); - jsTicket = JsapiTicket.getTicket(); - - JSONObject jsonTicket = new JSONObject(); - JSONObject jsontemp = new JSONObject(); - jsontemp.clear(); - jsontemp.put("ticket", jsTicket); - jsontemp.put("begin_time", curTime); - jsonTicket.put(Env.APP_KEY, jsontemp); - FileUtils.write2File(jsonTicket, "jsticket"); - } catch (Exception e) { - e.printStackTrace(); - } - return jsTicket; - } else { - return jsTicketValue.getString("ticket"); - } - } - - public static String sign(String ticket, String nonceStr, long timeStamp, String url) throws OApiException { - try { - return DingTalkJsApiSingnature.getJsApiSingnature(url, nonceStr, timeStamp, ticket); - } catch (Exception ex) { - throw new OApiException(0, ex.getMessage()); - } - } - - /** - * 计算当前请求的jsapi的签名数据
- *

- * 如果签名数据是通过ajax异步请求的话,签名计算中的url必须是给用户展示页面的url - * - * @param request - * @return - */ - public static String getConfig(HttpServletRequest request) { - String urlString = request.getRequestURL().toString(); - String queryString = request.getQueryString(); - - String queryStringEncode = null; - String url; - if (queryString != null) { - queryStringEncode = URLDecoder.decode(queryString); - url = urlString + "?" + queryStringEncode; - } else { - url = urlString; - } - /** - * 确认url与配置的应用首页地址一致 - */ - System.out.println(url); - - /** - * 随机字符串 - */ - String nonceStr = "abcdefg"; - long timeStamp = System.currentTimeMillis() / 1000; - String signedUrl = url; - String accessToken = null; - String ticket = null; - String signature = null; - - try { - accessToken = AuthHelper.getAccessToken(null); - - ticket = AuthHelper.getJsapiTicket(accessToken,null); - signature = AuthHelper.sign(ticket, nonceStr, timeStamp, signedUrl); - - } catch (OApiException e) { - e.printStackTrace(); - } - - Map configValue = new HashMap<>(); - configValue.put("jsticket", ticket); - configValue.put("signature", signature); - configValue.put("nonceStr", nonceStr); - configValue.put("timeStamp", timeStamp); - configValue.put("corpId", Env.CORP_ID); - configValue.put("agentId", Env.AGENT_ID); - - String config = JSON.toJSONString(configValue); - return config; - } - - public static String getSsoToken() throws OApiException { - String url = "https://oapi.dingtalk.com/sso/gettoken?corpid=" + Env.CORP_ID + "&corpsecret=" + Env.SSO_Secret; - JSONObject response = HttpHelper.httpGet(url); - String ssoToken; - if (response.containsKey("access_token")) { - ssoToken = response.getString("access_token"); - } else { - throw new OApiException("Sso_token"); - } - return ssoToken; - - } -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/department/DepartmentHelper.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/department/DepartmentHelper.java deleted file mode 100644 index 0d4976d..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/department/DepartmentHelper.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.chinagas.modules.schsf.openApi.department; - -import com.dingtalk.open.client.ServiceFactory; -import com.dingtalk.open.client.api.model.corp.Department; -import com.dingtalk.open.client.api.service.corp.CorpDepartmentService; -import com.dingtalk.open.client.common.SdkInitException; -import com.dingtalk.open.client.common.ServiceException; -import com.dingtalk.open.client.common.ServiceNotExistException; - -import java.util.List; - -/** - * 部门相关API - * - * https://open-doc.dingtalk.com/docs/doc.htm?treeId=371&articleId=106817&docType=1 - */ -public class DepartmentHelper { - - /** - * 创建部门 - */ - public static String createDepartment(String accessToken, String name, - String parentId, String order, boolean createDeptGroup) throws Exception { - - CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class); - return corpDepartmentService.deptCreate(accessToken, name, parentId, order, createDeptGroup); - } - - /** - * 获取部门列表 - */ - public static List listDepartments(String accessToken, String parentDeptId) - throws ServiceNotExistException, SdkInitException, ServiceException { - CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class); - List deptList = corpDepartmentService.getDeptList(accessToken, parentDeptId); - return deptList; - } - - - /** - * 删除部门 - */ - public static void deleteDepartment(String accessToken, Long id) throws Exception { - CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class); - corpDepartmentService.deptDelete(accessToken, id); - } - - /** - * 更新部门 - */ - public static void updateDepartment(String accessToken, long id, String name, - String parentId, String order, Boolean createDeptGroup, - boolean autoAddUser, String deptManagerUseridList, boolean deptHiding, String deptPerimits, - String userPerimits, Boolean outerDept, String outerPermitDepts, - String outerPermitUsers, String orgDeptOwner) throws Exception { - CorpDepartmentService corpDepartmentService = ServiceFactory.getInstance().getOpenService(CorpDepartmentService.class); - corpDepartmentService.deptUpdate(accessToken, id, name, parentId, order, createDeptGroup, - autoAddUser, deptManagerUseridList, deptHiding, deptPerimits, userPerimits, - outerDept, outerPermitDepts, outerPermitUsers, orgDeptOwner); - - } -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/eventchange/eventChangeHelper.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/eventchange/eventChangeHelper.java deleted file mode 100644 index 27a6bc8..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/eventchange/eventChangeHelper.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.chinagas.modules.schsf.openApi.eventchange; - -import com.chinagas.modules.schsf.constant.Env; -import com.chinagas.modules.schsf.exception.OApiException; -import com.chinagas.modules.schsf.utils.HttpHelper; -import com.alibaba.fastjson.JSONObject; - -import java.util.List; - -/** - * 通讯录回调相关事件 - *

- * https://open-doc.dingtalk.com/docs/doc.htm?treeId=371&articleId=104975&docType=1 - */ -public class eventChangeHelper { - - /** - * 注册事件回调接口 - */ - public static String registerEventChange(String accessToken, List callBackTag, String token, String aesKey, String url) throws OApiException { - String signUpUrl = Env.OAPI_HOST + "/call_back/register_call_back?" + - "access_token=" + accessToken; - JSONObject args = new JSONObject(); - args.put("call_back_tag", callBackTag); - args.put("token", token); - args.put("aes_key", aesKey); - args.put("url", url); - - JSONObject response = HttpHelper.httpPost(signUpUrl, args); - if (response.containsKey("errcode")) { - return response.getString("errcode"); - } else { - return null; - } - } - - //查询事件回调接口 - public static String getEventChange(String accessToken) throws OApiException { - String url = Env.OAPI_HOST + "/call_back/get_call_back?" + - "access_token=" + accessToken; - JSONObject response = HttpHelper.httpGet(url); - return response.toString(); - } - - //更新事件回调接口 - public static String updateEventChange(String accessToken, List callBackTag, String token, String aesKey, String url) throws OApiException { - String signUpUrl = Env.OAPI_HOST + "/call_back/update_call_back?" + - "access_token=" + accessToken; - JSONObject args = new JSONObject(); - args.put("call_back_tag", callBackTag); - args.put("token", token); - args.put("aes_key", aesKey); - args.put("url", url); - - JSONObject response = HttpHelper.httpPost(signUpUrl, args); - if (response.containsKey("errcode")) { - return response.getString("errcode"); - } else { - return null; - } - } - - //删除事件回调接口 - public static String deleteEventChange(String accessToken) throws OApiException { - String url = Env.OAPI_HOST + "/call_back/delete_call_back?" + - "access_token=" + accessToken; - JSONObject response = HttpHelper.httpGet(url); - return response.toString(); - } - - - public static String getFailedResult(String accessToken) throws OApiException { - String url = Env.OAPI_HOST + "/call_back/get_call_back_failed_result?" + - "access_token=" + accessToken; - JSONObject response = HttpHelper.httpGet(url); - return response.toString(); - } - - -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/media/MediaHelper.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/media/MediaHelper.java deleted file mode 100644 index 8fff5ab..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/media/MediaHelper.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.chinagas.modules.schsf.openApi.media; - -import com.chinagas.modules.schsf.constant.Env; -import com.chinagas.modules.schsf.utils.HttpHelper; -import com.alibaba.fastjson.JSONObject; -import com.dingtalk.open.client.ServiceFactory; -import com.dingtalk.open.client.api.model.corp.UploadResult; -import com.dingtalk.open.client.api.service.corp.MediaService; - -import java.io.File; - -/** - * 管理多媒体文件 - * https://open-doc.dingtalk.com/docs/doc.htm?source=search&treeId=373&articleId=104971&docType=1 - */ -public class MediaHelper { - - /** - * 资源文件类型 - */ - public static final String TYPE_IMAGE = "image"; - public static final String TYPE_VOICE = "voice"; - public static final String TYPE_VIDEO = "video"; - public static final String TYPE_FILE = "file"; - - - public static class MediaUploadResult { - public String type; - public String media_id; - public String created_at; - } - - /** - * 上传多媒体文件 - *

- */ - public static UploadResult upload(String accessToken, String type, File file) throws Exception { - - MediaService mediaService = ServiceFactory.getInstance().getOpenService(MediaService.class); - UploadResult uploadResult = mediaService.uploadMediaFile(accessToken, type, file); - return uploadResult; - } - - /** - * 下载多媒体文件,目前sdk没有封装此接口,需要通过HTTP访问 - */ - public static void download(String accessToken, String mediaId, String fileDir) throws Exception { - String url = Env.OAPI_HOST + "/media/downloadFile?" + - "access_token=" + accessToken + "&media_id=" + mediaId; - JSONObject response = HttpHelper.downloadMedia(url, fileDir); - System.out.println(response); - } -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/ConversationMessageDelivery.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/ConversationMessageDelivery.java deleted file mode 100644 index b3f90fe..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/ConversationMessageDelivery.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.chinagas.modules.schsf.openApi.message; - -public class ConversationMessageDelivery extends MessageDelivery { - - public String sender; - public String cid; - public String agentid; - - public ConversationMessageDelivery(String sender, String cid, - String agentId) { - this.sender = sender; - this.cid = cid; - this.agentid = agentId; - } - -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/ImageMessage.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/ImageMessage.java deleted file mode 100644 index b6c9585..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/ImageMessage.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.chinagas.modules.schsf.openApi.message; - - -public class ImageMessage extends Message { - - public String media_id; - - public ImageMessage(String mediaId) { - super(); - media_id = mediaId; - } - - @Override - public String type() { - return "image"; - } -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/LightAppMessageDelivery.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/LightAppMessageDelivery.java deleted file mode 100644 index b0200b7..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/LightAppMessageDelivery.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.chinagas.modules.schsf.openApi.message; - -public class LightAppMessageDelivery extends MessageDelivery { - - public String touser; - public String toparty; - public String agentid; - - public LightAppMessageDelivery(String toUsers, String toParties, String agentId) { - this.touser = toUsers; - this.toparty = toParties; - this.agentid = agentId; - } - -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/LinkMessage.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/LinkMessage.java deleted file mode 100644 index 88ed593..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/LinkMessage.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.chinagas.modules.schsf.openApi.message; - -public class LinkMessage extends Message { - - public String messageUrl; - public String picUrl; - public String title; - public String text; - - public LinkMessage(String messageUrl, String picUrl, String title, String text) { - super(); - this.messageUrl = messageUrl; - this.picUrl = picUrl; - this.title = title; - this.text = text; - } - - @Override - public String type() { - return "link"; - } -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/Message.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/Message.java deleted file mode 100644 index 3ed7d44..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/Message.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.chinagas.modules.schsf.openApi.message; - - -public abstract class Message { - public abstract String type(); -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/MessageDelivery.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/MessageDelivery.java deleted file mode 100644 index fdd905f..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/MessageDelivery.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.chinagas.modules.schsf.openApi.message; - -import com.dingtalk.open.client.api.model.corp.MessageBody; - -public class MessageDelivery { - - public String msgType; - public MessageBody message; - - public MessageDelivery withMessage(String msgType, MessageBody msg) { - this.msgType = msgType; - this.message = msg; - return this; - } -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/MessageHelper.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/MessageHelper.java deleted file mode 100644 index 7c3a552..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/MessageHelper.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.chinagas.modules.schsf.openApi.message; - -import com.dingtalk.open.client.ServiceFactory; -import com.dingtalk.open.client.api.model.corp.MessageSendResult; -import com.dingtalk.open.client.api.service.corp.MessageService; - -/** - * 发送消息 - */ -public class MessageHelper { - - public static class Receipt { - String invaliduser; - String invalidparty; - } - - /** - * 发送普通消息 - * - * @param accessToken - * @param delivery - * @return - * @throws Exception - */ - public static Receipt send(String accessToken, LightAppMessageDelivery delivery) - throws Exception { - MessageService messageService = ServiceFactory.getInstance().getOpenService(MessageService.class); - MessageSendResult reulst = messageService.sendToCorpConversation(accessToken, delivery.touser, - delivery.toparty, delivery.agentid, delivery.msgType, delivery.message); - Receipt receipt = new Receipt(); - receipt.invaliduser = reulst.getInvaliduser(); - receipt.invalidparty = reulst.getInvalidparty(); - return receipt; - } - - - public static String send(String accessToken, ConversationMessageDelivery delivery) - throws Exception { - MessageService messageService = ServiceFactory.getInstance().getOpenService(MessageService.class); - return messageService.sendToNormalConversation(accessToken, delivery.sender, - delivery.cid, delivery.msgType, delivery.message); - } -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/OAMessage.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/OAMessage.java deleted file mode 100644 index ba7db05..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/OAMessage.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.chinagas.modules.schsf.openApi.message; - -import java.util.List; - -/** - { - "message_url": "http://dingtalk.com", - "head": { - "bgcolor": "FFCC0000" - }, - "body": { - "title": "标题", - "form": [ - { - "key": "姓名", - "value": "张三" - }, - { - "key": "年龄", - "value": "30" - } - ], - "rich": { - "num": "15.6", - "unit": "元" - }, - "content": "大段文本", - "image": "@lADOAAGXIszazQKA", - "file_count": "3", - "author": "李四" - } - */ -public class OAMessage extends Message { - - public String message_url; - public Head head; - public Body body; - - - @Override - public String type() { - return "oa"; - } - - //content - public static class Head { - public String bgcolor; - } - - public static class Body { - public String title; - public List

form; - public Rich rich; - public String content; - public String image; - public String file_found; - public String author; - - public static class Form { - public String key; - public String value; - } - - public static class Rich { - public String num; - public String unit; - } - } -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/TextMessage.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/TextMessage.java deleted file mode 100644 index edf3445..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/message/TextMessage.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.chinagas.modules.schsf.openApi.message; - - -public class TextMessage extends Message { - - public String content; - - public TextMessage(String content) { - super(); - this.content = content; - } - - @Override - public String type() { - return "text"; - } -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/user/User.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/user/User.java deleted file mode 100644 index 2791a4c..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/user/User.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.chinagas.modules.schsf.openApi.user; - -import java.util.List; - -import com.alibaba.fastjson.JSONObject; - -public class User { - public String userid; - public String name; - public boolean active; - public String avatar; - public List department; - public String position; - public String mobile; - public String tel; - public String workPlace; - public String remark; - public String email; - public String jobnumber; - public JSONObject extattr; - public boolean isAdmin; - public boolean isBoss; - public String dingId; - - - - public User() { - } - - public User(String userid, String name) { - this.userid = userid; - this.name = name; - } - - @Override - public String toString() { - List users; - return "User[userid:" + userid + ", name:" + name + ", active:" + active + ", " - + "avatar:" + avatar + ", department:" + department + - ", position:" + position + ", mobile:" + mobile + ", email:" + email + - ", extattr:" + extattr; - } -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/user/UserHelper.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/user/UserHelper.java deleted file mode 100644 index 6720b15..0000000 --- a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/openApi/user/UserHelper.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.chinagas.modules.schsf.openApi.user; - -import com.chinagas.modules.schsf.constant.Env; -import com.chinagas.modules.schsf.exception.OApiException; -import com.chinagas.modules.schsf.utils.FileUtils; -import com.chinagas.modules.schsf.utils.HttpHelper; -import com.alibaba.fastjson.JSONObject; -import com.dingtalk.open.client.ServiceFactory; -import com.dingtalk.open.client.api.model.corp.CorpUserBaseInfo; -import com.dingtalk.open.client.api.model.corp.CorpUserDetail; -import com.dingtalk.open.client.api.model.corp.CorpUserDetailList; -import com.dingtalk.open.client.api.model.corp.CorpUserList; -import com.dingtalk.open.client.api.service.corp.CorpUserService; - -import java.util.List; -import java.util.Map; - -/** - * 通讯录成员相关的接口调用 - */ -public class UserHelper { - - - /** - * 根据免登授权码查询免登用户userId - * - * @param accessToken - * @param code - * @return - * @throws Exception - */ - public static CorpUserBaseInfo getUserInfo(String accessToken, String code) throws Exception { - CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); - return corpUserService.getUserinfo(accessToken, code); - } - - /** - * 创建企业成员 - *

- * https://open-doc.dingtalk.com/docs/doc.htm?treeId=385&articleId=106816&docType=1#s1 - */ - public static String createUser(String accessToken, CorpUserDetail userDetail) throws Exception { - CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); - JSONObject js = (JSONObject) JSONObject.parse(userDetail.getOrderInDepts()); - Map orderInDepts = FileUtils.toHashMap(js); - - String userId = corpUserService.createCorpUser(accessToken, userDetail.getUserid(), userDetail.getName(), orderInDepts, - userDetail.getDepartment(), userDetail.getPosition(), userDetail.getMobile(), userDetail.getTel(), userDetail.getWorkPlace(), - userDetail.getRemark(), userDetail.getEmail(), userDetail.getJobnumber(), - userDetail.getIsHide(), userDetail.getSenior(), userDetail.getExtattr()); - - // 员工唯一标识ID - return userId; - } - - - /** - * 更新成员 - *

- * https://open-doc.dingtalk.com/docs/doc.htm?treeId=385&articleId=106816&docType=1#s2 - */ - public static void updateUser(String accessToken, CorpUserDetail userDetail) throws Exception { - CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); - JSONObject js = (JSONObject) JSONObject.parse(userDetail.getOrderInDepts()); - Map orderInDepts = FileUtils.toHashMap(js); - - corpUserService.updateCorpUser(accessToken, userDetail.getUserid(), userDetail.getName(), orderInDepts, - userDetail.getDepartment(), userDetail.getPosition(), userDetail.getMobile(), userDetail.getTel(), userDetail.getWorkPlace(), - userDetail.getRemark(), userDetail.getEmail(), userDetail.getJobnumber(), - userDetail.getIsHide(), userDetail.getSenior(), userDetail.getExtattr()); - } - - - /** - * 删除成员 - */ - public static void deleteUser(String accessToken, String userid) throws Exception { - CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); - corpUserService.deleteCorpUser(accessToken, userid); - } - - - //获取成员 - public static CorpUserDetail getUser(String accessToken, String userid) throws Exception { - - CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); - return corpUserService.getCorpUser(accessToken, userid); - } - - //批量删除成员 - public static void batchDeleteUser(String accessToken, List useridlist) - throws Exception { - CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); - corpUserService.batchdeleteCorpUserListByUserids(accessToken, useridlist); - - } - - - //获取部门成员 - public static CorpUserList getDepartmentUser( - String accessToken, - long departmentId, - Long offset, - Integer size, - String order) - throws Exception { - - CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); - return corpUserService.getCorpUserSimpleList(accessToken, departmentId, - offset, size, order); - } - - - //获取部门成员(详情) - public static CorpUserDetailList getUserDetails( - String accessToken, - long departmentId, - Long offset, - Integer size, - String order) - throws Exception { - - CorpUserService corpUserService = ServiceFactory.getInstance().getOpenService(CorpUserService.class); - return corpUserService.getCorpUserList(accessToken, departmentId, - offset, size, order); - } - - - /** - * 管理后台免登时通过CODE换取微应用管理员的身份信息 - * - * @param ssoToken - * @param code - * @return - * @throws OApiException - */ - public static JSONObject getAgentUserInfo(String ssoToken, String code) throws OApiException { - String url = Env.OAPI_HOST + "/sso/getuserinfo?" + "access_token=" + ssoToken + "&code=" + code; - JSONObject response = HttpHelper.httpGet(url); - return response; - } - -} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/service/DingtalkService.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/service/DingtalkService.java new file mode 100644 index 0000000..b091dd6 --- /dev/null +++ b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/service/DingtalkService.java @@ -0,0 +1,13 @@ +package com.chinagas.modules.schsf.service; + +public interface DingtalkService { + + + String getAccessToken(Long timeStamp); + + + String getJsapiTicket(String accessToken, Long timeStamp); + + String getSign(String ticket, String nonceStr, Long timeStamp, String url); + +} diff --git a/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/service/impl/DingtalkServiceImpl.java b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/service/impl/DingtalkServiceImpl.java new file mode 100644 index 0000000..da423b0 --- /dev/null +++ b/zr-cloud/zr-modules/zr-schsf/src/main/java/com/chinagas/modules/schsf/service/impl/DingtalkServiceImpl.java @@ -0,0 +1,79 @@ +package com.chinagas.modules.schsf.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.chinagas.common.core.exceptions.ServiceException; +import com.chinagas.modules.schsf.constant.DingtalkConstant; +import com.chinagas.modules.schsf.exception.OApiException; +import com.chinagas.modules.schsf.service.DingtalkService; +import com.dingtalk.oapi.lib.aes.DingTalkJsApiSingnature; +import com.dingtalk.open.client.ServiceFactory; +import com.dingtalk.open.client.api.model.corp.JsapiTicket; +import com.dingtalk.open.client.api.service.corp.CorpConnectionService; +import com.dingtalk.open.client.api.service.corp.JsapiService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class DingtalkServiceImpl implements DingtalkService { + + @Autowired + private DingtalkConstant dingtalkConstant; + + + /** + * 调整到1小时50分钟 + */ + public static final long cacheTime = 1000 * 60 * 55 * 2; + + @Override + public String getAccessToken(Long timeStamp) { + long curTime = timeStamp == null ? System.currentTimeMillis() : timeStamp; + String accToken = ""; + JSONObject jsontemp = new JSONObject(); + try { + ServiceFactory serviceFactory = ServiceFactory.getInstance(); + CorpConnectionService corpConnectionService = serviceFactory.getOpenService(CorpConnectionService.class); + accToken = corpConnectionService.getCorpToken(dingtalkConstant.getAppKey(), dingtalkConstant.getAppSecret()); + JSONObject jsonAccess = new JSONObject(); + jsontemp.clear(); + jsontemp.put("access_token", accToken); + jsontemp.put("begin_time", curTime); + jsonAccess.put(dingtalkConstant.getAppKey(), jsontemp); + } catch (Exception e) { + e.printStackTrace(); + } + return accToken; + } + + @Override + public String getJsapiTicket(String accessToken, Long timeStamp) { + long curTime = timeStamp == null ? System.currentTimeMillis() : timeStamp; + String jsTicket = ""; + ServiceFactory serviceFactory; + try { + serviceFactory = ServiceFactory.getInstance(); + JsapiService jsapiService = serviceFactory.getOpenService(JsapiService.class); + JsapiTicket JsapiTicket = jsapiService.getJsapiTicket(accessToken, "jsapi"); + jsTicket = JsapiTicket.getTicket(); + JSONObject jsonTicket = new JSONObject(); + JSONObject jsontemp = new JSONObject(); + jsontemp.clear(); + jsontemp.put("ticket", jsTicket); + jsontemp.put("begin_time", curTime); + jsonTicket.put(dingtalkConstant.getAppKey(), jsontemp); + } catch (Exception e) { + e.printStackTrace(); + } + return jsTicket; + + } + + @Override + public String getSign(String ticket, String nonceStr, Long timeStamp, String url) { + try { + return DingTalkJsApiSingnature.getJsApiSingnature(url, nonceStr, timeStamp, ticket); + } catch (Exception ex) { + throw new ServiceException(ex.getMessage()); + } + } +} -- libgit2 0.21.2