极光推送-服务端开发
参数:
https://docs.jiguang.cn
https://community.jiguang.cn
REST API 基本约束
API 被设计为符合HTTP,REST规范.例如:查询请求使用GET方法;提交请求使用POST请求.
API 资源列表
描述 | 资源 | URL |
---|---|---|
推送消息API | POST /v3/push | https://api.jpush.cn |
操作Tag,Alias | GET /v3/devices | https://device.jpush.cn |
获取统计数据 | GET /v3/received | https://report.jpush.cn |
鉴权方式
-
极光RSET API采用HTTP基本认证的验证方式.
-
基本做法为: HTTP Header(头)里加Authorization:
Authorization: Basic $(base64_auth_string)
- Header名称是”Authorization",值是Base64加密后的”username:password”.
在JPushAPI的场景里,username是appKey,密码是masterSecret.
- 配置文件配置类
@Getter
@Component
@ConfigurationProperties("jpush")
public class JPushProperties {
@ApiModelProperty("应用程序:app_key&&master_secret")
private Map<String, Map<String, String>> applications = new HashMap<>(4);
private String appKey;
private String masterSecret;
public void initProperties(JpushAppEnum appEnum) {
Map<String, String> appMap = this.applications.get(appEnum.getCode());
this.appKey = appMap.get("app_key");
this.masterSecret = appMap.get("master_secret");
}
}
- 构建不同的HTTP请求
@Component
public class JpushUtils {
private JpushUtils {}
@Autowired
private JPushProperties properties;
private IHttpClient httpClient;
/**
* @param appEnum 应用(不同的应用有不同的appKey和masterSecret)
*/
private synchronized IHttpClient initInstance(JpushAppEnum appEnum) {
switch(appEnum) {
case xxx:
if (null != httpClient) {
properties.initProperties(appEnum);
String basicAuthorization = ServiceHelper.getBasicAuthorization(properties.getAppKey(), properties.getMasterSecret());
// 使用ApacheHttpClient
httpClient = new ApacheHttpClient(basicAuthorization, null, config);
}
break;
case xxx:
if (null != httpClient) {
properties.initProperties(appEnum);
String basicAuthorization = ServiceHelper.getBasicAuthorization(properties.getAppKey(), properties.getMasterSecret());
// 使用NativeHttpClient(极光默认的HttpClient:JPushClient)
httpClient = new NativeHttpClient(basicAuthorization, null, config);
}
break;
case xxx:
if (null != httpClient) {
properties.initProperties(appEnum);
String basicAuthorization = ServiceHelper.getBasicAuthorization(properties.getAppKey(), properties.getMasterSecret());
// 使用NettyHttpClient
httpClient = new NettyHttpClient(basicAuthorization, null, config);
}
break;
default:
if (null != httpClient) {
properties.initProperties(appEnum);
String basicAuthorization = ServiceHelper.getBasicAuthorization(properties.getAppKey(), properties.getMasterSecret());
// 使用Http2Client
httpClient = new Http2Client(basicAuthorization, null, config);
}
break
}
}
}
PUSH API
完全基于HTTPS,不再提供HTTP访问;
使用Http Basic Authentication的方式做访问授权.这样整个API请求可以使用常见的HTTP工具来完成;
推送内容完全使用JSON格式;
支持多tag的与或操作;可单独发送通知或者自定义消息,也可以同时推送通知与自定义消息.
推送对象
一个推送对象,以JSON格式表示,表示一条推送相关的所有信息.
关键字 | 选项 | 含义 |
---|---|---|
platform | 必填 | 推送平台设置 |
audience | 必填 | 推送设备指定 |
notification | 可选 | 通知内容体.与message二者必须有其一 |
message | 可选 | 消息内容体.与notification二者必须有其一 |
sms_message | 可选 | 短信渠道补充送达内容体 |
options | 可选 | 推送参数 |
cid | 可选 | 用于防止api调用端重试造成服务端的重复推送而定义的一个标识符 |
platform: 推送平台
- JPush当前支持Android,ios,WindowsPhone.其中关键字为: “android”, “ios”, “winphone”
- 注意: 如果目标平台为ios平台,推送Notification时需要在options中通过apns_production字段来设定推送环境.True表示推送生产环境,False表示要推送开发环境.如果不指定则为推送生产环境,一次只能推送给一个环境
audience: 推送目标
- 推送设备对象,表示一条推送可以被推送到哪些设备列表.确认推送设备对象,JPush提供了多种方式,比如:别名,标签,注册ID,分群,广播等
关键字 | 类型 | 含义 | 说明 | 备注 |
---|---|---|---|---|
all | JSONArray | 全部设备.(广播) | ||
tag | JSONArray | OR | 数组.多个标签之间的OR的关系 | 一个推送最多20个.每个tag的长度限制为40字节 |
tag_and | JSONArray | AND | 数组.多个标签之间是AND的关系 | 注意与tag的区别.一次推送最多20个 |
tag_not | JSONArray | NOT | 数组.多个标签之间,先取多标签的并集,再对该结果取补集 | 一次推送最多20个 |
alias | JSONArray | 别名 | 数组.多个别名之间是OR关系 | 一个设备只能绑定一个别名;一次推送最多1000个;每个alias的长度限制为40字节 |
Registration_id | JSONArray | 注册ID | 数组.多个注册ID之间是OR关系 | 设备标识.一次推送最多1000个,客户端集成SDK后可获取到该设备 |
notification: 通知
- 通知对象.是一条推送的实体内容对象之一
- alter : 通知的内容在各个平台上,都可能只有一个最基本的属性”alter”
message: 自定义消息
- 应用内消息.(自定义消息,透传消息)
- 此部分内容不会展示到通知栏上,JPushSDK收到消息内容后透传给APP,需要APP自行处理.
关键字 | 类型 | 选项 | 含义 |
---|---|---|---|
msg_content | string | 必填 | 消息内容本身 |
title | string | 可选 | 消息标题 |
content_type | string | 可选 | 消息内容类型 |
extras | JSONObject | 可选 | JSON格式的可选参数 |
案例说明
- 推送对象
@Data
private class JPushParam {
private Platform platform;
private Audience audience;
private JPushMessage message;
}
- 消息体
@Data
public class JPushMessage {
private String title;
private String msgContent;
private String contentType;
private Map<String, String> extras;
private Map<String, JsonObject> jsonExtras;
}
- 构建消息体
public class BuildPayloadUtils {
public static PushPayload getPayload(JpushParam param) {
JPushMessage message = param.getMessage();
PushPayload.Builder pushBuilder = PushPayload.newBuilder();
// 构建推送平台
if (null != param.getPlatform) {
pushBuilder.setPlatform(param.getPlatform());
} else {
pushBuilder.setPlatform(Platform.all());
}
// 构建推送目标
if (null != param.getAudience) {
pushBuilder.setAudience(param.getAudience());
} else {
pushBuilder.setAudience(param.all());
}
// 构建通知和自定义消息
setMessageOrAlter(pushBuilder, message, PushWayEnum.ALL);
}
/**
* @param wayEnum 通知和消息(只选其一还是两者都有)
*/
private static void setMessageOrAlter(PushPayload.Builder pushBuilder, JPushMessage message, PushWayEnum wayEnum) {
switch (wayEnum) {
case ALL:
pushBuilder.setNotification(Notification.newBuilder()
.setAlert(message.getMsgContent())
.addPlatformNotification(getAndroidNotificationBuilder(message).build())
.addPlatformNotification(getIosNotificationBuilder(message).build())
.build())
.setMessage(getMessageBuilder(message).build());
break;
case ALTER:
pushBuilder.setNotification(Notification.newBuilder()
.setAlert(message.getMsgContent())
.addPlatformNotification(getAndroidNotificationBuilder(message).build())
.addPlatformNotification(getIosNotificationBuilder(message).build())
.build());
break;
case MESSAGE:
pushBuilder.setMessage(getMessageBuilder(message).build());
break;
default:
break;
}
}
private static AndroidNotification.Builder getAndroidNotificationBuilder(JPushMessage message) {
AndroidNotification.Builder androidBuilder = AndroidNotification.newBuilder();
if (StringUtils.isNotEmpty(message.getTitle())) {
androidBuilder.setTitle(message.getTitle());
}
if (StringUtils.isNotEmpty(message.getMsgContent())) {
androidBuilder.setAlert(message.getMsgContent());
}
if (!CollectionUtils.isEmpty(message.getExtras())) {
androidBuilder.addExtras(message.getExtras());
}
return androidBuilder;
}
private static IosNotification.Builder getIosNotificationBuilder(JPushMessage message) {
IosNotification.Builder iosBuilder = IosNotification.newBuilder().incrBadge(1);
if (StringUtils.isNotEmpty(message.getMsgContent())) {
iosBuilder.setAlert(message.getMsgContent());
}
if (!CollectionUtils.isEmpty(message.getExtras())) {
iosBuilder.addExtras(message.getExtras());
}
return iosBuilder;
}
private static Message.Builder getMessageBuilder(JPushMessage message) {
Message.Builder messageBuilder = Message.newBuilder();
if (StringUtils.isNotEmpty(message.getTitle())) {
messageBuilder.setTitle(message.getTitle());
}
if (StringUtils.isNotEmpty(message.getMsgContent())) {
messageBuilder.setMsgContent(message.getMsgContent());
}
if (!CollectionUtils.isEmpty(message.getExtras())) {
messageBuilder.addExtras(message.getExtras());
}
if (!CollectionUtils.isEmpty(message.getJsonExtras())) {
Map<String, JsonObject> jsonExtras = message.getJsonExtras();
for (Map.Entry<String, JsonObject> entry : jsonExtras.entrySet()) {
messageBuilder.addExtra(entry.getKey(), entry.getValue());
}
}
return messageBuilder;
}
}
注意: 推送的消息体有大小限制.Android平台Notification+Message长度限制为4000字节.IOS中Notification中“ios”:{}及大括号内的总体长度不超过2000字节.IOS的Message部分长度不超过4000字节.
- 推送方法
private PushResult getPushResult(JPushAppEnum appEnum, PushPayload payload, String url) {
PushResult result = null;
try {
ResponseWrapper response = httpClient.sendPost(url, payload.toString());
result = BaseResult.fromResponse(response, PushResult,class);
} catch (ApiConnectionException e) {
log.error("[push] Connection error, should retry later", e);
log.warn("[push] push again. start....");
// 如果是因为连接超时导致推送失败,这里做个重新推送的操作(不过正常情况下,需要做下限制:比如多次推送都失败,就不应该让他一直重试.)
getPushResult(appEnum, payload, url);
} catch (APIRequestException e) {
log.error("[push] Should review the error, and fix the request", e);
log.error("[push] HTTP Status: " + e.getStatus());
log.error("[push] Error Code: " + e.getErrorCode());
log.error("[push] Error Message: " + e.getErrorMessage());
}
return result;
}