Browse Source

Merge branch 'dynamic_corp_follow_code'

# Conflicts:
#	netflix-service/src/main/java/com/cyksj/service/corp/CropChatService.java
#	netflix-service/src/main/java/com/cyksj/service/corp/WxCorpOps.java
#	netflix-service/src/main/java/com/cyksj/service/corp/impl/CropChatServiceImpl.java
#	netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java
zoujiajian 3 năm trước cách đây
mục cha
commit
762c153539
17 tập tin đã thay đổi với 331 bổ sung10 xóa
  1. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/corp/CorpFollowConfigMapper.java
  2. 26 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpFollowConfig.java
  3. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/CorpUser.java
  4. 105 0
      netflix-dao/src/main/java/com/cyksj/model/request/corp/CorpFollowContact.java
  5. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  6. 13 0
      netflix-service/src/main/java/com/cyksj/service/corp/CorpFollowDynamicConfigService.java
  7. 2 0
      netflix-service/src/main/java/com/cyksj/service/corp/CropChatService.java
  8. 9 0
      netflix-service/src/main/java/com/cyksj/service/corp/WxCorpOps.java
  9. 9 1
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpEventActionServiceImpl.java
  10. 45 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpFollowDynamicConfigServiceImpl.java
  11. 14 5
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java
  12. 18 2
      netflix-service/src/main/java/com/cyksj/service/corp/impl/CropChatServiceImpl.java
  13. 21 0
      netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java
  14. 1 1
      netflix-service/src/main/java/com/cyksj/service/corp/msg/CorpEventActionService.java
  15. 34 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpFollowConfigController.java
  16. 5 1
      netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java
  17. 10 0
      netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

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

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

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpFollowConfig.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: CorpFollowConfig
+ *创建者: JavaZou
+ *创建时间:2023/7/7 13:51
+ */
+@Getter
+@Setter
+public class CorpFollowConfig extends BaseEntity{
+	private String followId;
+
+	private String name;
+
+	private Long wxCorpId;
+
+	private Long goodsId;
+
+	private String configId;
+
+	private String qrCode;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpUser.java

@@ -42,4 +42,9 @@ public class CorpUser extends BaseEntity implements Serializable {
 	 * user表 关联用户id
 	 */
 	private Long userId;
+
+	/**
+	 * 添加渠道来源
+	 */
+	private String state;
 }

+ 105 - 0
netflix-dao/src/main/java/com/cyksj/model/request/corp/CorpFollowContact.java

@@ -0,0 +1,105 @@
+package com.cyksj.model.request.corp;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+
+@Getter
+@Setter
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class CorpFollowContact {
+	/**
+	 * 联系方式类型,1-单人, 2-多人
+	 */
+	private Integer type;
+
+	/**
+	 * 场景,1-在小程序中联系,2-通过二维码联系
+	 */
+	private Integer scene;
+
+	private Integer style;
+
+	private String remark;
+
+	private boolean skip_verify;
+
+	private String state;
+
+	private List<String> user;
+
+	private List<Integer> party;
+
+	private boolean is_temp;
+
+	private Integer expires_in;
+
+	private Integer chat_expires_in;
+
+	private String unionid;
+
+	private boolean is_exclusive;
+
+	private Conclusions conclusions;
+
+	@Getter
+	@Setter
+	@JsonInclude(JsonInclude.Include.NON_NULL)
+	class Conclusions {
+		private Text text;
+
+		private Image image;
+
+		private Link link;
+
+		@JsonProperty("miniprogram")
+		private MiniProgram miniprogram;
+	}
+
+	@Getter
+	@Setter
+	@JsonInclude(JsonInclude.Include.NON_NULL)
+	class Text {
+		private String content;
+	}
+
+
+	@Getter
+	@Setter
+	@JsonInclude(JsonInclude.Include.NON_NULL)
+	class MiniProgram {
+		private String title;
+
+		private String pic_media_id;
+
+		private String appid;
+
+		private String page;
+	}
+
+	@Getter
+	@Setter
+	@JsonInclude(JsonInclude.Include.NON_NULL)
+	class Image {
+		private String media_id;
+	}
+
+	@Getter
+	@Setter
+	@JsonInclude(JsonInclude.Include.NON_NULL)
+	class Link {
+		private String title;
+
+		private String picurl;
+
+		private String desc;
+
+		private String url;
+	}
+
+
+}

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

@@ -617,6 +617,7 @@ public class RedisService {
         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),
+        CORP_SERVICE_QR_CODE("corp_service_qr_code:", "企业微信客服活码", 60 * 60 * 24 * 15),
         GENERAL_POPULARIZE_CODE("general_popularize_code:", "普通推广者关联优惠券", 10l),
         //企业微信欢迎语 临时素材 mediaId
         CORP_WECLOME_MEDIA("corp:%s:weclome:media:","临时素材 mediaId",60*60*24*3 - 60*60*1L),

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/corp/CorpFollowDynamicConfigService.java

@@ -0,0 +1,13 @@
+package com.cyksj.service.corp;
+
+import com.cyksj.model.request.corp.CorpFollowContact;
+
+/*
+ *项目名: netflix
+ *文件名: CorpFollowDynamicConfigService
+ *创建者: JavaZou
+ *创建时间:2023/7/6 12:25
+ */
+public interface CorpFollowDynamicConfigService {
+	String corpFollowContactConfig(CorpFollowContact corpFollowContact) throws Exception;
+}

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

@@ -25,4 +25,6 @@ public interface CropChatService {
 	String getCropWxChatGroupByGoodsId(Long goodsId) throws Exception;
 
 	void updateGroupsConfig(CorpGroupConfig config) throws Exception;
+
+	String getCorpServiceCode(Long goodsId);
 }

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

@@ -5,6 +5,10 @@ import com.cyksj.dto.CorpOauth2UserInfo;
 import com.cyksj.model.request.corp.CorpGroupConfig;
 import com.cyksj.model.request.corp.CorpMsgTemplate;
 import com.cyksj.model.response.corp.*;
+import com.cyksj.model.request.corp.CorpFollowContact;
+import com.cyksj.model.response.CorpExternalContactInfo;
+import com.cyksj.model.response.CorpUserExternalTagGroupList;
+import com.cyksj.model.response.CorpUserInfo;
 
 import java.util.List;
 
@@ -136,4 +140,9 @@ public interface WxCorpOps {
 	List<CorpUserExternalTagGroupInfo.TagGroup> getAllCorpTagByGroupsId(String groupId,String corpId) throws Exception;
 
 	void updateGroupsConfig(CorpGroupConfig config) throws Exception;
+
+	/**
+	 * 联系客户配置
+	 */
+	String corpFollowContactConfig(CorpFollowContact corpFollowContact) throws Exception;
 }

+ 9 - 1
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpEventActionServiceImpl.java

@@ -87,7 +87,13 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 	 * 客户添加成员
 	 */
 	@Override
-	public CorpXmlOutMessage addExternalContact(String corpId, String userId, String externalUserId, String welcomeCode, Map<String, Object> context) throws Exception {
+	public CorpXmlOutMessage addExternalContact(CorpXmlMessage message, Map<String, Object> context) throws Exception {
+		String corpId = message.getToUserName();
+		String userId = message.getUserId();
+		String externalUserId = message.getExternalUserId();
+		String welcomeCode = message.getWelcomeCode();
+		//客服动态二维码配置state
+		String state = message.getState();
 		WxCorpApp wxCorpApp = WeChatCorpFactory.getCorpConfigStrategy(corpId);
 		//1.从企业微信获取客户信息
 		CorpExternalContactInfo externalContact = wxCorpOps.getExternalContact(corpId, externalUserId);
@@ -106,6 +112,8 @@ public class CorpEventActionServiceImpl implements CorpEventActionService {
 		corpUser.setGender(corpUserInfo.getGender());
 		corpUser.setAvatar(corpUserInfo.getAvatar());
 		corpUser.setType(corpUserInfo.getType());
+		//扫码来源
+		corpUser.setState(state);
 
 		//新增修改客户信息
 		if (corpUser.getId() == null) {

+ 45 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpFollowDynamicConfigServiceImpl.java

@@ -0,0 +1,45 @@
+package com.cyksj.service.corp.impl;
+
+import cn.hutool.json.JSONObject;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.mapper.corp.CorpFollowConfigMapper;
+import com.cyksj.model.entity.CorpFollowConfig;
+import com.cyksj.model.request.corp.CorpFollowContact;
+import com.cyksj.service.corp.CorpFollowDynamicConfigService;
+import com.cyksj.service.corp.WxCorpOps;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: CorpFollowDynamicConfigServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/7/6 12:25
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class CorpFollowDynamicConfigServiceImpl implements CorpFollowDynamicConfigService {
+	private final WxCorpOps wxCorpOps;
+
+	private final CorpFollowConfigMapper corpFollowConfigMapper;
+
+	@Override
+	public String corpFollowContactConfig(CorpFollowContact corpFollowContact) throws Exception {
+		String body = wxCorpOps.corpFollowContactConfig(corpFollowContact);
+		JSONObject jsonObject = Jsons.parseObject(body, JSONObject.class);
+		List<String> followIds = corpFollowContact.getUser();
+		log.info("body:{}", body);
+		followIds.forEach(followId->{
+			CorpFollowConfig corpFollowConfig = new CorpFollowConfig();
+			corpFollowConfig.setFollowId(followId);
+			corpFollowConfig.setQrCode(jsonObject.getStr("qr_code"));
+			corpFollowConfig.setConfigId(jsonObject.getStr("config_id"));
+			corpFollowConfigMapper.insert(corpFollowConfig);
+		});
+		return body;
+	}
+}

+ 14 - 5
netflix-service/src/main/java/com/cyksj/service/corp/impl/CorpServiceImpl.java

@@ -112,7 +112,7 @@ public class CorpServiceImpl implements CorpService {
 				.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);
+						return corpEventActionService.addExternalContact(message, context);
 					}
 				})
 				.end()
@@ -130,7 +130,7 @@ public class CorpServiceImpl implements CorpService {
 				.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);
+						return corpEventActionService.addExternalContact(message, context);
 					}
 				})
 				.end()
@@ -248,7 +248,10 @@ public class CorpServiceImpl implements CorpService {
 						THREAD_POOL.execute(() -> {
 							for (String externalUserid : list) {
 								try {
-									corpEventActionService.addExternalContact(corpId, null, externalUserid, null, null);
+									CorpXmlMessage message = new CorpXmlMessage();
+									message.setToUserName(corpId);
+									message.setExternalUserId(externalUserid);
+									corpEventActionService.addExternalContact(message, null);
 								} catch (Exception e) {
 									e.printStackTrace();
 								}
@@ -258,7 +261,10 @@ public class CorpServiceImpl implements CorpService {
 				} else {
 					for (String externalUserid : externalList) {
 						try {
-							corpEventActionService.addExternalContact(corpId, null, externalUserid, null, null);
+							CorpXmlMessage message = new CorpXmlMessage();
+							message.setToUserName(corpId);
+							message.setExternalUserId(externalUserid);
+							corpEventActionService.addExternalContact(message, null);
 						} catch (Exception e) {
 							e.printStackTrace();
 						}
@@ -317,7 +323,10 @@ public class CorpServiceImpl implements CorpService {
 		CorpUser corpUser = null;
 		if (corpUserAuth == null) {
 			//尝试添加客户
-			corpEventActionService.addExternalContact(corpId, null, externalUserid, null, null);
+			CorpXmlMessage message = new CorpXmlMessage();
+			message.setToUserName(corpId);
+			message.setExternalUserId(externalUserid);
+			corpEventActionService.addExternalContact(message, null);
 			corpUserAuth = corpUserAuthMapper.selectOne(corpUserAuthWrapper);
 			if (corpUserAuth != null) {
 				corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class).eq(CorpUser::getId, corpUserAuth.getCorpUserId()).last("limit 1"));

+ 18 - 2
netflix-service/src/main/java/com/cyksj/service/corp/impl/CropChatServiceImpl.java

@@ -3,8 +3,9 @@ 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.CorpFollowConfigMapper;
 import com.cyksj.mapper.corp.CorpGroupChatMapper;
-import com.cyksj.mapper.corp.WxCorpAppMapper;
+import com.cyksj.model.entity.CorpFollowConfig;
 import com.cyksj.model.entity.CorpGroupChat;
 import com.cyksj.model.request.corp.CorpGroupConfig;
 import com.cyksj.redis.RedisService;
@@ -28,7 +29,7 @@ import java.util.List;
 public class CropChatServiceImpl implements CropChatService {
 	private final WxCorpOps wxCorpOps;
 
-	private final WxCorpAppMapper wxCorpAppMapper;
+	private final CorpFollowConfigMapper corpFollowConfigMapper;
 
 	private final CorpGroupChatMapper corpGroupChatMapper;
 
@@ -75,4 +76,19 @@ public class CropChatServiceImpl implements CropChatService {
 	public void updateGroupsConfig(CorpGroupConfig config) throws Exception {
 		wxCorpOps.updateGroupsConfig(config);
 	}
+
+	@Override
+	public String getCorpServiceCode(Long goodsId) {
+		String qrCode = redisService.getStr(RedisService.key.CORP_SERVICE_QR_CODE.getName() + goodsId);
+		if (StrUtil.isBlank(qrCode)) {
+			CorpFollowConfig corpFollowConfig = corpFollowConfigMapper.selectOne(Wrappers.lambdaQuery(CorpFollowConfig.class)
+					.eq(CorpFollowConfig::getGoodsId, goodsId).last("limit 1"));
+			if (corpFollowConfig == null) {
+				throw BusinessRuntimeException.getInstance("");
+			}
+			qrCode = corpFollowConfig.getQrCode();
+		}
+		redisService.setNx(RedisService.key.CORP_SERVICE_QR_CODE.getName() + goodsId, qrCode, RedisService.key.CORP_SERVICE_QR_CODE.getTimeout());
+		return qrCode;
+	}
 }

+ 21 - 0
netflix-service/src/main/java/com/cyksj/service/corp/impl/WxCorpOpsImpl.java

@@ -22,6 +22,8 @@ import com.cyksj.model.response.UserExternalContactList;
 import com.cyksj.model.response.UserWithExternalPermission;
 import com.cyksj.model.response.WechatAccessToken;
 import com.cyksj.model.response.corp.*;
+import com.cyksj.model.request.corp.CorpFollowContact;
+import com.cyksj.model.response.*;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.corp.WxCorpOps;
 import lombok.extern.slf4j.Slf4j;
@@ -294,6 +296,25 @@ public class WxCorpOpsImpl implements WxCorpOps {
 		return body;
 	}
 
+	@Override
+	public String corpFollowContactConfig(CorpFollowContact corpFollowContact) throws Exception {
+		//配置
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_contact_way?access_token=" + getAccessToken(null);
+		HttpResponse<byte[]> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.cacheURI()
+						.body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(corpFollowContact), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofByteArray());
+		String body = IoKit.toString(res.body());
+		JSONObject jsonObject = Jsons.parseObject(body, JSONObject.class);
+		if (jsonObject.getInt("errcode") != 0) {
+			throw BusinessRuntimeException.getInstance("配置客服活码失败");
+		}
+		return body;
+	}
+
 	@Override
 	public CorpUserExternalTagGroupInfo addCorpTag(CorpUserExternalTagGroupInfo tagGroup, String corpId) throws Exception {
 		corpId = Optional.ofNullable(corpId).orElse(yhlXWxCorpConfig.getCorpId());

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/corp/msg/CorpEventActionService.java

@@ -12,7 +12,7 @@ import java.util.Map;
  *创建时间:2022/10/13 16:11
  */
 public interface CorpEventActionService {
-	CorpXmlOutMessage addExternalContact(String corpId, String userId, String externalUserId, String welcomeCode, Map<String, Object> context) throws Exception;
+	CorpXmlOutMessage addExternalContact(CorpXmlMessage message, Map<String, Object> context) throws Exception;
 
 	CorpXmlOutMessage editExternalContact(CorpXmlMessage message, Map<String, Object> context) throws Exception;
 

+ 34 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/CorpFollowConfigController.java

@@ -0,0 +1,34 @@
+package com.cyksj.web.controller.manage.corp;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.request.corp.CorpFollowContact;
+import com.cyksj.service.corp.CorpFollowDynamicConfigService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/*
+ *项目名: netflix
+ *文件名: CorpFollowConfigController
+ *创建者: JavaZou
+ *创建时间:2023/7/6 18:36
+ */
+@RestController
+@RequestMapping("/manage/corp")
+@RequiredArgsConstructor
+public class CorpFollowConfigController {
+
+	private final CorpFollowDynamicConfigService corpFollowDynamicConfigService;
+
+	/**
+	 * 生成动态配置
+	 */
+	@PostMapping("/post/config")
+	public Result<String> getCorpFollowConcat(@RequestBody CorpFollowContact corpFollowContact) throws Exception {
+		String body = corpFollowDynamicConfigService.corpFollowContactConfig(corpFollowContact);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(body);
+	}
+}

+ 5 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/coupon/CouponController.java

@@ -19,6 +19,7 @@ import com.cyksj.model.request.CorpCouponSendReq;
 import com.cyksj.model.request.CouponActiveReq;
 import com.cyksj.model.request.CouponClassificationReq;
 import com.cyksj.model.request.CouponDistributeReq;
+import com.cyksj.model.request.corp.CorpXmlMessage;
 import com.cyksj.model.views.*;
 import com.cyksj.service.corp.msg.CorpEventActionService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
@@ -424,7 +425,10 @@ public class CouponController {
 		CorpUser corpUser = null;
 		if (corpUserAuth == null) {
 			//尝试添加客户
-			corpEventActionService.addExternalContact(wxCorpApp.getCorpId(), null, externalUserId, null, null);
+			CorpXmlMessage message = new CorpXmlMessage();
+			message.setToUserName(wxCorpApp.getCorpId());
+			message.setExternalUserId(externalUserId);
+			corpEventActionService.addExternalContact(message, null);
 			corpUserAuth = corpUserAuthMapper.selectOne(corpUserAuthWrapper);
 			if (corpUserAuth != null) {
 				corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class).eq(CorpUser::getId, corpUserAuth.getCorpUserId()).last("limit 1"));

+ 10 - 0
netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

@@ -288,4 +288,14 @@ public class UserController {
         String qrCode = cropChatService.getCropWxChatGroupByGoodsId(goodsId);
         return GatewayResponse.SUCCESS.newBuilder().toResult(qrCode);
     }
+
+    /**
+     * 获取奈飞客服活码弹窗
+     */
+    @GetMapping("/get/corp/serviceCode/{goodsId}")
+    public Result<String> getCorpServiceCode(@PathVariable Long goodsId) {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        String qrCode = cropChatService.getCorpServiceCode(goodsId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(qrCode);
+    }
 }