REQ-3201: 运营push
This commit is contained in:
parent
bd22efdebb
commit
b22257d678
@ -2,10 +2,8 @@ package cn.axzo.msg.center.inside.notices.service.impl;
|
|||||||
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.api.MessagePushApi;
|
import cn.axzo.msg.center.api.MessagePushApi;
|
||||||
import cn.axzo.msg.center.api.request.BuildNimPayloadRequest;
|
|
||||||
import cn.axzo.msg.center.api.request.MsgBody4Guest;
|
import cn.axzo.msg.center.api.request.MsgBody4Guest;
|
||||||
import cn.axzo.msg.center.inside.notices.service.IYouMengMessageService;
|
import cn.axzo.msg.center.inside.notices.service.IYouMengMessageService;
|
||||||
import cn.axzo.msg.center.nimpush.NimPushService;
|
|
||||||
import cn.azxo.framework.common.model.CommonResponse;
|
import cn.azxo.framework.common.model.CommonResponse;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -22,8 +20,6 @@ public class MessagePushApiImpl implements MessagePushApi {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IYouMengMessageService youMengMessageService;
|
private IYouMengMessageService youMengMessageService;
|
||||||
@Autowired
|
|
||||||
private NimPushService nimPushService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResponse<Void> sendPushMessage(MsgBody4Guest msgBody) {
|
public CommonResponse<Void> sendPushMessage(MsgBody4Guest msgBody) {
|
||||||
@ -32,11 +28,4 @@ public class MessagePushApiImpl implements MessagePushApi {
|
|||||||
return CommonResponse.success();
|
return CommonResponse.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public CommonResponse<String> buildNimPayload(BuildNimPayloadRequest request) {
|
|
||||||
log.info("buildNimPayload, request={}", request);
|
|
||||||
String payload = nimPushService.buildPayloadString(request, request.getPushPeer());
|
|
||||||
return CommonResponse.success(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,260 +0,0 @@
|
|||||||
package cn.axzo.msg.center.inside.notices.service.impl.v3.msg;
|
|
||||||
|
|
||||||
import cn.axzo.framework.jackson.utility.JSON;
|
|
||||||
import cn.axzo.im.center.api.feign.MessageApi;
|
|
||||||
import cn.axzo.im.center.api.vo.ApiChannel;
|
|
||||||
import cn.axzo.im.center.api.vo.PersonAccountAttribute;
|
|
||||||
import cn.axzo.im.center.api.vo.req.ExcludePushPayload;
|
|
||||||
import cn.axzo.im.center.api.vo.req.SendTemplateMessageParam;
|
|
||||||
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
|
||||||
import cn.axzo.msg.center.api.enums.MsgStateV3Enum;
|
|
||||||
import cn.axzo.msg.center.api.request.v4.MessageSendBasicInfoV4;
|
|
||||||
import cn.axzo.msg.center.api.request.v4.MessageSendRequestV4;
|
|
||||||
import cn.axzo.msg.center.common.enums.TableIsDeleteEnum;
|
|
||||||
import cn.axzo.msg.center.common.utils.BizAssertions;
|
|
||||||
import cn.axzo.msg.center.common.utils.PlaceholderResolver;
|
|
||||||
import cn.axzo.msg.center.domain.entity.MessageRecordV3;
|
|
||||||
import cn.axzo.msg.center.message.domain.dto.TemplateModelV3;
|
|
||||||
import cn.axzo.msg.center.message.domain.vo.GeneralMessagePushVO;
|
|
||||||
import cn.axzo.msg.center.message.service.card.CardSupport;
|
|
||||||
import cn.axzo.msg.center.message.service.impl.v3.ModelV3Parser;
|
|
||||||
import cn.axzo.msg.center.message.service.impl.v3.UrlParser;
|
|
||||||
import cn.axzo.msg.center.nimpush.NimPushService;
|
|
||||||
import cn.axzo.msg.center.nimpush.PushChannel;
|
|
||||||
import cn.axzo.msg.center.nimpush.device.PushDeviceSnapshots;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.Intent;
|
|
||||||
import cn.axzo.msg.center.push.PushData;
|
|
||||||
import cn.axzo.msg.center.service.domain.PushPeer;
|
|
||||||
import cn.axzo.msg.center.service.dto.PersonV3DTO;
|
|
||||||
import cn.axzo.msg.center.service.enums.Channel;
|
|
||||||
import cn.axzo.msg.center.service.enums.OrganizationTypeEnum;
|
|
||||||
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedModelV3;
|
|
||||||
import cn.axzo.msg.center.utils.UUIDUtil;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static java.util.stream.Collectors.toList;
|
|
||||||
import static java.util.stream.Collectors.toSet;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class TemplateMessage {
|
|
||||||
|
|
||||||
private final MessageSendRequestV4 req;
|
|
||||||
private final String batchNo;
|
|
||||||
@Getter
|
|
||||||
private final Channel channel;
|
|
||||||
@Getter
|
|
||||||
private final TemplateModelV3 templateModel;
|
|
||||||
private final ApplicationContext beanFactory;
|
|
||||||
|
|
||||||
private List<MessageRecordV3> records;
|
|
||||||
private String title;
|
|
||||||
private String content;
|
|
||||||
|
|
||||||
String getTemplateCode() {
|
|
||||||
return templateModel.getTemplateCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection<Long> getMessageIds() {
|
|
||||||
return getMessageRecords().stream()
|
|
||||||
.map(MessageRecordV3::getId)
|
|
||||||
.collect(toSet());
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection<Long> getReceiverPersonIds() {
|
|
||||||
return getMessageRecords().stream()
|
|
||||||
.map(MessageRecordV3::getReceiverPersonId)
|
|
||||||
.collect(toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
List<MessageRecordV3> getMessageRecords() {
|
|
||||||
if (records != null) {
|
|
||||||
return records;
|
|
||||||
}
|
|
||||||
records = new ArrayList<>();
|
|
||||||
MessageSendBasicInfoV4 sendBasicInfo = req.getSendBasicInfo();
|
|
||||||
for (PersonV3DTO receiver : sendBasicInfo.distinctReceivers()) {
|
|
||||||
PersonV3DTO sender = sendBasicInfo.getSender();
|
|
||||||
MessageRecordV3 message = new MessageRecordV3();
|
|
||||||
records.add(message);
|
|
||||||
message.setBatchNo(batchNo);
|
|
||||||
message.setIdentityCode(UUIDUtil.uuidString());
|
|
||||||
message.setSenderPersonId(sender == null ? null : sender.getId());
|
|
||||||
message.setSenderOuId(sendBasicInfo.getSenderOuId());
|
|
||||||
message.setSenderWorkspaceId(sendBasicInfo.getSenderWorkspaceId());
|
|
||||||
message.setReceiverPersonId(receiver.getId());
|
|
||||||
message.setReceiverOuId(sendBasicInfo.determineReceiversOuId());
|
|
||||||
message.setReceiverWorkspaceId(sendBasicInfo.determineReceiversWorkspaceId());
|
|
||||||
message.setBizEventMappingCode(req.getEventMappingCode());
|
|
||||||
message.setTemplateCode(getTemplateCode());
|
|
||||||
message.setTitle(parseTitle());
|
|
||||||
message.setContent(parseContent());
|
|
||||||
OrganizationTypeEnum orgType = sendBasicInfo.getReceiversOrgType();
|
|
||||||
if (orgType == null) {
|
|
||||||
orgType = OrganizationTypeEnum.UNKNOWN;
|
|
||||||
}
|
|
||||||
message.setReceiverOrgType(orgType.stringCode());
|
|
||||||
message.setSubtitle(sendBasicInfo.getSubtitle());
|
|
||||||
message.setState(MsgStateV3Enum.UNSENT);
|
|
||||||
message.setBizCode(sendBasicInfo.determineBizCode());
|
|
||||||
message.setRouterParams(sendBasicInfo.determineRouterParams());
|
|
||||||
message.setBizExtParams(sendBasicInfo.determineBizExtParams());
|
|
||||||
message.setMsgExtInfo(getMsgExtInfo());
|
|
||||||
message.setFailCause(null);
|
|
||||||
message.setCreateAt(new Date());
|
|
||||||
message.setUpdateAt(new Date());
|
|
||||||
message.setIsDelete(TableIsDeleteEnum.NORMAL.value);
|
|
||||||
// 这里不设置发送时间, 有发送结果的时候再设置, 比较准确
|
|
||||||
}
|
|
||||||
return records;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendTemplateMessageParam buildImRequest(MessageTemplateParserV3 templateParser,
|
|
||||||
PushDeviceSnapshots deviceSnapshots,
|
|
||||||
AppTypeEnum appType) {
|
|
||||||
MessageRecordV3 sample = getMessageRecords().get(0);
|
|
||||||
GeneralMessagePushVO sendVo = templateParser.parse(sample, templateModel);
|
|
||||||
|
|
||||||
MessageSendBasicInfoV4 sendBasicInfo = req.getSendBasicInfo();
|
|
||||||
SendTemplateMessageParam imRequest = new SendTemplateMessageParam();
|
|
||||||
imRequest.setBizId(String.format("%s:%s", CardSupport.getBizIdPrefix(getTemplateCode()), sendBasicInfo.determineBizCode()));
|
|
||||||
imRequest.setSendPriority(templateModel.getTemplate().determineImSendPriority());
|
|
||||||
imRequest.setMsgHeader(parseTitle());
|
|
||||||
imRequest.setMsgContent(parseContent());
|
|
||||||
imRequest.setMsgTemplateId(getTemplateCode());
|
|
||||||
imRequest.setMsgTemplateContent(JSON.toJSONString(sendVo));
|
|
||||||
imRequest.setExcludePushPayloads(new ArrayList<>());
|
|
||||||
// 接收人
|
|
||||||
ArrayList<PersonAccountAttribute> receivers = new ArrayList<>();
|
|
||||||
Set<Long> cmUnique = new HashSet<>();
|
|
||||||
Set<OuAndPerson> cmpUnique = new HashSet<>();
|
|
||||||
|
|
||||||
PushData pushData = templateModel.getTemplate().parsePushData();
|
|
||||||
boolean pushable = pushData.determinePushable(log, getTemplateCode());
|
|
||||||
|
|
||||||
// 扩展信息
|
|
||||||
for (PersonV3DTO receiver : sendBasicInfo.receivers()) {
|
|
||||||
PersonV3DTO.ReceiveModel imReceiveModel = receiver.getImReceiveModel();
|
|
||||||
Long ouId = imReceiveModel == null ? sendBasicInfo.determineReceiversOuId() : imReceiveModel.getOuId();
|
|
||||||
if (appType == AppTypeEnum.CM && !cmUnique.add(receiver.getId())) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (appType == AppTypeEnum.CMP && !cmpUnique.add(new OuAndPerson(ouId, receiver.getId()))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean excludePayload = pushable &&
|
|
||||||
!deviceSnapshots.getDevice(receiver.getId())
|
|
||||||
.shouldPush(appType, PushChannel.NIM);
|
|
||||||
if (excludePayload) {
|
|
||||||
ExcludePushPayload excludePush = new ExcludePushPayload();
|
|
||||||
excludePush.setPersonId(receiver.getId() + "");
|
|
||||||
excludePush.setAppType(appType);
|
|
||||||
imRequest.getExcludePushPayloads().add(excludePush);
|
|
||||||
}
|
|
||||||
|
|
||||||
PersonAccountAttribute receiverAccount = new PersonAccountAttribute();
|
|
||||||
receiverAccount.setPersonId(receiver.getId() + "");
|
|
||||||
receiverAccount.setOuId(ouId);
|
|
||||||
receiverAccount.setAppType(appType);
|
|
||||||
receivers.add(receiverAccount);
|
|
||||||
if (appType == AppTypeEnum.CM)
|
|
||||||
cmUnique.add(receiver.getId());
|
|
||||||
else if (appType == AppTypeEnum.CMP)
|
|
||||||
cmpUnique.add(new OuAndPerson(ouId, receiver.getId()));
|
|
||||||
}
|
|
||||||
imRequest.setReceivePersons(receivers);
|
|
||||||
JSONObject ext = new JSONObject();
|
|
||||||
ext.put("minAppVersion", templateModel.getTemplate().getMinAppVersion());
|
|
||||||
if (sample.getReceiverWorkspaceId() != null) {
|
|
||||||
ext.put("workspaceId", String.valueOf(sample.getReceiverWorkspaceId()));
|
|
||||||
}
|
|
||||||
if (sample.getReceiverOuId() != null) {
|
|
||||||
ext.put("ouId", String.valueOf(sample.getReceiverOuId()));
|
|
||||||
}
|
|
||||||
imRequest.setExt(ext);
|
|
||||||
if (pushable) {
|
|
||||||
imRequest.setPayload(buildPayload(sample, appType));
|
|
||||||
if (StringUtils.isNotBlank(pushData.getVoiceFile()))
|
|
||||||
ext.put(Intent.INTENT_SOUND, pushData.getVoiceFile());
|
|
||||||
}
|
|
||||||
return imRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildPayload(MessageRecordV3 sample, AppTypeEnum appType) {
|
|
||||||
ModelV3Parser modelV3Parser = beanFactory.getBean(ModelV3Parser.class);
|
|
||||||
ParsedModelV3 parsedModelV3 = modelV3Parser.parseModel(templateModel,
|
|
||||||
sample.getBizExtParams(), new UrlParser(sample.getRouterParams()));
|
|
||||||
NimPushService nimPushService = beanFactory.getBean(NimPushService.class);
|
|
||||||
MessageApi messageApi = beanFactory.getBean(MessageApi.class);
|
|
||||||
String imSenderAccount = BizAssertions.assertResponse(
|
|
||||||
messageApi.findTemplateRobotImAccount(getTemplateCode()));
|
|
||||||
PushPeer peer = new PushPeer();
|
|
||||||
peer.setSenderImAccount(imSenderAccount);
|
|
||||||
peer.setOuId(sample.getReceiverOuId());
|
|
||||||
peer.setWorkspaceId(sample.getReceiverWorkspaceId());
|
|
||||||
peer.setAppType(appType);
|
|
||||||
peer.setApiChannel(ApiChannel.COMMON_MESSAGE);
|
|
||||||
return nimPushService.buildPayloadString(parsedModelV3, peer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------- 辅助方法
|
|
||||||
|
|
||||||
String parseTitle() {
|
|
||||||
if (title == null) {
|
|
||||||
title = PlaceholderResolver.tryResolve(
|
|
||||||
templateModel.getTemplate().getTitle(), req.getSendBasicInfo().getBizExtParams());
|
|
||||||
}
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
String parseContent() {
|
|
||||||
if (content == null) {
|
|
||||||
content = PlaceholderResolver.tryResolve(
|
|
||||||
templateModel.getTemplate().getContent(), req.getSendBasicInfo().getBizExtParams());
|
|
||||||
}
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 预留
|
|
||||||
*/
|
|
||||||
JSONObject getMsgExtInfo() {
|
|
||||||
return new JSONObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
private static class OuAndPerson {
|
|
||||||
private final Long ouId;
|
|
||||||
private final Long personId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
HashMap<String, Object> values = new HashMap<>();
|
|
||||||
values.put("batchNo", batchNo);
|
|
||||||
values.put("bizEventMappingCode", req.getEventMappingCode());
|
|
||||||
values.put("bizCode", req.getSendBasicInfo().getBizCode());
|
|
||||||
values.put("templateCode", templateModel.getTemplate().getCode());
|
|
||||||
values.put("messageIds", getMessageIds());
|
|
||||||
values.put("receiverPersonIds", getReceiverPersonIds());
|
|
||||||
return JSON.toJSONString(values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,9 +1,6 @@
|
|||||||
package cn.axzo.msg.center.message.migrate;
|
package cn.axzo.msg.center.message.migrate;
|
||||||
|
|
||||||
import cn.axzo.apollo.api.ApolloWorkerTaskOrderApi;
|
|
||||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||||
import cn.axzo.maokai.api.client.CooperateShipQueryApi;
|
|
||||||
import cn.axzo.maokai.api.client.OrganizationalNodeUserApi;
|
|
||||||
import cn.axzo.maokai.api.client.OrganizationalTeamOuRelationApi;
|
import cn.axzo.maokai.api.client.OrganizationalTeamOuRelationApi;
|
||||||
import cn.axzo.maokai.api.vo.response.OrganizationalTeamOuRelationResp;
|
import cn.axzo.maokai.api.vo.response.OrganizationalTeamOuRelationResp;
|
||||||
import cn.axzo.msg.center.common.utils.BizAssertions;
|
import cn.axzo.msg.center.common.utils.BizAssertions;
|
||||||
@ -65,9 +62,6 @@ public class OuIdMigrateService {
|
|||||||
private final PendingMessageRecordDao pendingMessageRecordDao;
|
private final PendingMessageRecordDao pendingMessageRecordDao;
|
||||||
private final OrganizationalTeamOuRelationApi organizationalTeamOuRelationApi;
|
private final OrganizationalTeamOuRelationApi organizationalTeamOuRelationApi;
|
||||||
private final TeamServiceApi teamServiceApi;
|
private final TeamServiceApi teamServiceApi;
|
||||||
private final CooperateShipQueryApi cooperateShipQueryApi;
|
|
||||||
private final ApolloWorkerTaskOrderApi apolloWorkerTaskOrderApi;
|
|
||||||
private final OrganizationalNodeUserApi organizationalNodeUserApi;
|
|
||||||
|
|
||||||
@Value("${message.pending.ouMigrateBatchSize:100}")
|
@Value("${message.pending.ouMigrateBatchSize:100}")
|
||||||
private final Long migrateBatchSize;
|
private final Long migrateBatchSize;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package cn.axzo.msg.center.message.service.card;
|
package cn.axzo.msg.center.message.service.card;
|
||||||
|
|
||||||
import cn.axzo.framework.jackson.utility.JSON;
|
import cn.axzo.framework.jackson.utility.JSON;
|
||||||
import cn.axzo.im.center.api.vo.ApiChannel;
|
|
||||||
import cn.axzo.im.center.api.vo.req.SendTemplateMessageParam;
|
import cn.axzo.im.center.api.vo.req.SendTemplateMessageParam;
|
||||||
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
||||||
import cn.axzo.im.center.common.enums.YesOrNo;
|
import cn.axzo.im.center.common.enums.YesOrNo;
|
||||||
@ -17,9 +16,7 @@ import cn.axzo.msg.center.message.service.impl.v3.ModelV3Service;
|
|||||||
import cn.axzo.msg.center.message.service.impl.v3.UrlParser;
|
import cn.axzo.msg.center.message.service.impl.v3.UrlParser;
|
||||||
import cn.axzo.msg.center.nimpush.NimPushService;
|
import cn.axzo.msg.center.nimpush.NimPushService;
|
||||||
import cn.axzo.msg.center.nimpush.device.PushDeviceSnapshots;
|
import cn.axzo.msg.center.nimpush.device.PushDeviceSnapshots;
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.Intent;
|
|
||||||
import cn.axzo.msg.center.push.PushData;
|
import cn.axzo.msg.center.push.PushData;
|
||||||
import cn.axzo.msg.center.service.domain.PushPeer;
|
|
||||||
import cn.axzo.msg.center.service.domain.card.AppVersionConfig;
|
import cn.axzo.msg.center.service.domain.card.AppVersionConfig;
|
||||||
import cn.axzo.msg.center.service.dto.PeerPerson;
|
import cn.axzo.msg.center.service.dto.PeerPerson;
|
||||||
import cn.axzo.msg.center.service.enums.MessageChannel;
|
import cn.axzo.msg.center.service.enums.MessageChannel;
|
||||||
@ -104,15 +101,6 @@ public class CardSupport {
|
|||||||
PushDeviceSnapshots deviceSnapshots,
|
PushDeviceSnapshots deviceSnapshots,
|
||||||
String imSenderAccount) {
|
String imSenderAccount) {
|
||||||
ParsedTemplateV3 template = sendModel.getTemplate();
|
ParsedTemplateV3 template = sendModel.getTemplate();
|
||||||
Supplier<String> payloadBuilder = () -> {
|
|
||||||
PushPeer peer = new PushPeer();
|
|
||||||
peer.setSenderImAccount(imSenderAccount);
|
|
||||||
peer.setOuId(group.getGroupKey().getOuId());
|
|
||||||
peer.setWorkspaceId(group.getGroupKey().getWorkspaceId());
|
|
||||||
peer.setAppType(group.getGroupKey().getAppType());
|
|
||||||
peer.setApiChannel(ApiChannel.COMMON_MESSAGE);
|
|
||||||
return nimPushService.buildPayloadString(sendModel.getParsedModel(), peer);
|
|
||||||
};
|
|
||||||
Supplier<JSONObject> extBuilder = () -> {
|
Supplier<JSONObject> extBuilder = () -> {
|
||||||
JSONObject ext = new JSONObject();
|
JSONObject ext = new JSONObject();
|
||||||
ext.put("minAppVersion", determineMinAppVersion(
|
ext.put("minAppVersion", determineMinAppVersion(
|
||||||
@ -137,10 +125,10 @@ public class CardSupport {
|
|||||||
imRequest.setExt(extBuilder.get());
|
imRequest.setExt(extBuilder.get());
|
||||||
imRequest.setUpdatable(sendModel.getCardTemplate().isUpdatable());
|
imRequest.setUpdatable(sendModel.getCardTemplate().isUpdatable());
|
||||||
if (pushData.determinePushable(log, template.getCode())) {
|
if (pushData.determinePushable(log, template.getCode())) {
|
||||||
imRequest.setPayload(payloadBuilder.get());
|
imRequest.setPushContent(nimPushService.buildPushContent(sendModel.getParsedModel(), false));
|
||||||
imRequest.setExcludePushPayloads(group.buildNimPushExcludes(deviceSnapshots));
|
imRequest.setExcludePushPayloads(group.buildNimPushExcludes(deviceSnapshots));
|
||||||
if (StringUtils.isNotBlank(pushData.getVoiceFile()))
|
if (StringUtils.isNotBlank(pushData.getVoiceFile()))
|
||||||
imRequest.getExt().put(Intent.INTENT_SOUND, pushData.getVoiceFile());
|
imRequest.getExt().put("sound", pushData.getVoiceFile());
|
||||||
}
|
}
|
||||||
return imRequest;
|
return imRequest;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import cn.axzo.msg.center.dal.MessageGroupNodeDao;
|
|||||||
import cn.axzo.msg.center.domain.entity.MessageGroupNode;
|
import cn.axzo.msg.center.domain.entity.MessageGroupNode;
|
||||||
import cn.axzo.msg.center.domain.persistence.BaseEntityExt;
|
import cn.axzo.msg.center.domain.persistence.BaseEntityExt;
|
||||||
import cn.axzo.msg.center.inside.notices.config.PendingMessageBizConfig;
|
import cn.axzo.msg.center.inside.notices.config.PendingMessageBizConfig;
|
||||||
import cn.axzo.msg.center.message.service.impl.v3.ModelV3Parser;
|
|
||||||
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
|
import cn.axzo.msg.center.service.enums.AppTerminalTypeEnum;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -43,7 +42,6 @@ public class PendingMessageNewServiceImpl {
|
|||||||
private final OrganizationalTeamOuRelationApi organizationalTeamOuRelationApi;
|
private final OrganizationalTeamOuRelationApi organizationalTeamOuRelationApi;
|
||||||
private final PendingMessageBizConfig pendingMessageBizConfig;
|
private final PendingMessageBizConfig pendingMessageBizConfig;
|
||||||
private final MessageGroupNodeDao messageGroupNodeDao;
|
private final MessageGroupNodeDao messageGroupNodeDao;
|
||||||
private final ModelV3Parser modelV3Parser;
|
|
||||||
|
|
||||||
public Map<String, Object> getTerminalConfigInfo() {
|
public Map<String, Object> getTerminalConfigInfo() {
|
||||||
Map<AppTerminalTypeEnum, List<Long>> appType2NodeIds = pendingMessageBizConfig.getMsgGroupConfig();
|
Map<AppTerminalTypeEnum, List<Long>> appType2NodeIds = pendingMessageBizConfig.getMsgGroupConfig();
|
||||||
|
|||||||
@ -2,11 +2,10 @@ package cn.axzo.msg.center.message.service.todo.manage.event;
|
|||||||
|
|
||||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||||
import cn.axzo.im.center.api.feign.MessageApi;
|
import cn.axzo.im.center.api.feign.MessageApi;
|
||||||
import cn.axzo.im.center.api.vo.ApiChannel;
|
|
||||||
import cn.axzo.im.center.api.vo.req.CustomMessageInfo;
|
import cn.axzo.im.center.api.vo.req.CustomMessageInfo;
|
||||||
|
import cn.axzo.im.center.api.vo.req.PushContent;
|
||||||
import cn.axzo.im.center.api.vo.resp.MessageCustomResp;
|
import cn.axzo.im.center.api.vo.resp.MessageCustomResp;
|
||||||
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
||||||
import cn.axzo.msg.center.common.utils.BizAssertions;
|
|
||||||
import cn.axzo.msg.center.domain.entity.MessageEntity;
|
import cn.axzo.msg.center.domain.entity.MessageEntity;
|
||||||
import cn.axzo.msg.center.domain.entity.MessageTemplateV3;
|
import cn.axzo.msg.center.domain.entity.MessageTemplateV3;
|
||||||
import cn.axzo.msg.center.domain.entity.Todo;
|
import cn.axzo.msg.center.domain.entity.Todo;
|
||||||
@ -21,7 +20,6 @@ import cn.axzo.msg.center.nimpush.device.PushDevice;
|
|||||||
import cn.axzo.msg.center.nimpush.device.PushDeviceService;
|
import cn.axzo.msg.center.nimpush.device.PushDeviceService;
|
||||||
import cn.axzo.msg.center.nimpush.device.PushDeviceSnapshots;
|
import cn.axzo.msg.center.nimpush.device.PushDeviceSnapshots;
|
||||||
import cn.axzo.msg.center.push.PushData;
|
import cn.axzo.msg.center.push.PushData;
|
||||||
import cn.axzo.msg.center.service.domain.PushPeer;
|
|
||||||
import cn.axzo.msg.center.service.enums.PushTerminalEnum;
|
import cn.axzo.msg.center.service.enums.PushTerminalEnum;
|
||||||
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedModelV3;
|
import cn.axzo.msg.center.service.pending.response.v3.model.ParsedModelV3;
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -69,7 +67,6 @@ public class TodoPushSenderNim implements ApplicationListener<NewTodoEvent> {
|
|||||||
if (pushData != null && !pushData.determinePushable(log, parsedModelV3.getTemplateCode())) {
|
if (pushData != null && !pushData.determinePushable(log, parsedModelV3.getTemplateCode())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String imSenderAccount = BizAssertions.assertResponse(messageApi.getCustomMessageSendImAccount());
|
|
||||||
PushDeviceSnapshots deviceSnapshots = pushDeviceService.createDeviceSnapshots();
|
PushDeviceSnapshots deviceSnapshots = pushDeviceService.createDeviceSnapshots();
|
||||||
for (Todo todo : event.getTodos()) {
|
for (Todo todo : event.getTodos()) {
|
||||||
executor.submit(() -> {
|
executor.submit(() -> {
|
||||||
@ -78,21 +75,15 @@ public class TodoPushSenderNim implements ApplicationListener<NewTodoEvent> {
|
|||||||
if (!pushDevice.shouldPush(appType, PushChannel.NIM))
|
if (!pushDevice.shouldPush(appType, PushChannel.NIM))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
PushPeer peer = new PushPeer();
|
PushContent pushContent = nimPushService.buildPushContent(parsedModelV3, true);
|
||||||
peer.setSenderImAccount(imSenderAccount);
|
if (pushContent == null)
|
||||||
peer.setOuId(todo.getOuId());
|
|
||||||
peer.setWorkspaceId(todo.getOrgId());
|
|
||||||
peer.setAppType(appType);
|
|
||||||
peer.setApiChannel(ApiChannel.CUSTOM_MESSAGE);
|
|
||||||
String payload = nimPushService.buildPayloadString(parsedModelV3, peer);
|
|
||||||
if (StringUtils.isBlank(payload))
|
|
||||||
continue;
|
continue;
|
||||||
CustomMessageInfo pushRequest = new CustomMessageInfo();
|
CustomMessageInfo pushRequest = new CustomMessageInfo();
|
||||||
pushRequest.setAppTypeList(Collections.singletonList(appType));
|
pushRequest.setAppTypeList(Collections.singletonList(appType));
|
||||||
pushRequest.setToPersonId(todo.getExecutorPersonId() + "");
|
pushRequest.setToPersonId(todo.getExecutorPersonId() + "");
|
||||||
pushRequest.setOuId(todo.getOuId());
|
pushRequest.setOuId(todo.getOuId());
|
||||||
pushRequest.setPayload(payload);
|
pushRequest.setPayload("{}");
|
||||||
pushRequest.setPush(true);
|
pushRequest.setPushContent(pushContent);
|
||||||
if (pushData != null && StringUtils.isNotBlank(pushData.getVoiceFile())) {
|
if (pushData != null && StringUtils.isNotBlank(pushData.getVoiceFile())) {
|
||||||
pushRequest.setSound(pushData.getVoiceFile());
|
pushRequest.setSound(pushData.getVoiceFile());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,115 +1,62 @@
|
|||||||
package cn.axzo.msg.center.nimpush;
|
package cn.axzo.msg.center.nimpush;
|
||||||
|
|
||||||
import cn.axzo.im.center.api.vo.ApiChannel;
|
import cn.axzo.basics.common.constant.enums.CodeDefinition;
|
||||||
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
import cn.axzo.im.center.api.vo.req.PushContent;
|
||||||
import cn.axzo.msg.center.common.utils.BizAssertions;
|
import cn.axzo.im.center.api.vo.req.PushMessageTye;
|
||||||
import cn.axzo.msg.center.nimpush.payload.PushPayloadBuilder;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.Intent;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.IntentValue;
|
|
||||||
import cn.axzo.msg.center.push.PushData;
|
import cn.axzo.msg.center.push.PushData;
|
||||||
import cn.axzo.msg.center.push.PushMessage;
|
import cn.axzo.msg.center.push.PushMessage;
|
||||||
import cn.axzo.msg.center.service.domain.PushPeer;
|
|
||||||
import cn.axzo.msg.center.service.domain.UrlConfig;
|
import cn.axzo.msg.center.service.domain.UrlConfig;
|
||||||
import cn.axzo.msg.center.service.domain.UrlConfigVisitor;
|
import cn.axzo.msg.center.service.domain.UrlConfigVisitor;
|
||||||
import cn.axzo.msg.center.service.domain.UrlConfigWalker;
|
import cn.axzo.msg.center.service.domain.UrlConfigWalker;
|
||||||
import cn.axzo.msg.center.service.domain.url.AppUrl;
|
import cn.axzo.msg.center.service.domain.url.AppUrl;
|
||||||
import cn.axzo.msg.center.service.enums.CodeDefinition;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yanglin
|
* @author yanglin
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class NimPushService {
|
public class NimPushService {
|
||||||
|
|
||||||
private final PushPayloadBuilder<?>[] payloadBuilders;
|
public PushContent buildPushContent(PushMessage message, boolean buildPushUrl) {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public NimPushService(ObjectProvider<PushPayloadBuilder[]> payloadBuilders) {
|
|
||||||
this.payloadBuilders = payloadBuilders.getIfAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String buildPayloadString(PushMessage message, PushPeer peer) {
|
|
||||||
JSONObject payload = buildPayload(message, peer);
|
|
||||||
return payload == null ? null : payload.toJSONString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private JSONObject buildPayload(PushMessage message, PushPeer peer) {
|
|
||||||
PushData pushData = message.getPushData();
|
PushData pushData = message.getPushData();
|
||||||
if (pushData == null || !pushData.isSwitchOn()) return null;
|
if (pushData == null || !pushData.isSwitchOn()) return null;
|
||||||
PushContent content = new PushContent();
|
PushContent content = new PushContent();
|
||||||
content.setTitle(message.getPushTitle());
|
content.setTitle(message.getPushTitle());
|
||||||
content.setContent(message.getPushContent());
|
content.setContent(message.getPushContent());
|
||||||
content.setCustomSoundFile(pushData.getVoiceFile());
|
|
||||||
content.setAppType(peer.getAppType());
|
|
||||||
content.setMessageTye(CodeDefinition
|
content.setMessageTye(CodeDefinition
|
||||||
.findByCode(PushMessageTye.class, pushData.getType())
|
.findByCode(PushMessageTye.class, pushData.getType())
|
||||||
.orElse(null));
|
.orElse(null));
|
||||||
content.setCustomSoundFile(pushData.getVoiceFile());
|
content.setCustomSoundFile(pushData.getVoiceFile());
|
||||||
if (peer.getApiChannel() == ApiChannel.CUSTOM_MESSAGE)
|
if (buildPushUrl)
|
||||||
populateUrl(content, message.getPushUrl(), peer.getAppType());
|
populateUrl(content, message.getPushUrl());
|
||||||
return buildPayload(content, peer);
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
private void populateUrl(PushContent content, UrlConfig url) {
|
||||||
private JSONObject buildPayload(PushContent content, PushPeer peer) {
|
if (url == null) return;
|
||||||
Consumer<Intent<?>> intentPopulator = intent -> {
|
|
||||||
intent.setValue(Intent.INTENT_TYPE,
|
|
||||||
peer.getApiChannel() == ApiChannel.CUSTOM_MESSAGE
|
|
||||||
? IntentValue.TYPE_SERVER
|
|
||||||
: IntentValue.TYPE_IM);
|
|
||||||
intent.setValue(Intent.INTENT_SESSION_TYPE, IntentValue.CONSTANT_SESSION_TYPE);
|
|
||||||
intent.setValue(Intent.INTENT_SESSION_ID, IntentValue.create(peer.getSenderImAccount()));
|
|
||||||
if (peer.getOuId() != null && peer.getOuId() != 0L)
|
|
||||||
intent.setValue(Intent.INTENT_OU_ID, IntentValue.create(peer.getOuId()));
|
|
||||||
if (peer.getWorkspaceId() != null && peer.getWorkspaceId() != 0L)
|
|
||||||
intent.setValue(Intent.INTENT_WORKSPACE_ID, IntentValue.create(peer.getWorkspaceId()));
|
|
||||||
if (StringUtils.isNotBlank(content.getCustomSoundFile()))
|
|
||||||
intent.setValue(Intent.INTENT_SOUND, IntentValue.create(content.getCustomSoundFile()));
|
|
||||||
};
|
|
||||||
JSONObject payload = new JSONObject();
|
|
||||||
payload.put("pushTitle", content.getTitle());
|
|
||||||
for (PushPayloadBuilder builder : payloadBuilders) {
|
|
||||||
Intent intent = builder.createIntent(content, peer);
|
|
||||||
BizAssertions.assertNotNull(intent, "intent can't be null");
|
|
||||||
intentPopulator.accept(intent);
|
|
||||||
builder.build(content, intent, payload);
|
|
||||||
}
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void populateUrl(PushContent content,
|
|
||||||
UrlConfig url,
|
|
||||||
AppTypeEnum appType) {
|
|
||||||
if (url == null || appType == null) return;
|
|
||||||
UrlConfigWalker.walkDown(url, new UrlConfigVisitor() {
|
UrlConfigWalker.walkDown(url, new UrlConfigVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visitAppManagerAndroid(AppUrl android) {
|
public void visitAppManagerAndroid(AppUrl android) {
|
||||||
if (android.hasUrl() && appType == AppTypeEnum.CMP)
|
if (android.hasUrl())
|
||||||
content.setAndroidPushUrl(android.getUrl());
|
content.setMangerAndroidPushUrl(android.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitAppManagerIos(AppUrl ios) {
|
public void visitAppManagerIos(AppUrl ios) {
|
||||||
if (ios.hasUrl() && appType == AppTypeEnum.CMP)
|
if (ios.hasUrl())
|
||||||
content.setIosPushUrl(ios.getUrl());
|
content.setManagerIosPushUrl(ios.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitAppWorkerAndroid(AppUrl android) {
|
public void visitAppWorkerAndroid(AppUrl android) {
|
||||||
if (android.hasUrl() && appType == AppTypeEnum.CM)
|
if (android.hasUrl())
|
||||||
content.setAndroidPushUrl(android.getUrl());
|
content.setWorkerAndroidPushUrl(android.getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitAppWorkerIos(AppUrl ios) {
|
public void visitAppWorkerIos(AppUrl ios) {
|
||||||
if (ios.hasUrl() && appType == AppTypeEnum.CM)
|
if (ios.hasUrl())
|
||||||
content.setIosPushUrl(ios.getUrl());
|
content.setWorkerIosPushUrl(ios.getUrl());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,65 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush;
|
|
||||||
|
|
||||||
import cn.axzo.im.center.common.enums.AppTypeEnum;
|
|
||||||
import cn.axzo.msg.center.inside.notices.config.push.PushProps.ChannelConfig;
|
|
||||||
import cn.axzo.msg.center.inside.notices.config.push.PushProps.ChannelIds;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Setter
|
|
||||||
@Getter
|
|
||||||
public class PushContent {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 主标题
|
|
||||||
*/
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 推送内容
|
|
||||||
*/
|
|
||||||
private String content;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* android点击push的跳转链接
|
|
||||||
*/
|
|
||||||
private String androidPushUrl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ios点击push的跳转链接
|
|
||||||
*/
|
|
||||||
private String iosPushUrl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 端信息
|
|
||||||
*/
|
|
||||||
private AppTypeEnum appType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* push消息类型. SYSTEM: 系统消息, OP: 运营消息
|
|
||||||
*/
|
|
||||||
private PushMessageTye messageTye;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义提示音
|
|
||||||
*/
|
|
||||||
private String customSoundFile;
|
|
||||||
|
|
||||||
public String determineAndroidCategory() {
|
|
||||||
return messageTye == PushMessageTye.OP
|
|
||||||
? "MARKETING"
|
|
||||||
: "IM";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String determineChannelId(ChannelConfig channelConfig) {
|
|
||||||
ChannelIds channelIds = appType == AppTypeEnum.CM
|
|
||||||
? channelConfig.getWorkerIds()
|
|
||||||
: channelConfig.getManagerIds();
|
|
||||||
return messageTye == PushMessageTye.OP
|
|
||||||
? channelIds.getOpMessageChannelId()
|
|
||||||
: channelIds.getWorkMessageChannelId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.service.enums.CodeDefinition;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public enum PushMessageTye implements CodeDefinition<String> {
|
|
||||||
|
|
||||||
SYSTEM("system", "系统消息"),
|
|
||||||
OP("op", "运营消息"),
|
|
||||||
;
|
|
||||||
|
|
||||||
private final String code;
|
|
||||||
private final String description;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getCode() {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.common.utils.BizAssertions;
|
|
||||||
import cn.axzo.msg.center.nimpush.PushContent;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.Intent;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.IntentValue;
|
|
||||||
import cn.axzo.msg.center.service.domain.PushPeer;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
abstract class AndroidPushPayloadBuilder<T extends Intent<?>>
|
|
||||||
implements PushPayloadBuilder<T> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final T createIntent(PushContent content, PushPeer peer) {
|
|
||||||
T intent = createIntent();
|
|
||||||
BizAssertions.assertNotNull(intent, "intent can't be null");
|
|
||||||
if (StringUtils.isNotBlank(content.getAndroidPushUrl()))
|
|
||||||
Intent.setRouter(intent, IntentValue
|
|
||||||
.create(content.getAndroidPushUrl())
|
|
||||||
.urlEncode());
|
|
||||||
return intent;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract T createIntent();
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.nimpush.PushContent;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.UriIntent;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 华为
|
|
||||||
*
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
class HWPushPayloadBuilder extends AndroidPushPayloadBuilder<UriIntent> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
UriIntent createIntent() {
|
|
||||||
return new UriIntent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void build(PushContent content, UriIntent intent, JSONObject payload) {
|
|
||||||
// 点击事件的内容
|
|
||||||
JSONObject clickAction = new JSONObject();
|
|
||||||
clickAction.put("type", 1);
|
|
||||||
clickAction.put("intent", intent.build());
|
|
||||||
|
|
||||||
// 通知的内容
|
|
||||||
|
|
||||||
JSONObject androidConfig = new JSONObject();
|
|
||||||
androidConfig.put("category", content.determineAndroidCategory());
|
|
||||||
|
|
||||||
JSONObject hwField = new JSONObject();
|
|
||||||
hwField.put("android", androidConfig);
|
|
||||||
hwField.put("style", 1);
|
|
||||||
hwField.put("big_title", content.getTitle());
|
|
||||||
hwField.put("big_body", content.getContent());
|
|
||||||
hwField.put("click_action", clickAction);
|
|
||||||
|
|
||||||
payload.put("hwField", hwField);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.inside.notices.config.push.PushProps;
|
|
||||||
import cn.axzo.msg.center.nimpush.PushContent;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.JsonIntent;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
class OppoPushPayloadBuilder extends AndroidPushPayloadBuilder<JsonIntent> {
|
|
||||||
|
|
||||||
private final PushProps pushProps;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonIntent createIntent() {
|
|
||||||
return new JsonIntent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void build(PushContent content, JsonIntent intent, JSONObject payload) {
|
|
||||||
PushProps.ChannelConfig xmCfg = pushProps.getOppoChannelConfig();
|
|
||||||
JSONObject oppoField = new JSONObject();
|
|
||||||
oppoField.put("channel_id", content.determineChannelId(xmCfg));
|
|
||||||
oppoField.put("category", content.determineAndroidCategory());
|
|
||||||
oppoField.put("notify_level", 2);
|
|
||||||
oppoField.put("click_action_type", 1);
|
|
||||||
oppoField.put("click_action_activity", "com.oppo.codelabpush.intent.action.test");
|
|
||||||
oppoField.put("action_parameters", intent.build().toJSONString());
|
|
||||||
|
|
||||||
payload.put("oppoField", oppoField);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.nimpush.PushContent;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.Intent;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.IntentValue;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.JsonIntent;
|
|
||||||
import cn.axzo.msg.center.service.domain.PushPeer;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 苹果
|
|
||||||
*
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
class PGPushPayloadBuilder implements PushPayloadBuilder<JsonIntent> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonIntent createIntent(PushContent content, PushPeer peer) {
|
|
||||||
JsonIntent intent = new JsonIntent();
|
|
||||||
if (StringUtils.isNotBlank(content.getIosPushUrl()))
|
|
||||||
Intent.setRouter(intent, IntentValue
|
|
||||||
.create(content.getIosPushUrl()));
|
|
||||||
return intent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void build(PushContent content, JsonIntent intent, JSONObject payload) {
|
|
||||||
JSONObject userInfo = new JSONObject();
|
|
||||||
userInfo.putAll(intent.build());
|
|
||||||
|
|
||||||
JSONObject alert = new JSONObject();
|
|
||||||
alert.put("title", content.getTitle());
|
|
||||||
alert.put("body", content.getContent());
|
|
||||||
alert.put("userInfo", userInfo);
|
|
||||||
|
|
||||||
JSONObject apsField = new JSONObject();
|
|
||||||
apsField.put("alert", alert);
|
|
||||||
|
|
||||||
payload.put("apsField", apsField);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.nimpush.PushContent;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.Intent;
|
|
||||||
import cn.axzo.msg.center.service.domain.PushPeer;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <a href="https://doc.yunxin.163.com/messaging/server-apis/DQyNjc5NjE?platform=server#apns%E6%8E%A8%E9%80%81%E6%B6%88%E6%81%AF">云信推送</a>
|
|
||||||
* <a href="https://doc.yunxin.163.com/messaging/guide/TY4MzU5MDc?platform=android#%E8%AE%BE%E7%BD%AE%E6%8E%A8%E9%80%81%E9%80%9A%E7%9F%A5%E6%A0%8F%E8%B7%B3%E8%BD%AC%E6%96%B9%E5%BC%8F">各端推送配置</a>
|
|
||||||
* <p/>
|
|
||||||
* 文字, 链接、声音
|
|
||||||
*
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
public interface PushPayloadBuilder<T extends Intent<?>> {
|
|
||||||
|
|
||||||
T createIntent(PushContent content, PushPeer peer);
|
|
||||||
|
|
||||||
void build(PushContent content, T intent, JSONObject payload);
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.nimpush.PushContent;
|
|
||||||
import cn.axzo.msg.center.nimpush.PushMessageTye;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.UriIntent;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 荣耀
|
|
||||||
*
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
class RYPushPayloadBuilder extends AndroidPushPayloadBuilder<UriIntent> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UriIntent createIntent() {
|
|
||||||
return new UriIntent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void build(PushContent content, UriIntent intent, JSONObject payload) {
|
|
||||||
// 点击事件的内容
|
|
||||||
JSONObject clickAction = new JSONObject();
|
|
||||||
clickAction.put("type", 1);
|
|
||||||
clickAction.put("intent", intent.build());
|
|
||||||
|
|
||||||
// 通知的内容
|
|
||||||
JSONObject notification = new JSONObject();
|
|
||||||
notification.put("title", content.getTitle());
|
|
||||||
notification.put("body", content.getContent());
|
|
||||||
notification.put("clickAction", clickAction);
|
|
||||||
notification.put("importance",
|
|
||||||
content.getMessageTye() == PushMessageTye.OP ? "LOW" : "NORMAL");
|
|
||||||
|
|
||||||
JSONObject honorField = new JSONObject();
|
|
||||||
honorField.put("notification", notification);
|
|
||||||
|
|
||||||
payload.put("honorField", honorField);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.nimpush.PushContent;
|
|
||||||
import cn.axzo.msg.center.nimpush.PushMessageTye;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.UriIntent;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* VIVO
|
|
||||||
*
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
class VivoPushPayloadBuilder extends AndroidPushPayloadBuilder<UriIntent> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UriIntent createIntent() {
|
|
||||||
return new UriIntent();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 没找到自定义声音相关的字段
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void build(PushContent content, UriIntent intent, JSONObject payload) {
|
|
||||||
JSONObject vivoField = new JSONObject();
|
|
||||||
vivoField.put("content", content.getContent());
|
|
||||||
vivoField.put("classification",
|
|
||||||
content.getMessageTye() == PushMessageTye.OP ? 0 : 1);
|
|
||||||
vivoField.put("skipType", 4);
|
|
||||||
vivoField.put("networkType", -1);
|
|
||||||
vivoField.put("category", content.determineAndroidCategory());
|
|
||||||
vivoField.put("skipContent", intent.build());
|
|
||||||
|
|
||||||
payload.put("vivoField", vivoField);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.inside.notices.config.push.PushProps;
|
|
||||||
import cn.axzo.msg.center.nimpush.PushContent;
|
|
||||||
import cn.axzo.msg.center.nimpush.payload.intent.UriIntent;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 小米
|
|
||||||
*
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
class XMPushPayloadBuilder extends AndroidPushPayloadBuilder<UriIntent> {
|
|
||||||
|
|
||||||
private final PushProps pushProps;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public UriIntent createIntent() {
|
|
||||||
return new UriIntent();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void build(PushContent content, UriIntent intent, JSONObject payload) {
|
|
||||||
PushProps.ChannelConfig xmCfg = pushProps.getXiaomiChannelConfig();
|
|
||||||
payload.put("channel_id", content.determineChannelId(xmCfg));
|
|
||||||
payload.put("notify_foreground", "1");
|
|
||||||
payload.put("notify_effect", "2");
|
|
||||||
payload.put("intent_uri", intent.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload.intent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
public interface Intent<T> {
|
|
||||||
|
|
||||||
String INTENT_ROUTER = "router";
|
|
||||||
String INTENT_SOUND = "sound";
|
|
||||||
String INTENT_TYPE = "type";
|
|
||||||
String INTENT_SESSION_TYPE = "sessionType";
|
|
||||||
String INTENT_SESSION_ID = "sessionId";
|
|
||||||
String INTENT_WORKSPACE_ID = "workspaceId";
|
|
||||||
String INTENT_OU_ID = "ouId";
|
|
||||||
|
|
||||||
void setValue(String key, IntentValue value);
|
|
||||||
|
|
||||||
T build();
|
|
||||||
|
|
||||||
// !! helper
|
|
||||||
|
|
||||||
static void setRouter(Intent<?> intent, IntentValue router) {
|
|
||||||
intent.setValue(INTENT_ROUTER, router);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload.intent;
|
|
||||||
|
|
||||||
import cn.axzo.basics.common.exception.ServiceException;
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class IntentValue {
|
|
||||||
|
|
||||||
private final Object value;
|
|
||||||
|
|
||||||
private static final IntentValue NULL = new IntentValue(null);
|
|
||||||
public static final IntentValue CONSTANT_SESSION_TYPE = new IntentValue("0");
|
|
||||||
public static final IntentValue TYPE_SERVER = new IntentValue("server");
|
|
||||||
public static final IntentValue TYPE_IM = new IntentValue("im");
|
|
||||||
|
|
||||||
public static IntentValue create(Object value) {
|
|
||||||
if (value == null) return NULL;
|
|
||||||
return new IntentValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 和app约定好了, intent里面都使用string类型的值
|
|
||||||
*/
|
|
||||||
public void consume(Consumer<String> consumer) {
|
|
||||||
if (value == null) return;
|
|
||||||
consumer.accept(String.valueOf(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public IntentValue urlEncode() {
|
|
||||||
if (value == null) return NULL;
|
|
||||||
try {
|
|
||||||
if (value instanceof String)
|
|
||||||
return create(URLEncoder.encode((String) value, "UTF-8"));
|
|
||||||
else
|
|
||||||
throw new ServiceException("only string can be url encoded");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
log.warn("url encode failed, intent value: {}", value, e);
|
|
||||||
throw new ServiceException(String.format("url encode failed, intent value: %s", value), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload.intent;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.common.utils.BizAssertions;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
public class JsonIntent implements Intent<JSONObject> {
|
|
||||||
|
|
||||||
private final JSONObject values = new JSONObject();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(String key, IntentValue value) {
|
|
||||||
BizAssertions.assertNotBlank(key, "key is required");
|
|
||||||
BizAssertions.assertNotNull(value, "value is required");
|
|
||||||
value.consume(stringValue -> values.put(key, stringValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JSONObject build() {
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush.payload.intent;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.common.utils.BizAssertions;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
public class UriIntent implements Intent<String> {
|
|
||||||
|
|
||||||
private static final String INTENT_PREFIX =
|
|
||||||
"intent://cn.axzo.codelabpush/deeplink?#Intent;scheme=pushschema;launchFlags=0x4000000;";
|
|
||||||
|
|
||||||
private final LinkedHashMap<String, IntentValue> values = new LinkedHashMap<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(String key, IntentValue value) {
|
|
||||||
BizAssertions.assertNotBlank(key, "key is required");
|
|
||||||
BizAssertions.assertNotNull(value, "value is required");
|
|
||||||
values.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String build() {
|
|
||||||
StringBuilder buf = new StringBuilder(INTENT_PREFIX);
|
|
||||||
for (Map.Entry<String, IntentValue> entry : values.entrySet()) {
|
|
||||||
entry.getValue().consume(stringValue ->
|
|
||||||
buf.append("S.")
|
|
||||||
.append(entry.getKey())
|
|
||||||
.append("=")
|
|
||||||
.append(stringValue)
|
|
||||||
.append(";"));
|
|
||||||
}
|
|
||||||
buf.append("end");
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,6 +1,5 @@
|
|||||||
package cn.axzo.msg.center.api;
|
package cn.axzo.msg.center.api;
|
||||||
|
|
||||||
import cn.axzo.msg.center.api.request.BuildNimPayloadRequest;
|
|
||||||
import cn.axzo.msg.center.api.request.MsgBody4Guest;
|
import cn.axzo.msg.center.api.request.MsgBody4Guest;
|
||||||
import cn.azxo.framework.common.model.CommonResponse;
|
import cn.azxo.framework.common.model.CommonResponse;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
@ -24,10 +23,4 @@ public interface MessagePushApi {
|
|||||||
@PostMapping("umeng/pushMsg")
|
@PostMapping("umeng/pushMsg")
|
||||||
CommonResponse<Void> sendPushMessage(@RequestBody MsgBody4Guest msgBody);
|
CommonResponse<Void> sendPushMessage(@RequestBody MsgBody4Guest msgBody);
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建云信push payload
|
|
||||||
*/
|
|
||||||
@PostMapping("push/nim/buildNimPayload")
|
|
||||||
CommonResponse<String> buildNimPayload(@RequestBody BuildNimPayloadRequest request);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
package cn.axzo.msg.center.nimpush;
|
|
||||||
|
|
||||||
import cn.axzo.msg.center.MsgCenterApplication;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author yanglin
|
|
||||||
*/
|
|
||||||
@SpringBootTest(classes = MsgCenterApplication.class)
|
|
||||||
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
|
||||||
class NimPushServiceTest {
|
|
||||||
|
|
||||||
private final NimPushService nimPushService;
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void exec() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user