WeGroupFissionServiceImpl.java 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. package com.linkwechat.service.impl;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.core.collection.CollectionUtil;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import com.baomidou.mybatisplus.core.metadata.IPage;
  6. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  7. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  8. import com.google.gson.JsonArray;
  9. import com.google.gson.JsonElement;
  10. import com.google.gson.JsonObject;
  11. import com.google.gson.JsonParser;
  12. import com.linkwechat.common.core.domain.AjaxResult;
  13. import com.linkwechat.common.core.domain.entity.SysUser;
  14. import com.linkwechat.common.core.domain.model.LoginUser;
  15. import com.linkwechat.common.core.page.TableDataInfo;
  16. import com.linkwechat.common.enums.WeErrorCodeEnum;
  17. import com.linkwechat.common.exception.CustomException;
  18. import com.linkwechat.common.utils.WxMiniProgramSchemeUtil;
  19. import com.linkwechat.domain.groupchat.vo.LinkGroupChatListVo;
  20. import com.linkwechat.domain.weGroupFission.bdsh.LocalMerchantInfo;
  21. import com.linkwechat.domain.weGroupFission.bdsh.LocalRightsInfo;
  22. import com.linkwechat.domain.weGroupFission.bdsh.LotteryActivity;
  23. import com.linkwechat.domain.weGroupFission.dto.DistDto;
  24. import com.linkwechat.domain.weGroupFission.dto.WeGroupFissionDetailDto;
  25. import com.linkwechat.domain.weGroupFission.dto.WeGroupFissionDto;
  26. import com.linkwechat.domain.weGroupFission.entity.*;
  27. import com.linkwechat.domain.weGroupFission.vo.*;
  28. import com.linkwechat.domain.wecom.query.WeBaseQuery;
  29. import com.linkwechat.domain.wecom.query.customer.WeCustomerQuery;
  30. import com.linkwechat.domain.wecom.query.customer.groupchat.WeGroupChatDetailQuery;
  31. import com.linkwechat.domain.wecom.query.customer.groupchat.WeGroupChatListQuery;
  32. import com.linkwechat.domain.wecom.vo.customer.WeCustomerDetailVo;
  33. import com.linkwechat.domain.wecom.vo.customer.WeFollowUserListVo;
  34. import com.linkwechat.domain.wecom.vo.customer.groupchat.WeGroupChatDetailVo;
  35. import com.linkwechat.domain.wecom.vo.customer.groupchat.WeGroupChatListVo;
  36. import com.linkwechat.fegin.QwCustomerClient;
  37. import com.linkwechat.framework.service.TokenService;
  38. import com.linkwechat.mapper.WeGroupFissionMapper;
  39. import com.linkwechat.service.*;
  40. import me.chanjar.weixin.common.error.WxErrorException;
  41. import me.chanjar.weixin.cp.api.WxCpExternalContactService;
  42. import me.chanjar.weixin.cp.api.WxCpService;
  43. import me.chanjar.weixin.cp.api.WxCpUserService;
  44. import me.chanjar.weixin.cp.bean.WxCpUser;
  45. import me.chanjar.weixin.cp.bean.external.WxCpContactWayInfo;
  46. import me.chanjar.weixin.cp.bean.external.WxCpContactWayResult;
  47. import me.chanjar.weixin.cp.bean.external.WxCpUserExternalGroupChatInfo;
  48. import me.chanjar.weixin.cp.bean.external.WxCpUserExternalGroupChatList;
  49. import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
  50. import org.apache.commons.lang3.StringUtils;
  51. import org.springframework.beans.BeanUtils;
  52. import org.springframework.beans.factory.annotation.Autowired;
  53. import org.springframework.stereotype.Service;
  54. import javax.annotation.Resource;
  55. import java.math.BigDecimal;
  56. import java.util.*;
  57. import java.util.stream.Collectors;
  58. /**
  59. * @Description: 群裂变活动表
  60. * @Author: jeecg-boot
  61. * @Date: 2026-01-28
  62. * @Version: V1.0
  63. */
  64. @Service
  65. public class WeGroupFissionServiceImpl extends ServiceImpl<WeGroupFissionMapper, WeGroupFission> implements IWeGroupFissionService {
  66. @Autowired
  67. private IWeGroupFissionExtraRecordService weGroupFissionExtraRecordService;
  68. @Autowired
  69. private IWeGroupFissionStepRecordService weGroupFissionStepRecordService;
  70. @Resource
  71. private WxMiniProgramSchemeUtil wxMiniProgramSchemeUtil;
  72. @Autowired
  73. private LocalMerchantInfoService localMerchantInfoService;
  74. @Resource
  75. private TokenService tokenService;
  76. @Autowired
  77. private ILotteryActivityService lotteryActivityService;
  78. @Autowired
  79. private LocalRightsInfoService localRightsInfoService;
  80. @Autowired
  81. private WxCpService wxCpService;
  82. @Autowired
  83. private IWeExternalChatService weExternalChatService;
  84. @Autowired
  85. private IWeGroupFissionQrCodeRecordService weGroupFissionQrCodeRecordService;
  86. /**
  87. * @version
  88. * @author: hxl
  89. * @Date: 2026/1/28 10:59
  90. * @Description: 群裂变列表+分页
  91. */
  92. @Override
  93. public TableDataInfo<?> getPageList(WeGroupFissionVo weGroupFissionVo) {
  94. TableDataInfo rspData = new TableDataInfo();
  95. if(weGroupFissionVo.getPageNum() == null){
  96. rspData.setCode(500);
  97. rspData.setMsg("当前页码不能为空");
  98. return rspData;
  99. }
  100. if(weGroupFissionVo.getPageSize() == null){
  101. rspData.setCode(500);
  102. rspData.setMsg("页数不能为空");
  103. return rspData;
  104. }
  105. Page<WeGroupFissionDto> page = new Page<WeGroupFissionDto>(weGroupFissionVo.getPageNum(), weGroupFissionVo.getPageSize());
  106. IPage<WeGroupFissionDto> pageList = this.getBaseMapper().getPageList(page, weGroupFissionVo);
  107. List<WeGroupFissionDto> records = pageList.getRecords();
  108. if(records==null || records.isEmpty()){
  109. records =new ArrayList<>();
  110. }
  111. rspData.setCode(200);
  112. rspData.setMsg("查询成功");
  113. rspData.setRows(records);
  114. rspData.setPageNum(weGroupFissionVo.getPageNum());
  115. rspData.setPageSize(weGroupFissionVo.getPageSize());
  116. rspData.setTotal(pageList.getTotal());
  117. return rspData;
  118. }
  119. /**
  120. * @version
  121. * @author: hxl
  122. * @Date: 2026/1/28 11:30
  123. * @Description: 群裂变添加或者修改
  124. */
  125. @Override
  126. public void addOrUpdate(WeGroupFissionAddVo weGroupFissionAddVo) {
  127. try{
  128. //获取平台用户登录id
  129. LoginUser loginUser = tokenService.getLoginUser();
  130. //验证数据正确性
  131. checkData(weGroupFissionAddVo);
  132. //判断是否有id 新增
  133. String id ="";
  134. if (StringUtils.isNotBlank(weGroupFissionAddVo.getId())) {
  135. WeGroupFission weGroupFissionUpdate = this.getById(weGroupFissionAddVo.getId());
  136. if(weGroupFissionUpdate==null){
  137. throw new CustomException("数据不存在");
  138. }
  139. id = weGroupFissionUpdate.getId();
  140. BeanUtil.copyProperties(weGroupFissionAddVo, weGroupFissionUpdate);
  141. //修改创建时间、创建人
  142. weGroupFissionUpdate.setUpdateTime(new Date());
  143. weGroupFissionUpdate.setUpdateUserId(String.valueOf(loginUser.getUserId()));
  144. this.updateById(weGroupFissionUpdate);
  145. }else{
  146. WeGroupFission weGroupFissionAdd =new WeGroupFission();
  147. BeanUtil.copyProperties(weGroupFissionAddVo, weGroupFissionAdd);
  148. //添加创建时间、创建人
  149. weGroupFissionAdd.setCreateTime(new Date());
  150. weGroupFissionAdd.setCreateUserId(String.valueOf(loginUser.getUserId()));
  151. //1.插入群打卡表
  152. this.save(weGroupFissionAdd);
  153. id = weGroupFissionAdd.getId();
  154. }
  155. //2.插入阶段记录表 先通过id删除再添加
  156. List<WeGroupFissionStepVo> weGroupFissionStepList = weGroupFissionAddVo.getWeGroupFissionStepList();
  157. if(weGroupFissionStepList!=null && !weGroupFissionStepList.isEmpty()) {
  158. weGroupFissionStepRecordService.deleteByGroupFissionId(id);
  159. List<WeGroupFissionStepRecord> list =new ArrayList<WeGroupFissionStepRecord>();
  160. String weGroupFissionId = id;
  161. for (WeGroupFissionStepVo weGroupFissionStepVo : weGroupFissionStepList) {
  162. WeGroupFissionStepRecord add = new WeGroupFissionStepRecord();
  163. add.setGroupFissionId(weGroupFissionId);
  164. add.setInvitationCount(weGroupFissionStepVo.getInvitationCount());
  165. add.setSortNum(weGroupFissionStepVo.getSortNum());
  166. add.setRewardAmount(weGroupFissionStepVo.getRewardAmount());
  167. add.setCreateTime(new Date());
  168. list.add(add);
  169. }
  170. weGroupFissionStepRecordService.saveBatch(list);
  171. }
  172. //2.插入额外奖励记录表 先通过id删除再添加
  173. List<WeGroupFissionExtraVo> weGroupFissionExtraList = weGroupFissionAddVo.getWeGroupFissionExtraList();
  174. if(weGroupFissionExtraList!=null && !weGroupFissionExtraList.isEmpty()) {
  175. weGroupFissionExtraRecordService.deleteByGroupFissionId(id);
  176. List<WeGroupFissionExtraRecord> list =new ArrayList<WeGroupFissionExtraRecord>();
  177. String weGroupFissionId = id;
  178. for (WeGroupFissionExtraVo weGroupFissionExtraVo : weGroupFissionExtraList) {
  179. WeGroupFissionExtraRecord add = new WeGroupFissionExtraRecord();
  180. add.setGroupFissionId(weGroupFissionId);
  181. add.setSortNum(weGroupFissionExtraVo.getSortNum());
  182. add.setRewardType(weGroupFissionExtraVo.getRewardType());
  183. add.setRewardAmount(weGroupFissionExtraVo.getRewardAmount());
  184. add.setRightInfoId(weGroupFissionExtraVo.getRightInfoId());
  185. add.setLotteryActivityId(weGroupFissionExtraVo.getLotteryActivityId());
  186. add.setCreateTime(new Date());
  187. list.add(add);
  188. }
  189. weGroupFissionExtraRecordService.saveBatch(list);
  190. }
  191. }catch (Exception e){
  192. throw new CustomException(e.getMessage());
  193. }
  194. }
  195. /**
  196. * @version
  197. * @author: hxl
  198. * @Date: 2026/1/28 14:34
  199. * @Description: 验证数据准确性
  200. */
  201. public void checkData(WeGroupFissionAddVo weGroupFissionAddVo){
  202. //1.触发条件判断 注:≥1,≤200(邀请新客户进群人数)
  203. if(weGroupFissionAddVo.getInvitationCount() <1 || weGroupFissionAddVo.getInvitationCount()>200){
  204. throw new CustomException("邀请新客户进群人数必须>=1且<=200");
  205. }
  206. //2.验证阶梯集合对象
  207. if (weGroupFissionAddVo.getWeGroupFissionStepList() == null || weGroupFissionAddVo.getWeGroupFissionStepList().isEmpty()) {
  208. throw new CustomException("阶梯列表不能为空!");
  209. }else{
  210. //验证每行数据不能为空
  211. validateStepList(weGroupFissionAddVo.getWeGroupFissionStepList());
  212. }
  213. //3.验证额外奖励集合对象
  214. if(weGroupFissionAddVo.getWeGroupFissionExtraList() == null || weGroupFissionAddVo.getWeGroupFissionExtraList().isEmpty()){
  215. throw new CustomException("额外奖励列表不能为空!");
  216. }else{
  217. //验证每行数据不能为空
  218. validateExtraList(weGroupFissionAddVo.getWeGroupFissionExtraList(),weGroupFissionAddVo.getWeGroupFissionStepList().size());
  219. }
  220. }
  221. /**
  222. * @version
  223. * @author: hxl
  224. * @Date: 2026/1/28 14:23
  225. * @Description: 验证额外奖励数据
  226. */
  227. private void validateExtraList(List<WeGroupFissionExtraVo> weGroupFissionExtraList, int size) {
  228. Set<Integer> sortNumSet = new HashSet<>();
  229. for (int i = 0; i < weGroupFissionExtraList.size(); i++) {
  230. WeGroupFissionExtraVo weGroupFissionExtraVo = weGroupFissionExtraList.get(i);
  231. String indexTip = "第" + (i + 1) + "条额外奖励记录:";
  232. if (weGroupFissionExtraVo == null) {
  233. throw new CustomException(indexTip + "额外奖励记录对象不能为空");
  234. }
  235. if (weGroupFissionExtraVo.getSortNum() == null) {
  236. throw new CustomException(indexTip + "阶梯序号不能为空");
  237. }
  238. if (weGroupFissionExtraVo.getSortNum()>size) {
  239. throw new CustomException(indexTip + "阶梯序号不能大于阶梯的数量");
  240. }
  241. if (sortNumSet.contains(weGroupFissionExtraVo.getSortNum())) {
  242. throw new CustomException("阶梯序号[" + weGroupFissionExtraVo.getSortNum() + "]重复");
  243. }
  244. sortNumSet.add(weGroupFissionExtraVo.getSortNum());
  245. if (weGroupFissionExtraVo.getRewardType() == null || weGroupFissionExtraVo.getRewardType().trim().isEmpty()) {
  246. throw new CustomException(indexTip + "奖励类型不能为空");
  247. }
  248. String rewardType = weGroupFissionExtraVo.getRewardType().trim();
  249. if (!"1".equals(rewardType) && !"2".equals(rewardType) && !"3".equals(rewardType)) {
  250. throw new CustomException(indexTip + "奖励类型不正确");
  251. }
  252. if ("1".equals(rewardType)) {
  253. if (weGroupFissionExtraVo.getRewardAmount() == null) {
  254. throw new CustomException(indexTip + "奖励金额不能为空");
  255. }
  256. if (weGroupFissionExtraVo.getRewardAmount().compareTo(BigDecimal.ZERO) <= 0) {
  257. throw new CustomException(indexTip + "奖励金额数值必须大于0");
  258. }
  259. }else if ("2".equals(rewardType)) {
  260. if (StringUtils.isBlank(weGroupFissionExtraVo.getRightInfoId())) {
  261. throw new CustomException(indexTip + "权益券id不能为空");
  262. }
  263. }else if ("3".equals(rewardType)) {
  264. if (StringUtils.isBlank(weGroupFissionExtraVo.getLotteryActivityId())) {
  265. throw new CustomException(indexTip + "大转盘或者九宫格活动id不能为空");
  266. }
  267. }
  268. }
  269. }
  270. /**
  271. * @version
  272. * @author: hxl
  273. * @Date: 2026/1/28 14:13
  274. * @Description: 验证数据
  275. */
  276. public static void validateStepList(List<WeGroupFissionStepVo> stepVoList) {
  277. // 验证数据
  278. WeGroupFissionStepVo prevStep = null;
  279. for (int i = 0; i < stepVoList.size(); i++) {
  280. WeGroupFissionStepVo currentStep = stepVoList.get(i);
  281. if (currentStep.getSortNum() == null) {
  282. throw new IllegalArgumentException("第" + (i + 1) + "条阶梯数据的序号不能为空");
  283. }
  284. if (currentStep.getInvitationCount() == null) {
  285. throw new IllegalArgumentException("第" + (i + 1) + "条阶梯数据的邀请人数不能为空");
  286. }
  287. if (currentStep.getRewardAmount() == null) {
  288. throw new IllegalArgumentException("第" + (i + 1) + "条阶梯数据的奖励金额不能为空");
  289. }
  290. if (i > 0 && prevStep != null) {
  291. if (currentStep.getInvitationCount() <= prevStep.getInvitationCount()) {
  292. throw new IllegalArgumentException(
  293. "第" + (i + 1) + "条阶梯数据的邀请人数(" + currentStep.getInvitationCount() + ")" +
  294. "必须大于第" + i + "条的邀请人数(" + prevStep.getInvitationCount() + ")"
  295. );
  296. }
  297. }
  298. prevStep = currentStep;
  299. }
  300. }
  301. /**
  302. * @version
  303. * @author: hxl
  304. * @Date: 2026/1/28 11:30
  305. * @Description: 通过id查询群裂变信息
  306. * @param type 1.后台结构 2.app结构
  307. */
  308. @Override
  309. public WeGroupFissionDetailDto queryDetailById(String id, String type) {
  310. WeGroupFission weGroupFission = this.getById(id);
  311. if(weGroupFission==null){
  312. throw new CustomException("群裂变活动不存在");
  313. }
  314. //1.基础数据赋值
  315. WeGroupFissionDetailDto dto =new WeGroupFissionDetailDto();
  316. BeanUtils.copyProperties(weGroupFission, dto);
  317. //2.关联阶梯奖励赋值
  318. List<WeGroupFissionStepRecord> stepList = weGroupFissionStepRecordService.findListByGroupCheckInId(id);
  319. if(stepList!=null && !stepList.isEmpty()) {
  320. if("1".equals(type)){
  321. List<WeGroupFissionStepVo> weGroupFissionStepList = new ArrayList<WeGroupFissionStepVo>();
  322. stepList.forEach(reward -> {
  323. WeGroupFissionStepVo weGroupFissionStepVo = new WeGroupFissionStepVo();
  324. BeanUtils.copyProperties(reward, weGroupFissionStepVo);
  325. weGroupFissionStepList.add(weGroupFissionStepVo);
  326. });
  327. dto.setWeGroupFissionStepList(weGroupFissionStepList);
  328. }
  329. }
  330. //3.关联额外奖励赋值
  331. List<WeGroupFissionExtraRecord> extraList = weGroupFissionExtraRecordService.findListByGroupFissionId(id);
  332. HashMap<String, WeGroupFissionExtraRecord> extraMap = new HashMap<>();
  333. if(extraList!=null && !extraList.isEmpty()) {
  334. List<WeGroupFissionExtraVo> weGroupFissionExtraList = new ArrayList<WeGroupFissionExtraVo>();
  335. extraList.forEach(reward -> {
  336. WeGroupFissionExtraVo weGroupFissionExtraVo = new WeGroupFissionExtraVo();
  337. BeanUtils.copyProperties(reward, weGroupFissionExtraVo);
  338. if(StringUtils.isNotBlank(reward.getRightInfoId())){
  339. LocalRightsInfo localRightsInfo = localRightsInfoService.getById(reward.getRightInfoId());
  340. weGroupFissionExtraVo.setRightInfoName(localRightsInfo!=null?localRightsInfo.getRightsName():null);
  341. }
  342. if(StringUtils.isNotBlank(reward.getLotteryActivityId())){
  343. LotteryActivity lotteryActivity = lotteryActivityService.getById(reward.getLotteryActivityId());
  344. weGroupFissionExtraVo.setLotteryActivityName(lotteryActivity!=null?lotteryActivity.getActivityName():null);
  345. }
  346. extraMap.put(reward.getSortNum()+"", reward);
  347. weGroupFissionExtraList.add(weGroupFissionExtraVo);
  348. });
  349. if("1".equals(type)){
  350. dto.setWeGroupFissionExtraList(weGroupFissionExtraList);
  351. }else if("2".equals(type)){
  352. //APP对象
  353. if(stepList!=null && !stepList.isEmpty()) {
  354. List<WeGroupFissionStepAppVo> weGroupFissionStepAppList = new ArrayList<WeGroupFissionStepAppVo>();
  355. stepList.forEach(reward -> {
  356. WeGroupFissionStepAppVo weGroupFissionStepVo = new WeGroupFissionStepAppVo();
  357. BeanUtils.copyProperties(reward, weGroupFissionStepVo);
  358. WeGroupFissionExtraRecord weGroupFissionExtraRecord = extraMap.get(reward.getSortNum() + "");
  359. if(weGroupFissionExtraRecord!=null){
  360. weGroupFissionStepVo.setExtraRewardAmount(weGroupFissionExtraRecord.getRewardAmount());
  361. weGroupFissionStepVo.setRewardType(weGroupFissionExtraRecord.getRewardType());
  362. }
  363. weGroupFissionStepAppList.add(weGroupFissionStepVo);
  364. });
  365. dto.setWeGroupFissionStepAppList(weGroupFissionStepAppList);
  366. }
  367. }
  368. }
  369. //4.查询商户名称
  370. LocalMerchantInfo merchantInfo = localMerchantInfoService.getById(weGroupFission.getMerchantId());
  371. dto.setMerchantName(merchantInfo!=null?merchantInfo.getStoreName():null);
  372. return dto;
  373. }
  374. /**
  375. * @version
  376. * @author: hxl
  377. * @Date: 2026/1/28 11:32
  378. * @Description: 通过id删除数据
  379. */
  380. @Override
  381. public void deleteByWeGroupFissionId(String id) {
  382. WeGroupFission weGroupFission = getStatusDetailsById(id);
  383. if("进行中".equals(weGroupFission.getActivityStatus())
  384. || "已结束".equals(weGroupFission.getActivityStatus())){
  385. throw new CustomException("活动进行中或已结束,不能删除");
  386. }else{
  387. this.removeById(id);
  388. //删除阶梯表
  389. weGroupFissionStepRecordService.deleteByGroupFissionId(id);
  390. //刪除关联额外奖励务表
  391. weGroupFissionExtraRecordService.deleteByGroupFissionId(id);
  392. }
  393. }
  394. /**
  395. * @version
  396. * @author: hxl
  397. * @Date: 2026/1/28 15:05
  398. * @Description: 生成小程序的短连接
  399. */
  400. @Override
  401. public String getWechatGroupFissionUrl(CreateWechatGroupFissionUrlVo createWechatGroupFissionUrlVo) {
  402. String queryParam = "groupFissionId="+createWechatGroupFissionUrlVo.getGroupFissionId()+"&source=poster";
  403. //添加分享人id
  404. if(StringUtils.isNotBlank(createWechatGroupFissionUrlVo.getShareUserId())){
  405. queryParam = queryParam + "&shareUserId="+createWechatGroupFissionUrlVo.getShareUserId();
  406. }
  407. String url ="";
  408. try{
  409. url = wxMiniProgramSchemeUtil.generateScheme(createWechatGroupFissionUrlVo.getUrl(), queryParam, 0,createWechatGroupFissionUrlVo.getVersion());
  410. }catch (Exception e){
  411. throw new CustomException("生成群打卡的短链失败");
  412. }
  413. return url;
  414. }
  415. /**
  416. * @version
  417. * @author: hxl
  418. * @Date: 2026/1/28 16:42
  419. * @Description: 获取企业微信群列表 优化
  420. */
  421. @Override
  422. public List<DistDto> getWecomGroupList() {
  423. List<DistDto> list = new ArrayList<>();
  424. List<WeExternalChat> chatList = weExternalChatService.list(new QueryWrapper<WeExternalChat>().eq("dismiss_flag", "0").orderByDesc("create_time"));
  425. if(chatList!=null && !chatList.isEmpty()){
  426. for (WeExternalChat weExternalChat : chatList) {
  427. DistDto dto = new DistDto();
  428. dto.setVal(weExternalChat.getChatId());
  429. dto.setName(weExternalChat.getChatName());
  430. list.add(dto);
  431. }
  432. }
  433. /* //获取企业微信群列表
  434. WxCpExternalContactService externalContactService = wxCpService.getExternalContactService();
  435. try{
  436. // 调用获取客户群列表接口
  437. WxCpUserExternalGroupChatList wxCpUserExternalGroupChatList = externalContactService.listGroupChat(0, 100, 0, null, null);
  438. if(wxCpUserExternalGroupChatList!=null && wxCpUserExternalGroupChatList.getGroupChatList()!=null && !wxCpUserExternalGroupChatList.getGroupChatList().isEmpty()){
  439. List<WxCpUserExternalGroupChatList.ChatStatus> groupChatList = wxCpUserExternalGroupChatList.getGroupChatList();
  440. for (WxCpUserExternalGroupChatList.ChatStatus chat : groupChatList) {
  441. WxCpUserExternalGroupChatInfo groupChat = externalContactService.getGroupChat(chat.getChatId());
  442. if (groupChat == null) {
  443. continue;
  444. }
  445. DistDto dto = new DistDto();
  446. dto.setVal(chat.getChatId());
  447. dto.setName(groupChat.getGroupChat().getName());
  448. list.add(dto);
  449. }
  450. }
  451. }catch (Exception e){
  452. log.error(e.getMessage());
  453. return new ArrayList<>();
  454. }*/
  455. return list;
  456. }
  457. // 企微原生API - 用户详情
  458. private static final String API_USER_DETAIL_GET = "https://qyapi.weixin.qq.com/cgi-bin/user/get?userid=%s";
  459. /**
  460. * @version
  461. * @author: hxl
  462. * @Date: 2026/1/28 16:42
  463. * @Description: 获取企业微信员工列表
  464. */
  465. @Override
  466. public List<DistDto> getWecomEmployeeList() {
  467. /* List<DistDto> list = new ArrayList<>();
  468. //获取外部联系人列表
  469. WxCpExternalContactService externalContactService = wxCpService.getExternalContactService();
  470. try{
  471. List<String> followerUserIdList = externalContactService.listFollowers();
  472. // 4. 补充成员详情(沿用 4.1.0 版本支持的 getUserService())
  473. WxCpUserService userService = wxCpService.getUserService();
  474. String accessToken = wxCpService.getAccessToken();
  475. for (String userId : followerUserIdList) {
  476. // WxCpUser userDetail = userService.getById(userId);
  477. String requestUrl = String.format(API_USER_DETAIL_GET, userId);
  478. String response = wxCpService.get(requestUrl,null);
  479. JsonObject userDetail = JsonParser.parseString(response).getAsJsonObject();
  480. if (userDetail == null) {
  481. continue;
  482. }
  483. DistDto dto = new DistDto();
  484. dto.setVal(userId);
  485. dto.setName(userDetail.get("name").getAsString());
  486. dto.setUnionid(userDetail.get("unionid")!=null ?userDetail.get("unionid").getAsString():null);
  487. list.add(dto);
  488. }
  489. }catch (Exception e){
  490. log.error(e.getMessage());
  491. return new ArrayList<>();
  492. }*/
  493. return getUserDictDtos();
  494. }
  495. /**
  496. * @version
  497. * @author: hxl
  498. * @Date: 2026/2/2 11:10
  499. * @Description: 获取用户列表
  500. */
  501. @Override
  502. public List<DistDto> getUserDictDtos() {
  503. List<DistDto> list = new ArrayList<>();
  504. List<SysUser> userList = this.getBaseMapper().getUserDictList();
  505. if(userList != null && userList.size() > 0){
  506. for(SysUser sysUser : userList){
  507. DistDto dto = new DistDto();
  508. dto.setVal(sysUser.getUserId()+"");
  509. dto.setName(sysUser.getUserName());
  510. list.add(dto);
  511. }
  512. }
  513. return list;
  514. }
  515. /**
  516. * 手动实现生成外部群二维码(适配 4.1.0 版本源码)
  517. * @param chatId 外部群ID
  518. * @param expireSeconds 有效期(1800~86400秒),默认86400
  519. * @return 二维码URL(直接返回接口原始JSON,可按需封装)
  520. * @throws WxErrorException 微信接口异常
  521. */
  522. public String generateGroupQrcode(String chatId, Integer expireSeconds) throws WxErrorException {
  523. // 1. 构建请求参数
  524. JsonObject json = new JsonObject();
  525. json.addProperty("chat_id", chatId);
  526. // 有效期可选,不传默认24小时
  527. if (expireSeconds != null && expireSeconds >= 1800 && expireSeconds <= 86400) {
  528. json.addProperty("expire_seconds", expireSeconds);
  529. }
  530. // 2. 调用企业微信官方接口(核心:手动拼接URL并请求)
  531. String url = wxCpService.getWxCpConfigStorage().getApiUrl("/cgi-bin/externalcontact/groupchat/get_join_qrcode");
  532. String responseContent = wxCpService.post(url, json.toString());
  533. return responseContent;
  534. }
  535. /**
  536. * @version
  537. * @author: hxl
  538. * @Date: 2026/2/11 17:26
  539. * @Description: 获取群二维码链接
  540. */
  541. @Override
  542. public String getChartQrCodeByChatId(String chatId, String activityId) {
  543. WeGroupFissionQrCodeRecord weGroupFissionQrCodeRecord = weGroupFissionQrCodeRecordService.findEntityByActivityIdAndChatId(activityId,chatId);
  544. JsonObject json = new JsonObject();
  545. // 必传:外部群ID列表
  546. JsonArray chatIdArray = new JsonArray();
  547. chatIdArray.add(chatId);
  548. json.add("chat_id_list", chatIdArray);
  549. //场景。1 - 群的小程序插件 2 - 群的二维码插件
  550. json.addProperty("scene", 2);
  551. //当群满了后,是否自动新建群。0-否;1-是。 默认为1
  552. json.addProperty("auto_create_room", 0);
  553. // 核心参数:state(自定义透传,≤30字符)
  554. json.addProperty("state", weGroupFissionQrCodeRecord.getId());
  555. // 2. 拼接原生接口地址并调用(核心:使用你指定的add_join_way接口)
  556. String apiUrl = "/cgi-bin/externalcontact/groupchat/add_join_way";
  557. String fullUrl = wxCpService.getWxCpConfigStorage().getApiUrl(apiUrl);
  558. try{
  559. String response = wxCpService.post(fullUrl, json.toString());
  560. JsonObject jsonObject = JsonParser.parseString(response).getAsJsonObject();
  561. if (jsonObject.get("errcode").getAsInt() != 0) {
  562. throw new RuntimeException("生成二维码失败:" + jsonObject.get("errmsg").getAsString());
  563. }
  564. String configId = jsonObject.get("config_id").getAsString();
  565. JsonObject getJoinWayJson = new JsonObject();
  566. getJoinWayJson.addProperty("config_id", configId);
  567. String getJoinWayUrl = wxCpService.getWxCpConfigStorage().getApiUrl("/cgi-bin/externalcontact/groupchat/get_join_way");
  568. String getJoinWayResponse = wxCpService.post(getJoinWayUrl, getJoinWayJson.toString());
  569. JsonObject getJoinWayJsonObject = JsonParser.parseString(getJoinWayResponse).getAsJsonObject();
  570. if (getJoinWayJsonObject.get("errcode").getAsInt() != 0) {
  571. throw new RuntimeException("查询二维码失败:" + getJoinWayJsonObject.get("errmsg").getAsString());
  572. }
  573. JsonObject joinWay = getJoinWayJsonObject.getAsJsonObject("join_way");
  574. String qrCode = joinWay.get("qr_code").getAsString();
  575. return qrCode;
  576. }catch (Exception e){
  577. throw new RuntimeException("生成二维码失败");
  578. }
  579. }
  580. /**
  581. * @version
  582. * @author: hxl
  583. * @Date: 2026/2/10 19:00
  584. * @Description: 查询单个群详情
  585. */
  586. private DistDto querySingleChatDetail(String chatId) {
  587. try {
  588. WxCpUserExternalGroupChatInfo groupChat =
  589. wxCpService.getExternalContactService().getGroupChat(chatId);
  590. WxCpUserExternalGroupChatInfo.GroupChat detail = groupChat.getGroupChat();
  591. DistDto dto = new DistDto();
  592. dto.setVal(detail.getChatId());
  593. dto.setName(detail.getName());
  594. return dto;
  595. } catch (WxErrorException e) {
  596. return null;
  597. }
  598. }
  599. /**
  600. * @version
  601. * @author: hxl
  602. * @Date: 2026/1/31 16:16
  603. * @Description: 获取九宫格活动列表
  604. */
  605. public List<DistDto> getActivityDictDtos() {
  606. List<DistDto> list = new ArrayList<>();
  607. List<LotteryActivity> activityList = lotteryActivityService.findListType(null);
  608. if(activityList != null && activityList.size() > 0){
  609. for(LotteryActivity info : activityList){
  610. DistDto dto = new DistDto();
  611. dto.setVal(info.getId());
  612. dto.setName(info.getActivityName());
  613. list.add(dto);
  614. }
  615. }
  616. return list;
  617. }
  618. /**
  619. * @version
  620. * @author: hxl
  621. * @Date: 2026/1/31 16:16
  622. * @Description: 获取权益券列表
  623. */
  624. public List<DistDto> getRightInfoDictDtos() {
  625. List<DistDto> list = new ArrayList<>();
  626. List<LocalRightsInfo> localRightsInfoList = localRightsInfoService.getRightInfoList();
  627. if(localRightsInfoList != null && localRightsInfoList.size() > 0){
  628. for(LocalRightsInfo info : localRightsInfoList){
  629. DistDto dto = new DistDto();
  630. dto.setVal(info.getId());
  631. dto.setName(info.getRightsName());
  632. list.add(dto);
  633. }
  634. }
  635. return list;
  636. }
  637. /**
  638. * @version
  639. * @author: hxl
  640. * @Date: 2026/1/31 16:15
  641. * @Description: 获取启用的商户
  642. */
  643. public List<DistDto> getLocalMerchantInfoDictDtos() {
  644. List<DistDto> list = new ArrayList<>();
  645. List<LocalMerchantInfo> merchantInfoList = localMerchantInfoService.getMerchantInfoList();
  646. if(merchantInfoList != null && merchantInfoList.size() > 0){
  647. for(LocalMerchantInfo info : merchantInfoList){
  648. DistDto dto = new DistDto();
  649. dto.setVal(info.getId());
  650. dto.setName(info.getStoreName());
  651. list.add(dto);
  652. }
  653. }
  654. return list;
  655. }
  656. /**
  657. * @version
  658. * @author: hxl
  659. * @Date: 2026/1/28 14:53
  660. * @Description: 查询状态
  661. */
  662. public WeGroupFission getStatusDetailsById(String id) {
  663. return this.getBaseMapper().getStatusDetailsById(id);
  664. }
  665. }