From 07f2cb3f0c2ead924587ec5988622a65e86ec7df Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Tue, 10 Jun 2025 17:48:15 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AA=E6=8E=A8=E6=8E=A8=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../account/controller/LoginController.java | 2 +- .../service/AccountUserBindGeTuiService.java | 2 +- .../impl/AccountUserBaseServiceImpl.java | 6 +- .../impl/AccountUserBindGeTuiServiceImpl.java | 35 +- .../mall/common/service/GeTuiPushService.java | 35 +- .../service/impl/GeTuiPushServiceImpl.java | 477 ++++++------------ .../service/SFExpressApiService.java | 12 + .../service/impl/SFExpressApiServiceImpl.java | 43 +- .../store/mapper/ShopStoreEmployeeMapper.java | 11 + .../service/ShopStoreEmployeeService.java | 10 + .../impl/ShopStoreEmployeeServiceImpl.java | 43 +- .../mapper/store/ShopStoreEmployeeMapper.xml | 26 +- 12 files changed, 343 insertions(+), 359 deletions(-) diff --git a/mall-account/src/main/java/com/suisung/mall/account/controller/LoginController.java b/mall-account/src/main/java/com/suisung/mall/account/controller/LoginController.java index df097d8b..af43b6e7 100644 --- a/mall-account/src/main/java/com/suisung/mall/account/controller/LoginController.java +++ b/mall-account/src/main/java/com/suisung/mall/account/controller/LoginController.java @@ -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) diff --git a/mall-account/src/main/java/com/suisung/mall/account/service/AccountUserBindGeTuiService.java b/mall-account/src/main/java/com/suisung/mall/account/service/AccountUserBindGeTuiService.java index 4432d88a..2405d7e1 100644 --- a/mall-account/src/main/java/com/suisung/mall/account/service/AccountUserBindGeTuiService.java +++ b/mall-account/src/main/java/com/suisung/mall/account/service/AccountUserBindGeTuiService.java @@ -7,7 +7,7 @@ import java.util.List; public interface AccountUserBindGeTuiService extends IBaseService { - Boolean addOrUpdate(AccountUserBindGeTui accountUserBindGeTui); + Boolean saveAccountUserBindGeTui(AccountUserBindGeTui accountUserBindGeTui); List getActive(AccountUserBindGeTui accountUserBindGeTui); } diff --git a/mall-account/src/main/java/com/suisung/mall/account/service/impl/AccountUserBaseServiceImpl.java b/mall-account/src/main/java/com/suisung/mall/account/service/impl/AccountUserBaseServiceImpl.java index 856706eb..8a643ce5 100644 --- a/mall-account/src/main/java/com/suisung/mall/account/service/impl/AccountUserBaseServiceImpl.java +++ b/mall-account/src/main/java/com/suisung/mall/account/service/impl/AccountUserBaseServiceImpl.java @@ -227,7 +227,7 @@ public class AccountUserBaseServiceImpl extends BaseServiceImpl 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 wrapper = new QueryWrapper() .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; } } diff --git a/mall-common/src/main/java/com/suisung/mall/common/service/GeTuiPushService.java b/mall-common/src/main/java/com/suisung/mall/common/service/GeTuiPushService.java index 1c21533d..ce15bbf4 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/service/GeTuiPushService.java +++ b/mall-common/src/main/java/com/suisung/mall/common/service/GeTuiPushService.java @@ -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 pushTransmissionToSingleByCid(String cid, String transmission); + Pair pushTransmissionToCid(String cid, String transmission); /** * 单个用户推送消息(支持H5、安卓、苹果系统) @@ -40,5 +42,34 @@ public interface GeTuiPushService { * @param clickContent * @return */ - Pair pushMessageToSingleByCid(String cid, String title, String content, String clickType, String clickContent); + Pair 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 pushListMessageToCids(List cidList, String title, String content, String clickType, String clickContent); + + /** + * 批量用户透传消息(支持H5、安卓、苹果系统) + * + * @param cidList + * @param transmission 透传消息 txt json 格式 + * @return + */ + Pair pushListTransmissionToCids(List cidList, String transmission); + } diff --git a/mall-common/src/main/java/com/suisung/mall/common/service/impl/GeTuiPushServiceImpl.java b/mall-common/src/main/java/com/suisung/mall/common/service/impl/GeTuiPushServiceImpl.java index 355f0f80..f0baa44b 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/service/impl/GeTuiPushServiceImpl.java +++ b/mall-common/src/main/java/com/suisung/mall/common/service/impl/GeTuiPushServiceImpl.java @@ -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 buildPushDTO(String transmission, String title, String content, String clickType, String clickContent, List cidList) { + PushDTO 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 pushDTO = new PushDTO<>(); - pushDTO.setPushChannel(pushChannel); - pushDTO.setPushMessage(pushMessage); - pushDTO.setAudience(audience); - pushDTO.setRequestId(UUID.randomUUID().toString()); // 设置唯一请求 ID - - // 调用个推 API 发送消息 - ApiResult>> 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 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 pushDTO = new PushDTO<>(); - pushDTO.setPushChannel(pushChannel); - pushDTO.setPushMessage(pushMessage); - pushDTO.setAudience(audience); - pushDTO.setRequestId(UUID.randomUUID().toString()); // 设置唯一请求 ID - - // 调用个推 API 发送消息 - ApiResult>> 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 pushTransmissionToSingleByCid(String cid, String transmission) { - PushDTO pushDTO = new PushDTO(); - // 设置推送参数 - 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 apiResult = creatPushApi().pushToSingleByCid(pushDTO); - if (!apiResult.isSuccess()) { - log.error("个推推送失败:{}", apiResult); - return Pair.of(false, "个推推送失败:" + apiResult.getMsg()); - } - - return Pair.of(true, "推送成功"); + return pushDTO; } /** - * 单个用户推送消息(支持H5、安卓、苹果系统) - *

- * 通知消息内容参考: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 pushMessageToSingleByCid(String cid, String title, String content, String clickType, String clickContent) { - //根据cid进行单推 - PushDTO pushDTO = new PushDTO(); - // 设置推送参数 - pushDTO.setRequestId(System.currentTimeMillis() + ""); + public Pair 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 pushDTO = buildPushDTO(null, title, content, clickType, clickContent, Collections.singletonList(cid)); + ApiResult>> 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 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 pushTransmissionToCid(String cid, String transmission) { + try { + if (StrUtil.isBlank(cid) || StrUtil.isBlank(transmission)) { + log.warn("推送消息时,cid 或 transmission 为空"); + return Pair.of(false, "缺少必要参数"); + } + + PushDTO pushDTO = buildPushDTO(transmission, null, null, null, null, Collections.singletonList(cid)); + ApiResult>> 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 pushListMessageToCids(List 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 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 pushListTransmissionToCids(List cidList, String transmission) { + try { + if (cidList == null || cidList.isEmpty() || StrUtil.isBlank(transmission)) { + log.warn("批量推送消息时,CIDs 或 transmission 为空"); + return Pair.of(false, "缺少必要参数"); + } + + PushDTO 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, "批量推送透传消息失败!"); + } + } +} \ No newline at end of file diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/SFExpressApiService.java b/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/SFExpressApiService.java index 73eb6675..0b287bb3 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/SFExpressApiService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/SFExpressApiService.java @@ -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); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java index e56cbfb4..a575fa7f 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java @@ -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 cidList = shopStoreEmployeeService.selectEmployeeGeTuiCidByStoreId(storeId, orderId, false); + if (CollUtil.isEmpty(cidList)) { + logger.error("获取不到店铺员工,无法推送消息!"); + return; + } + + // 推送消息到员工 + Pair result = geTuiPushService.pushListMessageToCids(cidList, "", message, "payload", payloadJson); + if (!result.getFirst()) { + logger.error("推送消息到员工失败:{}", result.getSecond()); + } + } catch (Exception e) { + logger.error("推送消息到员工时发生异常:{}", e.getMessage(), e); + } + } + // 私有方法 diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/mapper/ShopStoreEmployeeMapper.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/mapper/ShopStoreEmployeeMapper.java index af955f85..bc3315d8 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/mapper/ShopStoreEmployeeMapper.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/mapper/ShopStoreEmployeeMapper.java @@ -27,4 +27,15 @@ public interface ShopStoreEmployeeMapper extends BaseMapper { * @return */ List selectByStoreIdRightGroupId(@Param("storeId") Integer storeId, @Param("groupId") Integer groupId); + + + /** + * 根据店铺Id获取店铺的所有员工的个推 CID 列表 + * + * @param storeId 店铺Id 可选参数 ,storeId 和 orderId 必选一个 + * @param orderId 订单号 可选参数,storeId 和 orderId 必选一个 + * @param isAdmin 是否管理员?可选参数 + * @return + */ + List selectEmployeeGeTuiCidByStoreId(@Param("storeId") Integer storeId, @Param("orderId") String orderId, @Param("isAdmin") Boolean isAdmin); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreEmployeeService.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreEmployeeService.java index 023c7232..fef8f900 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreEmployeeService.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopStoreEmployeeService.java @@ -38,4 +38,14 @@ public interface ShopStoreEmployeeService extends IBaseService selectEmployeeByStoreId(Integer storeId, String rightsGroupName); + /** + * 根据店铺Id获取店铺的所有员工的个推 CID 列表 + * + * @param storeId 店铺Id,可选参数 ,storeId 和 orderId 必选一个 + * @param orderId 订单号,可选参数 + * @param isAdmin 是否管理员?可选参数 + * @return + */ + List selectEmployeeGeTuiCidByStoreId(Integer storeId, String orderId, Boolean isAdmin); + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreEmployeeServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreEmployeeServiceImpl.java index c4ee8546..8e8792ba 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreEmployeeServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreEmployeeServiceImpl.java @@ -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 implements ShopStoreEmployeeService { -// @Autowired -// private ShopStoreEmployeeService shopStoreEmployeeService; - @Autowired private AccountService accountService; @@ -57,6 +56,10 @@ public class ShopStoreEmployeeServiceImpl extends BaseServiceImpl wrapper, Integer pageNum, Integer pageSize) { @@ -232,4 +235,38 @@ public class ShopStoreEmployeeServiceImpl extends BaseServiceImpl 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 employeeGeTuiCids = (List) 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; + } } diff --git a/mall-shop/src/main/resources/mapper/store/ShopStoreEmployeeMapper.xml b/mall-shop/src/main/resources/mapper/store/ShopStoreEmployeeMapper.xml index 0f3eea12..b0ea2c3e 100644 --- a/mall-shop/src/main/resources/mapper/store/ShopStoreEmployeeMapper.xml +++ b/mall-shop/src/main/resources/mapper/store/ShopStoreEmployeeMapper.xml @@ -1,14 +1,13 @@ - - 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 - +