|
@@ -7,12 +7,13 @@ import com.alibaba.fastjson.JSONObject;
|
|
|
import com.fs.common.exception.CustomException;
|
|
import com.fs.common.exception.CustomException;
|
|
|
import com.fs.qw.domain.QwConversationMessage;
|
|
import com.fs.qw.domain.QwConversationMessage;
|
|
|
import com.fs.qw.domain.QwConversationParticipant;
|
|
import com.fs.qw.domain.QwConversationParticipant;
|
|
|
|
|
+import com.fs.qw.dto.SearchMsgRequest;
|
|
|
import com.fs.qw.mapper.QwConversationMessageMapper;
|
|
import com.fs.qw.mapper.QwConversationMessageMapper;
|
|
|
import com.fs.qw.mapper.QwConversationParticipantMapper;
|
|
import com.fs.qw.mapper.QwConversationParticipantMapper;
|
|
|
import com.fs.qw.service.ICorporateWeChatSpaceService;
|
|
import com.fs.qw.service.ICorporateWeChatSpaceService;
|
|
|
-import com.fs.qw.utils.WeChatSpaceDecryptUtil;
|
|
|
|
|
import com.fs.qw.utils.WeChatSpaceUtil;
|
|
import com.fs.qw.utils.WeChatSpaceUtil;
|
|
|
import com.fs.qw.vo.QwSessionConfigVo;
|
|
import com.fs.qw.vo.QwSessionConfigVo;
|
|
|
|
|
+import com.fs.qw.vo.SearchResultVO;
|
|
|
import com.fs.system.service.ISysConfigService;
|
|
import com.fs.system.service.ISysConfigService;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
@@ -24,6 +25,7 @@ import lombok.RequiredArgsConstructor;
|
|
|
import java.time.Instant;
|
|
import java.time.Instant;
|
|
|
import java.time.ZoneId;
|
|
import java.time.ZoneId;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Objects;
|
|
import java.util.Objects;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
@@ -45,6 +47,9 @@ public class ICorporateWeChatSpaceServiceImpl implements ICorporateWeChatSpaceSe
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private WeChatSpaceUtil weChatSpaceUtil;
|
|
private WeChatSpaceUtil weChatSpaceUtil;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private QwProgramInvoker qwProgramInvoker;
|
|
|
|
|
+
|
|
|
private final RestTemplate restTemplate = new RestTemplate();
|
|
private final RestTemplate restTemplate = new RestTemplate();
|
|
|
|
|
|
|
|
private final ConcurrentHashMap<String, String> consumedCodes = new ConcurrentHashMap<>();
|
|
private final ConcurrentHashMap<String, String> consumedCodes = new ConcurrentHashMap<>();
|
|
@@ -118,7 +123,7 @@ public class ICorporateWeChatSpaceServiceImpl implements ICorporateWeChatSpaceSe
|
|
|
@Override
|
|
@Override
|
|
|
public JSONObject getAgentConfigSignature(String url,String corpid) {
|
|
public JSONObject getAgentConfigSignature(String url,String corpid) {
|
|
|
QwSessionConfigVo qwSessionConfig = getQwSessionConfigByCorpid(corpid);
|
|
QwSessionConfigVo qwSessionConfig = getQwSessionConfigByCorpid(corpid);
|
|
|
- return weChatSpaceUtil.generateAgentConfigSignature(qwSessionConfig.getCorpid(), qwSessionConfig.getAgentSecret(), qwSessionConfig.getAgentid(), url);
|
|
|
|
|
|
|
+ return weChatSpaceUtil.generateAgentConfigSignature(qwSessionConfig.getCorpid(), qwSessionConfig.getAgentid(), url);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -136,7 +141,7 @@ public class ICorporateWeChatSpaceServiceImpl implements ICorporateWeChatSpaceSe
|
|
|
}
|
|
}
|
|
|
QwSessionConfigVo qwSessionConfig = getQwSessionConfigByCorpid(corpid);
|
|
QwSessionConfigVo qwSessionConfig = getQwSessionConfigByCorpid(corpid);
|
|
|
try {
|
|
try {
|
|
|
- String accessToken = weChatSpaceUtil.getAccessToken(qwSessionConfig.getCorpid(), qwSessionConfig.getAgentSecret());
|
|
|
|
|
|
|
+ String accessToken = weChatSpaceUtil.getAccessToken(qwSessionConfig.getCorpid());
|
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token="
|
|
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token="
|
|
|
+ accessToken + "&code=" + code;
|
|
+ accessToken + "&code=" + code;
|
|
|
JSONObject resp = restTemplate.getForObject(url, JSONObject.class);
|
|
JSONObject resp = restTemplate.getForObject(url, JSONObject.class);
|
|
@@ -192,81 +197,214 @@ public class ICorporateWeChatSpaceServiceImpl implements ICorporateWeChatSpaceSe
|
|
|
.orElseThrow(() -> new CustomException("未找到corpid为 " + corpid + " 的配置"));
|
|
.orElseThrow(() -> new CustomException("未找到corpid为 " + corpid + " 的配置"));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // ========== 关键词搜索 ==========
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public SearchResultVO searchMsg(SearchMsgRequest request) {
|
|
|
|
|
+ // 1. 获取企业配置,并找到 search_msg 能力ID
|
|
|
|
|
+ QwSessionConfigVo config = getQwSessionConfigByCorpid(request.getCorpId());
|
|
|
|
|
+ String abilityId = config.getAbilityIds().stream()
|
|
|
|
|
+ .filter(item -> "invokeSearchMsg".equals(item.getKey()))
|
|
|
|
|
+ .map(QwSessionConfigVo.AbilityItem::getValue)
|
|
|
|
|
+ .findFirst()
|
|
|
|
|
+ .orElseThrow(() -> new CustomException("未配置 invokeSearchMsg 能力,请在企微后台添加"));
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 构造请求数据
|
|
|
|
|
+ JSONObject requestData = new JSONObject();
|
|
|
|
|
+ requestData.put("query_word", request.getQueryWord());
|
|
|
|
|
+
|
|
|
|
|
+ // 构造 chat_info
|
|
|
|
|
+ if (request.getChatType() != null) {
|
|
|
|
|
+ JSONObject chatInfo = new JSONObject();
|
|
|
|
|
+ chatInfo.put("chat_type", request.getChatType());
|
|
|
|
|
+
|
|
|
|
|
+ if (request.getChatType() == 1) { // 单聊
|
|
|
|
|
+ JSONArray idList = new JSONArray();
|
|
|
|
|
+ idList.add(new JSONObject().fluentPut("open_userid", request.getStaffUserId()));
|
|
|
|
|
+ idList.add(new JSONObject().fluentPut("external_userid", request.getCustomerId()));
|
|
|
|
|
+ chatInfo.put("id_list", idList);
|
|
|
|
|
+ } else if (request.getChatType() == 2) { // 群聊
|
|
|
|
|
+ chatInfo.put("chat_id", request.getChatId());
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- private JSONArray processMessages(JSONArray msgList, String customerId, String staffUserId, QwSessionConfigVo qwConfig) {
|
|
|
|
|
- return msgList.parallelStream()
|
|
|
|
|
- .map(obj -> (JSONObject) obj)
|
|
|
|
|
- .filter(msg -> isMessageRelatedToUsers(msg, customerId, staffUserId))
|
|
|
|
|
- .map(msg -> decryptAndFormatMessage(msg, qwConfig))
|
|
|
|
|
- .filter(Objects::nonNull)
|
|
|
|
|
- .collect(Collectors.toCollection(JSONArray::new));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (request.getMsgTypeList() != null && !request.getMsgTypeList().isEmpty()) {
|
|
|
|
|
+ chatInfo.put("msg_type_list", request.getMsgTypeList());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.isNotBlank(request.getSenderUserId())) {
|
|
|
|
|
+ chatInfo.put("sender", new JSONObject().fluentPut("open_userid", request.getSenderUserId()));
|
|
|
|
|
+ }
|
|
|
|
|
+ requestData.put("chat_info", chatInfo);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (request.getStartTime() != null) requestData.put("start_time", request.getStartTime());
|
|
|
|
|
+ if (request.getEndTime() != null) requestData.put("end_time", request.getEndTime());
|
|
|
|
|
+ if (request.getSkipStopWords() != null) requestData.put("skip_stop_words", request.getSkipStopWords());
|
|
|
|
|
+ if (request.getLimit() != null) requestData.put("limit", Math.min(request.getLimit(), 100));
|
|
|
|
|
+ if (StringUtils.isNotBlank(request.getCursor())) requestData.put("cursor", request.getCursor());
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 调用企微 sync_call_program 接口
|
|
|
|
|
+ JSONObject response = qwProgramInvoker.callProgram(
|
|
|
|
|
+ config.getCorpid(),
|
|
|
|
|
+ config.getProgramId(),
|
|
|
|
|
+ abilityId,
|
|
|
|
|
+ requestData
|
|
|
|
|
+ );
|
|
|
|
|
+ if (response == null || response.getIntValue("errcode") != 0) {
|
|
|
|
|
+ String errMsg = response != null ? response.getString("errmsg") : "网络错误";
|
|
|
|
|
+ log.error("调用 search_msg 失败: {}", errMsg);
|
|
|
|
|
+ throw new CustomException("搜索失败:" + errMsg);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- private boolean isMessageRelatedToUsers(JSONObject msg, String customerId, String staffUserId) {
|
|
|
|
|
- // 如果都为空,则不过滤,返回全部
|
|
|
|
|
- if ((customerId == null || customerId.isEmpty()) && (staffUserId == null || staffUserId.isEmpty())) {
|
|
|
|
|
- return true;
|
|
|
|
|
|
|
+ String responseDataStr = response.getString("response_data");
|
|
|
|
|
+ if (StringUtils.isBlank(responseDataStr)) {
|
|
|
|
|
+ throw new CustomException("专区返回数据为空");
|
|
|
}
|
|
}
|
|
|
- boolean hasCustomer = (customerId == null || customerId.isEmpty());
|
|
|
|
|
- boolean hasStaff = (staffUserId == null || staffUserId.isEmpty());
|
|
|
|
|
-
|
|
|
|
|
- JSONObject sender = msg.getJSONObject("sender");
|
|
|
|
|
- JSONArray receivers = msg.getJSONArray("receiver_list");
|
|
|
|
|
-
|
|
|
|
|
- // 检查发送者
|
|
|
|
|
- if (sender != null) {
|
|
|
|
|
- String senderId = sender.getString("id");
|
|
|
|
|
- int senderType = sender.getIntValue("type");
|
|
|
|
|
- if (!hasCustomer && senderType == 2 && customerId.equals(senderId)) hasCustomer = true;
|
|
|
|
|
- if (!hasStaff && senderType == 1 && staffUserId.equals(senderId)) hasStaff = true;
|
|
|
|
|
|
|
+ JSONObject respData = JSON.parseObject(responseDataStr);
|
|
|
|
|
+ if (respData.getIntValue("errcode") != 0) {
|
|
|
|
|
+ throw new CustomException("搜索失败:" + respData.getString("errmsg"));
|
|
|
}
|
|
}
|
|
|
- if (hasCustomer && hasStaff) return true;
|
|
|
|
|
-
|
|
|
|
|
- // 检查接收者
|
|
|
|
|
- if (receivers != null) {
|
|
|
|
|
- for (int i = 0; i < receivers.size(); i++) {
|
|
|
|
|
- JSONObject recv = receivers.getJSONObject(i);
|
|
|
|
|
- String recvId = recv.getString("id");
|
|
|
|
|
- int recvType = recv.getIntValue("type");
|
|
|
|
|
- if (!hasCustomer && recvType == 2 && customerId.equals(recvId)) hasCustomer = true;
|
|
|
|
|
- if (!hasStaff && recvType == 1 && staffUserId.equals(recvId)) hasStaff = true;
|
|
|
|
|
- if (hasCustomer && hasStaff) return true;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 提取 msgid 列表
|
|
|
|
|
+ JSONArray msgListArray = respData.getJSONArray("msg_list");
|
|
|
|
|
+ if (msgListArray == null || msgListArray.isEmpty()) {
|
|
|
|
|
+ return new SearchResultVO(new JSONArray(), 0, "");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<String> msgIds = new ArrayList<>();
|
|
|
|
|
+ for (Object obj : msgListArray) {
|
|
|
|
|
+ JSONObject item = (JSONObject) obj;
|
|
|
|
|
+ msgIds.add(item.getString("msgid"));
|
|
|
}
|
|
}
|
|
|
- return hasCustomer && hasStaff;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 从本地数据库批量查询消息详情
|
|
|
|
|
+ List<QwConversationMessage> messages = messageMapper.selectByMsgIds(request.getCorpId(), msgIds);
|
|
|
|
|
+ if (messages.isEmpty()) {
|
|
|
|
|
+ return new SearchResultVO(new JSONArray(), respData.getIntValue("has_more"), respData.getString("next_cursor"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 构建返回数据
|
|
|
|
|
+ JSONArray resultList = new JSONArray();
|
|
|
|
|
+ for (QwConversationMessage msg : messages) {
|
|
|
|
|
+ JSONObject item = buildMessageJson(msg, request.getCorpId());
|
|
|
|
|
+ resultList.add(item);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return new SearchResultVO(resultList, respData.getIntValue("has_more"), respData.getString("next_cursor"));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private JSONObject decryptAndFormatMessage(JSONObject msg, QwSessionConfigVo qwConfig) {
|
|
|
|
|
- JSONObject result = new JSONObject();
|
|
|
|
|
- try {
|
|
|
|
|
- JSONObject encryptInfo = msg.getJSONObject("service_encrypt_info");
|
|
|
|
|
- if (encryptInfo == null) return null;
|
|
|
|
|
- String encryptedKey = encryptInfo.getString("encrypted_secret_key");
|
|
|
|
|
- if (encryptedKey == null) return null;
|
|
|
|
|
-
|
|
|
|
|
- // 解密得到 secretKey
|
|
|
|
|
- String secretKey = WeChatSpaceDecryptUtil.decryptSecretKey(encryptedKey, qwConfig.getPrivateKey());
|
|
|
|
|
-
|
|
|
|
|
- // 复制需要返回的字段
|
|
|
|
|
- result.put("msgid", msg.getString("msgid"));
|
|
|
|
|
- result.put("secretKey", secretKey);
|
|
|
|
|
- result.put("sender", msg.get("sender"));
|
|
|
|
|
- result.put("receiver_list", msg.get("receiver_list"));
|
|
|
|
|
- result.put("msgtype", msg.getInteger("msgtype"));
|
|
|
|
|
-
|
|
|
|
|
- Long sendTime = msg.getLong("send_time");
|
|
|
|
|
- if (sendTime != null) {
|
|
|
|
|
- String formattedTime = Instant.ofEpochSecond(sendTime)
|
|
|
|
|
- .atZone(ZoneId.systemDefault())
|
|
|
|
|
- .toLocalDateTime()
|
|
|
|
|
- .format(DATE_TIME_FORMATTER);
|
|
|
|
|
- result.put("send_time_str", formattedTime);
|
|
|
|
|
- result.put("send_time", sendTime);
|
|
|
|
|
- }
|
|
|
|
|
- return result;
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("解密消息失败, msgid: {}", msg.getString("msgid"), e);
|
|
|
|
|
- return null;
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 构建前端需要的消息JSON
|
|
|
|
|
+ */
|
|
|
|
|
+ private JSONObject buildMessageJson(QwConversationMessage msg, String corpId) {
|
|
|
|
|
+ JSONObject item = new JSONObject();
|
|
|
|
|
+ item.put("msgid", msg.getMsgid());
|
|
|
|
|
+ item.put("secretKey", msg.getSecretKey());
|
|
|
|
|
+
|
|
|
|
|
+ // 发送者
|
|
|
|
|
+ JSONObject sender = new JSONObject();
|
|
|
|
|
+ sender.put("type", msg.getSenderType());
|
|
|
|
|
+ sender.put("id", msg.getSenderId());
|
|
|
|
|
+ item.put("sender", sender);
|
|
|
|
|
+
|
|
|
|
|
+ // 接收者列表
|
|
|
|
|
+ List<QwConversationParticipant> receivers = participantMapper.selectByMsgidAndType(corpId, msg.getMsgid(), 2);
|
|
|
|
|
+ JSONArray receiverList = new JSONArray();
|
|
|
|
|
+ for (QwConversationParticipant p : receivers) {
|
|
|
|
|
+ JSONObject recv = new JSONObject();
|
|
|
|
|
+ recv.put("type", p.getUserType());
|
|
|
|
|
+ recv.put("id", p.getUserId());
|
|
|
|
|
+ receiverList.add(recv);
|
|
|
}
|
|
}
|
|
|
|
|
+ item.put("receiver_list", receiverList);
|
|
|
|
|
+
|
|
|
|
|
+ item.put("msgtype", msg.getMsgtype());
|
|
|
|
|
+
|
|
|
|
|
+ // 时间
|
|
|
|
|
+ if (msg.getSendTime() != null) {
|
|
|
|
|
+ item.put("send_time", msg.getSendTime());
|
|
|
|
|
+ String formattedTime = Instant.ofEpochSecond(msg.getSendTime())
|
|
|
|
|
+ .atZone(ZoneId.systemDefault())
|
|
|
|
|
+ .toLocalDateTime()
|
|
|
|
|
+ .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
|
|
|
+ item.put("send_time_str", formattedTime);
|
|
|
|
|
+ }
|
|
|
|
|
+ return item;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// private JSONArray processMessages(JSONArray msgList, String customerId, String staffUserId, QwSessionConfigVo qwConfig) {
|
|
|
|
|
+// return msgList.parallelStream()
|
|
|
|
|
+// .map(obj -> (JSONObject) obj)
|
|
|
|
|
+// .filter(msg -> isMessageRelatedToUsers(msg, customerId, staffUserId))
|
|
|
|
|
+// .map(msg -> decryptAndFormatMessage(msg, qwConfig))
|
|
|
|
|
+// .filter(Objects::nonNull)
|
|
|
|
|
+// .collect(Collectors.toCollection(JSONArray::new));
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// private boolean isMessageRelatedToUsers(JSONObject msg, String customerId, String staffUserId) {
|
|
|
|
|
+// // 如果都为空,则不过滤,返回全部
|
|
|
|
|
+// if ((customerId == null || customerId.isEmpty()) && (staffUserId == null || staffUserId.isEmpty())) {
|
|
|
|
|
+// return true;
|
|
|
|
|
+// }
|
|
|
|
|
+// boolean hasCustomer = (customerId == null || customerId.isEmpty());
|
|
|
|
|
+// boolean hasStaff = (staffUserId == null || staffUserId.isEmpty());
|
|
|
|
|
+//
|
|
|
|
|
+// JSONObject sender = msg.getJSONObject("sender");
|
|
|
|
|
+// JSONArray receivers = msg.getJSONArray("receiver_list");
|
|
|
|
|
+//
|
|
|
|
|
+// // 检查发送者
|
|
|
|
|
+// if (sender != null) {
|
|
|
|
|
+// String senderId = sender.getString("id");
|
|
|
|
|
+// int senderType = sender.getIntValue("type");
|
|
|
|
|
+// if (!hasCustomer && senderType == 2 && customerId.equals(senderId)) hasCustomer = true;
|
|
|
|
|
+// if (!hasStaff && senderType == 1 && staffUserId.equals(senderId)) hasStaff = true;
|
|
|
|
|
+// }
|
|
|
|
|
+// if (hasCustomer && hasStaff) return true;
|
|
|
|
|
+//
|
|
|
|
|
+// // 检查接收者
|
|
|
|
|
+// if (receivers != null) {
|
|
|
|
|
+// for (int i = 0; i < receivers.size(); i++) {
|
|
|
|
|
+// JSONObject recv = receivers.getJSONObject(i);
|
|
|
|
|
+// String recvId = recv.getString("id");
|
|
|
|
|
+// int recvType = recv.getIntValue("type");
|
|
|
|
|
+// if (!hasCustomer && recvType == 2 && customerId.equals(recvId)) hasCustomer = true;
|
|
|
|
|
+// if (!hasStaff && recvType == 1 && staffUserId.equals(recvId)) hasStaff = true;
|
|
|
|
|
+// if (hasCustomer && hasStaff) return true;
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
|
|
+// return hasCustomer && hasStaff;
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// private JSONObject decryptAndFormatMessage(JSONObject msg, QwSessionConfigVo qwConfig) {
|
|
|
|
|
+// JSONObject result = new JSONObject();
|
|
|
|
|
+// try {
|
|
|
|
|
+// JSONObject encryptInfo = msg.getJSONObject("service_encrypt_info");
|
|
|
|
|
+// if (encryptInfo == null) return null;
|
|
|
|
|
+// String encryptedKey = encryptInfo.getString("encrypted_secret_key");
|
|
|
|
|
+// if (encryptedKey == null) return null;
|
|
|
|
|
+//
|
|
|
|
|
+// // 解密得到 secretKey
|
|
|
|
|
+// String secretKey = WeChatSpaceDecryptUtil.decryptSecretKey(encryptedKey, qwConfig.getPrivateKey());
|
|
|
|
|
+//
|
|
|
|
|
+// // 复制需要返回的字段
|
|
|
|
|
+// result.put("msgid", msg.getString("msgid"));
|
|
|
|
|
+// result.put("secretKey", secretKey);
|
|
|
|
|
+// result.put("sender", msg.get("sender"));
|
|
|
|
|
+// result.put("receiver_list", msg.get("receiver_list"));
|
|
|
|
|
+// result.put("msgtype", msg.getInteger("msgtype"));
|
|
|
|
|
+//
|
|
|
|
|
+// Long sendTime = msg.getLong("send_time");
|
|
|
|
|
+// if (sendTime != null) {
|
|
|
|
|
+// String formattedTime = Instant.ofEpochSecond(sendTime)
|
|
|
|
|
+// .atZone(ZoneId.systemDefault())
|
|
|
|
|
+// .toLocalDateTime()
|
|
|
|
|
+// .format(DATE_TIME_FORMATTER);
|
|
|
|
|
+// result.put("send_time_str", formattedTime);
|
|
|
|
|
+// result.put("send_time", sendTime);
|
|
|
|
|
+// }
|
|
|
|
|
+// return result;
|
|
|
|
|
+// } catch (Exception e) {
|
|
|
|
|
+// log.error("解密消息失败, msgid: {}", msg.getString("msgid"), e);
|
|
|
|
|
+// return null;
|
|
|
|
|
+// }
|
|
|
|
|
+// }
|
|
|
}
|
|
}
|