Kaynağa Gözat

初代apppush

车车 4 ay önce
ebeveyn
işleme
21e5d583ee

+ 31 - 1
yudao-module-system/pom.xml

@@ -131,7 +131,37 @@
             <artifactId>arcsoft-sdk-face</artifactId>
             <version>3.0.0.0</version>
         </dependency>
-
+        <!-- app消息推动 -->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>alibabacloud-push20160801</artifactId>
+            <version>2.0.4</version>
+        </dependency>
+        <!-- Tea核心依赖(必须,push SDK的基础) -->
+        <!--<dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>tea-openapi</artifactId>
+            <version>0.2.7</version>
+        </dependency>-->
+        <!-- 阿里云核心SDK -->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.6.3</version>
+        </dependency>
+
+        <!-- 阿里云凭证依赖 -->
+        <!--<dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>credentials-java</artifactId>
+            <version>0.3.12</version>
+        </dependency>-->
+        <!-- 阿里云Push SDK(关键,必须是2.x版本) -->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-push</artifactId>
+            <version>3.13.0</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 25 - 0
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/appnotify/AppNotifySendService.java

@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.system.service.appnotify;
+
+import java.util.Map;
+
+/**
+ * app消息发送 Service 接口
+ *
+ * @author xrcoder
+ */
+public interface AppNotifySendService {
+
+    /**
+     * 发送单条站内信给管理后台的用户
+     *
+     * 在 mobile 为空时,使用 userId 加载对应管理员的手机号
+     *
+     * @param userId 用户编号
+     * @param templateCode 短信模板编号
+     * @param templateParams 短信模板参数
+     * @return 发送日志编号
+     */
+    Long sendSingleAppNotifyToAdmin(Long userId,
+                                 String templateCode, Map<String, Object> templateParams);
+
+}

+ 233 - 0
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/appnotify/AppNotifySendServiceImpl.java

@@ -0,0 +1,233 @@
+package cn.iocoder.yudao.module.system.service.appnotify;
+
+import com.aliyun.auth.credentials.utils.ParameterHelper;
+import com.aliyuncs.DefaultAcsClient;
+import com.aliyuncs.IAcsClient;
+import com.aliyuncs.exceptions.ClientException;
+import com.aliyuncs.exceptions.ServerException;
+import com.aliyuncs.profile.DefaultProfile;
+import com.aliyuncs.push.model.v20160801.PushRequest;
+import com.aliyuncs.push.model.v20160801.PushResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.Date;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * app消息发送 Service 实现类(修正Push类找不到的版本)
+ *
+ * @author xrcoder
+ */
+@Service
+@Validated
+@Slf4j
+public class AppNotifySendServiceImpl implements AppNotifySendService {
+
+    // ========== 配置项(放到application.yml中) ==========
+    /** 阿里云Push的AppKey */
+    @Value("${aliyun.push.app-key:}")
+    private Long appKey;
+
+    /** 阿里云AccessKey ID */
+    @Value("${aliyun.access-key-id:}")
+    private String accessKeyId;
+
+    /** 阿里云AccessKey Secret */
+    @Value("${aliyun.access-key-secret:}")
+    private String accessKeySecret;
+
+    /** 阿里云Push的地域ID(默认杭州) */
+    @Value("${aliyun.push.region-id:cn-hangzhou}")
+    private String regionId;
+
+    /**
+     * 根据用户ID发送单条App通知(核心业务方法)
+     */
+    @Override
+    public Long sendSingleAppNotifyToAdmin(Long userId, String templateCode, Map<String, Object> templateParams) {
+        // 1. 根据userId查询对应的设备ID(替换为你的实际查询逻辑)
+        String deviceId = getDeviceIdByUserId(userId);
+        if (deviceId.isEmpty()) {
+            log.warn("发送单用户App通知失败:用户{}未绑定设备ID", userId);
+            return null;
+        }
+
+        // 2. 解析模板标题和内容(替换为你的实际模板逻辑)
+        String pushTitle = parseTemplateTitle(templateCode, templateParams);
+        String pushBody = parseTemplateBody(templateCode, templateParams);
+
+        try {
+            // 3. 创建阿里云客户端(修正后的方式,不会报找不到Push类)
+            IAcsClient client = createAcsClient();
+
+            // 4. 构建单设备推送请求
+            PushRequest pushRequest = buildSingleDevicePushRequest(deviceId, pushTitle, pushBody);
+
+            // 5. 发送推送
+            PushResponse response = client.getAcsResponse(pushRequest);
+
+            // 6. 解析返回结果
+            String requestId = response.getRequestId();
+            String messageId = response.getMessageId();
+            log.info("单用户App推送成功:userId={}, requestId={}, messageId={}", userId, requestId, messageId);
+
+            // 返回消息ID(转为Long,若messageId是字符串可自行调整)
+            return Long.parseLong(messageId);
+        } catch (ServerException e) {
+            log.error("单用户App推送失败(服务端错误):userId={}, templateCode={}", userId, templateCode, e);
+            return null;
+        } catch (ClientException e) {
+            log.error("单用户App推送失败(客户端错误):userId={}, templateCode={}", userId, templateCode, e);
+            return null;
+        }
+    }
+
+    /**
+     * 通用推送方法(推送给全部用户)
+     */
+    public Boolean pushNotify() {
+        if (appKey == null || appKey == 0) {
+            log.error("App推送失败:未配置阿里云Push的appKey");
+            return Boolean.FALSE;
+        }
+
+        try {
+            // 创建客户端
+            IAcsClient client = createAcsClient();
+            // 构建全量推送请求
+            PushRequest pushRequest = buildAllDevicePushRequest("系统通知", "这是一条全量推送的测试通知");
+            // 发送推送
+            PushResponse response = client.getAcsResponse(pushRequest);
+
+            log.info("全量App推送成功:requestId={}, messageId={}", response.getRequestId(), response.getMessageId());
+            return Boolean.TRUE;
+        } catch (Exception e) {
+            log.error("全量App推送失败", e);
+            return Boolean.FALSE;
+        }
+    }
+
+    // ========== 私有工具方法 ==========
+
+    /**
+     * 创建阿里云ACS客户端(修正后的方式,解决Push类找不到的问题)
+     */
+    private IAcsClient createAcsClient() {
+        // 校验配置
+        if (accessKeyId.isEmpty() || accessKeySecret.isEmpty()) {
+            throw new IllegalArgumentException("阿里云AccessKey配置为空,请检查配置项");
+        }
+
+        // 初始化阿里云配置
+        DefaultProfile profile = DefaultProfile.getProfile(
+                regionId,       // 地域ID
+                accessKeyId,    // AccessKey ID
+                accessKeySecret // AccessKey Secret
+        );
+
+        // 创建客户端(这是阿里云官方推荐的稳定方式)
+        return new DefaultAcsClient(profile);
+    }
+
+    /**
+     * 构建单设备推送请求
+     */
+    private PushRequest buildSingleDevicePushRequest(String deviceId, String title, String body) {
+        PushRequest request = new PushRequest();
+        // 基础配置
+        request.setAppKey(appKey);
+        request.setTarget("DEVICE"); // 按设备推送
+        request.setTargetValue(deviceId); // 设备ID
+        request.setDeviceType("ALL"); // 支持Android+iOS
+        request.setPushType("NOTICE"); // 通知类型
+        request.setTitle(title);
+        request.setBody(body);
+
+        // iOS配置
+        request.setIOSBadge(1);
+        request.setIOSApnsEnv("PRODUCT");
+        request.setIOSRemind(true);
+        request.setIOSExtParameters("{\"type\":\"single\"}");
+
+        // Android配置
+        request.setAndroidOpenType("ACTIVITY");
+        request.setAndroidNotifyType("SOUND");
+        request.setAndroidExtParameters("{\"type\":\"single\"}");
+
+        // 推送时间(立即推送)
+        request.setPushTime(ParameterHelper.getISO8601Time(new Date()));
+        // 离线存储(12小时过期)
+        request.setStoreOffline(true);
+        request.setExpireTime(ParameterHelper.getISO8601Time(new Date(System.currentTimeMillis() + 12 * 3600 * 1000)));
+
+        return request;
+    }
+
+    /**
+     * 构建全量推送请求
+     */
+    private PushRequest buildAllDevicePushRequest(String title, String body) {
+        PushRequest request = new PushRequest();
+        // 基础配置
+        request.setAppKey(appKey);
+        request.setTarget("ALL");
+        request.setTargetValue("all");
+        request.setDeviceType("ALL");
+        request.setPushType("NOTICE");
+        request.setTitle(title);
+        request.setBody(body);
+
+        // iOS配置
+        request.setIOSBadge(5);
+        request.setIOSMusic("default");
+        request.setIOSApnsEnv("PRODUCT");
+        request.setIOSRemind(true);
+        request.setIOSRemindBody(body);
+        request.setIOSExtParameters("{\"k1\":\"ios\",\"k2\":\"v2\"}");
+
+        // Android配置
+        request.setAndroidOpenType("ACTIVITY");
+        request.setAndroidNotifyType("SOUND");
+        request.setAndroidOpenUrl("http://www.alibaba.com");
+        request.setAndroidMusic("alicloud_notification_sound");
+        request.setAndroidActivity("com.alibaba.push.PushActivity");
+        request.setAndroidPopupActivity("com.alibaba.push.PopupActivity");
+        request.setAndroidPopupTitle("系统通知");
+        request.setAndroidPopupBody(body);
+        request.setAndroidExtParameters("{\"k1\":\"android\",\"k2\":\"v2\"}");
+
+        // 推送时间(1小时后)
+        request.setPushTime(ParameterHelper.getISO8601Time(new Date(System.currentTimeMillis() + 3600 * 1000)));
+        // 离线存储
+        request.setStoreOffline(true);
+        request.setExpireTime(ParameterHelper.getISO8601Time(new Date(System.currentTimeMillis() + 12 * 3600 * 1000)));
+
+        return request;
+    }
+
+    /**
+     * 根据用户ID获取设备ID(替换为你的实际逻辑)
+     */
+    private String getDeviceIdByUserId(Long userId) {
+        // 示例:模拟返回设备ID
+        return "DEVICE" + UUID.randomUUID().toString().replace("-", "");
+    }
+
+    /**
+     * 解析模板标题(替换为你的实际逻辑)
+     */
+    private String parseTemplateTitle(String templateCode, Map<String, Object> params) {
+        return "【系统通知】" + params.get("titleSuffix");
+    }
+
+    /**
+     * 解析模板内容(替换为你的实际逻辑)
+     */
+    private String parseTemplateBody(String templateCode, Map<String, Object> params) {
+        return "您有一条新的通知:" + params.get("content");
+    }
+}