|
|
@@ -0,0 +1,272 @@
|
|
|
+package com.cyksj.service.corp.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.bean.BeanUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
+import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
|
|
|
+import com.cyksj.common.util.ListsUtil;
|
|
|
+import com.cyksj.common.util.Xmls;
|
|
|
+import com.cyksj.common.util.corp.WxCryptUtil;
|
|
|
+import com.cyksj.config.corp.BaseWxCorpConfig;
|
|
|
+import com.cyksj.config.corp.WxCorpFactory;
|
|
|
+import com.cyksj.config.corp.YHLXWxCorpConfig;
|
|
|
+import com.cyksj.dto.CorpOauth2UserInfo;
|
|
|
+import com.cyksj.mapper.corp.CorpFollowMapper;
|
|
|
+import com.cyksj.model.dto.WxCorpEncryptDto;
|
|
|
+import com.cyksj.model.entity.CorpFollow;
|
|
|
+import com.cyksj.model.request.corp.CorpXmlMessage;
|
|
|
+import com.cyksj.model.request.corp.CorpXmlOutMessage;
|
|
|
+import com.cyksj.model.response.CorpUserInfo;
|
|
|
+import com.cyksj.redis.RedisService;
|
|
|
+import com.cyksj.service.corp.CorpService;
|
|
|
+import com.cyksj.service.corp.WxCorpOps;
|
|
|
+import com.cyksj.service.corp.msg.CorpEventActionService;
|
|
|
+import com.cyksj.service.corp.msg.CorpMessageHandler;
|
|
|
+import com.cyksj.service.corp.msg.CorpMessageRouter;
|
|
|
+import com.cyksj.util.WxCorpUtil;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/*
|
|
|
+ *项目名: netflix
|
|
|
+ *文件名: CorpServiceImpl
|
|
|
+ *创建者: JavaZou
|
|
|
+ *创建时间:2022/10/13 14:59
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class CorpServiceImpl implements CorpService {
|
|
|
+ @Autowired
|
|
|
+ private YHLXWxCorpConfig yhlXWxCorpConfig;
|
|
|
+
|
|
|
+ private CorpMessageRouter corpMessageRouter;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CorpEventActionService corpEventActionService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private WxCorpOps wxCorpOps;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private CorpFollowMapper corpFollowMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private GlobalThreadPoolTaskExecutor THREAD_POOL;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedisService redisService;
|
|
|
+
|
|
|
+ @PostConstruct
|
|
|
+ private void init() {
|
|
|
+ corpMessageRouter = new CorpMessageRouter(this)
|
|
|
+ //添加企业客户事件
|
|
|
+ .rule().async(false).changeType("add_external_contact")
|
|
|
+ .handler(new CorpMessageHandler() {
|
|
|
+ @Override
|
|
|
+ public CorpXmlOutMessage handle(CorpXmlMessage message, Map<String, Object> context, CorpService corpService) throws Exception {
|
|
|
+ return corpEventActionService.addExternalContact(message.getToUserName(), message.getUserId(), message.getExternalUserId(), message.getWelcomeCode(), context);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .end()
|
|
|
+ //编辑企业客户事件
|
|
|
+ .rule().async(false).changeType("edit_external_contact")
|
|
|
+ .handler(new CorpMessageHandler() {
|
|
|
+ @Override
|
|
|
+ public CorpXmlOutMessage handle(CorpXmlMessage message, Map<String, Object> context, CorpService corpService) throws Exception {
|
|
|
+ return corpEventActionService.editExternalContact(message, context);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .end()
|
|
|
+ //外部联系人免验证添加成员事件
|
|
|
+ .rule().async(false).changeType("add_half_external_contact")
|
|
|
+ .handler(new CorpMessageHandler() {
|
|
|
+ @Override
|
|
|
+ public CorpXmlOutMessage handle(CorpXmlMessage message, Map<String, Object> context, CorpService corpService) throws Exception {
|
|
|
+ return corpEventActionService.addExternalContact(message.getToUserName(), message.getUserId(), message.getExternalUserId(), message.getWelcomeCode(), context);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .end()
|
|
|
+ //删除企业客户事件
|
|
|
+ .rule().async(false).changeType("del_external_contact")
|
|
|
+ .handler(new CorpMessageHandler() {
|
|
|
+ @Override
|
|
|
+ public CorpXmlOutMessage handle(CorpXmlMessage message, Map<String, Object> context, CorpService corpService) throws Exception {
|
|
|
+ return corpEventActionService.delExternalContact(message, context);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .end()
|
|
|
+ //删除跟进人员
|
|
|
+ .rule().async(false).changeType("del_follow_user")
|
|
|
+ .handler(new CorpMessageHandler() {
|
|
|
+ @Override
|
|
|
+ public CorpXmlOutMessage handle(CorpXmlMessage message, Map<String, Object> context, CorpService corpService) throws Exception {
|
|
|
+ return corpEventActionService.delFollowUser(message, context);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .end()
|
|
|
+ //企业客户标签创建事件
|
|
|
+ .rule().async(false).changeType("create").event("change_external_tag")
|
|
|
+ .handler(new CorpMessageHandler() {
|
|
|
+ @Override
|
|
|
+ public CorpXmlOutMessage handle(CorpXmlMessage message, Map<String, Object> context, CorpService corpService) throws Exception {
|
|
|
+ return corpEventActionService.saveCorpTag(message, context);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .end()
|
|
|
+ //企业客户标签变更事件
|
|
|
+ .rule().async(false).changeType("update").event("change_external_tag")
|
|
|
+ .handler(new CorpMessageHandler() {
|
|
|
+ @Override
|
|
|
+ public CorpXmlOutMessage handle(CorpXmlMessage message, Map<String, Object> context, CorpService corpService) throws Exception {
|
|
|
+ return corpEventActionService.saveCorpTag(message, context);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .end()
|
|
|
+ //企业客户标签删除事件
|
|
|
+ .rule().async(false).changeType("delete").event("change_external_tag")
|
|
|
+ .handler(new CorpMessageHandler() {
|
|
|
+ @Override
|
|
|
+ public CorpXmlOutMessage handle(CorpXmlMessage message, Map<String, Object> context, CorpService corpService) throws Exception {
|
|
|
+ return corpEventActionService.delCorpTag(message, context);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .end();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String VerifyURL(String msgSignature, String timestamp, String nonce, String echoStr) throws Exception {
|
|
|
+ WxCorpUtil wxCorpMsgUtil = new WxCorpUtil(yhlXWxCorpConfig.getToken(), yhlXWxCorpConfig.getEncodingAESKey(), yhlXWxCorpConfig.getCorpId());
|
|
|
+ return wxCorpMsgUtil.VerifyURL(msgSignature, timestamp, nonce, echoStr);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String corpMsg(String msgSignature, String timestamp, String nonce, String content) throws Exception {
|
|
|
+ WxCorpEncryptDto corpEncryptDto = Xmls.parseObject(content, WxCorpEncryptDto.class);
|
|
|
+ BaseWxCorpConfig corpConfig = WxCorpFactory.getBaseWxCorpConfig(corpEncryptDto.getToUserName());
|
|
|
+
|
|
|
+ WxCorpUtil wxCorpUtil = new WxCorpUtil(corpConfig.getToken(), corpConfig.getEncodingAESKey(), corpConfig.getCorpId());
|
|
|
+
|
|
|
+ String msg = wxCorpUtil.DecryptMsg(msgSignature, timestamp, nonce, corpEncryptDto);
|
|
|
+ log.info("企业微信 解密 msg:\n{}", msg);
|
|
|
+
|
|
|
+ CorpXmlMessage inMessage = Xmls.parseObject(msg, CorpXmlMessage.class);
|
|
|
+
|
|
|
+ //事件路由
|
|
|
+ CorpXmlOutMessage outMessage = corpMessageRouter.route(inMessage);
|
|
|
+
|
|
|
+ if (outMessage != null) {
|
|
|
+ return outMessage.toEncryptedXml(new WxCryptUtil(yhlXWxCorpConfig.getToken(), yhlXWxCorpConfig.getEncodingAESKey(), yhlXWxCorpConfig.getCorpId()));
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String dataInitByCorpId(String corpId) throws Exception {
|
|
|
+ //获取成员列表
|
|
|
+ List<String> followUserList = wxCorpOps.getFollowUserList(corpId);
|
|
|
+ for (String userId : followUserList) {
|
|
|
+ THREAD_POOL.execute(() -> {
|
|
|
+ CorpUserInfo userInfo = null;
|
|
|
+ try {
|
|
|
+ userInfo = wxCorpOps.getFollowUser(corpId, userId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ CorpFollow corpFollow = new CorpFollow();
|
|
|
+ BeanUtil.copyProperties(userInfo, corpFollow);
|
|
|
+ CorpFollow follow = corpFollowMapper.selectOne(Wrappers.lambdaQuery(CorpFollow.class).eq(CorpFollow::getUserid, corpFollow.getUserid()).eq(CorpFollow::getCorpId, corpId));
|
|
|
+ if (follow == null) {
|
|
|
+ corpFollow.setCorpId(corpId);
|
|
|
+ corpFollowMapper.insert(corpFollow);
|
|
|
+ } else {
|
|
|
+ corpFollow.setId(follow.getId());
|
|
|
+ corpFollowMapper.updateById(corpFollow);
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> externalList = null;
|
|
|
+ try {
|
|
|
+ externalList = wxCorpOps.listExternalContacts(corpId, userId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (externalList.size() > 1000) {
|
|
|
+ List<List<String>> lists = ListsUtil.averageAssign(externalList, 5);
|
|
|
+ for (List<String> list : lists) {
|
|
|
+ THREAD_POOL.execute(() -> {
|
|
|
+ for (String externalUserid : list) {
|
|
|
+ try {
|
|
|
+ corpEventActionService.addExternalContact(corpId, null, externalUserid, null, null);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ for (String externalUserid : externalList) {
|
|
|
+ try {
|
|
|
+ corpEventActionService.addExternalContact(corpId, null, externalUserid, null, null);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String createUrl(String corpId, String state) {
|
|
|
+ return wxCorpOps.createUrl(corpId, state);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CorpOauth2UserInfo getUserInfo(String corpId, String code) throws Exception {
|
|
|
+ return wxCorpOps.getUserInfo(corpId, code);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Throwable.class)
|
|
|
+ public CorpFollow saveFollowUser(String corpId, CorpOauth2UserInfo corpOauth2UserInfo) throws Exception {
|
|
|
+ CorpFollow corpFollow = corpFollowMapper.selectOne(Wrappers.lambdaQuery(CorpFollow.class).eq(CorpFollow::getCorpId, corpId).eq(CorpFollow::getUserid, corpOauth2UserInfo.getUserId()));
|
|
|
+ if (corpFollow == null) {
|
|
|
+ CorpUserInfo userInfo = wxCorpOps.getFollowUser(corpId, corpOauth2UserInfo.getUserId());
|
|
|
+ corpFollow = new CorpFollow();
|
|
|
+ BeanUtil.copyProperties(userInfo, corpFollow);
|
|
|
+ corpFollow.setCorpId(corpId);
|
|
|
+ corpFollowMapper.insert(corpFollow);
|
|
|
+ }
|
|
|
+
|
|
|
+ return corpFollow;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getJsTicket(String corpId) throws Exception {
|
|
|
+ String jsTicket = redisService.getStr(RedisService.key.CORP_JS_TICKET_KEY.getName() + corpId);
|
|
|
+ if (StrUtil.isBlank(jsTicket)) {
|
|
|
+ return wxCorpOps.getJsTicket(corpId);
|
|
|
+ }
|
|
|
+ return jsTicket;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getAgentJsTicket(String corpId, String agentId) throws Exception {
|
|
|
+ String jsTicket = redisService.getStr(RedisService.key.CORP_AGENT_JS_TICKET_KEY.getName() + corpId);
|
|
|
+ if (StrUtil.isBlank(jsTicket)) {
|
|
|
+ return wxCorpOps.getAgentJsTicket(corpId, agentId);
|
|
|
+ } else {
|
|
|
+ return jsTicket;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|