个推推送

This commit is contained in:
Jack 2025-06-10 17:48:15 +08:00
parent 3a8fb32bbd
commit 07f2cb3f0c
12 changed files with 343 additions and 359 deletions

View File

@ -72,7 +72,7 @@ public class LoginController extends BaseControllerImpl {
clinkContent = "";
}
return geTuiPushService.pushMessageToSingleByCid(paramsJSON.getStr("cid"), title, paramsJSON.getStr("message"), clickType, clinkContent);
return geTuiPushService.pushMessageToCid(paramsJSON.getStr("cid"), title, paramsJSON.getStr("message"), clickType, clinkContent);
}
@RequestMapping(value = "/testcase", method = RequestMethod.GET)

View File

@ -7,7 +7,7 @@ import java.util.List;
public interface AccountUserBindGeTuiService extends IBaseService<AccountUserBindGeTui> {
Boolean addOrUpdate(AccountUserBindGeTui accountUserBindGeTui);
Boolean saveAccountUserBindGeTui(AccountUserBindGeTui accountUserBindGeTui);
List<AccountUserBindGeTui> getActive(AccountUserBindGeTui accountUserBindGeTui);
}

View File

@ -227,7 +227,7 @@ public class AccountUserBaseServiceImpl extends BaseServiceImpl<AccountUserBaseM
AccountUserBindGeTui accountUserBindGeTui = new AccountUserBindGeTui();
accountUserBindGeTui.setUserId(user_id).setUserType(Convert.toInt(params.get("user_is_admin")))
.setCid(cid).setOsType(Convert.toInt(params.get("os_type")));
accountUserBindGeTuiService.addOrUpdate(accountUserBindGeTui);
accountUserBindGeTuiService.saveAccountUserBindGeTui(accountUserBindGeTui);
}
return restResult;
@ -3105,8 +3105,8 @@ public class AccountUserBaseServiceImpl extends BaseServiceImpl<AccountUserBaseM
params.put("password", "");
params.put("user_mobile", user_mobile);
params.put("is_merch", "1"); // 是否为商家入驻 1-其他-
params.put("cid", getParameter("cid"));
params.put("osType", getParameter("osType"));
params.put("cid", getParameter("cid")); // 个推客户端Id
params.put("osType", getParameter("osType"));// 个推客系统类别 1-Android2-iOS
return login(params);
}

View File

@ -15,34 +15,47 @@ import java.util.List;
@Slf4j
@Service
public class AccountUserBindGeTuiServiceImpl extends BaseServiceImpl<UserDeviceBindMapper, AccountUserBindGeTui> implements AccountUserBindGeTuiService {
/**
* 保存或更新用户与个推的绑定关系
*
* @param accountUserBindGeTui 用户与个推的绑定关系对象
* @return 成功返回 true失败返回 false
*/
@Override
public Boolean addOrUpdate(AccountUserBindGeTui accountUserBindGeTui) {
public Boolean saveAccountUserBindGeTui(AccountUserBindGeTui accountUserBindGeTui) {
try {
// 检查参数是否有效
if (ObjectUtil.isNull(accountUserBindGeTui) ||
StrUtil.isBlank(accountUserBindGeTui.getCid()) ||
ObjectUtil.isNull(accountUserBindGeTui.getUserId()) ||
ObjectUtil.isNull(accountUserBindGeTui.getOsType())) {
log.error("缺少必要参数cid={}, userId={}, osType={}",
accountUserBindGeTui != null ? accountUserBindGeTui.getCid() : "",
accountUserBindGeTui != null ? accountUserBindGeTui.getUserId() : "",
accountUserBindGeTui != null ? accountUserBindGeTui.getOsType() : "");
ObjectUtil.isNull(accountUserBindGeTui.getUserId())) {
log.error("缺少必要参数cid={}, userId={}",
accountUserBindGeTui != null ? accountUserBindGeTui.getCid() : null,
accountUserBindGeTui != null ? accountUserBindGeTui.getUserId() : null);
return false;
}
// 获取操作系统类型默认为0
Integer osType = accountUserBindGeTui.getOsType() != null ? accountUserBindGeTui.getOsType() : 0;
String cid = accountUserBindGeTui.getCid();
// 构建查询条件
QueryWrapper<AccountUserBindGeTui> wrapper = new QueryWrapper<AccountUserBindGeTui>()
.eq("user_id", accountUserBindGeTui.getUserId())
.eq("cid", accountUserBindGeTui.getCid())
.eq("os_type", accountUserBindGeTui.getOsType());
AccountUserBindGeTui existAccountUserBindGeTui = getOne(wrapper);
.eq("cid", cid)
.eq("os_type", osType);
// 查询是否存在记录
AccountUserBindGeTui existAccountUserBindGeTui = getOne(wrapper);
if (existAccountUserBindGeTui == null) {
return this.add(accountUserBindGeTui);
}
// 更新记录
accountUserBindGeTui.setId(existAccountUserBindGeTui.getId());
return this.updateById(accountUserBindGeTui);
} catch (Exception e) {
log.error("处理 addOrUpdate 时发生异常:{}", e.getMessage(), e);
// 捕获异常并记录错误日志
log.error("执行 saveAccountUserBindGeTui 方法时发生异常: {}", e.getMessage(), e);
return false;
}
}

View File

@ -10,6 +10,8 @@ package com.suisung.mall.common.service;
import org.springframework.data.util.Pair;
import java.util.List;
public interface GeTuiPushService {
/**
@ -19,7 +21,7 @@ public interface GeTuiPushService {
* @param transmission 透传消息 txt json 格式
* @return
*/
Pair<Boolean, Object> pushTransmissionToSingleByCid(String cid, String transmission);
Pair<Boolean, String> pushTransmissionToCid(String cid, String transmission);
/**
* 单个用户推送消息(支持H5安卓苹果系统)
@ -40,5 +42,34 @@ public interface GeTuiPushService {
* @param clickContent
* @return
*/
Pair<Boolean, Object> pushMessageToSingleByCid(String cid, String title, String content, String clickType, String clickContent);
Pair<Boolean, String> pushMessageToCid(String cid, String title, String content, String clickType, String clickContent);
/**
* 批量用户推送消息(支持H5安卓苹果系统)
*
* @param cidList
* @param title
* @param content
* @param clickType 点击通知后续动作
* * 目前支持以下后续动作
* * intent打开应用内特定页面intent和want字段必须填写一个
* * url打开网页地址
* * payload自定义消息内容启动应用
* * payload_custom自定义消息内容不启动应用
* * startapp打开应用首页
* * none纯通知无后续动作
* @param clickContent json 字符串内容
* @return
*/
Pair<Boolean, String> pushListMessageToCids(List<String> cidList, String title, String content, String clickType, String clickContent);
/**
* 批量用户透传消息(支持H5安卓苹果系统)
*
* @param cidList
* @param transmission 透传消息 txt json 格式
* @return
*/
Pair<Boolean, String> pushListTransmissionToCids(List<String> cidList, String transmission);
}

View File

@ -1,46 +1,32 @@
/*
* Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package com.suisung.mall.common.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
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.common.ApiResult;
import com.getui.push.v2.sdk.dto.req.Audience;
import com.getui.push.v2.sdk.dto.req.message.PushChannel;
import com.getui.push.v2.sdk.dto.req.AudienceDTO;
import com.getui.push.v2.sdk.dto.req.Settings;
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.harmony.HarmonyDTO;
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.suisung.mall.common.service.GeTuiPushService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@Slf4j
@Service
public class GeTuiPushServiceImpl implements GeTuiPushService {
private final Integer ttl = 3600 * 24 * 3 * 1000; // 离线消息过期时间单位为毫秒默认3天
@Value("${getui.push.appid}")
private String appId;
@Value("${getui.push.appkey}")
@ -50,344 +36,167 @@ public class GeTuiPushServiceImpl implements GeTuiPushService {
@Value("${getui.push.domain}")
private String getuiDomain;
// 私有构造函数防止外部实例化
private PushApi creatPushApi() {
// 初始化 PushApi 配置
/**
* 创建 PushApi 实例
*/
private PushApi createPushApi() {
GtApiConfiguration config = new GtApiConfiguration();
config.setAppId(appId);
config.setAppKey(appkey);
config.setMasterSecret(mastersecret);
config.setDomain(getuiDomain);
ApiHelper apiHelper = ApiHelper.build(config);
// 创建 PushApi 实例
return apiHelper.creatApi(PushApi.class);
return ApiHelper.build(config).creatApi(PushApi.class);
}
/**
* 发送在线或离线消息到单个 CID
*
* @param cid 客户端 ID
* @param title 消息标题
* @param content 消息内容
* @param payloadJson 自定义透传内容JSON 格式
* String payloadJson = "{\"action\":\"openPage\",\"pageId\":\"12345\",\"extraInfo\":\"Welcome to the app!\"}";
* @return 是否发送成功
* 设置推送参数
*/
public boolean sendMessageToSingleCid(String cid, String title, String content, String payloadJson) {
try {
// 参数校验
if (cid == null || cid.isEmpty() || title == null || content == null || payloadJson == null) {
log.error("参数无效cid={}, title={}, content={}, payloadJson={}", cid, title, content, payloadJson);
return false;
}
private PushDTO<Audience> buildPushDTO(String transmission, String title, String content, String clickType, String clickContent, List<String> cidList) {
PushDTO<Audience> pushDTO = new PushDTO<>();
pushDTO.setRequestId(String.valueOf(System.currentTimeMillis()));
// 配置 Android 消息
AndroidDTO androidDTO = new AndroidDTO();
Ups ups = new Ups();
ups.setTransmission(payloadJson); // 设置透传内容
androidDTO.setUps(ups);
// 设置离线消息过期时间
Settings settings = new Settings();
settings.setTtl(ttl);
pushDTO.setSettings(settings);
// 配置 iOS 消息
IosDTO iosDTO = new IosDTO();
iosDTO.setPayload(payloadJson); // 设置透传内容
Aps aps = new Aps();
Alert alert = new Alert();
alert.setTitle(title); // 设置标题
alert.setBody(content); // 设置内容
aps.setAlert(alert);
iosDTO.setAps(aps);
// 整合平台消息配置
PushChannel pushChannel = new PushChannel();
pushChannel.setAndroid(androidDTO);
pushChannel.setIos(iosDTO);
// 创建 PushMessage
PushMessage pushMessage = new PushMessage();
pushMessage.setTransmission(payloadJson); // 设置透传内容
// 创建 Audience
Audience audience = new Audience();
audience.addCid(cid);
// 创建 PushDTO
PushDTO<Audience> pushDTO = new PushDTO<>();
pushDTO.setPushChannel(pushChannel);
pushDTO.setPushMessage(pushMessage);
pushDTO.setAudience(audience);
pushDTO.setRequestId(UUID.randomUUID().toString()); // 设置唯一请求 ID
// 调用个推 API 发送消息
ApiResult<Map<String, Map<String, String>>> result = creatPushApi().pushToSingleByCid(pushDTO);
if (result.getCode() != 0) {
log.error("消息发送失败code={}, message={}", result.getCode(), result.getMsg());
return false;
}
log.info("消息发送成功CID: {}", cid);
return true;
} catch (Exception e) {
log.error("发送消息时发生异常:{}", e.getMessage(), e);
return false;
}
}
/**
* 发送在线或离线消息到多个 CID
*
* @param cids 客户端 ID 列表
* @param title 消息标题
* @param content 消息内容
* @param payloadJson 自定义透传内容JSON 格式
* String payloadJson = "{\"action\":\"openPage\",\"pageId\":\"12345\",\"extraInfo\":\"Welcome to the app!\"}";
* @return 是否全部发送成功
*/
public boolean sendMessageToMultipleCids(List<String> cids, String title, String content, String payloadJson) {
try {
// 参数校验
if (cids == null || cids.isEmpty() || title == null || content == null || payloadJson == null) {
log.error("参数无效cids={}, title={}, content={}, payloadJson={}", cids, title, content, payloadJson);
return false;
}
// 配置 Android 消息
AndroidDTO androidDTO = new AndroidDTO();
Ups ups = new Ups();
ups.setTransmission(payloadJson); // 设置透传内容
androidDTO.setUps(ups);
// 配置 iOS 消息
IosDTO iosDTO = new IosDTO();
iosDTO.setPayload(payloadJson); // 设置透传内容
Aps aps = new Aps();
Alert alert = new Alert();
alert.setTitle(title); // 设置标题
alert.setBody(content); // 设置内容
aps.setAlert(alert);
iosDTO.setAps(aps);
// 整合平台消息配置
PushChannel pushChannel = new PushChannel();
pushChannel.setAndroid(androidDTO);
pushChannel.setIos(iosDTO);
// 创建 PushMessage
PushMessage pushMessage = new PushMessage();
pushMessage.setTransmission(payloadJson); // 设置透传内容
// 创建 Audience
Audience audience = new Audience();
for (String cid : cids) {
audience.addCid(cid);
}
// 创建 PushDTO
PushDTO<Audience> pushDTO = new PushDTO<>();
pushDTO.setPushChannel(pushChannel);
pushDTO.setPushMessage(pushMessage);
pushDTO.setAudience(audience);
pushDTO.setRequestId(UUID.randomUUID().toString()); // 设置唯一请求 ID
// 调用个推 API 发送消息
ApiResult<Map<String, Map<String, String>>> result = creatPushApi().pushToSingleByCid(pushDTO);
if (result.getCode() != 0) {
log.error("消息发送失败code={}, message={}", result.getCode(), result.getMsg());
return false;
}
log.info("消息发送成功CIDs: {}", cids);
return true;
} catch (Exception e) {
log.error("发送消息时发生异常:{}", e.getMessage(), e);
return false;
}
}
/**
* 单个用户透传消息(支持H5安卓苹果系统)
*
* @param cid
* @param transmission
* @return
*/
@Override
public Pair<Boolean, Object> pushTransmissionToSingleByCid(String cid, String transmission) {
PushDTO pushDTO = new PushDTO<Audience>();
// 设置推送参数
pushDTO.setRequestId(System.currentTimeMillis() + "");
/**** 设置个推通道参数 *****/
// 设置推送消息
PushMessage pushMessage = new PushMessage();
pushMessage.setTransmission(transmission); // 设置透传消息
if (StrUtil.isNotBlank(transmission)) {
pushMessage.setTransmission(transmission); // 设置透传消息
} else {
GTNotification notification = new GTNotification();
notification.setTitle(StrUtil.isBlank(title) ? "小发同城" : title);
notification.setBody(content);
notification.setClickType(clickType);
switch (clickType) {
case "url":
notification.setUrl(clickContent);
break;
case "intent":
notification.setIntent(clickContent);
break;
case "payload":
case "payload_custom":
notification.setPayload(clickContent);
break;
default:
break;
}
pushMessage.setNotification(notification);
}
pushDTO.setPushMessage(pushMessage);
/**** 设置个推通道参数,更多参数请查看文档或对象源码 *****/
/**** 设置厂商相关参数 ****/
PushChannel pushChannel = new PushChannel();
pushDTO.setPushChannel(pushChannel);
/*配置安卓厂商参数*/
AndroidDTO androidDTO = new AndroidDTO();
pushChannel.setAndroid(androidDTO);
Ups ups = new Ups();
androidDTO.setUps(ups);
ups.setTransmission(transmission); // 设置透传消息
/*配置安卓厂商参数结束,更多参数请查看文档或对象源码*/
/*设置ios厂商参数*/
IosDTO iosDTO = new IosDTO();
pushChannel.setIos(iosDTO);
Aps aps = new Aps();
iosDTO.setAps(aps);
aps.setContentAvailable(1);
iosDTO.setPayload(transmission); // 设置透传消息
/*设置ios厂商参数结束更多参数请查看文档或对象源码*/
/*配置鸿蒙厂商参数*/
HarmonyDTO harmonyDTO = new HarmonyDTO();
pushChannel.setHarmony(harmonyDTO);
harmonyDTO.setTransmission(transmission);
/*配置鸿蒙厂商参数结束,更多参数请查看文档或对象源码*/
/*设置接收人信息*/
// 设置接收人信息
Audience audience = new Audience();
audience.addCid(cid);
audience.setCid(cidList);
pushDTO.setAudience(audience);
// 进行cid单推
ApiResult<JSONObject> apiResult = creatPushApi().pushToSingleByCid(pushDTO);
if (!apiResult.isSuccess()) {
log.error("个推推送失败:{}", apiResult);
return Pair.of(false, "个推推送失败:" + apiResult.getMsg());
}
return Pair.of(true, "推送成功");
return pushDTO;
}
/**
* 单个用户推送消息(支持H5安卓苹果系统)
* <p>
* 通知消息内容参考https://docs.getui.com/getui/server/rest_v2/common_args/?id=doc-title-6
*
* @param cid 设备id与用户关联的
* @param title 推送标题
* @param content 推送内容
* @param clickType: 点击通知后续动作
* 目前支持以下后续动作
* intent打开应用内特定页面intent和want字段必须填写一个
* url打开网页地址
* payload自定义消息内容启动应用
* payload_custom自定义消息内容不启动应用
* startapp打开应用首页
* none纯通知无后续动作
* @param clickContent
* @return
* 单个用户推送消息
*/
@Override
public Pair<Boolean, Object> pushMessageToSingleByCid(String cid, String title, String content, String clickType, String clickContent) {
//根据cid进行单推
PushDTO pushDTO = new PushDTO<Audience>();
// 设置推送参数
pushDTO.setRequestId(System.currentTimeMillis() + "");
public Pair<Boolean, String> pushMessageToCid(String cid, String title, String content, String clickType, String clickContent) {
try {
if (StrUtil.isBlank(cid) || StrUtil.isBlank(content)) {
log.warn("推送消息时cid 或 content 为空");
return Pair.of(false, "缺少必要参数");
}
title = StrUtil.isBlank(title) ? "小发同城" : title;
/**** 设置个推通道参数 *****/
PushMessage pushMessage = new PushMessage();
pushDTO.setPushMessage(pushMessage);
GTNotification notification = new GTNotification();
pushMessage.setNotification(notification);
notification.setTitle(title);
notification.setBody(content);
notification.setClickType(clickType);
switch (clickType) {
case "url":
notification.setUrl(clickContent);
break;
case "intent":
notification.setIntent(clickContent);
break;
case "want":
notification.setWant(clickContent);
break;
case "payload":
case "payload_custom":
notification.setPayload(clickContent);
break;
case "none":
case "startapp":
default:
break;
PushDTO<Audience> pushDTO = buildPushDTO(null, title, content, clickType, clickContent, Collections.singletonList(cid));
ApiResult<Map<String, Map<String, String>>> apiResult = createPushApi().pushToSingleByCid(pushDTO);
if (!apiResult.isSuccess()) {
log.error("个推推送失败:{}", apiResult);
return Pair.of(false, "个推推送失败:" + JSONUtil.toJsonStr(apiResult));
}
log.debug("推送返回数据:{}", apiResult);
return Pair.of(true, "推送成功");
} catch (Exception e) {
log.error("推送消息到 CID 时发生异常:{}", e.getMessage(), e);
return Pair.of(false, "推送消息失败!");
}
/**** 设置个推通道参数,更多参数请查看文档或对象源码 *****/
/**** 设置厂商相关参数 ****/
PushChannel pushChannel = new PushChannel();
pushDTO.setPushChannel(pushChannel);
/*配置安卓厂商参数*/
AndroidDTO androidDTO = new AndroidDTO();
pushChannel.setAndroid(androidDTO);
Ups ups = new Ups();
androidDTO.setUps(ups);
ThirdNotification thirdNotification = new ThirdNotification();
ups.setNotification(thirdNotification);
thirdNotification.setTitle(title);
thirdNotification.setBody(content);
thirdNotification.setClickType(clickType);
switch (clickType) {
case "url":
thirdNotification.setUrl(clickContent);
break;
case "intent":
thirdNotification.setIntent(clickContent);
break;
case "payload":
case "payload_custom":
thirdNotification.setPayload(clickContent);
break;
case "none":
case "startapp":
default:
break;
}
/*配置安卓厂商参数结束,更多参数请查看文档或对象源码*/
/*设置ios厂商参数*/
IosDTO iosDTO = new IosDTO();
pushChannel.setIos(iosDTO);
// 相同的collapseId会覆盖之前的消息
iosDTO.setApnsCollapseId("xxx");
Aps aps = new Aps();
iosDTO.setAps(aps);
Alert alert = new Alert();
aps.setAlert(alert);
alert.setTitle(title);
alert.setBody(content);
/*设置ios厂商参数结束更多参数请查看文档或对象源码*/
/*设置接收人信息*/
Audience audience = new Audience();
pushDTO.setAudience(audience);
audience.addCid(cid);
/*设置接收人信息结束*/
/**** 设置厂商相关参数,更多参数请查看文档或对象源码 ****/
// 进行cid单推
ApiResult<JSONObject> apiResult = creatPushApi().pushToSingleByCid(pushDTO);
if (!apiResult.isSuccess()) {
log.error("个推推送失败:{}", apiResult);
return Pair.of(false, "个推推送失败:" + JSONUtil.toJsonStr(apiResult));
}
log.debug("推送返回数据:{}", apiResult);
return Pair.of(true, "推送成功,返回数据:" + JSONUtil.toJsonStr(apiResult));
}
}
/**
* 单个用户透传消息
*/
@Override
public Pair<Boolean, String> pushTransmissionToCid(String cid, String transmission) {
try {
if (StrUtil.isBlank(cid) || StrUtil.isBlank(transmission)) {
log.warn("推送消息时cid 或 transmission 为空");
return Pair.of(false, "缺少必要参数");
}
PushDTO<Audience> pushDTO = buildPushDTO(transmission, null, null, null, null, Collections.singletonList(cid));
ApiResult<Map<String, Map<String, String>>> apiResult = createPushApi().pushToSingleByCid(pushDTO);
if (!apiResult.isSuccess()) {
log.error("个推推送失败:{}", apiResult);
return Pair.of(false, "个推推送失败:" + apiResult.getMsg());
}
return Pair.of(true, "推送成功");
} catch (Exception e) {
log.error("推送透传消息到 CID 时发生异常:{}", e.getMessage(), e);
return Pair.of(false, "推送透传消息失败!");
}
}
/**
* 批量用户推送消息
*/
@Override
public Pair<Boolean, String> pushListMessageToCids(List<String> cidList, String title, String content, String clickType, String clickContent) {
try {
if (cidList == null || cidList.isEmpty() || StrUtil.isBlank(content)) {
log.warn("批量推送消息时CIDs 或 content 为空");
return Pair.of(false, "缺少必要参数");
}
PushDTO<Audience> pushDTO = buildPushDTO(null, title, content, clickType, clickContent, cidList);
AudienceDTO audienceDTO = new AudienceDTO();
audienceDTO.setAudience(pushDTO.getAudience());
ApiResult<?> result = createPushApi().pushListByCid(audienceDTO);
if (!result.isSuccess()) {
log.error("批量推送消息失败:{}", result);
return Pair.of(false, result.getMsg());
}
log.info("批量推送消息成功CIDs: {}, result: {}", cidList, result.getData());
return Pair.of(true, "推送成功");
} catch (Exception e) {
log.error("批量推送消息时发生异常:{}", e.getMessage(), e);
return Pair.of(false, "批量推送消息失败!");
}
}
/**
* 批量用户透传消息
*/
@Override
public Pair<Boolean, String> pushListTransmissionToCids(List<String> cidList, String transmission) {
try {
if (cidList == null || cidList.isEmpty() || StrUtil.isBlank(transmission)) {
log.warn("批量推送消息时CIDs 或 transmission 为空");
return Pair.of(false, "缺少必要参数");
}
PushDTO<Audience> pushDTO = buildPushDTO(transmission, null, null, null, null, cidList);
AudienceDTO audienceDTO = new AudienceDTO();
audienceDTO.setAudience(pushDTO.getAudience());
ApiResult<?> result = createPushApi().pushListByCid(audienceDTO);
if (!result.isSuccess()) {
log.error("批量推送透传消息失败:{}", result);
return Pair.of(false, result.getMsg());
}
log.info("批量推送透传消息成功CIDs: {}, result: {}", cidList, result.getData());
return Pair.of(true, "推送成功");
} catch (Exception e) {
log.error("批量推送透传消息时发生异常:{}", e.getMessage(), e);
return Pair.of(false, "批量推送透传消息失败!");
}
}
}

View File

@ -137,4 +137,16 @@ public interface SFExpressApiService {
* @return
*/
ThirdApiRes receiveOrderCompleteNotify(String jsonData, String sign);
/**
* 个推推送消息到员工
*
* @param storeId
* @param orderId
* @param message
* @param payloadJson
* @return
*/
void pushMessage2Employee(Integer storeId, String orderId, String message, String payloadJson);
}

View File

@ -8,6 +8,7 @@
package com.suisung.mall.shop.sfexpress.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
@ -22,6 +23,7 @@ import com.suisung.mall.common.modules.store.ShopStoreSameCityTransportBase;
import com.suisung.mall.common.modules.store.ShopStoreSfOrder;
import com.suisung.mall.common.pojo.req.*;
import com.suisung.mall.common.pojo.res.ThirdApiRes;
import com.suisung.mall.common.service.GeTuiPushService;
import com.suisung.mall.common.utils.CommonUtil;
import com.suisung.mall.common.utils.I18nUtil;
import com.suisung.mall.common.utils.JsonUtil;
@ -29,6 +31,7 @@ import com.suisung.mall.common.utils.SseEmitterUtil;
import com.suisung.mall.shop.order.service.ShopOrderBaseService;
import com.suisung.mall.shop.order.service.ShopOrderInfoService;
import com.suisung.mall.shop.sfexpress.service.SFExpressApiService;
import com.suisung.mall.shop.store.service.ShopStoreEmployeeService;
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService;
import com.suisung.mall.shop.store.service.ShopStoreSfOrderService;
import com.suisung.mall.shop.wechat.service.WxOrderShippingService;
@ -75,6 +78,14 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
@Autowired
private WxOrderShippingService wxOrderShippingService;
@Lazy
@Autowired
private ShopStoreEmployeeService shopStoreEmployeeService;
@Lazy
@Autowired
private GeTuiPushService geTuiPushService;
@Override
public ThirdApiRes createOrder(String shopOrderId) {
// 组织请求参数
@ -697,11 +708,41 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
// 状态更改之后 SSE 监听服务发送更改的数据
// logger.debug("准备发送SSE消息...");
SseEmitterUtil.sendMessage(shopStoreSfOrder.getSf_order_id(), jsonData);
// SseEmitterUtil.sendMessage(shopStoreSfOrder.getSf_order_id(), jsonData);
// 个推消息推送
pushMessage2Employee(null, shopStoreSfOrder.getShop_order_id(), "顺丰同城订单[" + shopStoreSfOrder.getShop_order_id() + "]已完成配送。", jsonData);
return new ThirdApiRes().success("success");
}
/**
* 个推推送消息到员工
*
* @param storeId
* @param orderId
* @param message
* @param payloadJson
* @return
*/
@Override
public void pushMessage2Employee(Integer storeId, String orderId, String message, String payloadJson) {
try {
List<String> cidList = shopStoreEmployeeService.selectEmployeeGeTuiCidByStoreId(storeId, orderId, false);
if (CollUtil.isEmpty(cidList)) {
logger.error("获取不到店铺员工,无法推送消息!");
return;
}
// 推送消息到员工
Pair<Boolean, String> result = geTuiPushService.pushListMessageToCids(cidList, "", message, "payload", payloadJson);
if (!result.getFirst()) {
logger.error("推送消息到员工失败:{}", result.getSecond());
}
} catch (Exception e) {
logger.error("推送消息到员工时发生异常:{}", e.getMessage(), e);
}
}
// 私有方法

View File

@ -27,4 +27,15 @@ public interface ShopStoreEmployeeMapper extends BaseMapper<ShopStoreEmployee> {
* @return
*/
List<Integer> selectByStoreIdRightGroupId(@Param("storeId") Integer storeId, @Param("groupId") Integer groupId);
/**
* 根据店铺Id获取店铺的所有员工的个推 CID 列表
*
* @param storeId 店铺Id 可选参数 ,storeId orderId 必选一个
* @param orderId 订单号 可选参数,storeId orderId 必选一个
* @param isAdmin 是否管理员可选参数
* @return
*/
List<String> selectEmployeeGeTuiCidByStoreId(@Param("storeId") Integer storeId, @Param("orderId") String orderId, @Param("isAdmin") Boolean isAdmin);
}

View File

@ -38,4 +38,14 @@ public interface ShopStoreEmployeeService extends IBaseService<ShopStoreEmployee
*/
List<Integer> selectEmployeeByStoreId(Integer storeId, String rightsGroupName);
/**
* 根据店铺Id获取店铺的所有员工的个推 CID 列表
*
* @param storeId 店铺Id可选参数 ,storeId orderId 必选一个
* @param orderId 订单号可选参数
* @param isAdmin 是否管理员可选参数
* @return
*/
List<String> selectEmployeeGeTuiCidByStoreId(Integer storeId, String orderId, Boolean isAdmin);
}

View File

@ -19,12 +19,14 @@ import com.suisung.mall.common.modules.store.ShopStoreEmployee;
import com.suisung.mall.common.modules.store.ShopStoreEmployeeRightsGroup;
import com.suisung.mall.common.utils.CheckUtil;
import com.suisung.mall.common.utils.I18nUtil;
import com.suisung.mall.core.web.service.RedisService;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.store.mapper.ShopStoreEmployeeMapper;
import com.suisung.mall.shop.store.service.ShopStoreEmployeeRightsGroupService;
import com.suisung.mall.shop.store.service.ShopStoreEmployeeService;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -45,9 +47,6 @@ import static com.suisung.mall.common.utils.ContextUtil.getCurrentUser;
@Service
public class ShopStoreEmployeeServiceImpl extends BaseServiceImpl<ShopStoreEmployeeMapper, ShopStoreEmployee> implements ShopStoreEmployeeService {
// @Autowired
// private ShopStoreEmployeeService shopStoreEmployeeService;
@Autowired
private AccountService accountService;
@ -57,6 +56,10 @@ public class ShopStoreEmployeeServiceImpl extends BaseServiceImpl<ShopStoreEmplo
@Autowired
private ShopStoreEmployeeMapper shopStoreEmployeeMapper;
@Lazy
@Autowired
private RedisService redisService;
@Override
public Map getList(QueryWrapper<ShopStoreEmployee> wrapper, Integer pageNum, Integer pageSize) {
@ -232,4 +235,38 @@ public class ShopStoreEmployeeServiceImpl extends BaseServiceImpl<ShopStoreEmplo
return shopStoreEmployeeMapper.selectByStoreIdRightGroupId(storeId, rightsGroupId);
}
/**
* 根据店铺Id获取店铺的所有员工的个推 CID 列表
*
* @param storeId 店铺Id 可选参数 ,storeId orderId 必选一个
* @param orderId 订单号 可选参数,storeId orderId 必选一个
* @param isAdmin 是否管理员可选参数
* @return
*/
@Override
public List<String> selectEmployeeGeTuiCidByStoreId(Integer storeId, String orderId, Boolean isAdmin) {
// 如果店铺ID为空直接返回空列表
if ((ObjectUtil.isEmpty(storeId) || storeId <= 0) && StrUtil.isBlank(orderId)) {
return Collections.emptyList();
}
// 构建缓存键
String cacheKey = "mall:shop:store:employee:getui-cid:" + storeId + orderId + ":" + isAdmin;
// 从缓存中获取员工的个推CID列表
List<String> employeeGeTuiCids = (List<String>) redisService.get(cacheKey);
// 如果缓存中没有数据则从数据库查询并更新缓存
if (CollUtil.isEmpty(employeeGeTuiCids)) {
employeeGeTuiCids = shopStoreEmployeeMapper.selectEmployeeGeTuiCidByStoreId(storeId, orderId, isAdmin);
if (CollUtil.isNotEmpty(employeeGeTuiCids)) {
redisService.set(cacheKey, employeeGeTuiCids, 600000); // 缓存有效期10分钟
} else {
employeeGeTuiCids = Collections.emptyList(); // 如果查询结果为空返回空列表
}
}
return employeeGeTuiCids;
}
}

View File

@ -1,14 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.suisung.mall.shop.store.mapper.ShopStoreEmployeeMapper">
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
employee_id, store_id, user_id, rights_group_id, employee_is_admin, employee_login_time, employee_is_kefu
employee_id
, store_id, user_id, rights_group_id, employee_is_admin, employee_login_time, employee_is_kefu
</sql>
<select id="selectByStoreIdRightGroupId" resultType="Integer">
SELECT user_id
FROM shop_store_employee a
@ -22,4 +21,25 @@
</where>
</select>
<select id="selectEmployeeGeTuiCidByStoreId" resultType="String">
SELECT b.cid
FROM shop_store_employee a
JOIN account_user_bind_getui b on a.user_id = b.user_id
<if test="orderId!=null and orderId!=''">
JOIN shop_order_base c on a.store_id= c.store_id
</if>
<where>
<if test="storeId!=null and storeId>0">
and a.store_id = #{storeId}
</if>
<if test="orderId!=null and orderId!=''">
and c.order_id = #{orderId}
</if>
<if test="isAdmin!=null and isAdmin==true">
and a.employee_is_admin = 1
</if>
</where>
</select>
</mapper>