Browse Source

增加客服消息推送

Eric 2 years ago
parent
commit
15eb4f0b54

+ 21 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/controller/open/ImUserFriendController.java

@@ -1,7 +1,9 @@
 package com.yonge.cooleshow.admin.controller.open;
 
+import com.yonge.cooleshow.admin.io.request.im.IMNotifyMessageVO;
 import com.yonge.cooleshow.admin.io.request.im.UserFriendInfoVO;
 import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import io.swagger.annotations.Api;
@@ -44,5 +46,24 @@ public class ImUserFriendController extends BaseController {
 
         return succeed(ret > 0);
     }
+
+    /**
+     * 发送系统客服消息
+     * @param info IMNotifyMessageVO
+     * @return HttpResponseResult<Boolean>
+     */
+    @PostMapping(value = "/message")
+    public HttpResponseResult<Boolean> sendSysCustomerServiceMessage(@RequestBody IMNotifyMessageVO info) {
+
+        if (info.invalidRequestParam()) {
+            return failed("无效的请求参数");
+        }
+
+        // 发送客服通知消息
+        imUserFriendService.sendCustomerServiceNotifyMessage(info.getSender(),
+                CustomerService.NotifyMessage.from(info.jsonString()));
+
+        return succeed();
+    }
 }
 

+ 52 - 0
cooleshow-user/user-admin/src/main/java/com/yonge/cooleshow/admin/io/request/im/IMNotifyMessageVO.java

@@ -0,0 +1,52 @@
+package com.yonge.cooleshow.admin.io.request.im;
+
+import com.alibaba.fastjson.JSON;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 系统IM通知信息
+ * Created by Eric.Shang on 2022/9/20.
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class IMNotifyMessageVO implements Serializable {
+
+    @ApiModelProperty(value = "发送者ID")
+    private String sender;
+
+    @ApiModelProperty(value = "接收ID")
+    private List<String> receives;
+
+    @ApiModelProperty(value = "通知标题")
+    private String title;
+
+    @ApiModelProperty(value = "文件通知消息")
+    private String txtMessage;
+
+    @ApiModelProperty(value = "图片通知消息")
+    private String imgMessage;
+
+    @ApiModelProperty(value = "图片文件地址")
+    private String imgUrl;
+
+    public String jsonString() {
+
+        return JSON.toJSONString(this);
+    }
+
+    public boolean invalidRequestParam() {
+
+        return StringUtils.isEmpty(getSender())
+                || StringUtils.isAllBlank(getTxtMessage(), getImgMessage());
+    }
+}

+ 6 - 0
cooleshow-user/user-biz/pom.xml

@@ -43,6 +43,12 @@
             <version>${rongcloud.im.version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>net.coobird</groupId>
+            <artifactId>thumbnailator</artifactId>
+            <version>0.4.11</version>
+        </dependency>
+
         <!-- redisson -->
         <dependency>
             <groupId>org.redisson</groupId>

+ 8 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/ImUserFriendService.java

@@ -3,6 +3,7 @@ package com.yonge.cooleshow.biz.dal.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.yonge.cooleshow.biz.dal.dao.ImUserFriendDao;
 import com.yonge.cooleshow.biz.dal.entity.ImUserFriend;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
 
 import java.util.List;
 import java.util.Set;
@@ -43,5 +44,12 @@ public interface ImUserFriendService extends IService<ImUserFriend> {
      * @return Integer
      */
     Integer registerUserBindCustomerService(Long userId, List<Long> friendIds);
+
+    /**
+     * 发送系统客服消息
+     * @param sender 发送者
+     * @param info CustomerService.NotifyMessage
+     */
+    void sendCustomerServiceNotifyMessage(String sender, CustomerService.NotifyMessage info);
 }
 

+ 122 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ImUserFriendServiceImpl.java

@@ -1,6 +1,9 @@
 package com.yonge.cooleshow.biz.dal.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
@@ -11,12 +14,21 @@ import com.yonge.cooleshow.biz.dal.dao.TeacherDao;
 import com.yonge.cooleshow.biz.dal.dto.BasicUserInfo;
 import com.yonge.cooleshow.biz.dal.entity.ImUserFriend;
 import com.yonge.cooleshow.biz.dal.enums.MK;
+import com.yonge.cooleshow.biz.dal.mapper.SysUserMapper;
 import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
+import com.yonge.cooleshow.biz.dal.wrapper.im.CustomerService;
+import com.yonge.toolset.base.exception.BizException;
+import io.rong.messages.BaseMessage;
+import io.rong.messages.FileMessage;
+import io.rong.messages.ImgMessage;
+import io.rong.messages.ImgTextMessage;
 import io.rong.messages.TxtMessage;
 import io.rong.models.message.PrivateMessage;
 import io.rong.models.message.PushExt;
 import io.rong.models.response.ResponseResult;
 import lombok.extern.slf4j.Slf4j;
+import net.coobird.thumbnailator.Thumbnails;
+import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -24,6 +36,11 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
@@ -48,6 +65,8 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
     private SysUserFeignService sysUserFeignService;
     @Autowired
     private CustomerServiceConfig customerServiceConfig;
+    @Autowired
+    private SysUserMapper sysUserMapper;
 
     @Override
     public ImUserFriendDao getDao() {
@@ -168,5 +187,108 @@ public class ImUserFriendServiceImpl extends ServiceImpl<ImUserFriendDao, ImUser
         return CollectionUtils.size(friendIds);
     }
 
+    /**
+     * 发送系统客服消息
+     *
+     * @param sender 发送者
+     * @param info   CustomerService.NotifyMessage
+     */
+    @Override
+    public void sendCustomerServiceNotifyMessage(String sender, CustomerService.NotifyMessage info) {
+
+        // 发送者信息
+        com.yonge.cooleshow.biz.dal.entity.SysUser senderUser = sysUserMapper.selectOne(Wrappers.<com.yonge.cooleshow.biz.dal.entity.SysUser>lambdaQuery()
+                .eq(com.yonge.cooleshow.biz.dal.entity.SysUser::getPhone, sender));
+
+        if (Objects.isNull(senderUser)) {
+            throw new BizException("无效的客服联系方式");
+        }
+
+        LambdaQueryWrapper<com.yonge.cooleshow.biz.dal.entity.SysUser> wrapper = Wrappers.<com.yonge.cooleshow.biz.dal.entity.SysUser>lambdaQuery()
+                .select(com.yonge.cooleshow.biz.dal.entity.SysUser::getId,
+                        com.yonge.cooleshow.biz.dal.entity.SysUser::getUsername)
+                .in(com.yonge.cooleshow.biz.dal.entity.SysUser::getPhone, info.getReceives());
+
+        wrapper.last("LIMIT 1000");
+        // 接收者信息
+        List<com.yonge.cooleshow.biz.dal.entity.SysUser> sysUsers = sysUserMapper.selectList(wrapper);
+
+        // 发送图片消息
+        ImgMessage imgMessage = new ImgMessage(imageToBase64(info.getImgMessage(), "png"), "", info.getImgUrl());
+
+        // 发送文本消息
+        TxtMessage txtMessage = new TxtMessage(info.getTxtMessage(), "");
+
+        List<BaseMessage> messages = Lists.newArrayList(imgMessage, txtMessage);
+
+        // 拓展消息
+        PushExt pushExt = PushExt.build(info.getTitle(), 1,
+                new PushExt.HW("channelId", "NORMAL"), new PushExt.VIVO("1"),
+                new PushExt.APNs("", ""),
+                new PushExt.OPPO(""));
+
+        // 分批次发送用户消息
+        List<String> receiveUserIds = sysUsers.stream()
+                .map(com.yonge.cooleshow.biz.dal.entity.SysUser::getId)
+                .map(String::valueOf)
+                .collect(Collectors.toList());
+
+        String senderId = String.valueOf(senderUser.getId());
+        PrivateMessage privateMessage;
+        ResponseResult privateResult;
+        for (List<String> item : Lists.partition(receiveUserIds, 100)) {
+
+            try {
+
+                for (BaseMessage message : messages) {
+
+                    // 发送用户IM通知消息
+                    privateMessage = new PrivateMessage()
+                            .setSenderId(senderId)
+                            .setTargetId(item.toArray(new String[0]))
+                            .setObjectName(message.getType())
+                            .setContent(message)
+                            .setPushExt(pushExt)
+                            .setIsIncludeSender(0);
+
+                    privateResult = RongCloudConfig.rongCloud.message.msgPrivate.send(privateMessage);
+                    log.info("sendCustomerServiceNotifyMessage senderId={}, ret={}", senderId, privateResult.getCode());
+                }
+
+            } catch (Exception e) {
+                log.error("sendCustomerServiceNotifyMessage senderId={}", senderId, e);
+            }
+
+        }
+
+    }
+
+    public static String imageToBase64(String imgMessage, String suffix) {
+
+        Base64 encoder = new Base64();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try {
+            URL url = new URL(imgMessage);
+            BufferedImage bufferedImage = Thumbnails.of(url).scale(0.1f).outputQuality(0.25f).asBufferedImage();
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+            ImageIO.write(bufferedImage, suffix, outputStream);
+
+            byte[] bytes = outputStream.toByteArray();
+            outputStream.close();
+            int length = bytes.length;
+            //文件大小不能超过393216 Bytes
+            if (length > 393216) {
+                throw new BizException("文件过大请调整 像素 或 文件大小");
+            }
+
+            ImageIO.write(bufferedImage, suffix, baos);
+        } catch (IOException e) {
+            log.error("imageToBase64", e);
+        }
+        return new String(encoder.encode((baos.toByteArray())));
+    }
+
+
+
 }
 

+ 39 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/im/CustomerService.java

@@ -0,0 +1,39 @@
+package com.yonge.cooleshow.biz.dal.wrapper.im;
+
+import com.alibaba.fastjson.JSON;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 客服消息
+ * Created by Eric.Shang on 2022/9/30.
+ */
+public class CustomerService {
+
+    /**
+     * 客服通知消息
+     */
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class NotifyMessage implements Serializable {
+
+        private List<String> receives;
+
+        private String title;
+        private String txtMessage;
+        private String imgMessage;
+        private String imgUrl;
+
+        public static NotifyMessage from(String recv) {
+
+            return JSON.parseObject(recv, NotifyMessage.class);
+        }
+    }
+}