浏览代码

极光推送功能实现

yzc 1 年之前
父节点
当前提交
7105de096e

+ 28 - 0
hx-jpush/pom.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.ruoyi</groupId>
+        <artifactId>ruoyi</artifactId>
+        <version>3.8.5</version>
+    </parent>
+
+    <artifactId>hx-jpush</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+    <dependencies>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-framework</artifactId>
+        </dependency>
+
+    </dependencies>
+
+</project>

+ 25 - 0
hx-jpush/src/main/java/com/fjhx/jpush/code/JPushConfig.java

@@ -0,0 +1,25 @@
+package com.fjhx.jpush.code;
+
+import org.springframework.beans.factory.annotation.Value;
+
+public class JPushConfig {
+    /**
+     * 极光AppKey
+     */
+    public static String appKey;
+    /**
+     * 极光MasterSecret
+     */
+    public static String masterSecret;
+
+    @Value("${jPush.appKey}")
+    public static void setjPushAppKey(String appKey) {
+        JPushConfig.appKey = appKey;
+    }
+
+    @Value("${jPush.masterSecret}")
+    public static void setjPushMasterSecret(String masterSecret) {
+        JPushConfig.masterSecret = masterSecret;
+    }
+
+}

+ 91 - 0
hx-jpush/src/main/java/com/fjhx/jpush/code/JPushUtils.java

@@ -0,0 +1,91 @@
+package com.fjhx.jpush.code;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.jpush.entity.jpush.po.JpushInfo;
+import com.fjhx.jpush.service.jpush.JpushInfoService;
+import com.ruoyi.common.exception.ServiceException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.IOUtils;
+import org.springframework.stereotype.Component;
+
+import java.io.DataOutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.List;
+
+@Slf4j
+@Component
+public class JPushUtils {
+
+
+    private static final JpushInfoService jPushInfoService = SpringUtil.getBean(JpushInfoService.class);
+
+
+    /**
+     * 根据用户id列表 向极光推送消息
+     */
+    public static void jPushSendMsg(String msg, List<Long> userIds) {
+        //如果未配置极光推送相关信息直接跳过
+        if (ObjectUtil.isEmpty(JPushConfig.appKey) || ObjectUtil.isEmpty(JPushConfig.masterSecret)) {
+            return;
+        }
+
+        //根据用户id获取要推送的设备列表
+        List<String> registrationIds = jPushInfoService.listObject(JpushInfo::getRegistrationId, q -> q
+                .eq(JpushInfo::getUserId, userIds)
+                .isNotNull(JpushInfo::getRegistrationId)
+        );
+
+        //如果推送设备id列表为空直接跳过
+        if (ObjectUtil.isEmpty(registrationIds)) {
+            return;
+        }
+
+        //创建消息体
+        JpushMsgEntity.Audience audience = new JpushMsgEntity.Audience(registrationIds);
+        JpushMsgEntity.Notification notification = new JpushMsgEntity.Notification(msg);
+        JpushMsgEntity jpushMsgEntity = new JpushMsgEntity("all", audience, notification);
+
+        //推送消息
+        jPushSend(JSONObject.toJSONString(jpushMsgEntity));
+    }
+
+    /**
+     * 向极光推送消息
+     */
+    private static void jPushSend(String requestDate) {
+        try {
+            //通过base64编码认证信息
+            String token = JPushConfig.appKey + ":" + JPushConfig.masterSecret;
+            token = Base64.getEncoder().encodeToString(token.getBytes());
+
+            URL url = new URL("https://api.jpush.cn/v3/push");
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            conn.setRequestMethod("POST");
+            conn.setConnectTimeout(3000);
+            conn.setReadTimeout(3000);
+            conn.setDoInput(true);
+            conn.setDoOutput(true);
+            // 身份鉴权
+            conn.setRequestProperty("Content-Type", "application/json");
+            conn.setRequestProperty("Authorization", "Basic " + token);
+            // 发送消息
+            DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
+            dos.write(requestDate.getBytes(StandardCharsets.UTF_8));
+            dos.flush();
+            // 根据状态码获取流
+            int responseCode = conn.getResponseCode();
+            System.out.println(responseCode);
+            if (responseCode != 200) {
+                throw new ServiceException(IOUtils.toString(conn.getErrorStream(), StandardCharsets.UTF_8));
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            throw new ServiceException("极光消息推送异常:{}" + e.getMessage());
+        }
+    }
+}

+ 45 - 0
hx-jpush/src/main/java/com/fjhx/jpush/code/JpushMsgEntity.java

@@ -0,0 +1,45 @@
+package com.fjhx.jpush.code;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+@AllArgsConstructor
+public class JpushMsgEntity {
+	/**
+	 * 推送平台
+	 */
+	private String platform;
+	/**
+	 * 推送设备
+	 */
+	private Audience audience;
+	/**
+	 * 消息体
+	 */
+	private Notification notification;
+
+	@Getter
+	@Setter
+	@AllArgsConstructor
+	public static class Notification {
+		/**
+		 * 消息内容
+		 */
+		private String alert;
+	}
+
+	@Getter
+	@Setter
+	@AllArgsConstructor
+	public static class Audience {
+		/**
+		 * 设备注册码列表
+		 */
+		private List<String> registration_id;
+	}
+}

+ 46 - 0
hx-jpush/src/main/java/com/fjhx/jpush/controller/jpush/JpushInfoController.java

@@ -0,0 +1,46 @@
+package com.fjhx.jpush.controller.jpush;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import com.fjhx.jpush.entity.jpush.dto.JpushInfoDto;
+import com.fjhx.jpush.service.jpush.JpushInfoService;
+import com.ruoyi.common.constant.BaseSourceConstant;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * <p>
+ * 极光推送用户与设备绑定信息 前端控制器
+ * </p>
+ *
+ * @author
+ * @since 2023-10-08
+ */
+@DS(BaseSourceConstant.BASE)
+@RestController
+@RequestMapping("/jPushInfo")
+public class JpushInfoController {
+
+    @Autowired
+    private JpushInfoService jpushInfoService;
+
+    /**
+     * 极光推送用户与设备绑定信息绑定
+     */
+    @PostMapping("/userBinding")
+    public void userBinding(@RequestBody JpushInfoDto jpushInfoDto) {
+        jpushInfoService.userBinding(jpushInfoDto);
+    }
+
+    /**
+     * 极光推送用户与设备绑定信息解绑
+     */
+    @PostMapping("/userUnBinding")
+    public void userUnBinding(@RequestBody JpushInfoDto jpushInfoDto) {
+        jpushInfoService.userUnBinding(jpushInfoDto);
+    }
+
+}

+ 17 - 0
hx-jpush/src/main/java/com/fjhx/jpush/entity/jpush/dto/JpushInfoDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.jpush.entity.jpush.dto;
+
+import com.fjhx.jpush.entity.jpush.po.JpushInfo;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 极光推送用户与设备绑定信息新增编辑入参实体
+ *
+ * @author 
+ * @since 2023-10-08
+ */
+@Getter
+@Setter
+public class JpushInfoDto extends JpushInfo {
+
+}

+ 17 - 0
hx-jpush/src/main/java/com/fjhx/jpush/entity/jpush/dto/JpushInfoSelectDto.java

@@ -0,0 +1,17 @@
+package com.fjhx.jpush.entity.jpush.dto;
+
+import com.ruoyi.common.core.domain.BaseSelectDto;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 极光推送用户与设备绑定信息列表查询入参实体
+ *
+ * @author 
+ * @since 2023-10-08
+ */
+@Getter
+@Setter
+public class JpushInfoSelectDto extends BaseSelectDto {
+
+}

+ 32 - 0
hx-jpush/src/main/java/com/fjhx/jpush/entity/jpush/po/JpushInfo.java

@@ -0,0 +1,32 @@
+package com.fjhx.jpush.entity.jpush.po;
+
+import com.ruoyi.common.core.domain.BasePo;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 极光推送用户与设备绑定信息
+ * </p>
+ *
+ * @author 
+ * @since 2023-10-08
+ */
+@Getter
+@Setter
+@TableName("jpush_info")
+public class JpushInfo extends BasePo {
+
+    /**
+     * 系统用户id
+     */
+    private Long userId;
+
+    /**
+     * 极光推送设备注册码
+     */
+    private String registrationId;
+
+}

+ 17 - 0
hx-jpush/src/main/java/com/fjhx/jpush/entity/jpush/vo/JpushInfoVo.java

@@ -0,0 +1,17 @@
+package com.fjhx.jpush.entity.jpush.vo;
+
+import com.fjhx.jpush.entity.jpush.po.JpushInfo;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 极光推送用户与设备绑定信息列表查询返回值实体
+ *
+ * @author 
+ * @since 2023-10-08
+ */
+@Getter
+@Setter
+public class JpushInfoVo extends JpushInfo {
+
+}

+ 17 - 0
hx-jpush/src/main/java/com/fjhx/jpush/mapper/jpush/JpushInfoMapper.java

@@ -0,0 +1,17 @@
+package com.fjhx.jpush.mapper.jpush;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fjhx.jpush.entity.jpush.po.JpushInfo;
+
+/**
+ * <p>
+ * 极光推送用户与设备绑定信息 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2023-10-08
+ */
+public interface JpushInfoMapper extends BaseMapper<JpushInfo> {
+
+}

+ 27 - 0
hx-jpush/src/main/java/com/fjhx/jpush/service/jpush/JpushInfoService.java

@@ -0,0 +1,27 @@
+package com.fjhx.jpush.service.jpush;
+
+import com.fjhx.jpush.entity.jpush.dto.JpushInfoDto;
+import com.fjhx.jpush.entity.jpush.po.JpushInfo;
+import com.ruoyi.common.core.service.BaseService;
+
+
+/**
+ * <p>
+ * 极光推送用户与设备绑定信息 服务类
+ * </p>
+ *
+ * @author
+ * @since 2023-10-08
+ */
+public interface JpushInfoService extends BaseService<JpushInfo> {
+
+    /**
+     * 极光推送用户与设备绑定信息绑定
+     */
+    void userBinding(JpushInfoDto jpushInfoDto);
+
+    /**
+     * 极光推送用户与设备绑定信息解绑
+     */
+    void userUnBinding(JpushInfoDto jpushInfoDto);
+}

+ 59 - 0
hx-jpush/src/main/java/com/fjhx/jpush/service/jpush/impl/JpushInfoServiceImpl.java

@@ -0,0 +1,59 @@
+package com.fjhx.jpush.service.jpush.impl;
+
+
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.jpush.entity.jpush.dto.JpushInfoDto;
+import com.fjhx.jpush.entity.jpush.po.JpushInfo;
+import com.fjhx.jpush.mapper.jpush.JpushInfoMapper;
+import com.fjhx.jpush.service.jpush.JpushInfoService;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 极光推送用户与设备绑定信息 服务实现类
+ * </p>
+ *
+ * @author
+ * @since 2023-10-08
+ */
+@Service
+public class JpushInfoServiceImpl extends ServiceImpl<JpushInfoMapper, JpushInfo> implements JpushInfoService {
+
+    /**
+     * 极光推送用户与设备绑定信息绑定
+     */
+    @Override
+    public void userBinding(JpushInfoDto jpushInfoDto) {
+        if (ObjectUtil.isEmpty(jpushInfoDto.getRegistrationId())) {
+            throw new ServiceException("设备注册id不能为空");
+        }
+
+        jpushInfoDto.setUserId(SecurityUtils.getUserId());
+
+        //判断设备码是否已经绑定当前用户
+        long count = this.count(q -> q
+                .eq(JpushInfo::getUserId, jpushInfoDto.getUserId())
+                .eq(JpushInfo::getRegistrationId, jpushInfoDto.getRegistrationId())
+        );
+        //如果没有绑定当前用户就绑定
+        if (count == 0) {
+            this.remove(q -> q.eq(JpushInfo::getRegistrationId, jpushInfoDto.getRegistrationId()));
+            this.save(jpushInfoDto);
+        }
+    }
+
+    /**
+     * 极光推送用户与设备绑定信息解绑
+     */
+    @Override
+    public void userUnBinding(JpushInfoDto jpushInfoDto) {
+        if (ObjectUtil.isEmpty(jpushInfoDto.getRegistrationId())) {
+            throw new ServiceException("设备注册id不能为空");
+        }
+        this.remove(q -> q.eq(JpushInfo::getRegistrationId, jpushInfoDto.getRegistrationId()));
+    }
+
+}

+ 4 - 0
hx-jpush/src/main/resources/mapper/jpush/JpushInfoMapper.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fjhx.jpush.mapper.jpush.JpushInfoMapper">
+</mapper>

+ 6 - 0
hx-socket/pom.xml

@@ -33,6 +33,12 @@
             <groupId>com.ruoyi</groupId>
             <artifactId>ruoyi-framework</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>hx-jpush</artifactId>
+            <version>3.8.5</version>
+            <scope>compile</scope>
+        </dependency>
 
     </dependencies>
 

+ 9 - 0
hx-socket/src/main/java/com/fjhx/socket/core/WebSocketPush.java

@@ -6,6 +6,7 @@ import com.alibaba.fastjson2.JSONObject;
 import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.fjhx.jpush.code.JPushUtils;
 import com.fjhx.socket.core.event.WebSocketUserOfflineEvent;
 import com.fjhx.socket.entity.push.po.PushInfo;
 import com.fjhx.socket.service.push.PushInfoService;
@@ -16,8 +17,11 @@ import com.ruoyi.framework.mybatis.holder.TenantHolder;
 import com.ruoyi.system.service.ISysUserService;
 import org.springframework.context.ApplicationContext;
 
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 public class WebSocketPush {
 
@@ -30,6 +34,8 @@ public class WebSocketPush {
      */
     public static void byUser(PushTypeEnum pushTypeEnum, Long userId, String title, Integer businessType) {
         byUser(pushTypeEnum, userId, title, businessType, StringPool.EMPTY);
+        //将消息推送到极光
+        JPushUtils.jPushSendMsg(title, Collections.singletonList(userId));
     }
 
     /**
@@ -86,6 +92,9 @@ public class WebSocketPush {
         for (SysUser sysUser : sysUserList) {
             byUser(pushTypeEnum, sysUser.getUserId(), title, businessType, businessData);
         }
+        //将消息推送到极光
+        List<Long> userIds = sysUserList.stream().map(SysUser::getUserId).collect(Collectors.toList());
+        JPushUtils.jPushSendMsg(title,userIds);
         DynamicDataSourceContextHolder.poll();
     }
 

+ 1 - 0
pom.xml

@@ -207,6 +207,7 @@
         <module>hx-tenant</module>
         <module>hx-area</module>
         <module>hx-kd100</module>
+        <module>hx-jpush</module>
     </modules>
     <packaging>pom</packaging>