Ver código fonte

fix 企业微信客户群动态码获取

zoujiajian 3 anos atrás
pai
commit
6cdc805a73

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpGroupChatMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.corp;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CorpGroupChat;
+
+/*
+ *项目名: netflix
+ *文件名: CorpGroupChatMapper
+ *创建者: JavaZou
+ *创建时间:2023/6/26 17:37
+ */
+public interface CorpGroupChatMapper extends BaseMapper<CorpGroupChat> {
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpGroupChat.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: CorpGroupChat
+ *创建者: JavaZou
+ *创建时间:2023/6/26 17:36
+ */
+@Getter
+@Setter
+public class CorpGroupChat extends BaseEntity{
+	private String chatId;
+
+	private String chatName;
+
+	private Long wxCorpId;
+
+	private Long goodsId;
+
+	private String configId;
+}

+ 1 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -610,6 +610,7 @@ public class RedisService {
         IMPORT_ACCOUNT_CACHE_KEY("import_account_cache_key:%s", "导入缓存key", 60 * 10L),
         MAKERTING_MSG_KEY("makerting_msg_key", "营销短信", 60 * 60 * 24 * 30),
         PHONE_AREA_CODE("phone_area_code:key", "国家或地区码", 60 * 60 * 24 * 15),
+        CORP_CHAT_GROUP_CODE("corp_chat_group_code:", "企业微信群动态码", 60 * 60 * 24 * 15),
         ;
 
         private String name;

+ 24 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CropChatService.java

@@ -0,0 +1,24 @@
+package com.cyksj.service.corp;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: CropChatService
+ *创建者: JavaZou
+ *创建时间:2023/6/26 16:26
+ */
+public interface CropChatService {
+	void getCorpChat(String corpId, String configId) throws Exception;
+
+	String getGroupsList() throws Exception;
+
+	/**
+	 * 设置企业微信群配置
+	 */
+	void setGroupsConfig(List<String> chatIds) throws Exception;
+
+	String getGroupsDetail(String chatId) throws Exception;
+
+	String getCropWxChatGroupByGoodsId(Long goodsId) throws Exception;
+}

+ 8 - 0
netflix-service/src/main/java/com/cyksj/service/corp/WxCorpOps.java

@@ -74,4 +74,12 @@ public interface WxCorpOps {
 	 * 企业微信获取应用js_ticket
 	 */
 	String getAgentJsTicket(String corpId, String agentId) throws Exception;
+
+	String getCorpChatGroups(String corpId,String config) throws Exception;
+
+	String getGroupsList() throws Exception;
+
+	String setGroupsConfig(List<String> chatIds) throws Exception;
+
+	String getGroupsDetail(String chatId) throws Exception;
 }

+ 72 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CropChatServiceImpl.java

@@ -0,0 +1,72 @@
+package com.cyksj.service.corp.impl;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.corp.CorpGroupChatMapper;
+import com.cyksj.mapper.corp.WxCorpAppMapper;
+import com.cyksj.model.entity.CorpGroupChat;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.corp.CropChatService;
+import com.cyksj.service.corp.WxCorpOps;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: CropChatServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/6/26 16:26
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CropChatServiceImpl implements CropChatService {
+	private final WxCorpOps wxCorpOps;
+
+	private final WxCorpAppMapper wxCorpAppMapper;
+
+	private final CorpGroupChatMapper corpGroupChatMapper;
+
+	private final RedisService redisService;
+
+	@Override
+	public void getCorpChat(String corpId, String configId) throws Exception {
+		wxCorpOps.getCorpChatGroups(corpId,configId);
+	}
+
+	@Override
+	public String getGroupsList() throws Exception {
+		return wxCorpOps.getGroupsList();
+	}
+
+	@Override
+	public void setGroupsConfig(List<String> chatIds) throws Exception {
+		String body = wxCorpOps.setGroupsConfig(chatIds);
+		//记录 企业客户群的配置id
+		System.out.println(body);
+	}
+
+	@Override
+	public String getGroupsDetail(String chatId) throws Exception {
+		return wxCorpOps.getGroupsDetail(chatId);
+	}
+
+	@Override
+	public String getCropWxChatGroupByGoodsId(Long goodsId) throws Exception {
+		String configId = redisService.getStr(RedisService.key.CORP_CHAT_GROUP_CODE.getName() + goodsId);
+		if (StrUtil.isBlank(configId)) {
+			CorpGroupChat corpGroupChat = corpGroupChatMapper.selectOne(Wrappers.lambdaQuery(CorpGroupChat.class)
+					.eq(CorpGroupChat::getGoodsId, goodsId).last("limit 1"));
+			if (corpGroupChat == null) {
+				throw BusinessRuntimeException.getInstance("");
+			}
+			configId = corpGroupChat.getConfigId();
+		}
+		redisService.setNx(RedisService.key.CORP_CHAT_GROUP_CODE.getName() + goodsId, configId, RedisService.key.CORP_CHAT_GROUP_CODE.getTimeout());
+		return wxCorpOps.getCorpChatGroups(null, configId);
+	}
+}

+ 95 - 1
netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java

@@ -23,6 +23,7 @@ import java.net.URLEncoder;
 import java.net.http.HttpRequest;
 import java.net.http.HttpResponse;
 import java.util.List;
+import java.util.Optional;
 
 /*
  *项目名: netflix
@@ -57,7 +58,7 @@ public class WxCorpOpsImpl implements WxCorpOps {
 
 	@Override
 	public String getAccessToken(String corpId) throws Exception {
-		String accessToken = redisService.getStr(RedisKey.CORP_ACCESS_TOKEN_KEY + corpId);
+		String accessToken = StrUtil.EMPTY;
 		if (StringUtils.isNotBlank(accessToken)) {
 			return accessToken;
 		}
@@ -185,6 +186,99 @@ public class WxCorpOpsImpl implements WxCorpOps {
 		return ticket;
 	}
 
+	@Override
+	public String getCorpChatGroups(String corpId, String configId) throws Exception {
+		corpId = Optional.ofNullable(corpId).orElse(yhlXWxCorpConfig.getCorpId());
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/get_join_way?access_token=" + getAccessToken(corpId);
+		JSONObject jsonObject = new JSONObject();
+		jsonObject.putOpt("config_id", configId);
+		HttpResponse<byte[]> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.cacheURI()
+						.body(HttpRequest.BodyPublishers.ofString(jsonObject.toString(), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofByteArray());
+		String body = IoKit.toString(res.body());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("获取access_token失败: " + body);
+		}
+		JSONObject re = Jsons.parseObject(body, JSONObject.class);
+		Integer errcode = re.getInt("errcode");
+		if (null != errcode && 0 != errcode) {
+			throw BusinessRuntimeException.getInstance("获取企业微信access_token失败: " + re.getStr("errmsg") + "[" + errcode + "]");
+		}
+		JSONObject codeRe = Jsons.parseObject(re.getStr("join_way"), JSONObject.class);
+		String qr_code = codeRe.getStr("qr_code");
+		return qr_code;
+	}
+
+	@Override
+	public String getGroupsList() throws Exception {
+		String corpId = yhlXWxCorpConfig.getCorpId();
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/list?access_token=" + getAccessToken(corpId);
+		JSONObject jsonObject = new JSONObject();
+		jsonObject.putOpt("limit", 1000);
+		HttpResponse<byte[]> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.cacheURI()
+						.body(HttpRequest.BodyPublishers.ofString(jsonObject.toString(), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofByteArray());
+		String body = IoKit.toString(res.body());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("获取access_token失败: " + IoKit.toString(res.body()));
+		}
+		return body;
+	}
+
+	@Override
+	public String setGroupsConfig(List<String> chatIds) throws Exception {
+		String corpId = yhlXWxCorpConfig.getCorpId();
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/add_join_way?access_token=" + getAccessToken(corpId);
+		JSONObject jsonObject = new JSONObject();
+		//scene	是	场景。
+		//1 - 群的小程序插件
+		//2 - 群的二维码插件
+		jsonObject.putOpt("scene", 2);
+		jsonObject.putOpt("chat_id_list", chatIds);
+		jsonObject.putOpt("room_base_name", "Ai银河课堂 MJ SD教程分享");
+		HttpResponse<byte[]> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.cacheURI()
+						.body(HttpRequest.BodyPublishers.ofString(jsonObject.toString(), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofByteArray());
+		String body = IoKit.toString(res.body());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("获取access_token失败: " + body);
+		}
+		log.info("配置企业微信群返回信息body:{}", body);
+		return body;
+	}
+
+	@Override
+	public String getGroupsDetail(String chatId) throws Exception {
+		String corpId = yhlXWxCorpConfig.getCorpId();
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/get?access_token=" + getAccessToken(corpId);
+		JSONObject jsonObject = new JSONObject();
+		jsonObject.putOpt("chat_id", chatId);
+		HttpResponse<byte[]> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.cacheURI()
+						.body(HttpRequest.BodyPublishers.ofString(jsonObject.toString(), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofByteArray());
+		String body = IoKit.toString(res.body());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("获取access_token失败: " + body);
+		}
+		return body;
+	}
+
 	public String access_token(String corpId) throws Exception {
 		WxCorpApp wxCorpApp = WeChatCorpFactory.getCorpConfigStrategy(corpId);
 		if (corpId == null) {

+ 10 - 1
netflix-service/src/main/java/com/cyksj/service/user/impl/WorkOrderFrontServiceImpl.java

@@ -3,6 +3,7 @@ package com.cyksj.service.user.impl;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.mapper.AccountMapper;
@@ -51,6 +52,15 @@ public class WorkOrderFrontServiceImpl implements WorkOrderFrontService {
 	@Transactional(rollbackFor = Throwable.class)
 	public void submitWorkOrder(WorkOrderReq workOrderReq) {
 		Long userId = workOrderReq.getUserId();
+		Long relationId = workOrderReq.getRelationId();
+		//是否已提交过该工单
+		WorkOrder exists = workOrderMapper.selectOne(Wrappers.lambdaQuery(WorkOrder.class)
+				.eq(WorkOrder::getRelationId, relationId)
+				.eq(WorkOrder::getUserId, userId)
+				.last("limit 1"));
+		if (exists != null) {
+			throw BusinessRuntimeException.getInstance("您已提交过该车票工单");
+		}
 		User user = userService.getById(userId);
 		if (user == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
 		String content = workOrderReq.getContent();
@@ -63,7 +73,6 @@ public class WorkOrderFrontServiceImpl implements WorkOrderFrontService {
 			throw BusinessRuntimeException.getInstance("问题描述最多输入200字数以内");
 		}
 		List<Long> userIds = userService.getRelationUserIdList(userId, user);
-		Long relationId = workOrderReq.getRelationId();
 		GroupRelationDetailView detailView = beanSearcher.searchFirst(GroupRelationDetailView.class, MapUtils.builder()
 				.field(GroupRelationDetailView::getUserId, userIds).op(Operator.InList)
 				.field(GroupRelationDetailView::getRelationId, relationId)

+ 64 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpChatController.java

@@ -0,0 +1,64 @@
+package com.cyksj.web.controller.manage.corp;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.service.corp.CropChatService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: CorpChatController
+ *创建者: JavaZou
+ *创建时间:2023/6/26 16:24
+ */
+@RestController
+@RequestMapping("/manage/corpChat")
+@RequiredArgsConstructor
+public class CorpChatController {
+	private final CropChatService cropChatService;
+
+	/**
+	 * 客户群列表
+	 */
+	@GetMapping("/get/groups/list")
+	public Result<String> getGroupsList() throws Exception {
+		String body = cropChatService.getGroupsList();
+		return GatewayResponse.SUCCESS.newBuilder().toResult(body);
+	}
+
+	/**
+	 * 客户群详情
+	 */
+	@GetMapping("/get/groups/detail")
+	public Result<String> getGroupsDetail(String chatId) throws Exception {
+		String body = cropChatService.getGroupsDetail(chatId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(body);
+	}
+
+	/**
+	 * 客户群配置列表
+	 */
+	@GetMapping("/get/config/list")
+	public Result<String> getCorpChat(String corpId,String configId) throws Exception {
+		cropChatService.getCorpChat(corpId, configId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+
+	/**
+	 * 配置客户群
+	 */
+	@PostMapping("/set/group")
+	public Result<String> setGroupsConfig(@RequestBody List<String> chatIds) throws Exception {
+		cropChatService.setGroupsConfig(chatIds);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+}
+
+
+
+

+ 18 - 1
netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

@@ -18,6 +18,7 @@ import com.cyksj.model.request.ReceiveBenefitsReq;
 import com.cyksj.model.request.UserReq;
 import com.cyksj.model.request.WorkOrderReq;
 import com.cyksj.model.views.*;
+import com.cyksj.service.corp.CropChatService;
 import com.cyksj.service.exchange.ExchangeCodeService;
 import com.cyksj.service.order.UserRealOrderBenefitsService;
 import com.cyksj.service.relation.GroupRelationFrontService;
@@ -63,6 +64,8 @@ public class UserController {
 
     private final HttpServletRequest request;
 
+    private final CropChatService cropChatService;
+
     @GetMapping(value = "/wx/whoami")
     public Result<UserWhoami> whoami() {
         long userId = StpUserUtil.getLoginIdAsLong();
@@ -159,7 +162,10 @@ public class UserController {
     @GetMapping("/workOrder/get")
     public Result<SearchResult<UserWorkOrderView>> getWorkOrder() {
         long userId = StpUserUtil.getLoginIdAsLong();
-        SearchResult<UserWorkOrderView> search = beanSearcher.search(UserWorkOrderView.class, MapUtils.flatBuilder(request.getParameterMap()).field(UserWorkOrderView::getUserId, userId).build());
+        SearchResult<UserWorkOrderView> search = beanSearcher.search(UserWorkOrderView.class, MapUtils.flatBuilder(request.getParameterMap())
+                .field(UserWorkOrderView::getUserId, userId)
+                .orderBy(UserWorkOrderView::getCreatedTime).desc()
+                .build());
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
 
@@ -265,4 +271,15 @@ public class UserController {
                 .last("limit 1"));
         return GatewayResponse.SUCCESS.newBuilder().toResult(user);
     }
+
+    /**
+     * 获取群聊二维码
+     */
+    @GetMapping("/get/corp/ChatCode/{goodsId}")
+    public Result<String> getCorpChatCode(@PathVariable Long goodsId) throws Exception {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        //获取对应产品的企业微信客户群
+        String qrCode = cropChatService.getCropWxChatGroupByGoodsId(goodsId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(qrCode);
+    }
 }

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
netflix-web/src/main/resources/application-prd.yml


Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff