|
@@ -0,0 +1,173 @@
|
|
|
+package com.zanxiang.game.module.manage.service.impl;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
|
|
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.zanxiang.game.module.manage.enums.CpSendRoleResultEnum;
|
|
|
+import com.zanxiang.game.module.manage.pojo.dto.CpSendMsgResultDTO;
|
|
|
+import com.zanxiang.game.module.manage.service.ICpSendMsgLogService;
|
|
|
+import com.zanxiang.game.module.manage.service.ICpSendMsgResultService;
|
|
|
+import com.zanxiang.game.module.manage.service.IGameUserRoleService;
|
|
|
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgLog;
|
|
|
+import com.zanxiang.game.module.mybatis.entity.CpSendMsgResult;
|
|
|
+import com.zanxiang.game.module.mybatis.entity.GameUserRole;
|
|
|
+import com.zanxiang.game.module.mybatis.mapper.CpSendMsgLogMapper;
|
|
|
+import com.zanxiang.module.util.JsonUtil;
|
|
|
+import com.zanxiang.module.util.exception.BaseException;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.http.HttpEntity;
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
+import org.springframework.http.MediaType;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.support.TransactionTemplate;
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
+
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.security.MessageDigest;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author : lingfeng
|
|
|
+ * @time : 2024-03-14
|
|
|
+ * @description : CP消息发送记录
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class CpSendMsgLogServiceImpl extends ServiceImpl<CpSendMsgLogMapper, CpSendMsgLog> implements ICpSendMsgLogService {
|
|
|
+
|
|
|
+ private static final String SIGN_MD5 = "MD5";
|
|
|
+
|
|
|
+ private static final String CP_API_KEY = "355b7f07125c1ef71cfd10166e0b90aa";
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TransactionTemplate transactionTemplate;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RestTemplate restTemplate;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IGameUserRoleService gameUserRoleService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ICpSendMsgResultService cpSendMsgResultService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void cpSendMsg(Long taskId, Long gameId, String text, List<String> roleIdList) {
|
|
|
+ //查询角色区服信息
|
|
|
+ List<GameUserRole> gameUserRoleList = gameUserRoleService.list(new LambdaQueryWrapper<GameUserRole>()
|
|
|
+ .select(GameUserRole::getGameId, GameUserRole::getServerId, GameUserRole::getRoleId)
|
|
|
+ .eq(GameUserRole::getGameId, gameId)
|
|
|
+ .in(GameUserRole::getRoleId, roleIdList));
|
|
|
+ String msgId = UUID.randomUUID().toString().replace("-", "");
|
|
|
+ //保存发送记录
|
|
|
+ CpSendMsgLog cpSendMsgLog = this.transform(taskId, gameId, msgId, gameUserRoleList.size());
|
|
|
+ super.save(cpSendMsgLog);
|
|
|
+ if (CollectionUtils.isEmpty(gameUserRoleList)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //角色信息按区服分组
|
|
|
+ Map<String, List<GameUserRole>> serverIdRoleMap = gameUserRoleList.stream()
|
|
|
+ .collect(Collectors.groupingBy(GameUserRole::getServerId));
|
|
|
+ serverIdRoleMap.forEach((serverId, roleList) -> {
|
|
|
+ List<String> serverRoleIdList = roleList.stream().map(GameUserRole::getRoleId).collect(Collectors.toList());
|
|
|
+ try {
|
|
|
+ CpSendMsgResultDTO result = this.cpSendMsgApi(msgId, serverId, serverRoleIdList, text);
|
|
|
+ this.resultHandle(cpSendMsgLog, result, serverId, serverRoleIdList);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("CP消息发送API调用异常, serverId : {}, roleList : {}", serverId, roleList);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private CpSendMsgLog transform(Long taskId, Long gameId, String msgId, Integer roleCount) {
|
|
|
+ return CpSendMsgLog.builder()
|
|
|
+ .msgId(msgId)
|
|
|
+ .taskId(taskId)
|
|
|
+ .gameId(gameId)
|
|
|
+ .roleCount(roleCount)
|
|
|
+ .successCount(0L)
|
|
|
+ .failCount(0L)
|
|
|
+ .createTime(LocalDateTime.now())
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void resultHandle(CpSendMsgLog cpSendMsgLog, CpSendMsgResultDTO result, String serverId, List<String> roleList) {
|
|
|
+ //结果列表
|
|
|
+ List<CpSendMsgResult> resultList = new ArrayList<>();
|
|
|
+ roleList.forEach(roleId -> {
|
|
|
+ //状态判断
|
|
|
+ CpSendRoleResultEnum resultEnum = result.getFailList().contains(roleId) ?
|
|
|
+ CpSendRoleResultEnum.CP_SEND_ROLE_RESULT_FAIL : CpSendRoleResultEnum.CP_SEND_ROLE_RESULT_SUCCESS;
|
|
|
+ resultList.add(this.transform(cpSendMsgLog.getTaskId(), cpSendMsgLog.getMsgId(), resultEnum.getValue(),
|
|
|
+ cpSendMsgLog.getGameId(), serverId, roleId));
|
|
|
+ });
|
|
|
+ //在同一个事物中进行表更新
|
|
|
+ transactionTemplate.execute(status -> {
|
|
|
+ cpSendMsgResultService.saveBatch(resultList);
|
|
|
+ super.update(new LambdaUpdateWrapper<CpSendMsgLog>()
|
|
|
+ .setSql("success_count=success_count+" + result.getSucessCount())
|
|
|
+ .setSql("fail_count=fail_count+" + result.getFailList().size())
|
|
|
+ .eq(CpSendMsgLog::getMsgId, cpSendMsgLog.getMsgId())
|
|
|
+ );
|
|
|
+ return Boolean.TRUE;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private CpSendMsgResult transform(Long taskId, String msgId, String sendStatus, Long gameId, String serverId, String roleId) {
|
|
|
+ return CpSendMsgResult.builder()
|
|
|
+ .taskId(taskId)
|
|
|
+ .msgId(msgId)
|
|
|
+ .gameId(gameId)
|
|
|
+ .serverId(serverId)
|
|
|
+ .roleId(roleId)
|
|
|
+ .sendStatus(sendStatus)
|
|
|
+ .createTime(LocalDateTime.now())
|
|
|
+ .build();
|
|
|
+ }
|
|
|
+
|
|
|
+ private CpSendMsgResultDTO cpSendMsgApi(String msgId, String serverId, List<String> roleIdList, String text) throws Exception {
|
|
|
+ long time = System.currentTimeMillis() / 1000;
|
|
|
+ Map<String, Object> param = new HashMap<>(8);
|
|
|
+ param.put("msgId", msgId);
|
|
|
+ param.put("strRan", msgId);
|
|
|
+ param.put("time", time);
|
|
|
+ param.put("sign", this.MD5("key=" + CP_API_KEY + "&msgId=" + msgId + "&strRan=" + msgId + "&time=" + time));
|
|
|
+ param.put("pushType", 1);
|
|
|
+ param.put("serverid", serverId);
|
|
|
+ param.put("roleIds", roleIdList);
|
|
|
+ //图片地址弄一张最小的, CP方不会用, 有默认底图
|
|
|
+ List<String> imgList = Collections.singletonList("https://manage.84game.cn/image/WechatIMG56.jpeg");
|
|
|
+ Map<String, Object> msgContent = new HashMap<>(2);
|
|
|
+ msgContent.put("text", text);
|
|
|
+ msgContent.put("imgs", JsonUtil.toString(imgList));
|
|
|
+ param.put("msgContent", msgContent);
|
|
|
+ //请求头
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.setContentType(MediaType.APPLICATION_JSON);
|
|
|
+ headers.set(HttpHeaders.ACCEPT_CHARSET, "UTF-8");
|
|
|
+ HttpEntity<String> request = new HttpEntity<>(JsonUtil.toString(param), headers);
|
|
|
+ String result;
|
|
|
+ try {
|
|
|
+ result = restTemplate.postForObject("https://ht.lttx.t5yx.cn/extapi?action=BgzszhSendTip",
|
|
|
+ request, String.class);
|
|
|
+ } catch (Exception e) {
|
|
|
+ System.out.println(e.getMessage());
|
|
|
+ throw new BaseException("消息发送失败");
|
|
|
+ }
|
|
|
+ return JsonUtil.toObj(result, CpSendMsgResultDTO.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String MD5(String data) throws Exception {
|
|
|
+ java.security.MessageDigest md = MessageDigest.getInstance(SIGN_MD5);
|
|
|
+ byte[] array = md.digest(data.getBytes(StandardCharsets.UTF_8));
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ for (byte item : array) {
|
|
|
+ sb.append(Integer.toHexString((item & 0xFF) | 0x100), 1, 3);
|
|
|
+ }
|
|
|
+ return sb.toString();
|
|
|
+ }
|
|
|
+}
|