package com.ruoyi.framework.web.service; import cn.jiguang.common.ClientConfig; import cn.jiguang.common.ServiceHelper; import cn.jiguang.common.connection.NettyHttpClient; import cn.jiguang.common.resp.APIConnectionException; import cn.jiguang.common.resp.APIRequestException; import cn.jiguang.common.resp.ResponseWrapper; import cn.jpush.api.JPushClient; import cn.jpush.api.push.PushResult; import cn.jpush.api.push.model.Message; import cn.jpush.api.push.model.Platform; import cn.jpush.api.push.model.PushPayload; import cn.jpush.api.push.model.audience.Audience; import cn.jpush.api.push.model.notification.AndroidNotification; import cn.jpush.api.push.model.notification.IosNotification; import cn.jpush.api.push.model.notification.Notification; import cn.jpush.api.report.ReceivedsResult; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.framework.config.JpushConfig; import com.ruoyi.project.tr.JpushMsg.domain.JpushMsg; import com.ruoyi.project.tr.JpushMsg.service.IJpushMsgService; import io.netty.handler.codec.http.HttpMethod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.net.URI; import java.net.URISyntaxException; import java.util.*; /** * 极光推送服务 */ @Service("jpushService") public class JpushService { private static final Logger LOG = LoggerFactory.getLogger(JpushService.class); @Resource JpushConfig jpushConfig;// 注入配置信息 @Autowired private IJpushMsgService jpushMsgService; /** * 广播 (所有平台,所有设备, 不支持附加信息) * * @return */ public PushResult pushAll(String title, String content, Integer style, String bigText, Map extrasMap) { ClientConfig clientConfig = ClientConfig.getInstance(); clientConfig.setTimeToLive(Long.valueOf(jpushConfig.getLiveTime())); // 使用NativeHttpClient网络客户端,连接网络的方式,不提供回调函数 JPushClient jpushClient = new JPushClient(jpushConfig.getMasterSecret(), jpushConfig.getAppkey(), null, clientConfig); if (extrasMap == null || extrasMap.isEmpty()) { extrasMap = new HashMap(); } // 设置推送方式 PushPayload payload = PushPayload.newBuilder().setPlatform(Platform.android_ios()) // 别名为空,全员推送;别名不为空,按别名推送 .setAudience(Audience.all()) .setNotification(Notification.newBuilder().setAlert(content) .addPlatformNotification( AndroidNotification.newBuilder().setTitle(title).setStyle(style).setBigText(bigText).addExtras(extrasMap).build()) .addPlatformNotification(IosNotification.newBuilder().incrBadge(1).addExtras(extrasMap).build()) .build()) .build(); PushResult result = null; try { result = jpushClient.sendPush(payload); //数据库增加极光推送消息 JpushMsg jpushMsg = new JpushMsg(); jpushMsg.setTitle(title); jpushMsg.setContent(content); jpushMsg.setMethodType(extrasMap.get("methodType")); jpushMsg.setCreateTime(DateUtils.getNowDate()); jpushMsgService.insertJpushMsg(jpushMsg); LOG.info("极光推送结果 - " + result); } catch (APIConnectionException e) { LOG.error("极光推送连接错误,请稍后重试 ", e); LOG.error("Sendno: " + payload.getSendno()); } catch (APIRequestException e) { LOG.error("极光服务器响应出错,请修复! ", e); LOG.info("HTTP Status: " + e.getStatus()); LOG.info("Error Code: " + e.getErrorCode()); LOG.info("Error Message: " + e.getErrorMessage()); LOG.info("Msg ID: " + e.getMsgId()); LOG.error("Sendno: " + payload.getSendno()); } return result; } /** * 大文本通知栏样式 * * @param title App通知栏标题 * @param content App通知栏内容(为了单行显示全,尽量保持在22个汉字以下) * @param style 通知栏样式类型(默认为 0,还有 1,2,3 可选,用来指定选择哪种通知栏样式,其他值无效。有三种可选分别为 bigText=1,Inbox=2,bigPicture=3。) * @param bigText 大文本通知栏样式(当 style = 1 时可用,内容会被通知栏以大文本的形式展示出来。支持 api 16 以上的 rom。) * @param extrasMap 额外推送信息(不会显示在通知栏,传递数据用) * @param alias 别名数组,设定哪些用户手机能接收信息(为空则所有用户都推送) */ public PushResult sendPushByAndroidBigText(String title, String content, Integer style, String bigText, Map extrasMap, String... alias) { ClientConfig clientConfig = ClientConfig.getInstance(); clientConfig.setTimeToLive(Long.valueOf(jpushConfig.getLiveTime())); // 使用NativeHttpClient网络客户端,连接网络的方式,不提供回调函数 JPushClient jpushClient = new JPushClient(jpushConfig.getMasterSecret(), jpushConfig.getAppkey(), null, clientConfig); if (extrasMap == null || extrasMap.isEmpty()) { extrasMap = new HashMap(); } // 批量删除数组中空元素 String[] newAlias = removeArrayEmptyElement(alias); // 设置推送方式 PushPayload payload = PushPayload.newBuilder().setPlatform(Platform.android_ios()) // 别名为空,全员推送;别名不为空,按别名推送 .setAudience((null == newAlias || newAlias.length == 0) ? Audience.all() : Audience.alias(alias)) .setNotification(Notification.newBuilder().setAlert(content) .addPlatformNotification( AndroidNotification.newBuilder().setTitle(title).setStyle(style).setBigText(bigText).addExtras(extrasMap).build()) .addPlatformNotification(IosNotification.newBuilder().incrBadge(1).addExtras(extrasMap).build()) .build()) .build(); PushResult result = null; try { result = jpushClient.sendPush(payload); //数据库增加极光推送消息 JpushMsg jpushMsg = new JpushMsg(); jpushMsg.setTitle(title); jpushMsg.setContent(content); jpushMsg.setMethodType(extrasMap.get("methodType")); jpushMsg.setUserId((null == newAlias || newAlias.length == 0) ? "" : alias[0]); jpushMsg.setCreateTime(DateUtils.getNowDate()); jpushMsgService.insertJpushMsg(jpushMsg); LOG.info("极光推送结果 - " + result); } catch (APIConnectionException e) { LOG.error("极光推送连接错误,请稍后重试 ", e); LOG.error("Sendno: " + payload.getSendno()); } catch (APIRequestException e) { LOG.error("极光服务器响应出错,请修复! ", e); LOG.info("HTTP Status: " + e.getStatus()); LOG.info("Error Code: " + e.getErrorCode()); LOG.info("Error Message: " + e.getErrorMessage()); LOG.info("Msg ID: " + e.getMsgId()); LOG.info("以下存在不能识别别名: " + alias); LOG.error("Sendno: " + payload.getSendno()); } return result; } /** * 发送自定义推送,由APP端拦截信息后再决定是否创建通知(目前APP用此种方式) * * @param title App通知栏标题 * @param content App通知栏内容(为了单行显示全,尽量保持在22个汉字以下) * @param extrasMap 额外推送信息(不会显示在通知栏,传递数据用) * @param alias 别名数组,设定哪些用户手机能接收信息(为空则所有用户都推送) * @return PushResult */ public PushResult sendCustomPush(String title, String content, Map extrasMap, String... alias) { ClientConfig clientConfig = ClientConfig.getInstance(); clientConfig.setTimeToLive(Long.valueOf(jpushConfig.getLiveTime())); // 使用NativeHttpClient网络客户端,连接网络的方式,不提供回调函数 JPushClient jpushClient = new JPushClient(jpushConfig.getMasterSecret(), jpushConfig.getAppkey(), null, clientConfig); // 设置为消息推送方式为仅推送消息,不创建通知栏提醒 PushPayload payload = buildCustomPushPayload(title, content, extrasMap, alias); PushResult result = null; try { result = jpushClient.sendPush(payload); LOG.info("极光推送结果 - " + result + ",接收推送的别名列表:" + String.join(",", alias)); } catch (APIConnectionException e) { LOG.error("极光推送连接错误,请稍后重试 ", e); LOG.error("Sendno: " + payload.getSendno()); } catch (APIRequestException e) { LOG.error("极光服务器响应出错,请修复! ", e); LOG.info("HTTP Status: " + e.getStatus()); LOG.info("Error Code: " + e.getErrorCode()); LOG.info("Error Message: " + e.getErrorMessage()); LOG.info("Msg ID: " + e.getMsgId()); LOG.info("以下存在不能识别的别名: " + String.join(",", alias)); LOG.error("Sendno: " + payload.getSendno()); } return result; } /** * 原生方式推送 * * @param title App通知栏标题 * @param content App通知栏内容(为了单行显示全,尽量保持在22个汉字以下) * @param extrasMap 额外推送信息(不会显示在通知栏,传递数据用) * @param alias 别名数组,设定哪些用户手机能接收信息(为空则所有用户都推送) */ public PushResult sendPush(String title, String content, Map extrasMap, String... alias) { ClientConfig clientConfig = ClientConfig.getInstance(); clientConfig.setTimeToLive(Long.valueOf(jpushConfig.getLiveTime())); // 使用NativeHttpClient网络客户端,连接网络的方式,不提供回调函数 JPushClient jpushClient = new JPushClient(jpushConfig.getMasterSecret(), jpushConfig.getAppkey(), null, clientConfig); // 设置推送方式 PushPayload payload = buildPushPayload(title, content, extrasMap, alias); PushResult result = null; try { result = jpushClient.sendPush(payload); LOG.info("极光推送结果 - " + result); } catch (APIConnectionException e) { LOG.error("极光推送连接错误,请稍后重试 ", e); LOG.error("Sendno: " + payload.getSendno()); } catch (APIRequestException e) { LOG.error("极光服务器响应出错,请修复! ", e); LOG.info("HTTP Status: " + e.getStatus()); LOG.info("Error Code: " + e.getErrorCode()); LOG.info("Error Message: " + e.getErrorMessage()); LOG.info("Msg ID: " + e.getMsgId()); LOG.info("以下存在不能识别别名: " + alias); LOG.error("Sendno: " + payload.getSendno()); } return result; } /** * 异步请求推送方式 * * @param title 通知栏标题 * @param content 通知栏内容(为了单行显示全,尽量保持在22个汉字以下) * @param extrasMap 额外推送信息(不会显示在通知栏,传递数据用) * @param alias 需接收的用户别名数组(为空则所有用户都推送) * @see 使用NettyHttpClient,异步接口发送请求,通过回调函数可以获取推送成功与否情况 */ public void sendPushWithCallback(String title, String content, Map extrasMap, String... alias) { ClientConfig clientConfig = ClientConfig.getInstance(); clientConfig.setTimeToLive(Long.valueOf(jpushConfig.getLiveTime())); String host = (String) clientConfig.get(ClientConfig.PUSH_HOST_NAME); NettyHttpClient client = new NettyHttpClient( ServiceHelper.getBasicAuthorization(jpushConfig.getAppkey(), jpushConfig.getMasterSecret()), null, clientConfig); try { URI uri = new URI(host + clientConfig.get(ClientConfig.PUSH_PATH)); PushPayload payload = buildPushPayload(title, content, extrasMap, alias); client.sendRequest(HttpMethod.POST, payload.toString(), uri, new NettyHttpClient.BaseCallback() { @Override public void onSucceed(ResponseWrapper responseWrapper) { if (200 == responseWrapper.responseCode) { LOG.info("极光推送成功"); } else { LOG.info("极光推送失败,返回结果: " + responseWrapper.responseContent); } } }); } catch (URISyntaxException e) { e.printStackTrace(); } finally { // 需要手动关闭Netty请求进程,否则会一直保留 client.close(); } } /** * 构建Android和IOS的推送通知对象 * * @return PushPayload */ private PushPayload buildPushPayload(String title, String content, Map extrasMap, String... alias) { if (extrasMap == null || extrasMap.isEmpty()) { extrasMap = new HashMap(); } // 批量删除数组中空元素 String[] newAlias = removeArrayEmptyElement(alias); return PushPayload.newBuilder().setPlatform(Platform.android_ios()) // 别名为空,全员推送;别名不为空,按别名推送 .setAudience((null == newAlias || newAlias.length == 0) ? Audience.all() : Audience.alias(alias)) .setNotification(Notification.newBuilder().setAlert(content) .addPlatformNotification( AndroidNotification.newBuilder().setTitle(title).addExtras(extrasMap).build()) .addPlatformNotification(IosNotification.newBuilder().incrBadge(1).addExtras(extrasMap).build()) .build()) .build(); } /** * 构建Android和IOS的自定义消息的推送通知对象 * * @return PushPayload */ private PushPayload buildCustomPushPayload(String title, String content, Map extrasMap, String... alias) { // 批量删除数组中空元素 String[] newAlias = removeArrayEmptyElement(alias); return PushPayload.newBuilder().setPlatform(Platform.android_ios()) .setAudience((null == newAlias || newAlias.length == 0) ? Audience.all() : Audience.alias(alias)) .setMessage(Message.newBuilder().setTitle(title).setMsgContent(content).addExtras(extrasMap).build()) .build(); } /** * 查询记录推送成功条数(暂未使用) * * @param msg_id 在推送返回结果PushResult中保存 */ public void countPush(String msg_id) { JPushClient jpushClient = new JPushClient(jpushConfig.getMasterSecret(), jpushConfig.getAppkey()); try { ReceivedsResult result = jpushClient.getReportReceiveds(msg_id); ReceivedsResult.Received received = result.received_list.get(0); LOG.debug("Android接受信息:" + received.android_received + "\n IOS端接受信息:" + received.ios_apns_sent); LOG.debug("极光推送返回结果 - " + result); } catch (APIConnectionException e) { LOG.error("极光推送连接错误,请稍后重试", e); } catch (APIRequestException e) { LOG.error("检查错误,并修复推送请求", e); LOG.info("HTTP Status: " + e.getStatus()); LOG.info("Error Code: " + e.getErrorCode()); LOG.info("Error Message: " + e.getErrorMessage()); } } /** * 删除别名中的空元素(需删除如:null,""," ") * * @param strArray * @return String[] */ private String[] removeArrayEmptyElement(String... strArray) { if (null == strArray || strArray.length == 0) { return null; } List tempList = Arrays.asList(strArray); List strList = new ArrayList(); Iterator iterator = tempList.iterator(); while (iterator.hasNext()) { String str = iterator.next(); // 消除空格后再做比较 if (null != str && !"".equals(str.trim())) { strList.add(str); } } // 若仅输入"",则会将数组长度置为0 String[] newStrArray = strList.toArray(new String[strList.size()]); return newStrArray; } }