zoujiajian 1 rok temu
rodzic
commit
245c799a6d

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.corp.kf;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CorpKfAccountFollow;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfAccountFollowMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/12/30 18:20
+ */
+public interface CorpKfAccountFollowMapper extends BaseMapper<CorpKfAccountFollow> {
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.corp.kf;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CorpKfAccount;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfAccountMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/12/30 18:06
+ */
+public interface CorpKfAccountMapper extends BaseMapper<CorpKfAccount> {
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.corp.kf;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.CorpKfAccountSession;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfAccountSessionMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/12/30 18:22
+ */
+public interface CorpKfAccountSessionMapper extends BaseMapper<CorpKfAccountSession> {
+}

+ 28 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpKfAccount.java

@@ -0,0 +1,28 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfAccount
+ * 创建者: JavaZou
+ * 创建时间:2024/12/30 18:05
+ */
+@Getter
+@Setter
+public class CorpKfAccount extends BaseEntity{
+	private String name;
+
+	private String img;
+
+	private String openKfId;
+
+	private String url;
+
+	/**
+	 * 使用场景
+	 * 0官网 1其他场景
+	 */
+	private Integer scene;
+}

+ 32 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpKfAccountFollow.java

@@ -0,0 +1,32 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfAccountFollow
+ * 创建者: JavaZou
+ * 创建时间:2024/12/30 18:19
+ */
+@Getter
+@Setter
+public class CorpKfAccountFollow extends BaseEntity{
+
+	private String openKfId;
+
+	/**
+	 * 成员id list
+	 */
+	private String userIdList;
+
+	/**
+	 * 值班开始时间
+	 */
+	private Integer startTime;
+
+	/**
+	 * 值班结束时间
+	 */
+	private Integer endTime;
+}

+ 41 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/CorpKfAccountSession.java

@@ -0,0 +1,41 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfAccountSession
+ * 创建者: JavaZou
+ * 创建时间:2024/12/30 18:20
+ */
+@Getter
+@Setter
+public class CorpKfAccountSession extends BaseEntity{
+	private String openKfId;
+
+	/**
+	 * 默认0分配接待人员最少值班客服
+	 */
+	private Integer assignType;
+
+	/**
+	 * 接待上限
+	 */
+	private Integer maxNum;
+
+	/**
+	 * 欢迎语
+	 */
+	private String welcomeContent;
+
+	/**
+	 * 排队提示
+	 */
+	private String queueTips;
+
+	/**
+	 * 非值班提示
+	 */
+	private String noDutyTips;
+}

+ 30 - 0
netflix-dao/src/main/java/com/cyksj/model/kf/WxCpKfAccountAdd.java

@@ -0,0 +1,30 @@
+package com.cyksj.model.kf;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 添加客服帐号-请求参数
+ */
+@NoArgsConstructor
+@Data
+public class WxCpKfAccountAdd implements Serializable {
+
+	private static final long serialVersionUID = 3565729481246537411L;
+
+	/**
+	 * 客服名称;不多于16个字符
+	 */
+	@JsonProperty("name")
+	private String name;
+
+	/**
+	 * 客服头像临时素材。可以调用上传临时素材接口获取。
+	 * 不多于128个字节
+	 */
+	@JsonProperty("media_id")
+	private String mediaId;
+}

+ 30 - 0
netflix-dao/src/main/java/com/cyksj/model/kf/WxCpKfAccountAddResp.java

@@ -0,0 +1,30 @@
+package com.cyksj.model.kf;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 添加客服帐号-返回结果
+ *
+ */
+@NoArgsConstructor
+@Data
+public class WxCpKfAccountAddResp {
+
+
+  @JsonProperty("errcode")
+  protected Long errcode;
+
+  @JsonProperty("errmsg")
+  protected String errmsg;
+
+  private static final long serialVersionUID = -6649323005421772827L;
+
+  /**
+   * 新创建的客服帐号ID
+   */
+  @JsonProperty("open_kfid")
+  private String openKfid;
+
+}

+ 25 - 0
netflix-dao/src/main/java/com/cyksj/model/kf/WxCpKfAccountDel.java

@@ -0,0 +1,25 @@
+package com.cyksj.model.kf;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 删除客服帐号-请求参数
+ */
+@NoArgsConstructor
+@Data
+public class WxCpKfAccountDel implements Serializable {
+
+  private static final long serialVersionUID = 1997221467585676772L;
+
+  /**
+   * 客服帐号ID。
+   * 不多于64字节
+   */
+  @JsonProperty("open_kfid")
+  private String openKfid;
+
+}

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/kf/WxCpKfAccountUpd.java

@@ -0,0 +1,40 @@
+package com.cyksj.model.kf;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 修改客服帐号-请求参数
+ *
+ * @author Fu  created on  2022/1/19 19:10
+ */
+@NoArgsConstructor
+@Data
+public class WxCpKfAccountUpd implements Serializable {
+
+  private static final long serialVersionUID = -900712046553752529L;
+
+  /**
+   * 要修改的客服帐号ID。
+   * 不多于64字节
+   */
+  @JsonProperty("open_kfid")
+  private String openKfid;
+
+  /**
+   * 新的客服名称,如不需要修改可不填。
+   * 不多于16个字符
+   */
+  @JsonProperty("name")
+  private String name;
+
+  /**
+   * 新的客服头像临时素材,如不需要修改可不填。可以调用上传临时素材接口获取。
+   * 不多于128个字节
+   */
+  @JsonProperty("media_id")
+  private String mediaId;
+}

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

@@ -2,6 +2,10 @@ package com.cyksj.service.corp;
 
 import cn.hutool.json.JSONObject;
 import com.cyksj.dto.CorpOauth2UserInfo;
+import com.cyksj.model.kf.WxCpKfAccountAdd;
+import com.cyksj.model.kf.WxCpKfAccountAddResp;
+import com.cyksj.model.kf.WxCpKfAccountDel;
+import com.cyksj.model.kf.WxCpKfAccountUpd;
 import com.cyksj.model.request.corp.CorpFollowContact;
 import com.cyksj.model.request.corp.CorpGroupConfig;
 import com.cyksj.model.request.corp.CorpMsgTemplate;
@@ -188,4 +192,23 @@ public interface WxCorpOps {
 	 * 获取会话内容存档开启成员列表
 	 */
 	List<String> getPermitUserList(String corpId, String type) throws Exception;
+
+	/**
+	 * 添加客服帐号,并可设置客服名称和头像
+	 */
+	WxCpKfAccountAddResp addAccount(String corpId, WxCpKfAccountAdd add) throws Exception;
+
+	/**
+	 * 删除已有的客服帐号
+	 *
+	 * @param del 要删除的客服帐号
+	 */
+	void delAccount(String corpId, WxCpKfAccountDel del) throws Exception;
+
+	/**
+	 * 修改已有的客服帐号,可修改客服名称和头像。
+	 *
+	 * @param upd 新的客服账号信息
+	 */
+	void updAccount(String corpId, WxCpKfAccountUpd upd) throws Exception;
 }

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

@@ -15,6 +15,10 @@ import com.cyksj.config.corp.YHLXWxCorpConfig;
 import com.cyksj.dto.CorpOauth2UserInfo;
 import com.cyksj.dto.RedisKey;
 import com.cyksj.model.entity.WxCorpApp;
+import com.cyksj.model.kf.WxCpKfAccountAdd;
+import com.cyksj.model.kf.WxCpKfAccountAddResp;
+import com.cyksj.model.kf.WxCpKfAccountDel;
+import com.cyksj.model.kf.WxCpKfAccountUpd;
 import com.cyksj.model.request.corp.CorpFollowContact;
 import com.cyksj.model.request.corp.CorpGroupConfig;
 import com.cyksj.model.request.corp.CorpMsgTemplate;
@@ -826,4 +830,65 @@ public class WxCorpOpsImpl implements WxCorpOps {
 		}
 		return JSONUtil.parseObj(res.body()).getJSONArray("ids").toList(String.class);
 	}
+
+	@Override
+	public WxCpKfAccountAddResp addAccount(String corpId, WxCpKfAccountAdd add) throws Exception {
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/kf/account/add?access_token=" + getKfAccessToken(corpId);
+		HttpResponse<String> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.headers(J11HttpC.ReqType.raw_json)
+						.body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(add), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofString());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("添加客服帐号: " + res.body());
+		}
+
+		WxCpKfAccountAddResp resp = Jsons.parseObject(res.body(), WxCpKfAccountAddResp.class);
+		if (resp.getErrcode() != 0) {
+			throw BusinessRuntimeException.getInstance("添加客服帐号: " + resp.getErrmsg());
+		}
+		return resp;
+	}
+
+	@Override
+	public void delAccount(String corpId, WxCpKfAccountDel del) throws Exception {
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/kf/account/del?access_token=" + getKfAccessToken(corpId);
+		HttpResponse<String> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.headers(J11HttpC.ReqType.raw_json)
+						.body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(del), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofString());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("删除客服帐号: " + res.body());
+		}
+
+		JSONObject jsonObject = new JSONObject(res.body());
+		if (jsonObject.getInt("errcode") != 0) {
+			throw BusinessRuntimeException.getInstance("删除客服账号出错: " + jsonObject.getStr("errmsg"));
+		}
+	}
+
+	@Override
+	public void updAccount(String corpId, WxCpKfAccountUpd upd) throws Exception {
+		String url = "https://qyapi.weixin.qq.com/cgi-bin/kf/account/update?access_token=" + getKfAccessToken(corpId);
+		HttpResponse<String> res =
+				J11HttpC.custom()
+						.ofPost()
+						.url(url)
+						.headers(J11HttpC.ReqType.raw_json)
+						.body(HttpRequest.BodyPublishers.ofString(Jsons.toJson(upd), IoKit.Charsets.UTF_8.getCharset()))
+						.send(HttpResponse.BodyHandlers.ofString());
+		if (200 != res.statusCode()) {
+			throw BusinessRuntimeException.getInstance("修改客服帐号: " + res.body());
+		}
+
+		JSONObject jsonObject = new JSONObject(res.body());
+		if (jsonObject.getInt("errcode") != 0) {
+			throw BusinessRuntimeException.getInstance("修改客服账号出错: " + jsonObject.getStr("errmsg"));
+		}
+	}
 }

+ 17 - 0
netflix-service/src/main/java/com/cyksj/service/corp/kf/CorpKfService.java

@@ -0,0 +1,17 @@
+package com.cyksj.service.corp.kf;
+
+import com.cyksj.model.entity.CorpKfAccount;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfService
+ * 创建者: JavaZou
+ * 创建时间:2024/12/30 18:10
+ */
+public interface CorpKfService {
+	void addKfAccount(CorpKfAccount corpKfAccount) throws Exception;
+
+	void delKfAccount(Long id) throws Exception;
+
+	void updateKfAccount(CorpKfAccount corpKfAccount);
+}

+ 79 - 0
netflix-service/src/main/java/com/cyksj/service/corp/kf/impl/CorpKfServiceImpl.java

@@ -0,0 +1,79 @@
+package com.cyksj.service.corp.kf.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.config.corp.YHLXWxCorpConfig;
+import com.cyksj.mapper.corp.kf.CorpKfAccountFollowMapper;
+import com.cyksj.mapper.corp.kf.CorpKfAccountMapper;
+import com.cyksj.mapper.corp.kf.CorpKfAccountSessionMapper;
+import com.cyksj.model.entity.CorpKfAccount;
+import com.cyksj.model.entity.CorpKfAccountFollow;
+import com.cyksj.model.entity.CorpKfAccountSession;
+import com.cyksj.model.kf.WxCpKfAccountAdd;
+import com.cyksj.model.kf.WxCpKfAccountAddResp;
+import com.cyksj.model.kf.WxCpKfAccountDel;
+import com.cyksj.model.kf.WxCpKfAccountUpd;
+import com.cyksj.service.corp.WxCorpOps;
+import com.cyksj.service.corp.kf.CorpKfService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpKfServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/12/30 18:10
+ */
+@Service
+@RequiredArgsConstructor
+public class CorpKfServiceImpl implements CorpKfService {
+	private final CorpKfAccountMapper corpKfAccountMapper;
+
+	private final WxCorpOps wxCorpOps;
+
+	private final YHLXWxCorpConfig yhlxWxCorpConfig;
+
+	private final CorpKfAccountFollowMapper corpKfAccountFollowMapper;
+
+	private final CorpKfAccountSessionMapper corpKfAccountSessionMapper;
+
+	@Override
+	public void addKfAccount(CorpKfAccount corpKfAccount) throws Exception {
+		WxCpKfAccountAdd wxCpKfAccountAdd = new WxCpKfAccountAdd();
+		wxCpKfAccountAdd.setName(corpKfAccount.getName());
+		wxCpKfAccountAdd.setMediaId(wxCorpOps.getMediaIdByFileName("image", corpKfAccount.getImg(), yhlxWxCorpConfig.getCorpId()));
+		WxCpKfAccountAddResp resp = wxCorpOps.addAccount(yhlxWxCorpConfig.getCorpId(), wxCpKfAccountAdd);
+		corpKfAccount.setOpenKfId(resp.getOpenKfid());
+		corpKfAccountMapper.insert(corpKfAccount);
+	}
+
+	@Override
+	public void delKfAccount(Long id) throws Exception {
+		CorpKfAccount corpKfAccount = corpKfAccountMapper.selectById(id);
+		WxCpKfAccountDel wxCpKfAccountDel = new WxCpKfAccountDel();
+		wxCpKfAccountDel.setOpenKfid(corpKfAccount.getOpenKfId());
+		wxCorpOps.delAccount(yhlxWxCorpConfig.getCorpId(),wxCpKfAccountDel);
+		corpKfAccountMapper.deleteById(id);
+		//删除人员
+		corpKfAccountFollowMapper.delete(Wrappers.lambdaQuery(CorpKfAccountFollow.class).eq(CorpKfAccountFollow::getOpenKfId, corpKfAccount.getOpenKfId()));
+		//删除session设置
+		corpKfAccountSessionMapper.delete(Wrappers.lambdaQuery(CorpKfAccountSession.class).eq(CorpKfAccountSession::getOpenKfId, corpKfAccount.getOpenKfId()));
+	}
+
+	@Override
+	public void updateKfAccount(CorpKfAccount corpKfAccount) {
+		if(StringUtils.isNotBlank(corpKfAccount.getName()) && StringUtils.isNotBlank(corpKfAccount.getImg())){
+			CorpKfAccount kfAccount = corpKfAccountMapper.selectById(corpKfAccount.getId());
+			WxCpKfAccountUpd wxCpKfAccountUpd = new WxCpKfAccountUpd();
+			wxCpKfAccountUpd.setOpenKfid(kfAccount.getOpenKfId());
+			if (StringUtils.isNotBlank(corpKfAccount.getName())) {
+				wxCpKfAccountUpd.setName(corpKfAccount.getName());
+			}
+			if (StringUtils.isNotBlank(corpKfAccount.getImg())) {
+				wxCpKfAccountUpd.setMediaId(wxCorpOps.getMediaIdByFileName("image", corpKfAccount.getImg(), yhlxWxCorpConfig.getCorpId()));
+			}
+			wxCorpOps.updAccount(yhlxWxCorpConfig.getCorpId(),wxCpKfAccountUpd);
+		}
+		corpKfAccountMapper.updateById(corpKfAccount);
+	}
+}

+ 0 - 1
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderCommonServiceImpl.java

@@ -44,7 +44,6 @@ public class OrderCommonServiceImpl implements OrderCommonService {
 	private final RedisService redisService;
 
 	private final GroupRelationClearService clearService;
-
 	@Override
 	public void clearUnrealGoodsDetail(OrderDon orderDon, Integer goodsType, GoodsDonSku sku) {
 		if (goodsType == 1 && sku != null) {

+ 67 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/corp/wxkf/CorpKfController.java

@@ -0,0 +1,67 @@
+package com.cyksj.web.controller.manage.corp.wxkf;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.CorpKfAccount;
+import com.cyksj.service.corp.kf.CorpKfService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CorpWxKfController
+ * 创建者: JavaZou
+ * 创建时间:2024/12/30 18:02
+ */
+@RestController
+@RequestMapping("/manage/corp/kf")
+@RequiredArgsConstructor
+public class CorpKfController {
+	private final CorpKfService corpKfService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+
+	/**
+	 * 添加客服账号
+	 */
+	@PostMapping("/account/add")
+	public Result<String> addKfAccount(@RequestBody CorpKfAccount corpKfAccount) {
+		corpKfService.addKfAccount(corpKfAccount);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 删除客服账号
+	 */
+	@DeleteMapping("/account/del/{id}")
+	public Result<String> delKfAccount(@PathVariable Long id) {
+		corpKfService.delKfAccount(id);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 修改客服账号
+	 */
+	@PutMapping("/account/update")
+	public Result<String> updateKfAccount(@RequestBody CorpKfAccount corpKfAccount) {
+		corpKfService.updateKfAccount(corpKfAccount);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 客服账号列表
+	 */
+	@GetMapping("/account/get")
+	public Result<SearchResult<CorpKfAccount>> getKfAccount() {
+		SearchResult<CorpKfAccount> search = beanSearcher.search(CorpKfAccount.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+}