diff --git a/agileboot-admin/src/main/java/com/agileboot/admin/customize/service/QywxScheduleJob.java b/agileboot-admin/src/main/java/com/agileboot/admin/customize/service/QywxScheduleJob.java new file mode 100644 index 0000000..2cbcc3a --- /dev/null +++ b/agileboot-admin/src/main/java/com/agileboot/admin/customize/service/QywxScheduleJob.java @@ -0,0 +1,226 @@ +package com.agileboot.admin.customize.service; + +import cn.hutool.core.date.DateUtil; +import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService; +import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity; +import com.agileboot.domain.qywx.api.QywxApiUtil; +import com.agileboot.domain.qywx.api.response.DepartmentInfoResponse; +import com.agileboot.domain.qywx.api.response.DepartmentInfoResponse.Department; +import com.agileboot.domain.qywx.api.response.DepartmentListResponse; +import com.agileboot.domain.qywx.authCorpInfo.AuthCorpInfoApplicationService; +import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoEntity; +import com.agileboot.domain.qywx.department.DepartmentApplicationService; +import com.agileboot.domain.qywx.department.db.QyDepartmentEntity; +import com.agileboot.domain.qywx.template.TemplateApplicationService; +import com.agileboot.domain.qywx.template.command.UpdateTemplateCommand; +import com.agileboot.domain.qywx.template.db.QyTemplateEntity; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@RequiredArgsConstructor +@Component +@Slf4j +public class QywxScheduleJob { + private final TemplateApplicationService templateApplicationService; + private final AuthCorpInfoApplicationService authCorpInfoApplicationService; + private final AccessTokenApplicationService accessTokenApplicationService; + private final DepartmentApplicationService departmentApplicationService; + + private static final String appid = "QYTONG_YS_WXSHOP"; + private static final String appid2 = "QWTONG_YS_WXSHOP"; + + @Scheduled(cron = "0 10 * * * *") + public void getSuiteAccessTokenTask() { + try { + getSuiteAccessToken(appid); + } catch (Exception e) { + log.error("getSuiteAccessTokenTask appid: " + appid, e); + } + + try { + getSuiteAccessToken(appid2); + } catch (Exception e) { + log.error("getSuiteAccessTokenTask appid: " + appid2, e); + } + } + + public void getSuiteAccessToken(String appid) { + log.info("getSuiteAccessToken Current Thread : {}, Fixed Rate Task : The time is now {}", + Thread.currentThread().getName(), DateUtil.formatTime(new Date())); + + try { + QyTemplateEntity template = templateApplicationService.getByAppid(appid); + String suiteAccessToken = templateApplicationService.getSuiteAccessToken(template.getSuiteId(), template.getSecret(), + template.getSuiteTicket()); + + UpdateTemplateCommand command = new UpdateTemplateCommand(); + command.setId(template.getId()); + command.setSuiteAccessToken(suiteAccessToken); + templateApplicationService.updateTemplate(command); + } catch (Exception e) { + log.error("getSuiteAccessToken error", e); + } + } + + @Scheduled(cron = "0 20 * * * *") + public void getAccessTokenTask() { + try { + getAccessToken(appid); + } catch (Exception e) { + log.error("getAccessTokenTask error appid: " + appid, e); + } + + try { + getAccessToken(appid2); + } catch (Exception e) { + log.error("getAccessTokenTask error appid: " + appid2, e); + } + } + + public void getAccessToken(String appid) { + log.info("getAccessToken Current Thread : {}, Fixed Rate Task : The time is now {}", + Thread.currentThread().getName(), DateUtil.formatTime(new Date())); + try { + QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.getByAppid(appid); + if (null == authCorpInfo) { + return; + } + + accessTokenApplicationService.getAccessToken(authCorpInfo.getSuiteId(), authCorpInfo.getPermanentCode(), appid); + } catch (Exception e) { + log.error("getAccessToken error", e); + } + } + + @Scheduled(cron = "0 0 * * * *") + public void syncDepartmentInfoTask() { + try { + syncDepartmentInfo(appid); + } catch (Exception e) { + log.error("syncDepartmentInfoTask error appid: " + appid, e); + } + + try { + syncDepartmentInfo(appid2); + } catch (Exception e) { + log.error("syncDepartmentInfoTask error appid: " + appid2, e); + } + } + + + public void syncDepartmentInfo(String appid) { + log.info("syncDepartmentInfo Current Thread : {}, Fixed Rate Task : The time is now {}", + Thread.currentThread().getName(), DateUtil.formatTime(new Date())); + + try { + QyAuthCorpInfoEntity authCorpInfo = authCorpInfoApplicationService.getByAppid(appid); + if (authCorpInfo == null) { + return; + } + + QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid); + if (null == accessToken || StringUtils.isBlank(accessToken.getAccessToken())) { + log.error("syncDepartmentInfo accessToken is null"); + return; + } + + List txtDeptList = new ArrayList<>(); + // 获取部门列表 + DepartmentListResponse deptList = QywxApiUtil.getDepartmentSimplelist(accessToken.getAccessToken(), null); + if (deptList.getErrcode() != 0) { + log.error("获取部门列表失败: {}", deptList.getErrmsg()); + return; + } + + // 遍历部门获取详细信息 + for (DepartmentListResponse.DepartmentIdInfo dept : deptList.getDepartment_id()) { + DepartmentInfoResponse deptInfo = QywxApiUtil.getDepartmentInfo( + accessToken.getAccessToken(), + String.valueOf(dept.getId()) + ); + + txtDeptList.add(deptInfo.getDepartment()); + } + + if (!txtDeptList.isEmpty()) { + List departmentEntities = departmentApplicationService.getDepartmentList(); + if (null == departmentEntities) { + departmentEntities = new ArrayList<>(); + } + // 转换为Map结构 + Map localDeptMap = departmentEntities.stream() + .collect(Collectors.toMap(QyDepartmentEntity::getDepartmentId, Function.identity())); + + Map wxDeptMap = txtDeptList.stream() + .collect(Collectors.toMap(Department::getId, Function.identity())); + + // 识别新增部门(存在企业微信但不存在本地) + List toAdd = txtDeptList.stream() + .filter(d -> !localDeptMap.containsKey(String.valueOf(d.getId()))) + .collect(Collectors.toList()); + + // 识别删除部门(存在本地但不存在企业微信) + List toRemove = departmentEntities.stream() + .filter(d -> !wxDeptMap.containsKey(Long.parseLong(d.getDepartmentId()))) + .collect(Collectors.toList()); + + // 处理更新部门(ID相同但信息不同) + List toUpdate = departmentEntities.stream() + .filter(d -> wxDeptMap.containsKey(Long.parseLong(d.getDepartmentId()))) + .filter(d -> { + Department wxDept = wxDeptMap.get(Long.parseLong(d.getDepartmentId())); + return !d.getName().equals(wxDept.getName()) + || !d.getParentid().equals(String.valueOf(wxDept.getParentid())); + }) + .peek(d -> { + Department wxDept = wxDeptMap.get(Long.parseLong(d.getDepartmentId())); + d.setName(wxDept.getName()); + d.setParentid(String.valueOf(wxDept.getParentid())); + }) + .collect(Collectors.toList()); + + // 执行数据库操作 + if (!toAdd.isEmpty()) { + List newDeptList = toAdd.stream() + .map(d -> { + QyDepartmentEntity entity = new QyDepartmentEntity(); + entity.setDepartmentId(String.valueOf(d.getId())); + entity.setName(d.getName()); + entity.setNameEn(d.getName_en()); + String leader = String.join(",", d.getDepartment_leader()); + if (leader.length() > 255) { + leader = leader.substring(0, 255); + } + entity.setDepartmentLeader(leader); + entity.setParentid(String.valueOf(d.getParentid())); + entity.setAppid(appid); + entity.setEnable("1"); + return entity; + }) + .collect(Collectors.toList()); + departmentApplicationService.batchInsertDepartments(newDeptList); + } + if (!toUpdate.isEmpty()) { + departmentApplicationService.batchUpdateDepartments(toUpdate); + } + if (!toRemove.isEmpty()) { + departmentApplicationService.batchDeleteDepartments( + toRemove.stream().map(QyDepartmentEntity::getId).collect(Collectors.toList()) + ); + } + + } + } catch (Exception e) { + log.error("syncDepartmentInfo error", e); + } + } +} diff --git a/agileboot-api/src/main/java/com/agileboot/api/controller/QywxController.java b/agileboot-api/src/main/java/com/agileboot/api/controller/QywxController.java index 1680f19..127d6a7 100644 --- a/agileboot-api/src/main/java/com/agileboot/api/controller/QywxController.java +++ b/agileboot-api/src/main/java/com/agileboot/api/controller/QywxController.java @@ -1,21 +1,27 @@ package com.agileboot.api.controller; +import com.agileboot.api.customize.async.QyAsyncTaskFactory; import com.agileboot.common.exception.ApiException; import com.agileboot.common.exception.error.ErrorCode; import com.agileboot.common.utils.weixin.aes.WXBizMsgCrypt; import com.agileboot.domain.qywx.auth.AuthApplicationService; import com.agileboot.domain.qywx.auth.command.AddAuthCommand; +import com.agileboot.domain.qywx.authCorpInfo.AuthCorpInfoApplicationService; +import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoEntity; import com.agileboot.domain.qywx.message.db.QyMessageEntity; import com.agileboot.domain.qywx.template.TemplateApplicationService; import com.agileboot.domain.qywx.template.command.UpdateTemplateCommand; import com.agileboot.domain.qywx.template.db.QyTemplateEntity; +import com.agileboot.infrastructure.thread.ThreadPoolManager; import java.io.StringReader; import javax.annotation.PostConstruct; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; @@ -37,14 +43,52 @@ import org.xml.sax.InputSource; public class QywxController { private final TemplateApplicationService templateApplicationService; private final AuthApplicationService authApplicationService; + private final AuthCorpInfoApplicationService authCorpInfoApplicationService; + + @GetMapping("/getPermanentCode") + public String getPermanentCode( + @RequestParam String suiteAccessToken, + @RequestParam String authCode, + @RequestParam String appid) { + try { + QyAsyncTaskFactory.getPermanentCode(suiteAccessToken, authCode, appid); + return "success"; + } catch (Exception e) { + log.error("getPermanentCode error", e); + return e.getLocalizedMessage(); + } + } + + @GetMapping("/getSuiteAccessToken") + public String getSuiteAccessToken(@RequestParam String appid) { + try { + QyTemplateEntity template = templateApplicationService.getByAppid(appid); + String suiteAccessToken = templateApplicationService.getSuiteAccessToken(template.getSuiteId(), template.getSecret(), + template.getSuiteTicket()); + + if (StringUtils.isNotBlank(suiteAccessToken)) { + UpdateTemplateCommand command = new UpdateTemplateCommand(); + BeanUtils.copyProperties(template, command); + command.setId(template.getId()); + command.setSuiteAccessToken(suiteAccessToken); + templateApplicationService.updateTemplate(command); + return "success"; + } + return "fail"; + } catch (Exception e) { + log.error("getPermanentCode error", e); + return e.getLocalizedMessage(); + } + } @GetMapping("/callback/data") public String validateDataCallback(@RequestParam String msg_signature, @RequestParam String timestamp, @RequestParam String nonce, - @RequestParam String echostr) { + @RequestParam String echostr, + @RequestParam String appid) { try { - QyTemplateEntity template = templateApplicationService.getFirstEnabledTemplate(); + QyTemplateEntity template = templateApplicationService.getByAppid(appid); String token = template.getToken(); String encodingAesKey = template.getEncodingAESKey(); String corpId = template.getCorpid(); @@ -56,13 +100,35 @@ public class QywxController { } } + + @GetMapping("/callback/app") + public String validateAppCallback(@RequestParam String msg_signature, + @RequestParam String timestamp, + @RequestParam String nonce, + @RequestParam String echostr, + @RequestParam String appid) { + try { + QyAuthCorpInfoEntity qyAuthCorpInfo = authCorpInfoApplicationService.getByAppid(appid); + QyTemplateEntity template = templateApplicationService.getByAppid(appid); + String token = template.getToken(); + String encodingAesKey = template.getEncodingAESKey(); + String corpId = qyAuthCorpInfo.getCorpid(); + WXBizMsgCrypt wxCrypt = new WXBizMsgCrypt(token, encodingAesKey, corpId); + return wxCrypt.VerifyURL(msg_signature, timestamp, nonce, echostr); + } catch (Exception e) { + log.error("验证失败", e); + throw new ApiException(ErrorCode.FAILED, "验证失败", e); + } + } + @PostMapping("/callback/data") public String handleDataCallback(@RequestParam String msg_signature, @RequestParam String timestamp, @RequestParam String nonce, - @RequestBody String encryptedData) { + @RequestBody String encryptedData, + @RequestParam String appid) { try { - handleCommandCallback(msg_signature, timestamp, nonce, encryptedData); + handleCommandCallback(msg_signature, timestamp, nonce, encryptedData, appid); return "success"; } catch (Exception e) { log.error("验证失败", e); @@ -74,16 +140,18 @@ public class QywxController { public String validateCommandCallback(@RequestParam String msg_signature, @RequestParam String timestamp, @RequestParam String nonce, - @RequestParam String echostr) { - return validateDataCallback(msg_signature, timestamp, nonce, echostr); + @RequestParam String echostr, + @RequestParam String appid) { + return validateDataCallback(msg_signature, timestamp, nonce, echostr, appid); } @PostMapping("/callback/command") public String handleCommandCallback(@RequestParam String msg_signature, @RequestParam String timestamp, @RequestParam String nonce, - @RequestBody String encryptedData) { - Element root = parseXml(msg_signature, timestamp, nonce, encryptedData); + @RequestBody String encryptedData, + @RequestParam String appid) { + Element root = parseXml(msg_signature, timestamp, nonce, encryptedData, appid); NodeList InfoType = root.getElementsByTagName("InfoType"); String Content = InfoType.item(0).getTextContent(); // 处理业务逻辑 @@ -93,13 +161,13 @@ public class QywxController { String SuiteTicket = SuiteTicketNode.item(0).getTextContent(); NodeList SuiteIdNode = root.getElementsByTagName("SuiteId"); String SuiteId = SuiteIdNode.item(0).getTextContent(); - QyTemplateEntity template = templateApplicationService.getFirstEnabledTemplate(); + QyTemplateEntity template = templateApplicationService.getByAppid(appid); UpdateTemplateCommand command = new UpdateTemplateCommand(); command.setId(template.getId()); command.setSuiteTicket(SuiteTicket); - String suite_access_token = templateApplicationService.getSuiteAccessToken(SuiteId, template.getSecret(), SuiteTicket); - command.setSuiteAccessToken(suite_access_token); +// String suite_access_token = templateApplicationService.getSuiteAccessToken(SuiteId, template.getSecret(), SuiteTicket); +// command.setSuiteAccessToken(suite_access_token); templateApplicationService.updateTemplate(command); AddAuthCommand authCommand = new AddAuthCommand(); @@ -111,12 +179,13 @@ public class QywxController { authApplicationService.addAuth(authCommand); } break; - case "create_auth": { + case "create_auth": + case "reset_permanent_code": { NodeList AuthCodeNode = root.getElementsByTagName("AuthCode"); String AuthCode = AuthCodeNode.item(0).getTextContent(); NodeList SuiteIdNode = root.getElementsByTagName("SuiteId"); String SuiteId = SuiteIdNode.item(0).getTextContent(); - QyTemplateEntity template = templateApplicationService.getFirstEnabledTemplate(); + QyTemplateEntity template = templateApplicationService.getByAppid(appid); AddAuthCommand authCommand = new AddAuthCommand(); authCommand.setSuiteId(SuiteId); @@ -125,6 +194,10 @@ public class QywxController { authCommand.setAuthCode(AuthCode); authApplicationService.addAuth(authCommand); + String suiteAccessToken = template.getSuiteAccessToken(); + // 提交异步任务 +// ThreadPoolManager.execute(QyAsyncTaskFactory.getPermanentCodeTask(suiteAccessToken, AuthCode)); + QyAsyncTaskFactory.getPermanentCode(suiteAccessToken, AuthCode, appid); } break; default: @@ -139,13 +212,15 @@ public class QywxController { String msg_signature, String timestamp, String nonce, - String encryptedData) { + String encryptedData, + String appid) { try { - QyTemplateEntity template = templateApplicationService.getFirstEnabledTemplate(); + QyTemplateEntity template = templateApplicationService.getByAppid(appid); String token = template.getToken(); String encodingAesKey = template.getEncodingAESKey(); - String corpId = template.getCorpid(); - WXBizMsgCrypt wxCrypt = new WXBizMsgCrypt(token, encodingAesKey, corpId); +// String corpId = template.getCorpid(); + String SuiteId = template.getSuiteId(); + WXBizMsgCrypt wxCrypt = new WXBizMsgCrypt(token, encodingAesKey, SuiteId); String xmlContent = wxCrypt.DecryptMsg(msg_signature, timestamp, nonce, encryptedData); // 处理业务逻辑 // 解析XML内容 diff --git a/agileboot-api/src/main/java/com/agileboot/api/customize/async/GetAuthInfoResult.java b/agileboot-api/src/main/java/com/agileboot/api/customize/async/GetAuthInfoResult.java new file mode 100644 index 0000000..4808175 --- /dev/null +++ b/agileboot-api/src/main/java/com/agileboot/api/customize/async/GetAuthInfoResult.java @@ -0,0 +1,72 @@ +package com.agileboot.api.customize.async; + +import cn.hutool.json.JSONObject; +import lombok.Data; +import java.util.List; + +@Data +public class GetAuthInfoResult { + private Integer errcode; + private String errmsg; + private DealerCorpInfo dealer_corp_info; + private AuthCorpInfo auth_corp_info; + private AuthInfo auth_info; + + @Data + public static class DealerCorpInfo { + private String corpid; + private String corp_name; + } + + @Data + public static class AuthCorpInfo { + // 原有字段 + private String corpid; + private String corp_name; + private String corp_type; + private String corp_square_logo_url; + private Integer corp_user_max; + private String corp_full_name; + private Long verified_end_time; + private Integer subject_type; + + // 新增字段 + private String corp_scale; + private String corp_industry; + private String corp_sub_industry; + private CorpExName corp_ex_name; + + @Data + public static class CorpExName { + private String name_list; + } + } + + @Data + public static class AuthInfo { + private List agent; + } + + @Data + public static class Agent { + // 原有字段 + private Integer agentid; + private String name; + private String round_logo_url; + private String square_logo_url; + private Integer appid; + private JSONObject privilege; + + // 新增字段 + private Integer auth_mode; + private Boolean is_customized_app; + private Boolean auth_from_thirdapp; + private SharedFrom shared_from; + + @Data + public static class SharedFrom { + private String corpid; + private Integer share_type; + } + } +} \ No newline at end of file diff --git a/agileboot-api/src/main/java/com/agileboot/api/customize/async/GetPermanentCodeResult.java b/agileboot-api/src/main/java/com/agileboot/api/customize/async/GetPermanentCodeResult.java new file mode 100644 index 0000000..187eb8f --- /dev/null +++ b/agileboot-api/src/main/java/com/agileboot/api/customize/async/GetPermanentCodeResult.java @@ -0,0 +1,44 @@ +package com.agileboot.api.customize.async; + +import cn.hutool.json.JSONObject; +import lombok.Data; +import java.util.List; + +@Data +public class GetPermanentCodeResult { + private Integer errcode; + private String errmsg; + // 移除 access_token 和 expires_in 字段 + private String permanent_code; + private AuthCorpInfo auth_corp_info; + + // 新增字段 + private AuthUserInfo auth_user_info; + private RegisterCodeInfo register_code_info; + private String state; + + @Data + public static class AuthCorpInfo { + private String corpid; + private String corp_name; + // ... 保留其他字段不变 ... + } + + // 新增内部类 + @Data + public static class AuthUserInfo { + private String userid; + private String open_userid; + private String name; + private String avatar; + } + + @Data + public static class RegisterCodeInfo { + private String register_code; + private String template_id; + private String state; + } + + // 移除原有的 AuthInfo 和 Agent 类 +} \ No newline at end of file diff --git a/agileboot-api/src/main/java/com/agileboot/api/customize/async/QyAsyncTaskFactory.java b/agileboot-api/src/main/java/com/agileboot/api/customize/async/QyAsyncTaskFactory.java index eddc80d..70f6108 100644 --- a/agileboot-api/src/main/java/com/agileboot/api/customize/async/QyAsyncTaskFactory.java +++ b/agileboot-api/src/main/java/com/agileboot/api/customize/async/QyAsyncTaskFactory.java @@ -6,15 +6,23 @@ import cn.hutool.http.HttpRequest; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.agileboot.domain.qywx.auth.db.QyAuthService; +import com.agileboot.domain.qywx.authCorpInfo.AuthCorpInfoApplicationService; +import com.agileboot.domain.qywx.authCorpInfo.command.AddAuthCorpInfoCommand; +import com.agileboot.domain.qywx.authCorpInfo.command.UpdateAuthCorpInfoCommand; import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoService; +import com.agileboot.domain.qywx.template.TemplateApplicationService; +import com.agileboot.domain.qywx.template.db.QyTemplateEntity; import java.util.HashMap; import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +@Slf4j public class QyAsyncTaskFactory { - public static Runnable getPermanentCodeTask(String suiteAccessToken, String authCode) { + public static Runnable getPermanentCodeTask(String suiteAccessToken, String authCode, String appid) { return () -> { - String url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=" + suiteAccessToken; + String url = "https://qyapi.weixin.qq.com/cgi-bin/service/v2/get_permanent_code?suite_access_token=" + suiteAccessToken; Map requestBody = new HashMap(); requestBody.put("auth_code", authCode); @@ -22,19 +30,207 @@ public class QyAsyncTaskFactory { String response = HttpRequest.post(url) .body(JSONUtil.toJsonStr(requestBody)) .execute().body(); - - JSONObject result = JSONUtil.parseObj(response); - if(!result.containsKey("errcode")) { - handleSuccessResponse(result); - } else { - handleErrorResponse(result); - } + + GetPermanentCodeResult result = JSONUtil.toBean(response, GetPermanentCodeResult.class); + handleSuccessResponse(result, suiteAccessToken, authCode, appid); }; } - private static void handleSuccessResponse(JSONObject result) { + public static String getPermanentCode(String suiteAccessToken, String authCode, String appid) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/service/v2/get_permanent_code?suite_access_token=" + suiteAccessToken; + + Map requestBody = new HashMap(); + requestBody.put("auth_code", authCode); + + String response = HttpRequest.post(url) + .body(JSONUtil.toJsonStr(requestBody)) + .execute().body(); + + GetPermanentCodeResult result = JSONUtil.toBean(response, GetPermanentCodeResult.class); + log.info("getPermanentCode result:{}", response); + if(null == result.getErrcode() || 0 == result.getErrcode()) { + handleSuccessResponse(result, suiteAccessToken, authCode, appid); + } else { + handleErrorResponse(result); + } + + return "success"; } - private static void handleErrorResponse(JSONObject result) { + private static void handleSuccessResponse(GetPermanentCodeResult result, String suiteAccessToken, String authCode, String appid) { + AddAuthCorpInfoCommand command = new AddAuthCorpInfoCommand(); + command.setPermanentCode(result.getPermanent_code()); + command.setCorpid(result.getAuth_corp_info().getCorpid()); + command.setCorpName(result.getAuth_corp_info().getCorp_name()); + command.setUserid(result.getAuth_user_info().getUserid()); + command.setOpenUserid(result.getAuth_user_info().getOpen_userid()); + command.setName(result.getAuth_user_info().getName()); + command.setAvatar(result.getAuth_user_info().getAvatar()); + command.setState(result.getState()); + command.setAppid(appid); + + AuthCorpInfoApplicationService authCorpInfoApplicationService = SpringUtil.getBean(AuthCorpInfoApplicationService.class); + authCorpInfoApplicationService.addAuthCorpInfo(command); +// UpdateAuthCorpInfoCommand updateAuthCorpInfoCommand = new UpdateAuthCorpInfoCommand(); +// BeanUtils.copyProperties(command, updateAuthCorpInfoCommand); + /*try { + getAuthInfo(updateAuthCorpInfoCommand, suiteAccessToken); + } catch (Exception e) { + log.error("获取企业授权信息失败", e); + }*/ + } + + private static void handleErrorResponse(GetPermanentCodeResult result) { + } + + + + private static void getAuthInfo(UpdateAuthCorpInfoCommand updateAuthCorpInfoCommand, String suiteAccessToken) { + + String url = "https://qyapi.weixin.qq.com/cgi-bin/service/v2/get_auth_info?suite_access_token=" + suiteAccessToken; + + Map requestBody = new HashMap(); + requestBody.put("auth_corpid", updateAuthCorpInfoCommand.getCorpid()); + requestBody.put("permanent_code", updateAuthCorpInfoCommand.getPermanentCode()); + + String response = HttpRequest.post(url) + .body(JSONUtil.toJsonStr(requestBody)) + .execute().body(); + + GetAuthInfoResult result = JSONUtil.toBean(response, GetAuthInfoResult.class); + if(null == result.getErrcode() || 0 == result.getErrcode()) { +// updateAuthCorpInfoCommand.setId(); +// updateAuthCorpInfoCommand.setAuthCorpInfo(); +// updateAuthCorpInfoCommand.setAuthState(); +// updateAuthCorpInfoCommand.setUrl(); +// updateAuthCorpInfoCommand.setToken(); +// updateAuthCorpInfoCommand.setEncodingAESKey(); +// updateAuthCorpInfoCommand.setAppid(); +// updateAuthCorpInfoCommand.setSuiteId(); +// updateAuthCorpInfoCommand.setAuthCode(); +// updateAuthCorpInfoCommand.setAgentid(); +// updateAuthCorpInfoCommand.setAgentname(); +// updateAuthCorpInfoCommand.setCorpFullName(); +// updateAuthCorpInfoCommand.setCorpIndustry(); +// updateAuthCorpInfoCommand.setCorpScale(); +// updateAuthCorpInfoCommand.setCorpSquareLogoUrl(); +// updateAuthCorpInfoCommand.setCorpType(); +// updateAuthCorpInfoCommand.setCorpUserMax(); +// updateAuthCorpInfoCommand.setCorpWxqrcode(); +// updateAuthCorpInfoCommand.setSubjectType(); +// updateAuthCorpInfoCommand.setVerifiedEndTime(); +// updateAuthCorpInfoCommand.setCorpSubIndustry(); +// updateAuthCorpInfoCommand.setOperId(); + } + + } + + public static void main2(String[] args) throws Exception { + String res = "{\n" + + "\t\"errmsg\":\"ok\",\n" + + "\t\"permanent_code\": \"xxxx\", \n" + + "\t\"auth_corp_info\": \n" + + "\t{\n" + + "\t\t\"corpid\": \"xxxx\",\n" + + "\t\t\"corp_name\": \"name\"\n" + + "\t},\n" + + "\t\"auth_user_info\":\n" + + "\t{\n" + + "\t\t\"userid\":\"aa\",\n" + + "\t\t\"open_userid\":\"xxxxxx\",\n" + + "\t\t\"name\":\"xxx\",\n" + + "\t\t\"avatar\":\"http://xxx\"\n" + + "\t},\n" + + "\t\"register_code_info\":\n" + + "\t{\n" + + "\t\t\"register_code\":\"1111\",\n" + + "\t\t\"template_id\":\"tpl111\",\n" + + "\t\t\"state\":\"state001\"\n" + + "\t},\n" + + "\t\"state\":\"state001\"\n" + + "}"; + + GetPermanentCodeResult result = JSONUtil.toBean(res, GetPermanentCodeResult.class); + log.info("res: {}", res); + log.info("result: {}", result); + log.info("result: {}", JSONUtil.toJsonStr(result)); + } + + + public static void main(String[] args) throws Exception { + String res = "{\n" + + " \"errcode\":0,\n" + + " \"errmsg\":\"ok\",\n" + + "\t\"dealer_corp_info\": \n" + + "\t{\n" + + "\t\t\"corpid\": \"xxxx\",\n" + + "\t\t\"corp_name\": \"name\"\n" + + "\t},\n" + + "\t\"auth_corp_info\": \n" + + "\t{\n" + + "\t\t\"corpid\": \"xxxx\",\n" + + "\t\t\"corp_name\": \"name\",\n" + + "\t\t\"corp_type\": \"verified\",\n" + + "\t\t\"corp_square_logo_url\": \"yyyyy\",\n" + + "\t\t\"corp_user_max\": 50,\n" + + "\t\t\"corp_full_name\":\"full_name\",\n" + + "\t\t\"verified_end_time\":1431775834,\n" + + "\t\t\"subject_type\": 1,\n" + + "\t\t\"corp_scale\": \"1-50人\",\n" + + "\t\t\"corp_industry\": \"IT服务\",\n" + + "\t\t\"corp_sub_industry\": \"计算机软件/硬件/信息服务\",\n" + + "\t\t\"corp_ex_name\":{\n" + + "\t\t\t\"name_list\":\"xx\"\n" + + "\t\t}\n" + + "\t},\n" + + "\t\"auth_info\":\n" + + "\t{\n" + + "\t\t\"agent\" :\n" + + "\t\t[\n" + + "\t\t\t{\n" + + "\t\t\t\t\"agentid\":1,\n" + + "\t\t\t\t\"name\":\"NAME\",\n" + + "\t\t\t\t\"round_logo_url\":\"xxxxxx\",\n" + + "\t\t\t\t\"square_logo_url\":\"yyyyyy\",\n" + + "\t\t\t\t\"appid\":1,\n" + + "\t\t\t\t\"auth_mode\":1,\n" + + "\t\t\t\t\"is_customized_app\":false,\n" + + "\t\t\t\t\"auth_from_thirdapp\":false,\n" + + "\t\t\t\t\"privilege\":\n" + + "\t\t\t\t{\n" + + "\t\t\t\t\t\"level\":1,\n" + + "\t\t\t\t\t\"allow_party\":[1,2,3],\n" + + "\t\t\t\t\t\"allow_user\":[\"zhansan\",\"lisi\"],\n" + + "\t\t\t\t\t\"allow_tag\":[1,2,3],\n" + + "\t\t\t\t\t\"extra_party\":[4,5,6],\n" + + "\t\t\t\t\t\"extra_user\":[\"wangwu\"],\n" + + "\t\t\t\t\t\"extra_tag\":[4,5,6]\n" + + "\t\t\t\t},\n" + + "\t\t\t\t\"shared_from\":\n" + + "\t\t\t\t{\n" + + "\t\t\t\t\t\"corpid\":\"wwyyyyy\",\n" + + "\t\t\t\t\t\"share_type\": 1\n" + + "\t\t\t\t}\n" + + "\t\t\t},\n" + + "\t\t\t{\n" + + "\t\t\t\t\"agentid\":2,\n" + + "\t\t\t\t\"name\":\"NAME2\",\n" + + "\t\t\t\t\"round_logo_url\":\"xxxxxx\",\n" + + "\t\t\t\t\"square_logo_url\":\"yyyyyy\",\n" + + "\t\t\t\t\"appid\":5,\n" + + "\t\t\t\t\"shared_from\":\n" + + "\t\t\t\t{\n" + + "\t\t\t\t\t\"corpid\":\"wwyyyyy\",\n" + + "\t\t\t\t\t\"share_type\": 0\n" + + "\t\t\t\t}\n" + + "\t\t\t}\n" + + "\t\t]\n" + + "\t}\n" + + "}"; + + GetAuthInfoResult result = JSONUtil.toBean(res, GetAuthInfoResult.class); + log.info("res: {}", res); + log.info("result: {}", result); + log.info("result: {}", JSONUtil.toJsonStr(result)); } } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/AccessTokenApplicationService.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/AccessTokenApplicationService.java index e90bb74..f729a44 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/AccessTokenApplicationService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/AccessTokenApplicationService.java @@ -1,5 +1,8 @@ package com.agileboot.domain.qywx.accessToken; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import com.agileboot.common.core.page.PageDTO; import com.agileboot.domain.common.command.BulkOperationCommand; import com.agileboot.domain.qywx.accessToken.command.AddAccessTokenCommand; @@ -11,11 +14,15 @@ import com.agileboot.domain.qywx.accessToken.model.AccessTokenModel; import com.agileboot.domain.qywx.accessToken.model.AccessTokenModelFactory; import com.agileboot.domain.qywx.accessToken.query.SearchQyAccessTokenQuery; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import java.util.Date; import java.util.List; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +@Slf4j @Service @RequiredArgsConstructor public class AccessTokenApplicationService { @@ -48,4 +55,43 @@ public class AccessTokenApplicationService { model.deleteById(); } } + + public QyAccessTokenEntity getByAppid(String appid) { + return accessTokenService.getByAppid(appid); + } + + public void getAccessToken(String corpid, String corpsecret, String appid) { + String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid="+corpid+"&corpsecret="+corpsecret; + + String response = HttpUtil.get(url); + log.info("getAccessToken response: {}", response); + JSONObject jsonObject = JSONUtil.parseObj(response); + String access_token = jsonObject.getStr("access_token"); + Integer expires_in = jsonObject.getInt("expires_in"); + if (StringUtils.isBlank(access_token)) { + log.error("getAccessToken error: {}", response); + return; + } + + QyAccessTokenEntity accessToken = accessTokenService.getByAppid(appid); + if (null == accessToken) { + AddAccessTokenCommand command = new AddAccessTokenCommand(); + command.setAppid(appid); + command.setAccessToken(access_token); + command.setExpiresIn(expires_in); + command.setCorpid(corpid); + command.setSecret(corpsecret); + command.setGettokenTime(new Date()); + addAccessToken(command); + } else { + UpdateAccessTokenCommand command = new UpdateAccessTokenCommand(); + command.setId(accessToken.getId()); + command.setAccessToken(access_token); + command.setExpiresIn(expires_in); + command.setCorpid(corpid); + command.setSecret(corpsecret); + command.setGettokenTime(new Date()); + updateAccessToken(command); + } + } } \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenMapper.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenMapper.java index 8a317b7..bf998a7 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenMapper.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenMapper.java @@ -1,5 +1,6 @@ package com.agileboot.domain.qywx.accessToken.db; +import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoEntity; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.toolkit.Constants; @@ -30,4 +31,7 @@ public interface QyAccessTokenMapper extends BaseMapper { "WHERE enable = '1' " + "ORDER BY gettoken_time DESC") List selectAll(); + + @Select("SELECT * FROM qy_access_token WHERE appid = #{appid} LIMIT 1") + QyAccessTokenEntity selectByAppid(String appid); } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenService.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenService.java index 8ae10c4..3f28f24 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenService.java @@ -1,6 +1,7 @@ package com.agileboot.domain.qywx.accessToken.db; import com.agileboot.common.core.page.AbstractPageQuery; +import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoEntity; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import java.util.List; @@ -17,4 +18,6 @@ public interface QyAccessTokenService extends IService { Page getAccessTokenList(AbstractPageQuery query); List selectAll(); + + QyAccessTokenEntity getByAppid(String appid); } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenServiceImpl.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenServiceImpl.java index dc32f38..3b818f6 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenServiceImpl.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/accessToken/db/QyAccessTokenServiceImpl.java @@ -35,4 +35,9 @@ public class QyAccessTokenServiceImpl extends ServiceImpl department_leader; + private Long parentid; + private Integer order; + } +} diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/api/response/DepartmentListResponse.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/api/response/DepartmentListResponse.java new file mode 100644 index 0000000..0244100 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/api/response/DepartmentListResponse.java @@ -0,0 +1,22 @@ +package com.agileboot.domain.qywx.api.response; + +import lombok.Data; +import java.util.List; + +@Data +public class DepartmentListResponse { + private Integer errcode; + + private String errmsg; + + private List department_id; + + @Data + public static class DepartmentIdInfo { + private Long id; + + private Long parentid; + + private Long order; + } +} \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/AuthCorpInfoApplicationService.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/AuthCorpInfoApplicationService.java index 93d83e6..a7037b1 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/AuthCorpInfoApplicationService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/AuthCorpInfoApplicationService.java @@ -34,6 +34,7 @@ public class AuthCorpInfoApplicationService { AuthCorpInfoModel model = authCorpInfoModelFactory.create(); model.loadAddCommand(command); model.insert(); + command.setId(model.getId()); } public void updateAuthCorpInfo(UpdateAuthCorpInfoCommand command) { @@ -48,4 +49,9 @@ public class AuthCorpInfoApplicationService { model.deleteById(); } } + + + public QyAuthCorpInfoEntity getByAppid(String appid) { + return authCorpInfoService.getByAppid(appid); + } } \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoMapper.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoMapper.java index bd76dc0..44f8788 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoMapper.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoMapper.java @@ -30,4 +30,8 @@ public interface QyAuthCorpInfoMapper extends BaseMapper { "WHERE enable = '1' " + "ORDER BY verified_end_time DESC") List selectAll(); + + + @Select("SELECT * FROM qy_auth_corp_info WHERE appid = #{appid} LIMIT 1") + QyAuthCorpInfoEntity selectByAppid(String appid); } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoService.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoService.java index 97efb4d..ab400c1 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoService.java @@ -18,4 +18,6 @@ public interface QyAuthCorpInfoService extends IService { Page getAuthCorpInfoList(AbstractPageQuery query); List selectAll(); + + QyAuthCorpInfoEntity getByAppid(String appid); } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoServiceImpl.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoServiceImpl.java index 92f0806..3fadf22 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoServiceImpl.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/authCorpInfo/db/QyAuthCorpInfoServiceImpl.java @@ -29,4 +29,9 @@ public class QyAuthCorpInfoServiceImpl extends ServiceImpl wrapper = new LambdaQueryWrapper<>(); return this.list(wrapper); } + + @Override + public QyAuthCorpInfoEntity getByAppid(String appid) { + return baseMapper.selectByAppid(appid); + } } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/department/DepartmentApplicationService.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/department/DepartmentApplicationService.java index 866e0a6..8b62ab2 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/department/DepartmentApplicationService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/department/DepartmentApplicationService.java @@ -22,6 +22,18 @@ public class DepartmentApplicationService { private final QyDepartmentService departmentService; private final DepartmentModelFactory departmentModelFactory; + public void batchInsertDepartments(List departments) { + departmentService.saveBatch(departments); + } + + public void batchUpdateDepartments(List departments) { + departmentService.updateBatchById(departments); + } + + public void batchDeleteDepartments(List ids) { + departmentService.removeBatchByIds(ids); + } + public PageDTO getDepartmentList(SearchQyDepartmentQuery query) { Page page = departmentService.getDepartmentList(query); List dtoList = page.getRecords().stream() @@ -48,4 +60,8 @@ public class DepartmentApplicationService { model.deleteById(); } } + + public List getDepartmentList() { + return departmentService.selectAll(); + } } \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/TemplateApplicationService.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/TemplateApplicationService.java index 24307e7..a2938fa 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/TemplateApplicationService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/TemplateApplicationService.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.cache.annotation.Cacheable; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -26,6 +27,7 @@ import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONUtil; @Service +@Slf4j @RequiredArgsConstructor public class TemplateApplicationService { private final QyTemplateService templateService; @@ -78,6 +80,12 @@ public class TemplateApplicationService { return templateService.getBySuiteId(suiteId); } + + + public QyTemplateEntity getByAppid(String appid) { + return templateService.getByAppid(appid); + } + // @Cacheable(value = "qyTemplate", key = "#root.methodName", unless = "#result == null") public String getSuiteAccessToken(String suiteId, String suiteSecret, String suiteTicket) { String url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token"; @@ -89,11 +97,9 @@ public class TemplateApplicationService { .toString(); String response = HttpUtil.post(url, jsonParams); + log.info("getSuiteAccessToken response: {}", response); JSONObject jsonObject = JSONUtil.parseObj(response); - - if (jsonObject.getStr("errcode").equals("0")) { - return jsonObject.getStr("suite_access_token"); - } - throw new RuntimeException("获取suite_access_token失败"); + + return jsonObject.getStr("suite_access_token"); } } \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateMapper.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateMapper.java index 5ad90b4..2ec72fe 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateMapper.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateMapper.java @@ -40,4 +40,7 @@ public interface QyTemplateMapper extends BaseMapper { @Select("SELECT * FROM qy_template WHERE suiteId = #{suiteId} LIMIT 1") QyTemplateEntity selectBySuiteId(String suiteId); + + @Select("SELECT * FROM qy_template WHERE appid = #{appid} LIMIT 1") + QyTemplateEntity selectByAppid(String appid); } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateService.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateService.java index b6641b9..23d4d12 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateService.java @@ -21,4 +21,6 @@ public interface QyTemplateService extends IService { QyTemplateEntity getFirstEnabledTemplate(); QyTemplateEntity getBySuiteId(String suiteId); + + public QyTemplateEntity getByAppid(String appid); } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateServiceImpl.java b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateServiceImpl.java index 5201fb9..0accd40 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateServiceImpl.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/qywx/template/db/QyTemplateServiceImpl.java @@ -40,4 +40,8 @@ public class QyTemplateServiceImpl extends ServiceImpl 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [developer.work.weixin.qq.com](https://developer.work.weixin.qq.com/document/14942) 获取企业永久授权码 最后更新:2024/07/12 +> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [developer.work.weixin.qq.com](https://developer.work.weixin.qq.com/document/path/100776) 获取企业永久授权码 最后更新:2025/03/10 -该 API 用于使用临时授权码换取授权方的永久授权码,并换取授权信息、企业 access_token,临时授权码一次有效。 +该 API 用于使用临时授权码换取授权方的永久授权码以及企业信息,临时授权码一次有效。 **请求方式:**POST(**HTTPS**) -**请求地址:** https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=SUITE_ACCESS_TOKEN +**请求地址:** https://qyapi.weixin.qq.com/cgi-bin/service/v2/get_permanent_code?suite_access_token=SUITE_ACCESS_TOKEN **请求包体:** @@ -15,7 +15,7 @@ **参数说明:** -
参数是否必须说明
auth_code临时授权码,会在授权成功时附加在 redirect_uri 中跳转回第三方服务商网站,或通过授权成功通知回调推送给服务商。长度为 64 至 512 个字节
+
参数是否必须说明
auth_code临时授权码,会在授权成功时附加在 redirect_uri 中跳转回第三方服务商网站,或通过授权成功通知回调推送给服务商。长度为 64 至 512 个字节。临时授权码一次有效
**返回结果:** @@ -23,71 +23,11 @@ { "errcode":0, "errmsg":"ok", - "access_token": "xxxxxx", - "expires_in": 7200, "permanent_code": "xxxx", - "dealer_corp_info": - { - "corpid": "xxxx", - "corp_name": "name" - }, "auth_corp_info": { "corpid": "xxxx", - "corp_name": "name", - "corp_type": "verified", - "corp_square_logo_url": "yyyyy", - "corp_user_max": 50, - "corp_full_name":"full_name", - "verified_end_time":1431775834, - "subject_type": 1, - "corp_wxqrcode": "zzzzz", - "corp_scale": "1-50人", - "corp_industry": "IT服务", - "corp_sub_industry": "计算机软件/硬件/信息服务" - }, - "auth_info": - { - "agent" : - [ - { - "agentid":1, - "name":"NAME", - "round_logo_url":"xxxxxx", - "square_logo_url":"yyyyyy", - "appid":1, - "auth_mode":1, - "is_customized_app":false, - "auth_from_thirdapp":false, - "privilege": - { - "level":1, - "allow_party":[1,2,3], - "allow_user":["zhansan","lisi"], - "allow_tag":[1,2,3], - "extra_party":[4,5,6], - "extra_user":["wangwu"], - "extra_tag":[4,5,6] - }, - "shared_from": - { - "corpid":"wwyyyyy", - "share_type": 1 - } - }, - { - "agentid":2, - "name":"NAME2", - "round_logo_url":"xxxxxx", - "square_logo_url":"yyyyyy", - "appid":5, - "shared_from": - { - "corpid":"wwyyyyy", - "share_type": 0 - } - } - ] + "corp_name": "name" }, "auth_user_info": { @@ -108,11 +48,10 @@ **参数说明:** -
参数说明
access_token授权方(企业)access_token, 最长为 512 字节。代开发自建应用安装时不返回。
expires_in授权方(企业)access_token 超时时间(秒)。代开发自建应用安装时不返回。
permanent_code企业微信永久授权码, 最长为 512 字节
auth_corp_info授权方企业信息
auth_corp_info.corpid授权方企业微信 id
auth_corp_info.corp_name授权方企业名称,即企业简称
auth_corp_info.corp_type授权方企业类型,认证号:verified, 注册号:unverified
auth_corp_info.corp_square_logo_url授权方企业方形头像
auth_corp_info.corp_user_max授权方企业用户规模
auth_corp_info.corp_full_name授权方企业的主体名称 (仅认证或验证过的企业有),即企业全称。企业微信将逐步回收该字段,后续实际返回内容为企业名称,即 auth_corp_info.corp_name。
auth_corp_info.subject_type企业类型,1. 企业; 2. 政府以及事业单位; 3. 其他组织, 4. 团队号
auth_corp_info.verified_end_time认证到期时间
auth_corp_info.corp_wxqrcode授权企业在微信插件(原企业号)的二维码,可用于关注微信插件
auth_corp_info.corp_scale企业规模。当企业未设置该属性时,值为空。成员授权下,即 auth_info.agent.auth_mode 为 1 时值为空
auth_corp_info.corp_industry企业所属行业。当企业未设置该属性时,值为空。成员授权下,即 auth_info.agent.auth_mode 为 1 时值为空
auth_corp_info.corp_sub_industry企业所属子行业。当企业未设置该属性时,值为空。成员授权下,即 auth_info.agent.auth_mode 为 1 时值为空
auth_info授权信息。如果是通讯录应用,且没开启实体应用,是没有该项的。通讯录应用拥有企业通讯录的全部信息读写权限。「第三方会话存档接口」不返回该字段
auth_info.agent授权的应用信息,注意是一个数组,但仅旧的多应用套件授权时会返回多个 agent,对新的单应用授权,永远只返回一个 agent
auth_info.agent.agentid授权方应用 id
auth_info.agent.name授权方应用名字
auth_info.agent.square_logo_url授权方应用方形头像
auth_info.agent.round_logo_url授权方应用圆形头像
auth_info.agent.appid旧的多应用套件中的对应应用 id,新开发者请忽略
auth_info.agent.auth_mode授权模式,0 为管理员授权;1 为成员授权
auth_info.agent.is_customized_app是否为代开发自建应用
auth_info.agent.auth_from_thirdapp来自第三方应用接口唤起, 仅通过第三方应用添加自建应用 获取授权链接授权代开发自建应用时,才返回该字段
auth_info.agent.privilege应用对应的权限
auth_info.agent.privilege.allow_party应用可见范围(部门)
auth_info.agent.privilege.allow_tag应用可见范围(标签)
auth_info.agent.privilege.allow_user应用可见范围(成员)
auth_info.agent.privilege.extra_party额外通讯录(部门)
auth_info.agent.privilege.extra_user额外通讯录(成员)
auth_info.agent.privilege.extra_tag额外通讯录(标签)
auth_info.agent.privilege.level权限等级。
1: 通讯录基本信息只读
2: 通讯录全部信息只读
3: 通讯录全部信息读写
4: 单个基本信息只读
5: 通讯录全部信息只写
auth_info.agent.shared_from共享了应用的企业信息,仅当由企业互联或者上下游共享应用触发的安装时才返回
auth_info.agent.shared_from.corpid共享了应用的企业信息,仅当企业互联或者上下游共享应用触发的安装时才返回
auth_info.agent.shared_from.share_type共享了途径,0 表示企业互联,1 表示上下游
auth_user_info授权管理员的信息,可能不返回
auth_user_info.userid授权管理员的 userid,可能为空
auth_user_info.open_userid授权管理员的 open_userid,可能为空
auth_user_info.name授权管理员的 name,可能为空
auth_user_info.avatar授权管理员的头像 url,可能为空
dealer_corp_info代理服务商企业信息。应用被代理后才有该信息
dealer_corp_info.corpid代理服务商企业微信 id
dealer_corp_info.corp_name代理服务商企业微信名称
register_code_info推广二维码安装相关信息,扫推广二维码安装时返回。成员授权时暂不支持。(注:无论企业是否新注册,只要通过扫推广二维码安装,都会返回该字段)
register_code_info.register_code注册码
register_code_info.template_id推广包 ID
register_code_info.state仅当获取注册码指定该字段时才返回
state安装应用时,扫码或者授权链接中带的 state 值。详见 state 说明
- - -**注意**:因历史原因,该接口在调用失败时才返回 errcode。没返回 errcode 视为调用成功 +
参数说明
access_token授权方(企业)access_token, 最长为 512 字节。代开发自建应用安装时不返回。
expires_in授权方(企业)access_token 超时时间(秒)。代开发自建应用安装时不返回。
permanent_code企业微信永久授权码, 最长为 512 字节
auth_corp_info授权方企业信息
auth_corp_info.corpid授权方企业微信 id
auth_corp_info.corp_name授权方企业名称,即企业简称
auth_user_info授权管理员的信息,可能不返回
auth_user_info.userid授权管理员的 userid,可能为空
auth_user_info.open_userid授权管理员的 open_userid,可能为空
auth_user_info.name授权管理员的 name,可能为空
auth_user_info.avatar授权管理员的头像 url,可能为空
register_code_info推广二维码安装相关信息,扫推广二维码安装时返回。成员授权时暂不支持。(注:无论企业是否新注册,只要通过扫推广二维码安装,都会返回该字段)
register_code_info.register_code注册码
register_code_info.template_id推广包 ID
register_code_info.state仅当获取注册码指定该字段时才返回
state安装应用时,扫码或者授权链接中带的 state 值。详见 state 说明
**state 说明:** -目前会返回 state 包含以下几个场景。 -(1)扫带参二维码授权代开发模版。 \ No newline at end of file +目前会返回 state 包含以下场景: +扫带参二维码授权代开发模版 + +> 注:旧[获取企业永久授权码](#14942)接口耗时长,若安装应用流程,开发者拿到临时授权码后同步调用获取永久授权码接口,推荐使用该文档中 v2 接口,该接口耗时更短。 \ No newline at end of file