package com.doumee.core.utils.jpush;
|
|
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONObject;
|
import com.doumee.core.utils.HttpsUtil;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.lang3.StringUtils;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Component;
|
|
import javax.annotation.PostConstruct;
|
import java.util.Base64;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* 极光推送工具类(基于JPush REST API)
|
*
|
* @author rk
|
* @date 2026/04/24
|
*/
|
@Component
|
@Slf4j
|
public class JPushUtil {
|
|
private static final String PUSH_URL = "https://bjapi.push.jiguang.cn/v3/push";
|
|
private static String authHeader;
|
private static boolean apnsProduction;
|
|
@Value("${jpush.appKey:}")
|
private String appKey;
|
|
@Value("${jpush.masterSecret:}")
|
private String masterSecret;
|
|
@Value("${jpush.apnsProduction:false}")
|
private boolean apnsProd;
|
|
@PostConstruct
|
public void init() {
|
if (StringUtils.isNotBlank(appKey) && StringUtils.isNotBlank(masterSecret)) {
|
authHeader = "Basic " + Base64.getEncoder().encodeToString((appKey + ":" + masterSecret).getBytes());
|
apnsProduction = apnsProd;
|
log.info("JPush initialized, appKey={}", appKey);
|
} else {
|
log.warn("JPush not configured, push disabled");
|
}
|
}
|
|
// ==================== 通知栏推送 ====================
|
|
/**
|
* 按别名推送通知
|
*
|
* @param alias 别名(如会员ID/司机ID/门店ID)
|
* @param title 通知标题
|
* @param content 通知内容
|
* @param extras 附加字段(可选)
|
* @return 是否推送成功
|
*/
|
public static boolean sendByAlias(String alias, String title, String content, Map<String, String> extras) {
|
return sendByAliases(Collections.singletonList(alias), title, content, extras);
|
}
|
|
/**
|
* 按别名批量推送通知
|
*/
|
public static boolean sendByAliases(List<String> aliases, String title, String content, Map<String, String> extras) {
|
if (!available() || aliases == null || aliases.isEmpty()) {
|
return false;
|
}
|
JSONObject body = buildNotificationBody(aliases, "alias", title, content, extras);
|
return doPush(body, "sendByAliases");
|
}
|
|
/**
|
* 按RegistrationId推送通知
|
*/
|
public static boolean sendByRegId(String regId, String title, String content, Map<String, String> extras) {
|
return sendByRegIds(Collections.singletonList(regId), title, content, extras);
|
}
|
|
/**
|
* 按RegistrationId批量推送通知
|
*/
|
public static boolean sendByRegIds(List<String> regIds, String title, String content, Map<String, String> extras) {
|
if (!available() || regIds == null || regIds.isEmpty()) {
|
return false;
|
}
|
JSONObject body = buildNotificationBody(regIds, "registration_id", title, content, extras);
|
return doPush(body, "sendByRegIds");
|
}
|
|
/**
|
* 广播推送通知(推送给所有用户)
|
*/
|
public static boolean sendToAll(String title, String content, Map<String, String> extras) {
|
if (!available()) {
|
return false;
|
}
|
JSONObject body = buildNotificationBody(null, "all", title, content, extras);
|
return doPush(body, "sendToAll");
|
}
|
|
// ==================== 自定义消息(静默推送,不显示通知栏) ====================
|
|
/**
|
* 按别名推送自定义消息
|
*/
|
public static boolean sendMessageByAlias(String alias, String content, Map<String, String> extras) {
|
return sendMessagesByAlias(Collections.singletonList(alias), content, extras);
|
}
|
|
/**
|
* 按别名批量推送自定义消息
|
*/
|
public static boolean sendMessagesByAlias(List<String> aliases, String content, Map<String, String> extras) {
|
if (!available() || aliases == null || aliases.isEmpty()) {
|
return false;
|
}
|
JSONObject body = buildMessageBody(aliases, "alias", content, extras);
|
return doPush(body, "sendMessageByAlias");
|
}
|
|
// ==================== 内部方法 ====================
|
|
private static boolean available() {
|
return StringUtils.isNotBlank(authHeader);
|
}
|
|
/**
|
* 构建通知栏推送请求体
|
*/
|
private static JSONObject buildNotificationBody(List<String> targets, String audienceType,
|
String title, String content, Map<String, String> extras) {
|
JSONObject body = new JSONObject();
|
// platform
|
body.put("platform", "all");
|
|
// audience
|
if ("all".equals(audienceType)) {
|
body.put("audience", "all");
|
} else {
|
JSONObject audience = new JSONObject();
|
JSONArray arr = new JSONArray();
|
arr.addAll(targets);
|
audience.put(audienceType, arr);
|
body.put("audience", audience);
|
}
|
|
// notification
|
JSONObject notification = new JSONObject();
|
|
// Android
|
JSONObject android = new JSONObject();
|
android.put("title", title);
|
android.put("alert", content);
|
if (extras != null && !extras.isEmpty()) {
|
android.put("extras", mapToJson(extras));
|
}
|
notification.put("android", android);
|
|
// iOS
|
JSONObject ios = new JSONObject();
|
ios.put("alert", content);
|
ios.put("sound", "default");
|
if (extras != null && !extras.isEmpty()) {
|
ios.put("extras", mapToJson(extras));
|
}
|
notification.put("ios", ios);
|
|
body.put("notification", notification);
|
|
// options
|
JSONObject options = new JSONObject();
|
options.put("apns_production", apnsProduction);
|
body.put("options", options);
|
|
return body;
|
}
|
|
/**
|
* 构建自定义消息请求体(不显示通知栏)
|
*/
|
private static JSONObject buildMessageBody(List<String> targets, String audienceType,
|
String content, Map<String, String> extras) {
|
JSONObject body = new JSONObject();
|
body.put("platform", "all");
|
|
JSONObject audience = new JSONObject();
|
JSONArray arr = new JSONArray();
|
arr.addAll(targets);
|
audience.put(audienceType, arr);
|
body.put("audience", audience);
|
|
// message
|
JSONObject message = new JSONObject();
|
message.put("msg_content", content);
|
if (extras != null && !extras.isEmpty()) {
|
message.put("extras", mapToJson(extras));
|
}
|
body.put("message", message);
|
|
JSONObject options = new JSONObject();
|
options.put("apns_production", apnsProduction);
|
body.put("options", options);
|
|
return body;
|
}
|
|
/**
|
* Map<String, String> → JSONObject
|
*/
|
private static JSONObject mapToJson(Map<String, String> map) {
|
JSONObject json = new JSONObject();
|
json.putAll(map);
|
return json;
|
}
|
|
/**
|
* 执行推送请求
|
*/
|
private static boolean doPush(JSONObject body, String action) {
|
try {
|
String response = HttpsUtil.postJson(PUSH_URL, body.toJSONString(), authHeader);
|
log.info("JPush {}, response={}", action, response);
|
if (StringUtils.isNotBlank(response)) {
|
JSONObject resp = JSONObject.parseObject(response);
|
return resp.containsKey("msg_id") || (resp.containsKey("statusCode") && resp.getIntValue("statusCode") == 0);
|
}
|
return false;
|
} catch (Exception e) {
|
log.error("JPush {} error", action, e);
|
return false;
|
}
|
}
|
}
|