极光推送REST API与Java后台对接

简介: 极光推送REST API与Java后台对接

极光推送官网的web推送页面
image.png

因为是对接它的api,所以我参照这这个样式实现了一个,效果如下:

  • 定时任务推送界面,可定制。实现了推送一次和每日定时推送,如果再扩展的话有每周、每月的功能,只是没有这个业务需求。
    image.png
  • 普通的单次消息推送
    image.png

极光的官方文档地址:https://docs.jiguang.cn/jpush/server/push/rest_api_v3_push
image.png

如果实在没看懂的话,也可以到官方的代码仓库把demo下下来看,有很多案例。地址:https://github.com/jpush/jpush-api-java-client.git。首先我们需要创建自己的应用程序,会给出appKeymasterSecret
image.png

下面贴一下我这边的关键代码,业务代码就省略了,具体可以根据自己的业务来实现

首先是引入jar包,由于我的是springcloud项目,所以其他的引用就省略了。
pom.xml

<dependency>
    <groupId>cn.jpush.api</groupId>
    <artifactId>jpush-client</artifactId>
    <version>3.6.6</version>
</dependency>

如果报错的话,可能还需要引入以下依赖

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.6.Final</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.3</version>
</dependency>

通用的常量 Constants,用来判断是否设置为生产环境

/**
 * 生产环境标识
 */
public static final String PROD_ENV = "prod";

极光推送配置的读取,使用的是nacos作为配置中心,当然也可以写到本地
JPushConfig

@Data
@Component
@ConfigurationProperties(prefix = "jpush.push")
public class JPushConfig {
   
   
     /**
     * AppKey
     */
    private String appKey;

    /**
     * 密钥
     */
    private String masterSecret;

    /**
     * 离线消息保留时长(秒)
     */
    private Integer liveTime;

    /**
     * 配置安卓平台消息点击之后跳转的页面
     */
    private String intent;

    /**
     * 回调url
     */
    private String callback;
}

极光推送的常量
JPushConstants

/**
 * JPush常量
 * @author: 
 * @date: 2023/1/4
 */
public class JPushConstants {
   
   
     /** 任务类型 */
    /** 普通类型 */
    public static final String TASK_TYPE_COMMON = "common";
    /** 定时任务 */
    public static final String TASK_TYPE_SCHEDULE = "schedule";

    /** 指定推送平台 */
    public static final String PLATFORM_ALL = "all";
    public static final String PLATFORM_ANDROID = "android";
    public static final String PLATFORM_IOS = "ios";
    public static final String PLATFORM_WINPHONE = "winphone";
    public static final String PLATFORM_ANDROID_IOS = "android_ios";
    public static final String PLATFORM_ANDROID_WINPHONE = "android_winphone";
    public static final String PLATFORM_IOS_WINPHONE = "ios_winphone";

    /** 指定推送目标 */
    /** 广播推送(全部设备) */
    public static final String AUDIENCE_ALL = "all";
    /** 标签推送,多个标签之间是 OR 的关系,即取并集。一次推送最多 20 个。 */
    public static final String AUDIENCE_TAG_AND = "tag_and";
    /** 标签推送,多个标签之间是 AND 关系,即取交集。一次推送最多 20 个。 */
    public static final String AUDIENCE_TAG_NOT = "tag_not";
    /** 标签推送,多个标签之间,先取多标签的并集,再对该结果取补集。一次推送最多 20 个。 */
    public static final String AUDIENCE_TAG = "tag";
    /** 别名推送,多个别名之间是 OR 关系,即取并集。一次推送最多 1000 个。 */
    public static final String AUDIENCE_ALIAS = "alias";
    /** 注册ID推送,多个注册ID之间是 OR 关系,即取并集。一次推送最多 1000 个。 */
    public static final String AUDIENCE_REGISTRATION_ID = "registration_id";
    /** 用户分群ID推送,定义为数组,但目前限制一次只能推送一个。 */
    public static final String AUDIENCE_SEGMENT = "segment";
    /** A/B Test ID推送,定义为数组,但目前限制是一次只能推送一个。 */
    public static final String AUDIENCE_ABTEST = "abTest";

    /** 指定通知对象 */
    public static final String NOTIFICATION_ANDROID = "android";
    public static final String NOTIFICATION_IOS = "ios";
    public static final String NOTIFICATION_ANDROID_IOS = "android_ios";
    public static final String NOTIFICATION_WINPHONE = "winphone";

    /** 下发策略 */
    public static final String CHANNEL_FIRST_OSPUSH = "first_ospush";
    public static final String CHANNEL_OSPUSH = "ospush";
    public static final String CHANNEL_JPUSH = "jpush";
    public static final String CHANNEL_SECONDARY_PUSH = "secondary_push";

    /** 默认的留存时间 */
    public static final Integer DEFAULT_LIVE_TIME = 86400;
}

从前端传入的附加字段Bean
Extra

@Data
public class Extra {
   
   
    String label;
    String value;
}

从前端传入的推送消息Bean,下面出现的SysMessage结构与其类似,故省略。
PushBean

@Data
public class PushBean {
   
   
     /**
     * 主键
     */
    private Long id;
    /**
     * 关联的活动id
     */
    private Long activityId;
    /**
     * 必填, 通知内容, 内容可以为空字符串,则表示不展示到通知栏
     */
    @NotBlank
    private String content;
    /**
     * 可选, 附加信息, 供业务使用
     */
    private List<Extra> extras;
    /**
     * android专用 可选, 通知标题,如果指定了,则通知里原来展示 App名称的地方,将展示成这个字段
     */
    private String title;
    /**
     * 指定推送平台
     */
    private String platform;
    /**
     * Android点击通知打开
     */
    private String intent;
    /**
     * 通知下发策略
     */
    private String channel;
    /**
     * 指定推送范围
     */
    private String audience;
    /**
     * 指定推送目标
     */
    private List<String> audienceValues;

    /**
     * 任务类型: common(普通类型)、schedule(定时任务)
     */
    private String taskType;

    /**
     * 定时推送
     */
    private String time;

    /**
     * 请求参数
     */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private Map<String, String> params;
}

极光推送的关键代码,这里包含了推送业务和数据库的存储、读取(代码省略)。
JPushService

@Service
@Slf4j
@RefreshScope
public class JPushService {
   
   
    @Value("${spring.profiles.active}")
    private String profile;

    /**
     * 一次推送最大数量 (极光限制1000)
     */
    private static final int MAX_SIZE = 1000;

    @Autowired
    private JPushConfig config;
    @Autowired
    private MessageMapper messageMapper;


    /**
     * 向所有用户推送push消息
     *
     * @param pushBean
     * @return boolean
     */
    public boolean sendPush(PushBean pushBean) {
   
   
        Message message = genSysMessage(pushBean);
        // 默认全部用户
        pushBean.setAudience(JPushConstants.AUDIENCE_ALL);
        PushPayload payload = buildPushPayload(pushBean, null, message.getCode());
        message.setSendNo(payload.getSendno() + "");
        message.setPayload(payload.toString());
        boolean result;
        if (JPushConstants.TASK_TYPE_COMMON.equals(pushBean.getTaskType())) {
   
   
            result = sendPush(payload, message);
        } else {
   
   
            //定时推送
            String time = pushBean.getTime();
            Map<String, String> params = pushBean.getParams();
            result = createSchedule(params, time, payload, message);
        }
        if (pushBean.getId() != null) {
   
   
            messageMapper.updateMessage(message);
        } else {
   
   
            messageMapper.insertMessage(message);
        }
        return result;
    }

    /**
     * 分批推送push消息
     *
     * @param pushBean
     * @param audienceValues
     * @return boolean
     */
    public boolean sendPush(PushBean pushBean, List<String> audienceValues) {
   
   
        Message message = genSysMessage(pushBean);
        boolean result = false;
        //由于jpush接口最大限制1000,需要分批推送
        List<List<String>> partition = Lists.partition(audienceValues, MAX_SIZE);
        // 推送push消息
        for (List<String> values : partition) {
   
   
            // 构建推送对象
            PushPayload payload = buildPushPayload(pushBean, values, message.getCode());
            message.setPayload(payload.toString());
            if (StringUtils.isBlank(message.getSendNo())) {
   
   
                message.setSendNo(payload.getSendno() + "");
            }

            if (JPushConstants.TASK_TYPE_COMMON.equals(pushBean.getTaskType())) {
   
   
                result = sendPush(payload, message);
            } else {
   
   
                //定时推送
                String time = pushBean.getTime();
                Map<String, String> params = pushBean.getParams();
                result = createSchedule(params, time, payload, message);
            }

            if (result) {
   
   
                if (pushBean.getId() != null) {
   
   
                    //如果是修改,则把历史数据全部删除,然后再重新插入
                    Message sysMessage = messageMapper.getMessageById(pushBean.getId());
                    messageMapper.deleteMessageTargetByCode(sysMessage.getCode());
                }
                // 批量保存指定用户的ID
                List<MessageTarget> list = new ArrayList<>(MAX_SIZE);
                values.forEach(item -> {
   
   
                    MessageTarget target = new MessageTarget();
                    target.setCode(message.getCode());
                    //未读状态
                    target.setStatus(0);
                    target.setTarget(item);
                    list.add(target);
                });
                messageMapper.batchAddMessageTarget(list);
            }
        }
        if (pushBean.getId() != null) {
   
   
            messageMapper.updateMessage(message);
        } else {
   
   
            messageMapper.insertMessage(message);
        }

        return result;
    }

    /**
     * 定时推送push消息
     *
     * @param time    定时
     * @param payload 推送对象
     * @return int
     */
    private boolean createSchedule(Map<String, String> params, String time, PushPayload payload, Message message) {
   
   
        log.info("开始定时推送push消息:{}", payload);
        JPushClient jpushClient = buildJPushClient();
        try {
   
   
            ScheduleResult result;
            if (params == null || params.isEmpty()) {
   
   
                // 定时推送
                String name = "schedule_push_task";
                result = jpushClient.createSingleSchedule(name, time, payload, config.getMasterSecret(), config.getAppKey());
            } else {
   
   
                // 每日定时推送
                String name = "daily_schedule_push_task";
                // 开始日期
                String start = params.get("start");
                // 结束日期
                String end = params.get("end");
                message.setStart(start);
                message.setEnd(end);
                result = jpushClient.createDailySchedule(name, start, end, time, payload, config.getMasterSecret(), config.getAppKey());
            }
            log.info("定时推送请求完成: {}", result);
            message.setTime(time);
            message.setScheduleId(result.getSchedule_id());
            message.setEnabled(result.isResultOK());
            message.setStatus(result.isResultOK() ? 0 : 1);
            return result.isResultOK();
        } catch (APIConnectionException e) {
   
   
            log.error("Connection error. Should retry later. ", e);
            throw new ServiceException(e.getMessage());
        } catch (APIRequestException e) {
   
   
            log.error("Error response from JPush server. ", e);
            log.info("Error Code: " + e.getErrorCode());
            throw new ServiceException(e.getErrorMessage());
        }
    }

    /**
     * 推送push消息
     *
     * @param payload 推送对象
     * @return int
     */
    private boolean sendPush(PushPayload payload, Message message) {
   
   
        log.info("开始推送push消息:{}", payload);
        JPushClient jpushClient = buildJPushClient();
        try {
   
   
            PushResult result = jpushClient.sendPush(payload);
            log.info("推送请求完成: {}", result);
            message.setMsgId(result.msg_id + "");
            message.setStatus(result.isResultOK() ? 0 : 1);
            return result.isResultOK();
        } catch (APIConnectionException e) {
   
   
            log.error("Connection error. Should retry later. ", e);
            throw new ServiceException(e.getMessage());
        } catch (APIRequestException e) {
   
   
            log.error("Error response from JPush server. {}", e.getErrorMessage());
            log.info("Error Code: " + e.getStatus());
            throw new ServiceException(e.getErrorMessage());
        }
    }

    /**
     * 生成JpushClient
     *
     * @return
     */
    private JPushClient buildJPushClient() {
   
   
        ClientConfig clientConfig = ClientConfig.getInstance();
        // ClientConfig.getInstance().setPushHostName("https://api.jpush.cn/v3/push");
        // ClientConfig.getInstance().setPushHostName("https://bjapi.push.jiguang.cn");
        clientConfig.setMaxRetryTimes(5);
        // 10 seconds
        clientConfig.setConnectionTimeout(10 * 1000);
        // JPush server supports SSLv3, TLSv1, TLSv1.1, TLSv1.2
        clientConfig.setSSLVersion("TLSv1.2");

        String authCode = ServiceHelper.getBasicAuthorization(config.getAppKey(), config.getMasterSecret());

        NativeHttpClient httpClient = new NativeHttpClient(authCode, null, clientConfig);

        JPushClient jpushClient = new JPushClient(config.getMasterSecret(), config.getAppKey(), null, clientConfig);
        jpushClient.getPushClient().setHttpClient(httpClient);
        return jpushClient;
    }

    /**
     * 构建推送对象
     *
     * @param pushBean 参数
     * @return PushPayload
     */
    private PushPayload buildPushPayload(PushBean pushBean, List<String> audienceValues, String code) {
   
   
        List<Extra> extrasArr = pushBean.getExtras();
        Map<String, String> extras = CollectionUtils.isEmpty(extrasArr) ? null : extrasArr.stream().collect(Collectors.toMap(Extra::getLabel, Extra::getValue));

        PushPayload.Builder builder = PushPayload.newBuilder()
                // Platform指定推送平台
                .setPlatform(buildPlatform(pushBean.getPlatform()))
                // Audience指定推送目标
                .setAudience(buildAudience(pushBean.getAudience(), audienceValues))
                // Notification推送通知内容体
                .setNotification(buildNotification(pushBean, extras))
                // Message推送通知内容体
                .setMessage(buildMessage(pushBean.getContent(), extras))
                // 应用内提醒,当用户前台运行 APP 时,会通过应用内消息的方式展示通知栏消息内容
                // 不能和message公用,会报错,注释
                //.setInappMessage(InappMessage.newBuilder().setInappMessage(true).build())
                // Options推送参数,设置离线消息保留时长
                .setOptions(buildOptions(pushBean.getChannel()));
        // 生产环境下构建回调路径信息
        /*if (StringUtils.isNotBlank(config.getCallback()) && Constants.PROD_ENV.equals(profile)) {
            builder.addCustom("callback", buildCallback(config.getCallback(), code));
        }*/

        return builder.build();
    }

    /**
     * 构建下发策略等
     *
     * @param channel 下发通道,目前只开通华为、小米、vivo、oppo
     * @return Options
     */
    private Options buildOptions(String channel) {
   
   
        Options.Builder builder = Options.newBuilder()
                //API 调用标识
                //.setSendno()
                //该字段仅对 iOS 的 Notification 有效,  true:表示推送生产环境。false:表示推送开发环境, 默认
                .setApnsProduction(Constants.PROD_ENV.equals(profile));
                //.setApnsProduction(false);

        //推送当前用户不在线时,为该用户保留多长时间的离线消息,以便其上线时再次推送。默认 86400 (1 天)
        Integer liveTime = config.getLiveTime();
        if (liveTime != null && liveTime > JPushConstants.DEFAULT_LIVE_TIME) {
   
   
            builder.setTimeToLive(liveTime);
        }

        //配置下发策略,当不强制走极光的时候生效
        if (StringUtils.isNotBlank(channel) && !JPushConstants.CHANNEL_JPUSH.equalsIgnoreCase(channel.trim())) {
   
   
            Map<String, JsonObject> thirdMap = new HashMap<>(7);

            //小米
            JsonObject xiaomi = new JsonObject();
            xiaomi.addProperty("distribution", channel);
            if (JPushConstants.CHANNEL_OSPUSH.equalsIgnoreCase(channel)) {
   
   
                //是否跳过配额判断及扣除,目前仅对小米和 oppo 有效,默认为 false。
                //true-表示跳过判断及跳过扣除极光侧的配额,false-表示不跳过
                //当仅通过厂商通道下发时设置为true
                xiaomi.addProperty("skip_quota", true);
            }
            thirdMap.put("xiaomi", xiaomi);

            //华为
            JsonObject huawei = new JsonObject();
            huawei.addProperty("distribution", channel);
            thirdMap.put("huawei", huawei);

            //荣耀
            JsonObject honor = new JsonObject();
            honor.addProperty("distribution", channel);
            thirdMap.put("honor", honor);

            //魅族
            JsonObject meizu = new JsonObject();
            meizu.addProperty("distribution", channel);
            thirdMap.put("meizu", meizu);

            //FCM
            JsonObject fcm = new JsonObject();
            fcm.addProperty("distribution", channel);
            thirdMap.put("fcm", fcm);

            //OPPO
            JsonObject oppo = new JsonObject();
            oppo.addProperty("distribution", channel);
            if (JPushConstants.CHANNEL_OSPUSH.equalsIgnoreCase(channel)) {
   
   
                //是否跳过配额判断及扣除,目前仅对小米和 oppo 有效,默认为 false。
                //true-表示跳过判断及扣除极光侧的配额,false-表示不跳过
                //当仅通过厂商通道下发时设置为true
                oppo.addProperty("skip_quota", true);
            }
            thirdMap.put("oppo", oppo);

            //VIVO
            JsonObject vivo = new JsonObject();
            vivo.addProperty("distribution", channel);
            //通知栏消息类型,0-表示正式推送,1-表示测试推送
            vivo.addProperty("push_mode", Constants.PROD_ENV.equals(profile) ? 0 : 1);
            thirdMap.put("vivo", vivo);

            builder.setThirdPartyChannelV2(thirdMap);
        }
        return builder.build();
    }

    /**
     * 构建通知内容体
     *
     * @param pushBean 通知
     * @param extras   扩展字段
     * @return Notification
     */
    private Notification buildNotification(PushBean pushBean, Map<String, String> extras) {
   
   
        return Notification.newBuilder()
                // alert通知,推送到Platform指定的多个平台
                .setAlert(pushBean.getContent())
                // 构建Android平台上的通知结构
                .addPlatformNotification(androidNotificationBuilder(pushBean, extras))
                // 构建iOS平台上的通知结构
                .addPlatformNotification(iosNotificationBuilder(pushBean, extras)).build();
    }

    /**
     * 构建通知内容体
     *
     * @param message 通知内容
     * @param extras  扩展字段
     * @return Notification
     */
    private cn.jpush.api.push.model.Message buildMessage(String message, Map<String, String> extras) {
   
   
        if (extras == null || extras.isEmpty()) {
   
   
            return cn.jpush.api.push.model.Message.newBuilder().setMsgContent(message).build();
        }
        return cn.jpush.api.push.model.Message.newBuilder().setMsgContent(message).addExtras(extras).build();
    }

    /**
     * 处理附加信息
     *
     * @param extras
     * @return
     */
    private IosNotification iosNotificationBuilder(PushBean pushBean, Map<String, String> extras) {
   
   
        if (extras == null || extras.isEmpty()) {
   
   
            return IosNotification.newBuilder()
                    .setAlert(pushBean.getContent())
                    .incrBadge(1)
                    .build();
        }
        return IosNotification.newBuilder()
                .setAlert(pushBean.getContent())
                //通知扩展,说明是支持 iOS 10 的 UNNotificationServiceExtension
                //.setMutableContent(true)
                .incrBadge(1)
                // 这个 key(my-attachment)值,需要与客户端的值对应,客户端工程拿到 key 值对应的 url 图标加载出来
                // .addExtra("my-attachment","https://raw.githubusercontent.com/Tikon/imgRepo/master/ic_launcher.png")
                .addExtras(extras)
                .build();
    }

    /**
     * 处理附加信息
     *
     * @param extras
     * @return
     */
    private AndroidNotification androidNotificationBuilder(PushBean pushBean, Map<String, String> extras) {
   
   
        String title = pushBean.getTitle();
        String msg = pushBean.getContent();
        String intent = pushBean.getIntent();
        String channel = pushBean.getChannel();
        //文本条目通知栏样式
        JsonObject inbox = new JsonObject();
        inbox.addProperty("key", "value");

        AndroidNotification.Builder builder = AndroidNotification.newBuilder()
                //通知内容
                .setAlert(msg)
                //通知提醒方式, 可选范围为 -1~7 ,默认-1, 即0111二进制,左数第二位代表 light,第三位代表 vibrate,第四位代表 sound。 0:不生效,1:生效
                .setAlertType(-1)
                //通知标题
                .setTitle(title)
                //通知栏展示优先级,默认为 0,范围为 -2~2
                .setPriority(0)
                //通知栏样式类型,默认为 0, 1-bigText; 2-Inbox; 3-bigPicture
                //.setStyle(3)
                //大文本通知栏样式,style=1时生效
                //.setBigText(msg)
                //文本条目通知栏样式,style=2时生效,json 的每个 key 对应的 value 会被当作文本条目逐条展示
                //.setInbox(inbox)
                //大图片通知栏样式,style=3时生效
                //.setBigPicPath("")
                //通知栏大图标
                //.setLargeIcon("")
                //通知栏小图标
                //.setSmallIconUri("")
                //定时展示开始时间(yyyy-MM-dd HH:mm:ss),默认立即展示
                //.setShowBeginTime("")
                //通知栏样式 ID
                .setBuilderId(2);

        //有扩展字段
        if (extras != null && !extras.isEmpty()) {
   
   
            //扩展字段
            builder.addExtras(extras);
        }

        // 默认的跳转地址,需要配置到配置文件
        intent = StringUtils.isBlank(intent) ? config.getIntent() : intent;
        //要避免配置文件没有配置的情况
        if (StringUtils.isNotBlank(intent)) {
   
   
            //指定跳转页面,三种类型:
            // 1. 跳转到目标页: intent:#Intent;action=action 路径;component= 包名 /Activity 全名;end      (OPPO 和 FCM 通道必须传 "action 路径", 其他厂商必须传 "Activity 全名", 否则将出现对应厂商无法跳转问题)
            // 2. 跳转到deeplink地址: scheme://test?key1=val1&key2=val2
            // 3. 应用首页: intent:#Intent;action=android.intent.action.MAIN;end  (固定为此地址)
            JsonObject intentObj = new JsonObject();
            intentObj.addProperty("url", intent);
            builder.setIntent(intentObj);
        }

        return builder.build();
    }


    /**
     * 构建推送平台
     *
     * @param platform 指定推送平台
     * @return Platform
     */
    private Platform buildPlatform(String platform) {
   
   
        switch (platform) {
   
   
            case JPushConstants.PLATFORM_ANDROID:
                return Platform.android();
            case JPushConstants.PLATFORM_IOS:
                return Platform.ios();
            case JPushConstants.PLATFORM_WINPHONE:
                return Platform.winphone();
            case JPushConstants.PLATFORM_ANDROID_IOS:
                return Platform.android_ios();
            case JPushConstants.PLATFORM_ANDROID_WINPHONE:
                return Platform.android_winphone();
            case JPushConstants.PLATFORM_IOS_WINPHONE:
                return Platform.ios_winphone();
            default:
                return Platform.all();
        }
    }

    /**
     * 构建推送目标
     *
     * @param audience       指定推送范围
     * @param audienceValues 指定推送目标
     * @return Audience
     */
    private Audience buildAudience(String audience, List<String> audienceValues) {
   
   
        switch (audience) {
   
   
            case JPushConstants.AUDIENCE_TAG:
                return Audience.tag(audienceValues);
            case JPushConstants.AUDIENCE_TAG_AND:
                return Audience.tag_and(audienceValues);
            case JPushConstants.AUDIENCE_TAG_NOT:
                return Audience.tag_not(audienceValues);
            case JPushConstants.AUDIENCE_ALIAS:
                return Audience.alias(audienceValues);
            case JPushConstants.AUDIENCE_REGISTRATION_ID:
                return Audience.registrationId(audienceValues);
            case JPushConstants.AUDIENCE_SEGMENT:
                return Audience.segment(audienceValues);
            case JPushConstants.AUDIENCE_ABTEST:
                return Audience.abTest(audienceValues);
            default:
                return Audience.all();
        }
    }

    /**
     * 构建回调信息
     *
     * @return
     */
    private JsonObject buildCallback(String url, String code) {
   
   
        JsonObject callback = new JsonObject();
        //回调url
        callback.addProperty("url", url);
        JsonObject params = new JsonObject();
        //唯一标识
        params.addProperty("code", code);
        callback.add("params", params);
        // 可选,1: 送达回执, 2: 点击回执, 3: 送达和点击回执, 8: 推送成功回执, 9: 成功和送达回执, 10: 成功和点击回执, 11: 成功和送达以及点击回执
        callback.addProperty("type", 3);
        return callback;
    }

    /**
     * 装配SysMessage
     *
     * @param pushBean 前端传的参数
     * @return SysMessage
     */
    private Message genSysMessage(PushBean pushBean) {
   
   
        Message message = new Message();
        if (pushBean.getId() != null) {
   
   
            message = messageMapper.getMessageById(pushBean.getId());
        } else {
   
   
            message.setCode(UUID.fastUUID().toString(true));
        }
        message.setActivityId(pushBean.getActivityId());
        message.setAudience(pushBean.getAudience());
        message.setContent(pushBean.getContent());
        message.setTitle(pushBean.getTitle());
        message.setPlatform(pushBean.getPlatform());
        message.setType("notification");
        message.setTaskType(pushBean.getTaskType());

        List<Extra> extras = pushBean.getExtras();
        if (!CollectionUtils.isEmpty(extras)) {
   
   
            Map<String, String> map = extras.stream().collect(Collectors.toMap(Extra::getLabel, Extra::getValue));
            message.setExtras(JSONObject.toJSONString(map));
        }
        message.setCreateBy(SecurityUtils.getUsername());
        return message;
    }

    /**
     * 撤回推送消息
     *
     * @param msgId
     * @return
     * @throws APIConnectionException
     * @throws APIRequestException
     */
    public boolean delMessage(String msgId) {
   
   
        try {
   
   
            JPushClient jpushClient = buildJPushClient();
            DefaultResult result = jpushClient.deletePush(msgId);
            log.info("撤回推送消息请求完成: {}", result);
            return result.isResultOK();
        } catch (APIConnectionException e) {
   
   
            log.error("Connection error. Should retry later. ", e);
            throw new ServiceException(e.getMessage());
        } catch (APIRequestException e) {
   
   
            log.error("Error response from JPush server. {}", e.getErrorMessage());
            log.info("Error Code: " + e.getStatus());
            throw new ServiceException(e.getErrorMessage());
        }
    }

    /**
     * 删除定时任务
     *
     * @param scheduleId
     * @return
     * @throws APIConnectionException
     * @throws APIRequestException
     */
    public boolean delSchedule(String scheduleId) {
   
   
        try {
   
   
            JPushClient jpushClient = buildJPushClient();
            jpushClient.deleteSchedule(scheduleId);
            return Boolean.TRUE;
        } catch (APIConnectionException e) {
   
   
            log.error("Connection error. Should retry later. ", e);
            throw new ServiceException(e.getMessage());
        } catch (APIRequestException e) {
   
   
            log.error("Error response from JPush server. {}", e.getErrorMessage());
            log.info("Error Code: " + e.getStatus());
            throw new ServiceException(e.getErrorMessage());
        }
    }

    /**
     * 禁用定时任务
     *
     * @param scheduleId
     * @return
     * @throws APIConnectionException
     * @throws APIRequestException
     */
    public boolean disableSchedule(String scheduleId) {
   
   
        try {
   
   
            JPushClient jpushClient = buildJPushClient();
            ScheduleResult result = jpushClient.disableSchedule(scheduleId);
            log.info("禁用定时任务请求完成: {}", result);
            boolean ok = result.isResultOK();
            return ok;
        } catch (APIConnectionException e) {
   
   
            log.error("Connection error. Should retry later. ", e);
            throw new ServiceException(e.getMessage());
        } catch (APIRequestException e) {
   
   
            log.error("Error response from JPush server. {}", e.getErrorMessage());
            log.info("Error Code: " + e.getStatus());
            throw new ServiceException(e.getErrorMessage());
        }
    }

    /**
     * 启用定时任务
     *
     * @param scheduleId
     * @return
     * @throws APIConnectionException
     * @throws APIRequestException
     */
    public boolean enableSchedule(String scheduleId) {
   
   
        try {
   
   
            JPushClient jpushClient = buildJPushClient();
            ScheduleResult result = jpushClient.enableSchedule(scheduleId);
            log.info("启用定时任务请求完成: {}", result);
            boolean ok = result.isResultOK();
            return ok;
        } catch (APIConnectionException e) {
   
   
            log.error("Connection error. Should retry later. ", e);
            throw new ServiceException(e.getMessage());
        } catch (APIRequestException e) {
   
   
            log.error("Error response from JPush server. {}", e.getErrorMessage());
            log.info("Error Code: " + e.getStatus());
            throw new ServiceException(e.getErrorMessage());
        }
    }

    /**
     * 获取定时任务的的msgIds
     *
     * @param scheduleId
     * @return
     * @throws APIConnectionException
     * @throws APIRequestException
     */
    public ScheduleMsgIdsResult getScheduleMsgIds(String scheduleId) {
   
   
        try {
   
   
            JPushClient jpushClient = buildJPushClient();
            ScheduleMsgIdsResult result = jpushClient.getScheduleMsgIds(scheduleId);
            log.info("获取定时任务的的msgIds请求完成: {}", result);
            return result;
        } catch (APIConnectionException e) {
   
   
            log.error("Connection error. Should retry later. ", e);
            throw new ServiceException(e.getMessage());
        } catch (APIRequestException e) {
   
   
            log.error("Error response from JPush server. {}", e.getErrorMessage());
            log.info("Error Code: " + e.getStatus());
            throw new ServiceException(e.getErrorMessage());
        }
    }

    /**
     * 根据msgId获取推送统计
     *
     * @param msgId
     * @return
     * @throws APIConnectionException
     * @throws APIRequestException
     */
    public ReceivedsResult getReport(String msgId) {
   
   
        try {
   
   
            JPushClient jpushClient = buildJPushClient();
            ReceivedsResult result = jpushClient.getReportReceiveds(msgId);
            //测试账号没有下面这个api的权限,会报错
            //MessagesResult messages = jpushClient.getReportMessages(msgId);
            return result;
        } catch (APIConnectionException e) {
   
   
            log.error("Connection error. Should retry later. ", e);
            throw new ServiceException(e.getMessage());
        } catch (APIRequestException e) {
   
   
            log.error("Error response from JPush server. {}", e.getErrorMessage());
            log.info("Error Code: " + e.getStatus());
            throw new ServiceException(e.getErrorMessage());
        }
    }

    /**
     * 注册别名
     * @param rid 极光regId
     * @param alias 用户id
     * @return
     */
    public Boolean registerAlias(String rid, String alias) {
   
   
        try {
   
   
            JPushClient jpushClient = buildJPushClient();
            //先解绑别名
            DefaultResult delRes = jpushClient.deleteAlias(alias, null);
            log.info("[{}]删除别名请求结果: {}", alias, delRes.isResultOK());
            //再重新绑定
            DefaultResult result = jpushClient.updateDeviceTagAlias(rid, alias, null, null);
            boolean ok = result.isResultOK();
            log.info("[{}] 注册别名请求结果: {}", alias, ok);
            return ok;
        } catch (APIConnectionException e) {
   
   
            log.error("Connection error. Should retry later. ", e);
            throw new ServiceException(e.getMessage());
        } catch (APIRequestException e) {
   
   
            log.error("Error response from JPush server. {}", e.getErrorMessage());
            log.info("Error Code: " + e.getStatus());
            throw new ServiceException(e.getErrorMessage());
        }
    }

    /**
     * 重新推送
     * @param message
     */
    public Boolean repush(Message message) {
   
   
        String payload = message.getPayload();
        log.info("重新推送push消息:{}", payload);
        JPushClient jpushClient = buildJPushClient();
        try {
   
   
            PushResult result = jpushClient.sendPush(payload);
            log.info("重新推送请求完成: {}", result);
            message.setMsgId(result.msg_id + "");
            messageMapper.updateMessage(message);
            return result.isResultOK();
        } catch (APIConnectionException e) {
   
   
            log.error("Connection error. Should retry later. ", e);
            throw new ServiceException(e.getMessage());
        } catch (APIRequestException e) {
   
   
            log.error("Error response from JPush server. {}", e.getErrorMessage());
            log.info("Error Code: " + e.getStatus());
            throw new ServiceException(e.getErrorMessage());
        }
    }
}

本篇就介绍到这里了。

相关文章
|
3天前
|
Oracle 安全 Java
JAVA用Mail发送API的方法步骤教程
使用Java和Mail发送API实现自动化邮件发送,提高效率。步骤包括:1. 安装JDK并配置JAVA_HOME,2. 添加JavaMail库(可通过Maven或官网下载)。配置邮件发送涉及邮件服务器地址、端口和认证信息。创建邮件会话、邮件消息对象,然后使用Transport发送。示例代码展示完整流程。注意处理认证失败、连接问题和邮件发送失败等常见问题。
|
3天前
|
编解码 前端开发 Java
Java网络API之Netty深度解析
Java网络API之Netty深度解析
11 0
|
3天前
|
Java API
Java 8新特性之Lambda表达式和Stream API
【5月更文挑战第31天】本文将详细介绍Java 8中的两个重要特性:Lambda表达式和Stream API。通过对比传统编程方式,我们将探讨这两个特性如何简化代码、提高可读性和性能。文章还将通过实例演示如何使用Lambda表达式和Stream API进行集合操作、过滤和转换等任务。
|
4天前
|
Java API 数据处理
Java 8中的Stream API简介及其在数据处理中的应用
【5月更文挑战第30天】 本文旨在介绍Java 8中引入的Stream API,它是一种用于处理集合的新方法。与传统的循环和迭代器相比,Stream API提供了一种更简洁、高效的方式来处理数据。文章将详细介绍Stream API的基本概念、常用操作以及在实际项目中的应用场景。
|
4天前
|
Java API
Java 8新特性之Stream API详解
【5月更文挑战第30天】本文将详细介绍Java 8中的一个重要新特性——Stream API。Stream API是Java 8中引入的一种新的数据处理方式,它允许我们以声明式的方式处理数据,使得代码更加简洁、易读。文章将从Stream的基本概念、创建方式、常用操作以及实战案例等方面进行详细讲解,帮助读者深入理解并掌握Stream API的使用。
|
5天前
|
Java API
Java 8新特性之Lambda表达式与Stream API
【5月更文挑战第29天】本文将介绍Java 8中的两个重要特性——Lambda表达式和Stream API。Lambda表达式简化了函数式编程,使得代码更加简洁易读;而Stream API则为集合操作提供了更加高效且易于理解的方法。通过本文的学习,你将掌握这两个特性的基本用法,并了解如何在实际项目中应用它们。
|
5天前
|
安全 Java API
Java 8中的Stream API:简介与实用指南深入理解Java并发编程:线程安全与锁优化
【5月更文挑战第29天】本文旨在介绍Java 8中引入的Stream API,这是一种用于处理集合的新方法。我们将探讨Stream API的基本概念,以及如何使用它来简化集合操作,提高代码的可读性和效率。 【5月更文挑战第29天】 在Java并发编程中,线程安全和性能优化是两个核心议题。本文将深入探讨如何通过不同的锁机制和同步策略来保证多线程环境下的数据一致性,同时避免常见的并发问题如死锁和竞态条件。文章还将介绍现代Java虚拟机(JVM)针对锁的优化技术,包括锁粗化、锁消除以及轻量级锁等概念,并指导开发者如何合理选择和使用这些技术以提升应用的性能。
|
JSON NoSQL Java
Day 13: Dropwizard —— 非常棒的Java REST服务器栈
我们发现了比较有趣的系列文章《30天学习30种新技术》,准备翻译,一天一篇更新,年终礼包。下面是第十三天的内容。 我已经是一个使用了8年Java的软件开发人员了,我写过的大多数应用程序是用的Spring框架或Java EE。最近,我花了一些时间学习用Python进行web开发,其中印象非常深刻的是 Flask 框架——一个微型架构,这使得它很容易写REST后端。所以今天我决定找一个Java的Python Flask框架替代品,做一些研究后,我发现 Dropwizard 框架可以帮助达到Flask框架同样的生产力。在这篇博客中,我们将学习如何使用Dropwizard构建一个基于REST的Jav
552 0
Day 13: Dropwizard —— 非常棒的Java REST服务器栈
|
3天前
|
Java 开发者 UED
掌握Java多线程编程:从基础到高级
【5月更文挑战第31天】本文深入探讨了Java多线程编程的核心概念,包括线程的创建、生命周期、同步机制以及高级并发工具。通过实际示例和代码片段,读者将学会如何有效地管理和协调线程,以编写高效且稳定的并发应用程序。
|
3天前
|
安全 Java 调度
Java语言多线程编程技术深度解析
Java语言多线程编程技术深度解析
127 1