| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- package com.ruoyi.app.flashdelivery.service;
- import com.ruoyi.app.order.dto.OrderPushBodyDto;
- import com.ruoyi.app.utils.PayPush;
- import com.ruoyi.app.utils.event.PushEventService;
- import com.ruoyi.common.core.domain.entity.SysDictData;
- import com.ruoyi.common.utils.DictUtils;
- import com.ruoyi.framework.manager.AsyncManager;
- import com.ruoyi.system.domain.InfoUser;
- import com.ruoyi.system.domain.RiderPosition;
- import com.ruoyi.system.domain.flash.FlashDeliveryOrder;
- import com.ruoyi.system.mapper.InfoUserMapper;
- import com.ruoyi.system.mapper.RiderPositionMapper;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.support.TransactionSynchronization;
- import org.springframework.transaction.support.TransactionSynchronizationManager;
- import java.util.List;
- import java.util.TimerTask;
- import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.ACCEPTED;
- import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.CANCELLED;
- import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.DELIVERED;
- import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.PICKED_UP;
- import static com.ruoyi.system.domain.flash.FlashDeliveryStatus.WAITING_ACCEPTANCE;
- /**
- * 闪送订单消息推送:可抢新单推符合条件的骑手,履约事件推寄件用户,取消事件推接单骑手。
- * 推送统一在事务提交后异步执行,失败仅记日志,不影响订单状态流转本身。
- */
- @Service
- public class FlashDeliveryNotificationService {
- private static final Logger log = LoggerFactory.getLogger(FlashDeliveryNotificationService.class);
- private static final String TITLE_KEY = "no.message.push.message";
- private static final String CONTENT_ACCEPTED = "no.message.push.delivery.personnel.receiving.order";
- private static final String CONTENT_PICKED_UP = "no.message.push.delivery.personnel.qspsz.order";
- private static final String CONTENT_DELIVERED = "no.message.push.delivery.personnel.qsysd.order";
- private static final String CONTENT_CANCELLED = "no.message.push.order.cancelled";
- private static final String CONTENT_AVAILABLE = "no.message.push.new.flash.order";
- private static final int RIDER_NOTIFICATION_LIMIT = 20;
- /** 推送 payload 的业务类型:1=外卖、2=充值,3=闪送。 */
- private static final int PUSH_TYPE_FLASH = 3;
- /** -1 表示非语音提醒;0 表示骑手新单提醒。 */
- private static final int PUSH_PAYLOAD_TYPE_NONE = -1;
- private final InfoUserMapper userMapper;
- private final PushEventService pushEventService;
- private final RiderPositionMapper riderPositionMapper;
- public FlashDeliveryNotificationService(InfoUserMapper userMapper, PushEventService pushEventService) {
- this(userMapper, pushEventService, null);
- }
- @Autowired
- public FlashDeliveryNotificationService(InfoUserMapper userMapper, PushEventService pushEventService,
- RiderPositionMapper riderPositionMapper) {
- this.userMapper = userMapper;
- this.pushEventService = pushEventService;
- this.riderPositionMapper = riderPositionMapper;
- }
- /** 按订单取寄件用户;订单或用户缺失时静默跳过。 */
- InfoUser senderOf(FlashDeliveryOrder order) {
- if (order == null || order.getUserId() == null) return null;
- return userMapper.selectById(order.getUserId());
- }
- /** 按订单取接单骑手;未接单(riderId 为空)或骑手缺失时静默跳过。 */
- InfoUser riderOf(FlashDeliveryOrder order) {
- if (order == null || order.getRiderId() == null) return null;
- return userMapper.selectById(order.getRiderId());
- }
- /** 向寄件用户推送指定状态文案;消息入库由通道内 PublisherEvent 完成,cid 为空时仅入库。 */
- void sendToUser(InfoUser recipient, FlashDeliveryOrder order, String status, String contentKey) {
- if (recipient == null || recipient.getUserId() == null) return;
- String orderNo = order.getOrderNo();
- String body = OrderPushBodyDto.getJson(orderNo, status, PUSH_PAYLOAD_TYPE_NONE, PUSH_TYPE_FLASH);
- AsyncManager.me().execute(new TimerTask() {
- @Override
- public void run() {
- try {
- PayPush.userPushHandleLocal(new PayPush(), pushEventService, recipient.getUserId(),
- recipient.getCid(), TITLE_KEY, contentKey, body, "", orderNo);
- } catch (Exception e) {
- log.error("闪送用户推送失败,userId:{}, orderNo:{}", recipient.getUserId(), orderNo, e);
- }
- }
- });
- }
- /** 向接单骑手推送指定状态文案;与用户端一致,失败仅记日志。 */
- void sendToRider(InfoUser recipient, FlashDeliveryOrder order, String status, String contentKey) {
- sendToRider(recipient, order, status, contentKey, PUSH_PAYLOAD_TYPE_NONE);
- }
- private void sendToRider(InfoUser recipient, FlashDeliveryOrder order, String status,
- String contentKey, int payloadType) {
- if (recipient == null || recipient.getUserId() == null) return;
- String orderNo = order.getOrderNo();
- String body = OrderPushBodyDto.getJson(orderNo, status, payloadType, PUSH_TYPE_FLASH);
- AsyncManager.me().execute(new TimerTask() {
- @Override
- public void run() {
- try {
- PayPush.qsPushHandleLocal(new PayPush(), pushEventService, recipient.getUserId(),
- recipient.getCid(), TITLE_KEY, contentKey, body, "", orderNo);
- } catch (Exception e) {
- log.error("闪送骑手推送失败,riderId:{}, orderNo:{}", recipient.getUserId(), orderNo, e);
- }
- }
- });
- }
- /** 向一名可接单骑手发送闪送新单提醒;type=0 保留骑手端新单语音语义。 */
- void sendAvailableOrderToRider(RiderPosition rider, FlashDeliveryOrder order) {
- if (rider == null || rider.getRiderId() == null) return;
- InfoUser recipient = new InfoUser();
- recipient.setUserId(rider.getRiderId());
- recipient.setCid(rider.getCid());
- sendToRider(recipient, order, WAITING_ACCEPTANCE, CONTENT_AVAILABLE, 0);
- }
- /** 订单已向骑手开放后,通知附近最多 20 名符合闪送接单条件的骑手。 */
- public void notifyAvailable(FlashDeliveryOrder order) {
- if (order == null || riderPositionMapper == null || !WAITING_ACCEPTANCE.equals(order.getStatus())
- || !Boolean.TRUE.equals(order.getIsDisplay()) || order.getRiderId() != null
- || order.getPickupLongitude() == null || order.getPickupLatitude() == null) {
- return;
- }
- runAfterCommit(() -> {
- int vehicleType = Integer.valueOf(2).equals(order.getVehicleType()) ? 2 : 1;
- List<RiderPosition> riders = riderPositionMapper.getFlashRiderNotificationList(
- order.getPickupLongitude(), order.getPickupLatitude(), vehicleType,
- order.getDeliveryType(), newTaskDistanceLimit(), RIDER_NOTIFICATION_LIMIT);
- if (riders != null) {
- riders.forEach(rider -> sendAvailableOrderToRider(rider, order));
- }
- });
- }
- /** 骑手抢单成功后通知寄件用户;未解析到寄件用户时跳过。 */
- public void notifyAccepted(FlashDeliveryOrder order) {
- runAfterCommit(() -> {
- InfoUser sender = senderOf(order);
- if (sender != null) sendToUser(sender, order, ACCEPTED, CONTENT_ACCEPTED);
- });
- }
- /** 骑手取件成功后通知寄件用户;未解析到寄件用户时跳过。 */
- public void notifyPickedUp(FlashDeliveryOrder order) {
- runAfterCommit(() -> {
- InfoUser sender = senderOf(order);
- if (sender != null) sendToUser(sender, order, PICKED_UP, CONTENT_PICKED_UP);
- });
- }
- /** 骑手送达后通知寄件用户;未解析到寄件用户时跳过。 */
- public void notifyDelivered(FlashDeliveryOrder order) {
- runAfterCommit(() -> {
- InfoUser sender = senderOf(order);
- if (sender != null) sendToUser(sender, order, DELIVERED, CONTENT_DELIVERED);
- });
- }
- /** 订单取消后通知接单骑手;未接单(无骑手归属)或骑手缺失时跳过,寄件用户不推。 */
- public void notifyCancelled(FlashDeliveryOrder order) {
- runAfterCommit(() -> {
- InfoUser rider = riderOf(order);
- if (rider != null) sendToRider(rider, order, CANCELLED, CONTENT_CANCELLED);
- });
- }
- /** 仅事务提交后执行推送准备;无事务同步时(单测)直接执行。 */
- static void runAfterCommit(Runnable action) {
- if (!TransactionSynchronizationManager.isSynchronizationActive()) {
- action.run();
- return;
- }
- TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
- @Override
- public void afterCommit() {
- action.run();
- }
- });
- }
- private Integer newTaskDistanceLimit() {
- try {
- List<SysDictData> values = DictUtils.getDictCache("sys_qs_newtask_distance");
- if (values != null && !values.isEmpty()) {
- int limit = Integer.parseInt(values.get(0).getDictValue());
- return limit > 0 ? limit : null;
- }
- } catch (Exception ignored) {
- // 与骑手新任务列表保持一致:缺失或非法配置时不限制距离。
- }
- return null;
- }
- }
|