首页 > 其他分享 >消息推送第三方平台(个推)接入工具类

消息推送第三方平台(个推)接入工具类

时间:2024-09-09 20:13:19浏览次数:11  
标签:body String title 接入 token static import 推送 第三方

个推官方文档:https://docs.getui.com/getui/server/rest_v2/push/

首先申请个推官方账号,然后注册App获取AppID、AppKey、AppSecret、MasterSecret

接入教程

1、编写配置文件   

  修改.yml文件

getui: 
  AppID: OokKLlwRjU7tJMccVVra72
  AppKey: f8C6lK7OGu1115ckOfVxD8
  MasterSecret: aTxslPiUJy9kzzZaPONL26
  AppSecret: sAoJ9sQ66S13P0PG3c1y02

  编写映射文件

GeTuiConfig
 package com.common.disposition;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "getui")
public class GeTuiConfig {

    private String appId;
    private String appKey;
    private String masterSecret;
    private String appSecret;
}

2、编写工具类

GeTuiUtil
 package com.common.util;

import com.common.disposition.GeTuiConfig;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.concurrent.TimeUnit;

@Component
public class GeTuiUtil {

    private static String APP_ID;
    private static String APP_KEY;
    private static String MASTER_SECRET;

    // 在构造函数中初始化配置
    @Autowired
    public GeTuiUtil(GeTuiConfig config) {
        APP_ID = config.getAppId();
        APP_KEY = config.getAppKey();
        MASTER_SECRET = config.getMasterSecret();
    }

    private static final String REDIS_TOKEN_KEY = "GETUI_ACCESS_TOKEN";

    private static RedisTemplate<String, String> redisTemplate;
    private static ObjectMapper objectMapper = new ObjectMapper();  // 用于解析 JSON 响应

    // 初始化 RedisTemplate,手动注入
    @Autowired
    public void setRedisTemplate(@Qualifier("stringRedisTemplate") RedisTemplate<String, String> redisTemplate) {
        GeTuiUtil.redisTemplate = redisTemplate;
    }

    // 获取 access_token,优先从 Redis 中获取
    public static String getAccessToken() throws Exception {
        String accessToken = redisTemplate.opsForValue().get(REDIS_TOKEN_KEY);
        if (accessToken == null || accessToken.isEmpty()) {
            System.out.println("在Redis中找不到访问令牌,正在从GeTui获取...");
            accessToken = getAccessTokenFromGeTui();
        } else {
            System.out.println("从Redis检索到的访问令牌。");
        }
        return accessToken;
    }

    // 从个推获取 access_token
    private static String getAccessTokenFromGeTui() throws Exception {
        long timestamp = System.currentTimeMillis();
        String sign = sha256(APP_KEY + timestamp + MASTER_SECRET);

        String jsonPayload = String.format(
                "{\"sign\": \"%s\", \"timestamp\": \"%s\", \"appkey\": \"%s\"}",
                sign, timestamp, APP_KEY
        );

        String response = postRequest("https://restapi.getui.com/v2/" + APP_ID + "/auth", jsonPayload);
        String accessToken = parseAccessTokenFromResponse(response);
        long expireTime = parseExpireTimeFromResponse(response); // 获取过期时间

        // 将 token 存入 Redis,并设置过期时间
        redisTemplate.opsForValue().set(REDIS_TOKEN_KEY, accessToken, expireTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);

        return accessToken;
    }

    // 发送cid单推消息 (toSingle)
    public static void sendPushMessageCid(String clientId, String title, String body) throws Exception {
        String token = getAccessToken();

        String jsonPayload = String.format(
                "{\"request_id\": \"unique_request_id\", \"audience\": {\"cid\": [\"%s\"]}, \"push_message\": {\"notification\": {\"title\": \"%s\", \"body\": \"%s\", \"click_type\": \"none\"}}, \"push_channel\": {\"ios\": {\"type\": \"notify\"}, \"android\": {\"ups\": {\"notification\": {\"title\": \"%s\", \"body\": \"%s\", \"click_type\": \"none\"}}}}}",
                clientId, title, body, title, body
        );

        postRequest("https://restapi.getui.com/v2/" + APP_ID + "/push/single/cid", jsonPayload, token);
    }

    // 发送别名(alias)单推消息 (toSingle)
    public static void sendPushMessageAlias(String clientId, String title, String body) throws Exception {
        String token = getAccessToken();

        String jsonPayload = String.format(
                "{\"request_id\": \"unique_request_id\", \"audience\": {\"alias\": [\"%s\"]}, \"push_message\": {\"notification\": {\"title\": \"%s\", \"body\": \"%s\", \"click_type\": \"none\"}}, \"push_channel\": {\"ios\": {\"type\": \"notify\"}, \"android\": {\"ups\": {\"notification\": {\"title\": \"%s\", \"body\": \"%s\", \"click_type\": \"none\"}}}}}",
                clientId, title, body, title, body
        );

        postRequest("https://restapi.getui.com/v2/" + APP_ID + "/push/single/cid", jsonPayload, token);
    }

    // 发送cid批量推消息 (toList)
    public static void sendBatchPushMessageCid(String[] clientIds, String title, String body) throws Exception {
        String token = getAccessToken();

        StringBuilder cidArray = new StringBuilder();
        for (String clientId : clientIds) {
            cidArray.append("\"").append(clientId).append("\",");
        }
        // Remove trailing comma
        String cidList = cidArray.substring(0, cidArray.length() - 1);

        String jsonPayload = String.format(
                "{\"audience\": {\"cid\": [%s]}, \"push_message\": {\"notification\": {\"title\": \"%s\", \"body\": \"%s\", \"click_type\": \"none\"}}, \"push_channel\": {\"ios\": {\"type\": \"notify\"}, \"android\": {\"ups\": {\"notification\": {\"title\": \"%s\", \"body\": \"%s\", \"click_type\": \"none\"}}}}}",
                cidList, title, body, title, body
        );

        postRequest("https://restapi.getui.com/v2/" + APP_ID + "/push/list/cid", jsonPayload, token);
    }

    // 发送别名(alias)批量推消息 (toList)
    public static void sendBatchPushMessageAlias(String[] clientIds, String title, String body) throws Exception {
        String token = getAccessToken();

        StringBuilder cidArray = new StringBuilder();
        for (String clientId : clientIds) {
            cidArray.append("\"").append(clientId).append("\",");
        }
        // Remove trailing comma
        String cidList = cidArray.substring(0, cidArray.length() - 1);

        String jsonPayload = String.format(
                "{\"audience\": {\"alias\": [%s]}, \"push_message\": {\"notification\": {\"title\": \"%s\", \"body\": \"%s\", \"click_type\": \"none\"}}, \"push_channel\": {\"ios\": {\"type\": \"notify\"}, \"android\": {\"ups\": {\"notification\": {\"title\": \"%s\", \"body\": \"%s\", \"click_type\": \"none\"}}}}}",
                cidList, title, body, title, body
        );

        postRequest("https://restapi.getui.com/v2/" + APP_ID + "/push/list/cid", jsonPayload, token);
    }

    // 发送群推消息 (toApp)
    public static void sendPushToApp(String title, String body) throws Exception {
        String token = getAccessToken();

        String jsonPayload = String.format(
                "{\"request_id\": \"unique_request_id\", \"audience\": \"all\", \"push_message\": {\"notification\": {\"title\": \"%s\", \"body\": \"%s\", \"click_type\": \"none\"}}, \"push_channel\": {\"ios\": {\"type\": \"notify\"}, \"android\": {\"ups\": {\"notification\": {\"title\": \"%s\", \"body\": \"%s\", \"click_type\": \"none\"}}}}}",
                title, body, title, body
        );

        postRequest("https://restapi.getui.com/v2/" + APP_ID + "/push/all", jsonPayload, token);
    }

    // 通用的 POST 请求,带 Token
    private static String postRequest(String requestUrl, String payload, String token) throws Exception {
        URL url = new URL(requestUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("token", token);
        conn.setDoOutput(true);

        try (OutputStream os = conn.getOutputStream()) {
            byte[] input = payload.getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
        }

        int responseCode = conn.getResponseCode();
        if (responseCode == 200) {
            System.out.println("推送消息发送成功。");
        } else {
            System.out.println("发送推送消息失败。响应代码: " + responseCode);
        }

        return new String(conn.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
    }

    // 重载的 POST 请求,不带 Token
    private static String postRequest(String requestUrl, String payload) throws Exception {
        URL url = new URL(requestUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setDoOutput(true);

        try (OutputStream os = conn.getOutputStream()) {
            byte[] input = payload.getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
        }

        int responseCode = conn.getResponseCode();
        if (responseCode == 200) {
            System.out.println("Request successful.");
        } else {
            System.out.println("发送请求失败。响应代码: " + responseCode);
        }

        return new String(conn.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
    }

    // 解析获取到的 access_token
    private static String parseAccessTokenFromResponse(String response) throws Exception {
        JsonNode rootNode = objectMapper.readTree(response);
        return rootNode.path("data").path("token").asText();
    }

    // 解析过期时间
    private static long parseExpireTimeFromResponse(String response) throws Exception {
        JsonNode rootNode = objectMapper.readTree(response);
        return rootNode.path("data").path("expire_time").asLong();
    }

    // 生成 SHA-256 签名
    private static String sha256(String input) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
        StringBuilder hexString = new StringBuilder();
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1){
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
}

3、调用示例

单推送消息
     // 单推送消息
    @PostMapping("sendBatchPushMessage")
    @Operation(summary = "单推送消息")
    public ApiResult<String> sendBatchPushMessage(@RequestParam("clientId") String clientId,
                                                  @RequestParam("title") String title,
                                                  @RequestParam("body") String body) {
        try {
            GeTuiUtil.sendPushMessageCid(clientId, title, body);
            return ApiResult.success("推送成功");
        } catch (Exception e) {
            // 打印详细的错误信息以便调试
            e.printStackTrace();
            return ApiResult.fail("推送失败,内部错误:" + e.getMessage());
        }
    }

 

标签:body,String,title,接入,token,static,import,推送,第三方
From: https://www.cnblogs.com/xd99/p/18405250

相关文章

  • FastGPT 正式接入 Flux,准备好迎接 AI 绘画的狂风了么?
    Flux大家最近都听说了吧?它是一款新推出的AI绘画模型,拳打StableDiffusion3,脚踢Midjourney,整个AI绘画界都沸腾了。Flux的主创团队来自由StableDiffusion原班人马打造的黑森林实验室(BlackForestLabs),2024年8月1日才正式宣布成立。Flux在图像质量、文本提示理解、细......
  • Prometheus的拉取模式与zabbix推送模式有何区别?各有什么优缺点?
    Prometheus的拉取模式与Zabbix的推送模式在监控数据收集和处理方式上存在显著区别。以下是它们的主要区别及各自的优缺点:1.数据收集模式Prometheus拉取模式:Prometheus定期从被监控的目标(如Exporter、应用程序等)主动拉取数据。每个目标都需要暴露一个HTTP接口,Prome......
  • 淘宝返利微信机器人的消息处理与推送技术
    淘宝返利微信机器人的消息处理与推送技术大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!今天我们来讨论如何实现淘宝返利微信机器人的消息处理与推送技术。微信机器人可以有效地提升用户体验,通过自动化的消息处理和推送,帮助用户获取最新的返利......
  • yum安装nginx没有某一模块,该如何添加第三方模块
    本文将以添加--with-stream模块为例,演示如何去添加新的模块进去。需求:生产有个接口是通过socket通信。nginx1.9开始支持tcp层的转发,通过stream实现的,而socket也是基于tcp通信。实现方法:Centos7.5下yum直接安装的nginx,添加新模块支持tcp转发;重新编译Nginx并添加--with-stream参数。......
  • Vue.js入门系列(二十三):集成第三方动画库、总结过渡与动画、配置代理
    个人名片......
  • C#开发移动应用系列(4.调用系统应用,以及第三方应用(调用与被调用))
    写完这篇..本系列基本也就结束了.看完这些,基本做个Webapp应该是毫无问题的了..其实略微有点伤感,Xamarin确实是好东西..奈何,生不逢时..等完善了.开源了..社区化了..APP应用(指的是安装包类客户端)已经逐渐没落了..算了,话不多说.开始正文确定一下本篇的学习目标:1.学......
  • 如何使用 Git 和 SSH 将项目推送到 GitHub
    目录1.前提条件2.安装Git3.生成SSH密钥生成SSH密钥的步骤:添加SSH密钥到SSHAgent:4.将SSH密钥添加到GitHub5.配置Git用户信息6.将本地代码推送到GitHub1.初始化本地Git仓库2.添加远程仓库3.添加文件并提交4.推送到GitHub7.常见问题及......
  • SpringBoot集成WebSocket实现后端向前端推送数据
    SpringBoot集成WebSocket实现后端向前端推送数据这里最好了解一定websocket参考地址:https://developer.mozilla.org/zh-CN/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications在此之前可以了解一下【轮询(Polling)、长轮询(LongPolling)、服务器发送事件(Server......
  • 扫码获取微信公众号用户的openid,向某个用户推送消息
    1.生成二维码:生成二维码比较简单的方法是直接使用phpqrcode程序包(可在网上下载得到)。若想获得ThinkPHP支持,需将程序包放在ThinkPHP/Extend/Vendor目录下,让后在程序中引用,代码如下:vendor("phpqrcode.phpqrcode");//要生成二维码的数据$text="扫码后要跳转的页面的url";  ......
  • git 推送本地文件
    引言参考文章:Git操作全流程介绍Git的工作流程如下所示:1.创建仓库1.1新建gitee仓库在gitee中创建一个仓库HelloWorld,如下所示:1.2初始化本地仓库假设本机有一个MyCode文件夹,进入该文件夹目录下,在该处打开gitbash。,输入命令将该文件夹初始化为git仓库:len......