This commit is contained in:
zhangzhicheng 2024-10-26 18:52:02 +08:00
parent fb0c6fc2fc
commit c5b2c7250b
13 changed files with 701 additions and 42 deletions

View File

@ -0,0 +1,57 @@
package org.dromara.web.config;
import com.getui.push.v2.sdk.ApiHelper;
import com.getui.push.v2.sdk.GtApiConfiguration;
import com.getui.push.v2.sdk.api.PushApi;
import com.getui.push.v2.sdk.api.UserApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* @Author: zzc
* @Date: 22:24 2024/10/23
*/
@Component
public class CInit {
@Autowired
private CustomGeTuiConfig customGeTuiConfig;
@Bean("customPushApi")
public PushApi getPushApi(){
GtApiConfiguration apiConfiguration = new GtApiConfiguration();
//填写应用配置
apiConfiguration.setAppId(customGeTuiConfig.getAppId());
apiConfiguration.setAppKey(customGeTuiConfig.getAppKey());
apiConfiguration.setMasterSecret(customGeTuiConfig.getMasterSecret());
// 接口调用前缀请查看文档: 接口调用规范 -> 接口前缀, 可不填写appId
apiConfiguration.setDomain("https://restapi.getui.com/v2/");
// 实例化ApiHelper对象用于创建接口对象
ApiHelper apiHelper = ApiHelper.build(apiConfiguration);
// 创建对象建议复用目前有PushApiStatisticApiUserApi
PushApi pushApi = apiHelper.creatApi(PushApi.class);
return pushApi;
}
@Bean("customUserApi")
public UserApi getUserApi() {
GtApiConfiguration apiConfiguration = new GtApiConfiguration();
//填写应用配置
apiConfiguration.setAppId(customGeTuiConfig.getAppId());
apiConfiguration.setAppKey(customGeTuiConfig.getAppKey());
apiConfiguration.setMasterSecret(customGeTuiConfig.getMasterSecret());
// 接口调用前缀请查看文档: 接口调用规范 -> 接口前缀, 可不填写appId
apiConfiguration.setDomain("https://restapi.getui.com/v2/");
// 实例化ApiHelper对象用于创建接口对象
ApiHelper apiHelper = ApiHelper.build(apiConfiguration);
// 创建对象建议复用目前有PushApiStatisticApiUserApi
UserApi userApi = apiHelper.creatApi(UserApi.class);
return userApi;
}
public String pageName(){
return customGeTuiConfig.getPackageName();
}
}

View File

@ -0,0 +1,16 @@
package org.dromara.web.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component(value = "custom")
@Data
@ConfigurationProperties(prefix = "custom")
public class CustomGeTuiConfig {
private String appId;
private String appKey;
private String masterSecret;
private String packageName;
}

View File

@ -1,42 +1,42 @@
package org.dromara.web.config; //package org.dromara.web.config;
//
import com.getui.push.v2.sdk.ApiHelper; //import com.getui.push.v2.sdk.ApiHelper;
import com.getui.push.v2.sdk.GtApiConfiguration; //import com.getui.push.v2.sdk.GtApiConfiguration;
import com.getui.push.v2.sdk.api.PushApi; //import com.getui.push.v2.sdk.api.PushApi;
import org.springframework.beans.factory.annotation.Value; //import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; //import org.springframework.context.annotation.Bean;
//
public class GeTuiConfig { //public class GeTuiConfig {
//
@Value("${getui.baseUrl}") // @Value("${getui.baseUrl}")
private String baseUrl; // private String baseUrl;
//
@Value("${getui.appId}") // @Value("${getui.appId}")
private String appId; // private String appId;
//
@Value("${getui.appKey}") // @Value("${getui.appKey}")
private String appKey; // private String appKey;
//
@Value("${getui.appSecret}") // @Value("${getui.appSecret}")
private String appSecret; // private String appSecret;
//
@Value("${getui.masterSecret}") // @Value("${getui.masterSecret}")
private String masterSecret; // private String masterSecret;
//
@Bean(name = "pushApi") // @Bean(name = "pushApi")
public PushApi pushApi() { // public PushApi pushApi() {
GtApiConfiguration apiConfiguration = new GtApiConfiguration(); // GtApiConfiguration apiConfiguration = new GtApiConfiguration();
//填写应用配置 // //填写应用配置
apiConfiguration.setAppId(appId); // apiConfiguration.setAppId(appId);
apiConfiguration.setAppKey(appKey); // apiConfiguration.setAppKey(appKey);
apiConfiguration.setMasterSecret(masterSecret); // apiConfiguration.setMasterSecret(masterSecret);
// 接口调用前缀请查看文档: 接口调用规范 -> 接口前缀, 可不填写appId // // 接口调用前缀请查看文档: 接口调用规范 -> 接口前缀, 可不填写appId
apiConfiguration.setDomain(baseUrl); // apiConfiguration.setDomain(baseUrl);
// 实例化ApiHelper对象用于创建接口对象 // // 实例化ApiHelper对象用于创建接口对象
ApiHelper apiHelper = ApiHelper.build(apiConfiguration); // ApiHelper apiHelper = ApiHelper.build(apiConfiguration);
// 创建对象建议复用目前有PushApiStatisticApiUserApi // // 创建对象建议复用目前有PushApiStatisticApiUserApi
PushApi pushApi = apiHelper.creatApi(PushApi.class); // PushApi pushApi = apiHelper.creatApi(PushApi.class);
return pushApi; // return pushApi;
} // }
//
} //}

View File

@ -0,0 +1,58 @@
package org.dromara.web.config;
import com.getui.push.v2.sdk.ApiHelper;
import com.getui.push.v2.sdk.GtApiConfiguration;
import com.getui.push.v2.sdk.api.PushApi;
import com.getui.push.v2.sdk.api.UserApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* @Author: zzc
* @Date: 22:24 2024/10/23
*/
@Component
public class PInit {
@Autowired
private PlatformGeTuiConfig platformGeTuiConfig;
@Bean("platformPushApi")
public PushApi getPushApi(){
GtApiConfiguration apiConfiguration = new GtApiConfiguration();
//填写应用配置
apiConfiguration.setAppId(platformGeTuiConfig.getAppId());
apiConfiguration.setAppKey(platformGeTuiConfig.getAppKey());
apiConfiguration.setMasterSecret(platformGeTuiConfig.getMasterSecret());
// 接口调用前缀请查看文档: 接口调用规范 -> 接口前缀, 可不填写appId
apiConfiguration.setDomain("https://restapi.getui.com/v2/");
// 实例化ApiHelper对象用于创建接口对象
ApiHelper apiHelper = ApiHelper.build(apiConfiguration);
// 创建对象建议复用目前有PushApiStatisticApiUserApi
PushApi pushApi = apiHelper.creatApi(PushApi.class);
return pushApi;
}
@Bean("platformUserApi")
public UserApi getUserApi() {
GtApiConfiguration apiConfiguration = new GtApiConfiguration();
//填写应用配置
apiConfiguration.setAppId(platformGeTuiConfig.getAppId());
apiConfiguration.setAppKey(platformGeTuiConfig.getAppKey());
apiConfiguration.setMasterSecret(platformGeTuiConfig.getMasterSecret());
// 接口调用前缀请查看文档: 接口调用规范 -> 接口前缀, 可不填写appId
apiConfiguration.setDomain("https://restapi.getui.com/v2/");
// 实例化ApiHelper对象用于创建接口对象
ApiHelper apiHelper = ApiHelper.build(apiConfiguration);
// 创建对象建议复用目前有PushApiStatisticApiUserApi
UserApi userApi = apiHelper.creatApi(UserApi.class);
return userApi;
}
public String pageName(){
return platformGeTuiConfig.getPackageName();
}
}

View File

@ -0,0 +1,15 @@
package org.dromara.web.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component(value = "platform")
@Data
@ConfigurationProperties(prefix = "platform")
public class PlatformGeTuiConfig {
private String appId;
private String appKey;
private String masterSecret;
private String packageName;
}

View File

@ -0,0 +1,59 @@
package org.dromara.web.controller;
import lombok.extern.slf4j.Slf4j;
import org.dromara.web.config.CInit;
import org.dromara.web.config.PInit;
import org.dromara.web.dto.PushUniDoing;
import org.dromara.web.dto.PushVo;
import org.dromara.web.service.PushService;
import org.dromara.web.utils.Result;
import org.dromara.web.utils.ResultCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* @Author zzc
* @Date 23:22 2024/10/25
* @Description
**/
@RestController
@RequestMapping("/uni")
@Slf4j
public class PushController {
@Autowired
private CInit cInit;
@Autowired
private PInit pInit;
@Autowired
private PushService doPush;
@PostMapping("push")
public Result pushUni(@RequestBody PushVo pushVo){
PushUniDoing pushUniDoing = new PushUniDoing();
pushUniDoing.setCid(pushVo.getCid());
pushUniDoing.setClientType(2);
pushUniDoing.setTitle(pushVo.getTitle());
pushUniDoing.setContent(pushVo.getContent());
pushUniDoing.setPath("msg");
if (pushVo.getType()==0){
pushUniDoing.setPackageName(pInit.pageName());
pushUniDoing.setPushApi(pInit.getPushApi());
pushUniDoing.setUserApi(pInit.getUserApi());
}else {
pushUniDoing.setPackageName(cInit.pageName());
pushUniDoing.setPushApi(cInit.getPushApi());
pushUniDoing.setUserApi(cInit.getUserApi());
}
Map<String, Object> push = doPush.push(pushUniDoing);
log.info("推送结果:{}",push);
return new Result(ResultCode.SUCCESS,push);
}
}

View File

@ -0,0 +1,37 @@
package org.dromara.web.dto;
import com.getui.push.v2.sdk.api.PushApi;
import com.getui.push.v2.sdk.api.UserApi;
import lombok.Data;
/**
* @Author zzc
* @Date 22:24 2024/10/23
* @Description
**/
@Data
public class PushUniDoing {
private String cid;
private String title;
private String content;
/**
* 1.苹果 2.Android
*/
private Integer clientType;
/***
* 需要打开的地址 msg:消息
*/
private String path;
private PushApi pushApi;
private UserApi userApi;
/***
* 应用包名
*/
private String packageName;
}

View File

@ -0,0 +1,22 @@
package org.dromara.web.dto;
import lombok.Data;
@Data
public class PushVo {
private String cid;
private Integer type; //0 是平台 1是企业
private String title;
private String content;
}

View File

@ -0,0 +1,230 @@
package org.dromara.web.service;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.getui.push.v2.sdk.api.UserApi;
import com.getui.push.v2.sdk.common.ApiResult;
import com.getui.push.v2.sdk.dto.req.Audience;
import com.getui.push.v2.sdk.dto.req.Settings;
import com.getui.push.v2.sdk.dto.req.Strategy;
import com.getui.push.v2.sdk.dto.req.message.PushChannel;
import com.getui.push.v2.sdk.dto.req.message.PushDTO;
import com.getui.push.v2.sdk.dto.req.message.PushMessage;
import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO;
import com.getui.push.v2.sdk.dto.req.message.android.GTNotification;
import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification;
import com.getui.push.v2.sdk.dto.req.message.android.Ups;
import com.getui.push.v2.sdk.dto.req.message.ios.Alert;
import com.getui.push.v2.sdk.dto.req.message.ios.Aps;
import com.getui.push.v2.sdk.dto.req.message.ios.IosDTO;
import com.getui.push.v2.sdk.dto.res.CidStatusDTO;
import lombok.extern.slf4j.Slf4j;
import org.dromara.web.dto.PushUniDoing;
import org.dromara.web.utils.RRException;
import org.springframework.stereotype.Service;
import java.util.*;
/**
* @Author zzc
* @Date 20:11 2024/10/25
* @Description
**/
@Service
@Slf4j
public class PushService {
public Map<String, Object> push(PushUniDoing push){
Map<String, Object> map=new HashMap<>();
Boolean userOnline = getUserOnline(push.getUserApi(),push.getCid());
if (ObjectUtil.isNull(userOnline)){
throw new RRException("请求个推服务器发送错误");
}
if (userOnline){ //在线就用个推
map= gtPush(push);
}else { //不在线就用厂商推
map= BusinessPush(push);
}
return map;
}
/***
* 查看用户状态
* online在线
* offline离线
* @param cid
* @return
*/
public Boolean getUserOnline(UserApi userApi, String cid){
Set<String> cids = new HashSet<String>();
cids.add(cid);
// 查询用户状态
ApiResult<Map<String, CidStatusDTO>> apiResult = userApi.queryUserStatus(cids);
if (apiResult.isSuccess()) {
Map<String, CidStatusDTO> data = apiResult.getData();
CidStatusDTO cidStatusDTO = data.get(cid);
log.error("当前cid:{}查询在线状态",cidStatusDTO.getStatus());
return cidStatusDTO.getStatus().equals("online")?true:false;
}
log.error("当前cid:{}查询在线状态出现错误 ,code:{},msg:",cid,apiResult.getCode(),apiResult.getMsg());
return null;
}
/***
* 厂商推送
* @param pushUni
*/
public Map<String, Object> BusinessPush(PushUniDoing pushUni){
JSONObject jsonObject = new JSONObject();
jsonObject.put("path",pushUni.getPath());
//根据cid进行单推
PushDTO<Audience> pushDTO = new PushDTO<Audience>();
// 设置推送参数
pushDTO.setRequestId(System.currentTimeMillis() + "");//requestid需要每次变化唯一
//配置推送条件
/****
*
* 1: 表示该消息在用户在线时推送个推通道用户离线时推送厂商通道;
* 2: 表示该消息只通过厂商通道策略下发不考虑用户是否在线;
* 3: 表示该消息只通过个推通道下发不考虑用户是否在线
* 4: 表示该消息优先从厂商通道下发若消息内容在厂商通道代发失败后会从个推通道下发
*
*/
Strategy strategy=new Strategy();
strategy.setDef(1);
/**
* ios通道策略1-4表示含义同上要推送ios通道需要在个推开发者中心上传ios证书建议填写2或4否则可能会有消息不展示的问题
*/
strategy.setIos(4);
Settings settings=new Settings();
settings.setStrategy(strategy);
pushDTO.setSettings(settings);
settings.setTtl(3600000);//消息有效期走厂商消息需要设置该值
PushChannel pushChannel = new PushChannel();
if (pushUni.getClientType()==1){
//推送苹果离线通知标题内容
Alert alert=new Alert();
alert.setTitle(pushUni.getTitle());
alert.setBody(pushUni.getContent());
Aps aps = new Aps();
//1表示静默推送(无通知栏消息)静默推送时不需要填写其他参数
//苹果建议1小时最多推送3条静默消息
aps.setContentAvailable(0);
aps.setSound("default");
aps.setAlert(alert);
IosDTO iosDTO = new IosDTO();
iosDTO.setPayload(JSON.toJSONString(jsonObject));
iosDTO.setAps(aps);
iosDTO.setType("notify");
pushChannel.setIos(iosDTO);
}else {
AndroidDTO androidDTO = new AndroidDTO();
Ups ups = new Ups();
ThirdNotification notification1 = new ThirdNotification();;
ups.setNotification(notification1);
notification1.setTitle(pushUni.getTitle());
notification1.setBody(pushUni.getContent());
notification1.setClickType("intent");
notification1.setIntent("intent:#Intent;action=android.intent.action.oppopush;launchFlags=0x14000000;"
+"component=" +pushUni.getPackageName() +"/io.dcloud.PandoraEntry;S.UP-OL-SU=true;S.title="+pushUni.getTitle()
+";S.content="+pushUni.getContent()
+";S.payload="+ JSON.toJSONString(jsonObject)
+";end");
//各厂商自有功能单项设置
// ups.addOption("HW", "/message/android/notification/badge/class", "io.dcloud.PandoraEntry");
// ups.addOption("HW", "/message/android/notification/badge/add_num", 1);
// ups.addOption("HW", "/message/android/notification/importance", "HIGH");
// ups.addOption("VV","classification",1);
// ups.addOption("HO", "/message/android/notification/badge/badgeClass", "io.dcloud.PandoraEntry");
// ups.addOption("HO","/message/android/notification/badge/addNum",1);
//设置options 方式二
Map<String, Map<String, Object>> options = new HashMap<String, Map<String, Object>>();
Map<String, Object> all = new HashMap<String, Object>();
all.put("channel", "default");
all.put("badgeAddNum", 1);
all.put("badgeClass", "com.getui.demo.GetuiSdkDemoActivity");
options.put("ALL", all);
Map<String, Object> hw = new HashMap<String, Object>();
options.put("HW", hw);
hw.put("/message/android/notification/badge/class", "io.dcloud.PandoraEntry");
hw.put("/message/android/notification/badge/add_num",1);
Map<String, Object> ho = new HashMap<String, Object>();
options.put("HO", ho);
ho.put("/message/android/notification/badge/badgeClass", "io.dcloud.PandoraEntry");
ho.put("/message/android/notification/badge/addNum",1);
ups.setOptions(options);
androidDTO.setUps(ups);
pushChannel.setAndroid(androidDTO);
}
pushDTO.setPushChannel(pushChannel);
// PushMessage在线走个推通道才会起作用的消息体
PushMessage pushMessage = new PushMessage();
pushDTO.setPushMessage(pushMessage);
pushMessage.setTransmission(JSON.toJSONString(jsonObject));
// 设置接收人信息
Audience audience = new Audience();
pushDTO.setAudience(audience);
audience.addCid(pushUni.getCid());
// 进行cid单推
ApiResult<Map<String, Map<String, String>>> apiResult = pushUni.getPushApi().pushToSingleByCid(pushDTO);
return getMapValue(apiResult,pushUni.getCid());
}
/***
* 个推消息推送
* @param pushUni
* @return
*/
public Map<String, Object> gtPush(PushUniDoing pushUni){
PushDTO<Audience> pushDTO = new PushDTO<Audience>();
// 设置推送参数
pushDTO.setRequestId(System.currentTimeMillis() + "");
PushMessage pushMessage = new PushMessage();
pushDTO.setPushMessage(pushMessage);
GTNotification notification = new GTNotification();
pushMessage.setNotification(notification);
notification.setTitle(pushUni.getTitle());
notification.setBody(pushUni.getContent());
JSONObject jsonObject = new JSONObject();
jsonObject.put("path",pushUni.getPath());
notification.setClickType("payload");
jsonObject.put("showTitle", pushUni.getTitle());
jsonObject.put("showContent", pushUni.getContent());
notification.setPayload(JSON.toJSONString(jsonObject));
Audience audience = new Audience();
pushDTO.setAudience(audience);
audience.addCid(pushUni.getCid());
// 进行cid单推
ApiResult<Map<String, Map<String, String>>> apiResult = pushUni.getPushApi().pushToSingleByCid(pushDTO);
return getMapValue(apiResult,pushUni.getCid());
}
/***
* 返回结果进行封装
* @param apiResult
* @param cid
* @return
*/
private Map<String, Object> getMapValue(ApiResult<Map<String, Map<String, String>>> apiResult,String cid){
Map<String, Object> map = MapUtil.newHashMap();
if (apiResult.isSuccess()) {
Map<String, Map<String, String>> data = apiResult.getData();
Optional<Map.Entry<String, Map<String, String>>> first = data.entrySet().stream().findFirst();
Map.Entry<String, Map<String, String>> stringMapEntry = first.get();
Map<String, String> value = stringMapEntry.getValue();
String result = value.get(cid);
map.put("code",200);
map.put("result",result);
} else {
map.put("code",apiResult.getCode());
map.put("result",apiResult.getMsg());
}
return map;
}
}

View File

@ -0,0 +1,53 @@
package org.dromara.web.utils;
/**
* @Author: zzc
* @Date: 22:24 2024/10/23
*/
public class RRException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String msg;
private int code = 500;
public RRException(String msg) {
super(msg);
this.msg = msg;
}
public RRException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
}
public RRException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
}
public RRException(String msg, int code, Throwable e) {
super(msg, e);
this.msg = msg;
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}

View File

@ -0,0 +1,49 @@
package org.dromara.web.utils;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class Result {
private boolean success;
private Integer code;
private String message;
private Object data;
public Result(ResultCode code) {
this.success = code.success;
this.code = code.code;
this.message = code.message;
}
public Result(ResultCode code, Object data) {
this.success = code.success;
this.code = code.code;
this.message = code.message;
this.data = data;
}
public Result(Integer code,String message,boolean success) {
this.code = code;
this.message = message;
this.success = success;
}
public static Result SUCCESS() {
return new Result(ResultCode.SUCCESS);
}
public static Result FAIL() {
return new Result(ResultCode.FAIL);
}
public static Result ERROR2(Integer code,String message) {
return new Result(code, message, false);
}
}

View File

@ -0,0 +1,48 @@
package org.dromara.web.utils;
/**
* 公共的返回码
*/
public enum ResultCode {
/**
* 系统错误返回码
*/
SUCCESS(true,10000,"操作成功"),
FAIL(false,10001,"操作失败"),
/*****************************************************************************权限类 end********************************************************************************/
;
/**
* 操作是否成功
*/
boolean success;
/**
* 操作代码
*/
int code;
/**
* 提示信息
*/
String message;
ResultCode(boolean success, int code, String message){
this.success = success;
this.code = code;
this.message = message;
}
public boolean success() {
return success;
}
public int code() {
return code;
}
public String message() {
return message;
}
}

View File

@ -279,3 +279,18 @@ getui:
appKey: v4bFxTyIbg58qrGuTH8N03 appKey: v4bFxTyIbg58qrGuTH8N03
appSecret: T5Rak0PGsc9ingNvrtSWo8 appSecret: T5Rak0PGsc9ingNvrtSWo8
masterSecret: Cejg8JZIH790HTeEaq20b1 masterSecret: Cejg8JZIH790HTeEaq20b1
#平台
platform:
appId: npL6vVou0R9ht97RS78uG8
appKey: v4bFxTyIbg58qrGuTH8N03
masterSecret: Cejg8JZIH790HTeEaq20b1
packageName: com.getui.demo
#企业
custom:
appId: npL6vVou0R9ht97RS78uG8
appKey: v4bFxTyIbg58qrGuTH8N03
masterSecret: Cejg8JZIH790HTeEaq20b1
packageName: com.getui.demo