From 7901224f014a52dbd693c723eee7b20fac1e1def Mon Sep 17 00:00:00 2001
From: xsx <825657193@qq.com>
Date: Sun, 7 Jul 2024 19:28:47 +0800
Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=8E=A5=E5=85=A5unipush?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
im-platform/pom.xml | 5 +
.../bx/implatform/config/UniPushConfig.java | 44 +++++++
.../com/bx/implatform/contant/RedisKey.java | 6 +
.../controller/LoginController.java | 13 +-
.../java/com/bx/implatform/dto/LoginDTO.java | 3 +
.../java/com/bx/implatform/dto/LogoutDTO.java | 19 +++
.../java/com/bx/implatform/entity/User.java | 5 +
.../listener/PrivateMessageListener.java | 39 +++++-
.../service/INotifyPrivateService.java | 98 ++++++++++++++
.../bx/implatform/service/IUserService.java | 9 ++
.../service/impl/GroupServiceImpl.java | 6 +-
.../impl/PrivateMessageServiceImpl.java | 6 +-
.../service/impl/UserServiceImpl.java | 24 ++++
.../service/thirdparty/UniPushService.java | 122 ++++++++++++++++++
.../bx/implatform/session/NotifySession.java | 43 ++++++
.../src/main/resources/application.yml | 10 ++
im-platform/src/main/resources/db/db.sql | 1 +
im-uniapp/App.vue | 17 +++
im-uniapp/manifest.json | 14 +-
im-uniapp/pages/login/login.vue | 8 +-
20 files changed, 477 insertions(+), 15 deletions(-)
create mode 100644 im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java
create mode 100644 im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java
create mode 100644 im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java
create mode 100644 im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java
create mode 100644 im-platform/src/main/java/com/bx/implatform/session/NotifySession.java
diff --git a/im-platform/pom.xml b/im-platform/pom.xml
index 16e987c..9e7502a 100644
--- a/im-platform/pom.xml
+++ b/im-platform/pom.xml
@@ -115,6 +115,11 @@
redisson
3.17.3
+
+ com.getui.push
+ restful-sdk
+ 1.0.3.0
+
diff --git a/im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java b/im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java
new file mode 100644
index 0000000..641c3f6
--- /dev/null
+++ b/im-platform/src/main/java/com/bx/implatform/config/UniPushConfig.java
@@ -0,0 +1,44 @@
+package com.bx.implatform.config;
+
+import com.getui.push.v2.sdk.ApiHelper;
+import com.getui.push.v2.sdk.GtApiConfiguration;
+import com.getui.push.v2.sdk.api.PushApi;
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author: 谢绍许
+ * @date: 2024-07-06
+ * @version: 1.0
+ */
+@Data
+@Component
+public class UniPushConfig {
+
+ @Value("${notify.uniPush.appId}")
+ private String appId;
+ @Value("${notify.uniPush.appKey}")
+ private String appKey;
+ @Value("${notify.uniPush.masterSecret}")
+ private String masterSecret;
+
+ @Bean
+ public GtApiConfiguration uniPushConfiguration(){
+ GtApiConfiguration apiConfiguration = new GtApiConfiguration();
+ apiConfiguration.setAppId(appId);
+ apiConfiguration.setAppKey(appKey);
+ apiConfiguration.setMasterSecret(masterSecret);
+ return apiConfiguration;
+ }
+
+ @Bean
+ public PushApi uniPushApi(GtApiConfiguration configuration){
+ // 实例化ApiHelper对象,用于创建接口对象
+ ApiHelper apiHelper = ApiHelper.build(configuration);
+ // 创建对象,建议复用。目前有PushApi、StatisticApi、UserApi
+ PushApi pushApi = apiHelper.creatApi(PushApi.class);
+ return pushApi;
+ }
+}
diff --git a/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java b/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java
index 026e3c9..b2dd88b 100644
--- a/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java
+++ b/im-platform/src/main/java/com/bx/implatform/contant/RedisKey.java
@@ -10,6 +10,11 @@ public final class RedisKey {
* 已读群聊消息位置(已读最大id)
*/
public static final String IM_GROUP_READED_POSITION = "im:readed:group:position";
+
+ /**
+ * 私聊离线通知
+ */
+ public static final String IM_OFFLINE_NOTIFY_PRIVATE = "im:notify:private";
/**
* webrtc 单人通话
*/
@@ -45,4 +50,5 @@ public final class RedisKey {
*/
public static final String IM_LOCK_RTC_GROUP = IM_LOCK + "rtc:group";
+
}
diff --git a/im-platform/src/main/java/com/bx/implatform/controller/LoginController.java b/im-platform/src/main/java/com/bx/implatform/controller/LoginController.java
index 4a5e2d4..dbf07c2 100644
--- a/im-platform/src/main/java/com/bx/implatform/controller/LoginController.java
+++ b/im-platform/src/main/java/com/bx/implatform/controller/LoginController.java
@@ -1,6 +1,7 @@
package com.bx.implatform.controller;
import com.bx.implatform.dto.LoginDTO;
+import com.bx.implatform.dto.LogoutDTO;
import com.bx.implatform.dto.ModifyPwdDTO;
import com.bx.implatform.dto.RegisterDTO;
import com.bx.implatform.result.Result;
@@ -21,13 +22,21 @@ public class LoginController {
private final IUserService userService;
+
@PostMapping("/login")
- @ApiOperation(value = "用户注册", notes = "用户注册")
- public Result register(@Valid @RequestBody LoginDTO dto) {
+ @ApiOperation(value = "用户登陆", notes = "用户注册")
+ public Result login(@Valid @RequestBody LoginDTO dto) {
LoginVO vo = userService.login(dto);
return ResultUtils.success(vo);
}
+ @PostMapping("/logout")
+ @ApiOperation(value = "用户退出登陆", notes = "用户退出登陆")
+ public Result logout(@Valid @RequestBody LogoutDTO dto) {
+ userService.logout(dto);
+ return ResultUtils.success();
+ }
+
@PutMapping("/refreshToken")
@ApiOperation(value = "刷新token", notes = "用refreshtoken换取新的token")
diff --git a/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java b/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java
index 0cdede2..cea3110 100644
--- a/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java
+++ b/im-platform/src/main/java/com/bx/implatform/dto/LoginDTO.java
@@ -27,4 +27,7 @@ public class LoginDTO {
@ApiModelProperty(value = "用户密码")
private String password;
+ @ApiModelProperty(value = "用户客户端id")
+ private String cid;
+
}
diff --git a/im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java b/im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java
new file mode 100644
index 0000000..4b252af
--- /dev/null
+++ b/im-platform/src/main/java/com/bx/implatform/dto/LogoutDTO.java
@@ -0,0 +1,19 @@
+package com.bx.implatform.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Data
+@ApiModel("用户登录DTO")
+public class LogoutDTO {
+
+ @ApiModelProperty(value = "用户客户端id")
+ private String cid;
+
+}
diff --git a/im-platform/src/main/java/com/bx/implatform/entity/User.java b/im-platform/src/main/java/com/bx/implatform/entity/User.java
index 639b43b..67937fc 100644
--- a/im-platform/src/main/java/com/bx/implatform/entity/User.java
+++ b/im-platform/src/main/java/com/bx/implatform/entity/User.java
@@ -79,6 +79,11 @@ public class User extends Model {
@TableField("password")
private String password;
+ /**
+ * 客户端id,用于uni-push推送
+ */
+ @TableField("cid")
+ private String cid;
/**
* 最后登录时间
*/
diff --git a/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java b/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java
index 194f469..5843302 100644
--- a/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java
+++ b/im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java
@@ -6,10 +6,12 @@ import com.bx.imclient.annotation.IMListener;
import com.bx.imclient.listener.MessageListener;
import com.bx.imcommon.enums.IMListenerType;
import com.bx.imcommon.enums.IMSendCode;
+import com.bx.imcommon.enums.IMTerminalType;
import com.bx.imcommon.model.IMSendResult;
import com.bx.implatform.entity.PrivateMessage;
import com.bx.implatform.enums.MessageStatus;
import com.bx.implatform.service.IPrivateMessageService;
+import com.bx.implatform.service.INotifyPrivateService;
import com.bx.implatform.vo.PrivateMessageVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -25,24 +27,49 @@ public class PrivateMessageListener implements MessageListener
@Lazy
@Autowired
private IPrivateMessageService privateMessageService;
+
+ @Lazy
+ @Autowired
+ private INotifyPrivateService uniPushService;
+
@Override
public void process(List> results) {
+ // 更新消息状态
+ updateMessageStatus(results);
+ // 推送离线通知
+ sendOfflineNotify(results);
+ }
+
+ private void updateMessageStatus(List> results) {
Set messageIds = new HashSet<>();
- for(IMSendResult result : results){
+ for (IMSendResult result : results) {
PrivateMessageVO messageInfo = result.getData();
// 更新消息状态,这里只处理成功消息,失败的消息继续保持未读状态
if (result.getCode().equals(IMSendCode.SUCCESS.code())) {
messageIds.add(messageInfo.getId());
- log.info("消息送达,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(), result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal());
+ log.info("消息送达,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(),
+ result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal());
}
}
- // 批量修改状态
- if(CollUtil.isNotEmpty(messageIds)){
+ // 对发送成功的消息修改状态
+ if (CollUtil.isNotEmpty(messageIds)) {
UpdateWrapper updateWrapper = new UpdateWrapper<>();
updateWrapper.lambda().in(PrivateMessage::getId, messageIds)
- .eq(PrivateMessage::getStatus, MessageStatus.UNSEND.code())
- .set(PrivateMessage::getStatus, MessageStatus.SENDED.code());
+ .eq(PrivateMessage::getStatus, MessageStatus.UNSEND.code())
+ .set(PrivateMessage::getStatus, MessageStatus.SENDED.code());
privateMessageService.update(updateWrapper);
}
}
+
+ private void sendOfflineNotify(List> results) {
+ for (IMSendResult result : results) {
+ PrivateMessageVO messageInfo = result.getData();
+ if (result.getCode().equals(IMSendCode.SUCCESS.code()) && result.getReceiver().getTerminal()
+ .equals(IMTerminalType.APP.code())) {
+ uniPushService.sendMessage(messageInfo.getSendId(), messageInfo.getRecvId(), messageInfo.getContent());
+ log.info("推送离线通知,消息id:{},发送者:{},接收者:{}", messageInfo.getId(), result.getSender().getId(),
+ result.getReceiver().getId());
+ }
+ }
+ }
}
diff --git a/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java b/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java
new file mode 100644
index 0000000..6fa2f5a
--- /dev/null
+++ b/im-platform/src/main/java/com/bx/implatform/service/INotifyPrivateService.java
@@ -0,0 +1,98 @@
+package com.bx.implatform.service;
+
+import cn.hutool.core.util.StrUtil;
+import com.bx.implatform.contant.RedisKey;
+import com.bx.implatform.entity.User;
+import com.bx.implatform.session.NotifySession;
+import com.bx.implatform.service.thirdparty.UniPushService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 私聊离线通知服务
+ *
+ * @author: blue
+ * @date: 2024-07-06
+ * @version: 1.0
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class INotifyPrivateService {
+ private final UniPushService uniPushService;
+ private final IUserService userService;
+ private final RedisTemplate redisTemplate;
+ @Value("${notify.enable}")
+ private Boolean enable = false;
+ @Value("${notify.max.private}")
+ private Integer max = -1;
+ public void sendMessage(Long sendId, Long recvId, String content) {
+ if(!enable){
+ return;
+ }
+ NotifySession session = findNotifySession(sendId, recvId);
+ if (Objects.isNull(session)) {
+ session = createNotifySession(sendId, recvId);
+ }
+ // 未上报cid,无法推送
+ if (StrUtil.isEmpty(session.getCid())) {
+ log.info("用户'{}'未上报cid,无法推送离线通知", recvId);
+ return;
+ }
+ // 已达到最大数量
+ if (max > 0 && session.getCount() >= max) {
+ log.info("用户'{}'已到达推送数量上线,不再推送离线通知", recvId);
+ return;
+ }
+ // 消息数量加1
+ session.setCount(session.getCount()+1);
+ String body = String.format("%s:%s", session.getSendNickName(),content);
+ // 大于1条时需要展示数量
+ if (session.getCount() > 1) {
+ body = String.format("[%d条] ", session.getCount()) + body;
+ }
+ uniPushService.pushByCid(session,body);
+ // 保存会话
+ saveNotifySession(session,sendId,recvId);
+ }
+
+ public void removeNotifySession(Long sendId, Long recvId){
+ String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, "*", recvId);
+ Set keys = redisTemplate.keys(key);
+ redisTemplate.delete(keys);
+ }
+
+ private NotifySession createNotifySession(Long sendId, Long recvId) {
+ String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId);
+ User sendUser = userService.getById(sendId);
+ User recvUser = userService.getById(recvId);
+ NotifySession session = new NotifySession();
+ session.setCount(0);
+ session.setCid(recvUser.getCid());
+ session.setTitle(sendUser.getNickName());
+ session.setSendNickName(sendUser.getNickName());
+ session.setNotifyId(Math.abs(key.hashCode()));
+ session.setLogo(sendUser.getHeadImageThumb());
+ redisTemplate.opsForValue().set(key, session, 30, TimeUnit.DAYS);
+ return session;
+ }
+
+ private NotifySession findNotifySession(Long sendId, Long recvId) {
+ String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId);
+ return (NotifySession)redisTemplate.opsForValue().get(key);
+ }
+
+ private void saveNotifySession(NotifySession session, Long sendId, Long recvId) {
+ String key = StrUtil.join(":", RedisKey.IM_OFFLINE_NOTIFY_PRIVATE, sendId, recvId);
+ redisTemplate.opsForValue().set(key, session);
+ }
+
+}
diff --git a/im-platform/src/main/java/com/bx/implatform/service/IUserService.java b/im-platform/src/main/java/com/bx/implatform/service/IUserService.java
index a24e0c3..1d1c823 100644
--- a/im-platform/src/main/java/com/bx/implatform/service/IUserService.java
+++ b/im-platform/src/main/java/com/bx/implatform/service/IUserService.java
@@ -2,6 +2,7 @@ package com.bx.implatform.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bx.implatform.dto.LoginDTO;
+import com.bx.implatform.dto.LogoutDTO;
import com.bx.implatform.dto.ModifyPwdDTO;
import com.bx.implatform.dto.RegisterDTO;
import com.bx.implatform.entity.User;
@@ -21,6 +22,14 @@ public interface IUserService extends IService {
*/
LoginVO login(LoginDTO dto);
+ /**
+ * 用户退出登陆
+ *
+ * @param dto 退出登陆dto
+ * @return
+ */
+ void logout(LogoutDTO dto);
+
/**
* 修改用户密码
*
diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java
index feb13c8..c32de84 100644
--- a/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java
+++ b/im-platform/src/main/java/com/bx/implatform/service/impl/GroupServiceImpl.java
@@ -75,7 +75,7 @@ public class GroupServiceImpl extends ServiceImpl implements
return vo;
}
- @CacheEvict(value = "#vo.getId()")
+ @CacheEvict(key = "#vo.getId()")
@Transactional(rollbackFor = Exception.class)
@Override
public GroupVO modifyGroup(GroupVO vo) {
@@ -100,7 +100,7 @@ public class GroupServiceImpl extends ServiceImpl implements
}
@Transactional(rollbackFor = Exception.class)
- @CacheEvict(value = "#groupId")
+ @CacheEvict(key = "#groupId")
@Override
public void deleteGroup(Long groupId) {
UserSession session = SessionContext.getSession();
@@ -178,7 +178,7 @@ public class GroupServiceImpl extends ServiceImpl implements
return vo;
}
- @Cacheable(value = "#groupId")
+ @Cacheable(key = "#groupId")
@Override
public Group getById(Long groupId) {
Group group = super.getById(groupId);
diff --git a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java
index 0e10922..3c0dc4d 100644
--- a/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java
+++ b/im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java
@@ -21,6 +21,7 @@ import com.bx.implatform.exception.GlobalException;
import com.bx.implatform.mapper.PrivateMessageMapper;
import com.bx.implatform.service.IFriendService;
import com.bx.implatform.service.IPrivateMessageService;
+import com.bx.implatform.service.INotifyPrivateService;
import com.bx.implatform.session.SessionContext;
import com.bx.implatform.session.UserSession;
import com.bx.implatform.util.BeanUtils;
@@ -43,7 +44,7 @@ public class PrivateMessageServiceImpl extends ServiceImpl implements IU
private final JwtProperties jwtProperties;
private final IMClient imClient;
+
@Override
public LoginVO login(LoginDTO dto) {
User user = this.findUserByUserName(dto.getUserName());
@@ -56,6 +61,12 @@ public class UserServiceImpl extends ServiceImpl implements IU
if (!passwordEncoder.matches(dto.getPassword(), user.getPassword())) {
throw new GlobalException(ResultCode.PASSWOR_ERROR);
}
+ // 更新用户登陆时间和cid
+ user.setLastLoginTime(new Date());
+ if(StrUtil.isNotEmpty(dto.getCid())){
+ user.setCid(dto.getCid());
+ }
+ this.updateById(user);
// 生成token
UserSession session = BeanUtils.copyProperties(user, UserSession.class);
session.setUserId(user.getId());
@@ -71,6 +82,19 @@ public class UserServiceImpl extends ServiceImpl implements IU
return vo;
}
+ @Override
+ public void logout(LogoutDTO dto) {
+ UserSession session = SessionContext.getSession();
+ if(StrUtil.isNotEmpty(dto.getCid())){
+ // 清除cid,不再推送离线通知
+ LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate();
+ wrapper.eq(User::getId,session.getUserId());
+ wrapper.eq(User::getCid,dto.getCid());
+ wrapper.set(User::getCid, Strings.EMPTY);
+ this.update(wrapper);
+ }
+ }
+
@Override
public LoginVO refreshToken(String refreshToken) {
//验证 token
diff --git a/im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java b/im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java
new file mode 100644
index 0000000..f0c367b
--- /dev/null
+++ b/im-platform/src/main/java/com/bx/implatform/service/thirdparty/UniPushService.java
@@ -0,0 +1,122 @@
+package com.bx.implatform.service.thirdparty;
+
+import com.bx.implatform.session.NotifySession;
+import com.getui.push.v2.sdk.api.PushApi;
+import com.getui.push.v2.sdk.common.ApiResult;
+import com.getui.push.v2.sdk.dto.req.Audience;
+import com.getui.push.v2.sdk.dto.req.Settings;
+import com.getui.push.v2.sdk.dto.req.message.PushChannel;
+import com.getui.push.v2.sdk.dto.req.message.PushDTO;
+import com.getui.push.v2.sdk.dto.req.message.PushMessage;
+import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO;
+import com.getui.push.v2.sdk.dto.req.message.android.GTNotification;
+import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification;
+import com.getui.push.v2.sdk.dto.req.message.android.Ups;
+import com.getui.push.v2.sdk.dto.req.message.ios.Alert;
+import com.getui.push.v2.sdk.dto.req.message.ios.Aps;
+import com.getui.push.v2.sdk.dto.req.message.ios.IosDTO;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: 谢绍许
+ * @date: 2024-07-06
+ * @version: 1.0
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class UniPushService {
+
+ private final PushApi pushApi;
+
+ public void pushByCid(NotifySession session, String body){
+ //根据cid进行单推
+ PushDTO pushDTO = new PushDTO();
+ // 设置推送参数,requestid需要每次变化唯一
+ pushDTO.setRequestId(System.currentTimeMillis()+"");
+ Settings settings = new Settings();
+ pushDTO.setSettings(settings);
+ //消息有效期,走厂商消息必须设置该值
+ settings.setTtl(3600000);
+ //在线走个推通道时推送的消息体
+ PushMessage pushMessage = new PushMessage();
+ pushDTO.setPushMessage(pushMessage);
+ //此格式的透传消息由 unipush 做了特殊处理,会自动展示通知栏。开发者也可自定义其它格式,在客户端自己处理。
+ GTNotification gtNotification = new GTNotification();
+ gtNotification.setTitle(session.getTitle());
+ gtNotification.setBody(body);
+ gtNotification.setClickType("startapp");
+ gtNotification.setNotifyId(session.getNotifyId().toString());
+ gtNotification.setLogoUrl(session.getLogo());
+ gtNotification.setBadgeAddNum("1");
+ pushMessage.setNotification(gtNotification);
+ // 设置接收人信息
+ Audience audience = new Audience();
+ pushDTO.setAudience(audience);
+ audience.addCid(session.getCid());
+ //设置离线推送时的消息体
+ PushChannel pushChannel = new PushChannel();
+ //安卓离线厂商通道推送的消息体
+ AndroidDTO androidDTO = new AndroidDTO();
+ Ups ups = new Ups();
+ ThirdNotification thirdNotification = new ThirdNotification();
+ ups.setNotification(thirdNotification);
+ ups.setOptions(buildOptions(session.getLogo()));
+ thirdNotification.setTitle(session.getTitle());
+ thirdNotification.setBody(body);
+ thirdNotification.setNotifyId(session.getNotifyId().toString());
+ // 打开首页
+ thirdNotification.setClickType("startapp");
+ androidDTO.setUps(ups);
+ pushChannel.setAndroid(androidDTO);
+ // ios离线apn通道推送的消息体
+ Alert alert = new Alert();
+ alert.setTitle(session.getTitle());
+ alert.setBody(body);
+ Aps aps = new Aps();
+ // 0:普通通知消息 1:静默推送(无通知栏消息),静默推送时不需要填写其他参数。苹果建议1小时最多推送3条静默消息
+ aps.setContentAvailable(0);
+ // default: 系统铃声 不填:无声
+ aps.setSound("default");
+ aps.setAlert(alert);
+
+ IosDTO iosDTO = new IosDTO();
+ iosDTO.setAps(aps);
+ iosDTO.setType("notify");
+ pushChannel.setIos(iosDTO);
+ pushDTO.setPushChannel(pushChannel);
+ // 进行cid单推
+ ApiResult