SSE 消息开发

This commit is contained in:
Jack 2024-12-21 00:30:44 +08:00
parent 0ec8e3f0a8
commit 85d06fc9b0
11 changed files with 271 additions and 78 deletions

View File

@ -0,0 +1,100 @@
package com.suisung.mall.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
@Slf4j
public class SseEmitterUtil {
//当前连接数
public static final AtomicInteger count = new AtomicInteger(0);
//使用 map 对象便于根据 userId 来获取对应的 SseEmitter或者放 redis 里面
public static final Map<String, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();
/**
* 创建用户连接并返回 SseEmitter
*
* @param channel 通道
*/
public static SseEmitter connect(String channel) {
//设置超时时间0表示不过期默认30秒超过时间未完成会抛出异常AsyncRequestTimeoutException
SseEmitter sseEmitter = new SseEmitter(1200000L); // 20分钟
try {
//注册回调完成失败超时
sseEmitter.onCompletion(completionCallBack(channel));
sseEmitter.onError(errorCallBack(channel));
sseEmitter.onTimeout(timeoutCallBack(channel));
// 缓存
sseEmitterMap.put(channel, sseEmitter);
// 数量+1
count.getAndIncrement();
log.debug("创建新的sse连接当前通道{}", channel);
} catch (Exception e) {
log.error("创建新的sse连接异常当前通道{}", channel);
}
return sseEmitter;
}
/**
* 给指定通道发送信息
*/
public static SseEmitter sendMessage(String channel, String message) {
SseEmitter sseEmitter = sseEmitterMap.get(channel);
if (sseEmitter == null) {
sseEmitter = connect(channel);
}
try {
sseEmitter.send(message);
log.info("向通道:{} 发送了:{}", channel, message);
return sseEmitter;
} catch (IOException e) {
log.error("通道:{} 推送异常:{}", channel, e.getMessage());
removeChannel(channel);
return null;
}
}
/**
* 移除通道连接
*/
public static void removeChannel(String channel) {
sseEmitterMap.remove(channel);
// 数量-1
count.getAndDecrement();
log.debug("移除通道:{}", channel);
}
/**
* 获取当前连接数量
*/
public static int getUserCount() {
return count.intValue();
}
private static Runnable completionCallBack(String channel) {
return () -> {
log.debug("结束连接:{}", channel);
removeChannel(channel);
};
}
private static Runnable timeoutCallBack(String channel) {
return () -> {
log.error("连接超时:{}", channel);
removeChannel(channel);
};
}
private static Consumer<Throwable> errorCallBack(String channel) {
return throwable -> {
log.error("连接异常:{}", channel);
removeChannel(channel);
};
}
}

View File

@ -1,5 +1,7 @@
package com.suisung.mall.common.utils;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -12,6 +14,8 @@ import java.util.Date;
import java.util.Locale;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 字符串工具类继承lang3字符串工具类
@ -20,7 +24,18 @@ import java.util.UUID;
*/
public final class StringUtils extends org.apache.commons.lang3.StringUtils {
private static Logger logger = LoggerFactory.getLogger(StringUtils.class);
public static void main(String[] args) {
System.out.println(removeProvinceCityDistrict("广西壮族自治区贵港市桂平市西山镇新安街粤桂花城1102号"));
}
/**
* 随机字符串
*/
private static final String INT_TEMP = "0123456789";
private static final String STR_TEMP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static final String ALL_TEMP = INT_TEMP + STR_TEMP;
private static final Random RANDOM = new Random();
private static final Logger logger = LoggerFactory.getLogger(StringUtils.class);
public static String encode(String str) {
String encode = null;
@ -41,7 +56,6 @@ public final class StringUtils extends org.apache.commons.lang3.StringUtils {
return UUID.randomUUID().toString().replace("-", "");
}
/**
* 要求外部订单号必须唯一
*
@ -97,33 +111,6 @@ public final class StringUtils extends org.apache.commons.lang3.StringUtils {
return txt.replaceAll("[   `·•<C2B7>\\f\\t\\v]", "");
}
/**
* 随机字符串
*/
private static final String INT_TEMP = "0123456789";
private static final String STR_TEMP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
private static final String ALL_TEMP = INT_TEMP + STR_TEMP;
private static final Random RANDOM = new Random();
/**
* 生成的随机数类型
*/
public enum RandomType {
/**
* 整数
*/
INT,
/**
* 字符串
*/
STRING,
/**
* 所有类型
*/
ALL
}
/**
* 随机数生成
*
@ -170,12 +157,11 @@ public final class StringUtils extends org.apache.commons.lang3.StringUtils {
return "";
}
public static String[] shortUrl(String url) {
// 可以自定义生成 MD5 加密字符传前的混合 KEY
String key = "alexis";
// 要使用生成 URL 的字符
String[] chars = new String[] { "a", "b", "c", "d", "e", "f", "g", "h",
String[] chars = new String[]{"a", "b", "c", "d", "e", "f", "g", "h",
"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
"u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H",
@ -208,8 +194,10 @@ public final class StringUtils extends org.apache.commons.lang3.StringUtils {
}
return resUrl;
}
/**
* MD5加密(32位大写)
*
* @param src
* @return
*/
@ -235,4 +223,55 @@ public final class StringUtils extends org.apache.commons.lang3.StringUtils {
return "";
}
}
/**
* 全地址去除省市区保留详细地址
* @param fullAddress 比如广西壮族自治区贵港市桂平市西山镇新安街粤桂花城1102号 -> 西山镇新安街粤桂花城1102号
* @return
*/
public static String removeProvinceCityDistrict(String fullAddress) {
if (StrUtil.isBlank(fullAddress)) {
return "";
}
// 使用正则表达式匹配省市区信息
Pattern pattern = Pattern.compile("(.*?省|.*?自治区)?(.*?市|.*?自治州)?(.*?区|.*?县|.*?市辖区|.*?市)?");
Matcher matcher = pattern.matcher(fullAddress);
if (!matcher.find()) {
return fullAddress;
}
if (matcher.group(1) != null) {
fullAddress = fullAddress.replace(matcher.group(1), "");
}
if (matcher.group(2) != null) {
fullAddress = fullAddress.replace(matcher.group(2), "");
}
if (matcher.group(3) != null) {
fullAddress = fullAddress.replace(matcher.group(3), "");
}
return fullAddress;
}
/**
* 生成的随机数类型
*/
public enum RandomType {
/**
* 整数
*/
INT,
/**
* 字符串
*/
STRING,
/**
* 所有类型
*/
ALL
}
}

6
mall-shop/README.MD Normal file
View File

@ -0,0 +1,6 @@
项目备份录
account_user_bind_connect 用户手机、邮件、微博、QQ、微信绑定表
admin_base_protocol
admin_rights_base
权限赋值的表

View File

@ -8370,6 +8370,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
// 顺丰同城给的测试店铺id
String shopId = "3243279847393";
//3269768224353 到时启用这个正式店铺 type:便利店
Integer businessType = 6;// 生鲜分类
if (enable_sf_express.equals(CommonConstant.Enable)) {//开启正式配送服务的时候
// 顺丰同城业务员给的店铺id
@ -8431,6 +8432,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
SFOrderShopReq shop = new SFOrderShopReq();
SFOrderReceiveReq receive = new SFOrderReceiveReq();
if (enable_sf_express.equals(CommonConstant.Enable)) {//开启正式配送服务的时候
// 店铺信息发货人信息
Pair<Boolean, StandardAddressDTO> pairShopAddr = shopStoreBaseService.checkStoreAddress(shopStoreBase);
shop.setShop_name(shopStoreBase.getStore_name());
@ -8438,6 +8440,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
shop.setShop_address(pairShopAddr.getSecond().getFullAddress());
shop.setShop_lng(pairShopAddr.getSecond().getLongitude());
shop.setShop_lat(pairShopAddr.getSecond().getLatitude());
// 收货人信息
Pair<Boolean, StandardAddressDTO> pairReceiveAddr = shopOrderDeliveryAddressService.checkAddress(shopOrderDeliveryAddress);
receive.setUser_name(shopOrderDeliveryAddress.getDa_name());
@ -8445,6 +8448,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
receive.setUser_address(pairReceiveAddr.getSecond().getFullAddress());
receive.setUser_lng(pairReceiveAddr.getSecond().getLongitude());
receive.setUser_lat(pairReceiveAddr.getSecond().getLatitude());
} else {
// 店铺信息发货人信息
shop.setShop_name("顺丰同城开放平台");

View File

@ -3,6 +3,7 @@ package com.suisung.mall.shop.order.service.impl;
import cn.hutool.core.util.StrUtil;
import com.suisung.mall.common.modules.order.ShopOrderDeliveryAddress;
import com.suisung.mall.common.pojo.dto.StandardAddressDTO;
import com.suisung.mall.common.utils.StringUtils;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.order.mapper.ShopOrderDeliveryAddressMapper;
import com.suisung.mall.shop.order.service.ShopOrderDeliveryAddressService;
@ -58,7 +59,7 @@ public class ShopOrderDeliveryAddressServiceImpl extends BaseServiceImpl<ShopOrd
sb.append(shopOrderDeliveryAddress.getDa_county());
}
if(StrUtil.isNotBlank(shopOrderDeliveryAddress.getDa_address())){
sb.append(shopOrderDeliveryAddress.getDa_address());
sb.append(StringUtils.removeProvinceCityDistrict(shopOrderDeliveryAddress.getDa_address()));
}

View File

@ -8,18 +8,27 @@
package com.suisung.mall.shop.sfexpress.controller.api;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.pojo.res.SFExpressApiRes;
import com.suisung.mall.common.utils.SseEmitterUtil;
import com.suisung.mall.shop.sfexpress.service.SFExpressApiService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.CopyOnWriteArrayList;
@Api(tags = "顺丰同城Api端")
@RestController
@RequestMapping("/shop/sf-express")
public class SFExpressApiController {
private final CopyOnWriteArrayList<SseEmitter> emitters = new CopyOnWriteArrayList<>();
@Autowired
private SFExpressApiService sfExpressApiService;

View File

@ -8,15 +8,15 @@
package com.suisung.mall.shop.sfexpress.controller.mobile;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.pojo.res.SFExpressApiRes;
import com.suisung.mall.common.utils.SseEmitterUtil;
import com.suisung.mall.shop.sfexpress.service.SFExpressApiService;
import com.suisung.mall.shop.store.service.ShopStoreSfOrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.annotation.Resource;
import java.util.HashMap;
@ -87,4 +87,27 @@ public class SFExpressController {
params.put("order_id", shopStoreSfOrderService.getSfOrderIdByShopOrderId(orderId));
return sfExpressApiService.riderViewV2(params);
}
/**
* 顺丰同城订单状态监听 SSE 服务
* @param channel
* @return
*/
@CrossOrigin(allowCredentials = "true")
@GetMapping(value = "/order/status/listening", produces = "text/event-stream;charset=UTF-8")
public SseEmitter sfOrderStatusSseConn(@RequestParam(value = "channel", required = true) String channel) {
return SseEmitterUtil.connect(channel);
}
/**
* 关闭顺丰同城订单状态监听 SSE 服务
* @param channel
* @return
*/
@CrossOrigin(allowCredentials = "true")
@GetMapping(value ="/order/status/listening/close")
public CommonResult sfOrderStatusSseClose(@RequestParam(name = "channel") String channel) {
SseEmitterUtil.removeChannel(channel);
return CommonResult.success();
}
}

View File

@ -10,18 +10,22 @@ package com.suisung.mall.shop.sfexpress.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.api.StateCode;
import com.suisung.mall.common.constant.SFExpressConstant;
import com.suisung.mall.common.domain.UserDto;
import com.suisung.mall.common.exception.ApiException;
import com.suisung.mall.common.modules.store.ShopStoreSfOrder;
import com.suisung.mall.common.pojo.req.*;
import com.suisung.mall.common.pojo.res.SFExpressApiRes;
import com.suisung.mall.common.utils.I18nUtil;
import com.suisung.mall.common.utils.JsonUtil;
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;
@ -42,6 +46,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.suisung.mall.common.utils.ContextUtil.getCurrentUser;
@Service
public class SFExpressApiServiceImpl implements SFExpressApiService {
@ -147,12 +153,12 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
@Transactional
@Override
public Pair<Boolean, String> innerCreateSfExpressOrder(String shopOrderId, Long orderPickupNum) {
if(StrUtil.isBlank(shopOrderId) || orderPickupNum == null|| orderPickupNum <=0) {
if (StrUtil.isBlank(shopOrderId) || orderPickupNum == null || orderPickupNum <= 0) {
return Pair.of(false, "顺丰同城下单时,缺少必要参数!");
}
// 检查 shop_store_sf_order 订单是否已存在
if(shopStoreSfOrderService.exists(devId,shopOrderId)){
if (shopStoreSfOrderService.exists(devId, shopOrderId)) {
return Pair.of(true, "顺丰同城已下单过!");
}
@ -235,7 +241,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
public SFExpressApiRes cancelOrder(Map<String, Object> params) {
// TODO 检验用户权限
if (params == null || params.get("order_id") == null) {
if (params == null || ObjectUtil.isEmpty(params.get("order_id"))) {
return new SFExpressApiRes().fail(1003, "请求参数有误!");
}
@ -267,7 +273,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
// 判断订单的状态是否已经取消了已取消不再执行
ShopStoreSfOrder shopStoreSfOrderExist = shopStoreSfOrderService.getBySfOrderId(orderId);
if (shopStoreSfOrderExist == null) {
return new SFExpressApiRes().fail(2,"订单有误!");
return new SFExpressApiRes().fail(2, "订单有误!");
}
if (shopStoreSfOrderExist.getOrder_status() != null
@ -306,7 +312,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
*/
@Override
public SFExpressApiRes addOrderGratuityFee(Map<String, Object> params) {
if (params == null || params.get("order_id") == null || params.get("gratuity_fee") == null) {
if (params == null || ObjectUtil.isEmpty(params.get("order_id")) || params.get("gratuity_fee") == null) {
return new SFExpressApiRes().fail(1003, "请求参数有误!");
}
@ -334,7 +340,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
*/
@Override
public SFExpressApiRes reminderOrder(Map<String, Object> params) {
if (params == null || params.get("order_id") == null) {
if (params == null || ObjectUtil.isEmpty(params.get("order_id"))) {
return new SFExpressApiRes().fail(1003, "请求参数有误!");
}
@ -364,7 +370,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
*/
@Override
public SFExpressApiRes listOrderFeed(Map<String, Object> params) {
if (params == null || params.get("order_id") == null) {
if (params == null || ObjectUtil.isEmpty(params.get("order_id"))) {
return new SFExpressApiRes().fail(1003, "请求参数有误!");
}
@ -392,7 +398,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
*/
@Override
public SFExpressApiRes riderLatestPosition(Map<String, Object> params) {
if (params == null || params.get("order_id") == null) {
if (params == null || ObjectUtil.isEmpty(params.get("order_id"))) {
return new SFExpressApiRes().fail(1003, "请求参数有误!");
}
@ -420,7 +426,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
*/
@Override
public SFExpressApiRes riderViewV2(Map<String, Object> params) {
if (params == null || params.get("order_id") == null) {
if (params == null || ObjectUtil.isEmpty(params.get("order_id"))) {
return new SFExpressApiRes().fail(1003, "请求参数有误!");
}
@ -564,11 +570,15 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
}
success = shopOrderInfoService.changeOrderStatus(shopStoreSfOrder.getShop_order_id(), orderStatus, orderIsOutStatus, orderIsShippedStatus);
if (!success) {
throw new ApiException(I18nUtil._("状态处理失败!"));
}
// 状态更改之后 SSE 监听服务发送更改的数据
// logger.debug("准备发送SSE消息...");
SseEmitterUtil.sendMessage(shopStoreSfOrder.getSf_order_id(), jsonData);
// logger.debug("向 SSE 通道 {} 发送了:{}", shopStoreSfOrder.getSf_order_id(), jsonData);
return new SFExpressApiRes().success("success");
}

View File

@ -1,9 +1,11 @@
package com.suisung.mall.shop.store.controller.admin;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.modules.store.ShopStorePrinter;
import com.suisung.mall.common.utils.PositionUtil;
import com.suisung.mall.common.utils.SseEmitterUtil;
import com.suisung.mall.shop.store.service.ShopStoreEmployeeService;
import com.suisung.mall.shop.store.service.ShopStorePrinterService;
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService;
@ -13,10 +15,12 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -43,7 +47,10 @@ public class ShopStorePrinterController {
// BigDecimal s = new BigDecimal(2.50).setScale(2, RoundingMode.HALF_UP);
// List<Integer> list = shopStoreEmployeeService.selectEmployeeByStoreId(3,"店铺管理员");
return CommonResult.success(data);
String userId = "1";
SseEmitterUtil.sendMessage(userId, JSONUtil.toJsonStr(data));
return CommonResult.success(1);
}
@ApiOperation(value = "测试打印模版消息", notes = "测试打印模版消息")

View File

@ -1,10 +1,7 @@
package com.suisung.mall.shop.store.controller.mobile;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.pojo.dto.ShopStoreSameCityTransportBaseDTO;
import com.suisung.mall.common.utils.JsonUtil;
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService;
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
@ -14,17 +11,14 @@ import javax.annotation.Resource;
@Api(tags = "同城配送运费设置控制器")
@RestController
@RequestMapping("/mobile/shop/store/same-city-transport")
public class ShopStoreSameCityTransportBaseController {
public class ShopStoreSameCityTransportBaseMobileController {
@Resource
private ShopStoreSameCityTransportBaseService transportBaseService;
@Resource
private ShopStoreSameCityTransportService transportService;
@ApiOperation(value = "下单前检测同城订单配送是否符合要求", notes = "下单前检测同城订单配送是否符合要求")
@RequestMapping(value = "/check/same-city/delivery", method = {RequestMethod.POST})
public CommonResult checkSameCityDelivery(@RequestBody ShopStoreSameCityTransportBaseDTO transportBaseDTO) {
public CommonResult checkSameCityDelivery(@RequestParam(name = "store_id", defaultValue = "0") Integer storeId) {
return transportBaseService.ShopStoreSameCityTransportBaseDetail();
}
}

View File

@ -40,6 +40,7 @@ import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
@ -53,6 +54,7 @@ import java.util.List;
import static com.suisung.mall.common.utils.ContextUtil.getCurrentUser;
@Lazy
@Service
public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<ShopStoreSameCityTransportBaseMapper, ShopStoreSameCityTransportBase> implements ShopStoreSameCityTransportBaseService {
@ -61,8 +63,6 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
private ShopStoreSameCityTransportService shopStoreSameCityTransportService;
@Resource
private ShopStoreBaseService shopStoreBaseService;
@Resource
private ShopChainUserController user;
/**
* 获取同城配送设置详情信息
@ -381,24 +381,25 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
return new SameCityDeliveryFeeRespDTO(false, false, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, "同城配送缺少店铺基本信息。");
}
String storeName = storeBase.getStore_name();
String storeLng = storeBase.getStore_longitude();
String storeLat = storeBase.getStore_latitude();
if (StrUtil.isBlank(storeLng) || StrUtil.isBlank(storeLat)) {
logger.error("同城配送费计算:店铺经纬度为空");
logger.error("{}同城配送费计算:店铺经纬度为空", storeName);
if (canThrow) {
throw new ApiException(I18nUtil._("无法获取店铺的具体位置,请联系商家。"));
throw new ApiException(I18nUtil._("无法获取" + storeName + "的具体位置,请联系商家。"));
}
return new SameCityDeliveryFeeRespDTO(false, false, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, "无法获取店铺的具体位置,请联系商家。");
return new SameCityDeliveryFeeRespDTO(false, false, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, "无法获取" + storeName + "的具体位置,请联系商家。");
}
// 获取基础运费设置记录
ShopStoreSameCityTransportBase transportBase = getShopStoreSameCityTransportBaseById(storeId);
if (transportBase == null) {
logger.error("同城配送费计算:无法获取基础运费设置记录。");
logger.error("{}同城配送费计算:无法获取基础运费设置记录。", storeName);
if (canThrow) {
throw new ApiException(I18nUtil._("商家尚未完成同城配送设置。"));
}
return new SameCityDeliveryFeeRespDTO(false, false, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, "商家尚未完成同城配送设置。");
return new SameCityDeliveryFeeRespDTO(false, false, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, storeName + "尚未完成同城配送设置。");
}
if (transportBase.getDistance_base() == null) {
@ -418,7 +419,7 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
}
// 实际配送距离单位米
Integer distance = distanceD.intValue();
logger.debug("下单时,店铺与收货地址两地,经纬度:{},{}|{},{} 距离:{} 米", storeLng, storeLat, orderLongitude, orderLatitude, distance);
logger.debug(storeName + "下单时,店铺与收货地址两地,经纬度:{},{}|{},{} 距离:{} 米", storeLng, storeLat, orderLongitude, orderLatitude, distance);
// ### 基础配送费计算
BigDecimal deliveryBaseFee = transportBase.getDelivery_base_fee();
@ -456,11 +457,10 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
deliveryBaseFee = deliveryBaseFee.add(transportBase.getWeight_increase_fee().multiply(times));
}
logger.debug("下单时,店铺与收货地址超出基础距离和重量:额外增加 {} 元运费。", deliveryBaseFee);
logger.debug(storeName + "下单时,店铺与收货地址超出基础距离和重量:额外增加 {} 元运费。", deliveryBaseFee);
// #### 基础配送费计算完毕
// 优惠减免的配送费重要
BigDecimal reduceDeliveryFee = BigDecimal.ZERO;
@ -480,7 +480,7 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
for (ShopStoreSameCityTransport transport : transportList) {
DeliveryFeeResultDTO deliveryFeeResultDTO = new DeliveryFeeResultDTO();
deliveryFeeResultDTO.setId(transport.getTransport_id());
logger.debug("下单时,店铺与收货地址的距离是{}米,最大配送范围是{}米以内", distance, transport.getMax_delivery_radius());
logger.debug(storeName + "下单时,店铺与收货地址的距离是{}米,最大配送范围是{}米以内", distance, transport.getMax_delivery_radius());
// 判断订单距离在不在配送范围内
if (transport.getMax_delivery_radius() < distance) {
@ -488,7 +488,7 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
// 订单距离不在配送范围内返回不送了
deliveryFeeResultDTO.setLevel(2);
deliveryFeeResultDTO.setDistancePassed(false);
deliveryFeeResultDTO.setDistanceReason("订单不在配送范围内,订单无法配送。");
deliveryFeeResultDTO.setDistanceReason(storeName + "订单不在配送范围内,订单无法配送。");
noPassed.add(deliveryFeeResultDTO);
@ -502,7 +502,7 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
deliveryFeeResultDTO.setMoneyPassed(false);
BigDecimal diffMoney = transport.getMin_delivery_amount().subtract(orderProductAmount);
deliveryFeeResultDTO.setDiffMoney(diffMoney);
deliveryFeeResultDTO.setMoneyReason(String.format("商品原价金额还差%.2f元,才满足配送条件,请检查订单。", diffMoney));
deliveryFeeResultDTO.setMoneyReason(String.format("%s商品原价金额还差%.2f元,才满足配送条件,请检查订单。", storeName, diffMoney));
} else {
deliveryFeeResultDTO.setMoneyPassed(true);
}
@ -513,7 +513,7 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
deliveryFeeResultDTO.setMoneyPassed(false);
BigDecimal diffMoney = transport.getMin_delivery_amount().subtract(orderDiscountAmount);
deliveryFeeResultDTO.setDiffMoney(diffMoney);
deliveryFeeResultDTO.setMoneyReason(String.format("订单折后金额还差%.2f元,才满足配送条件,请检查订单。", diffMoney));
deliveryFeeResultDTO.setMoneyReason(String.format("%s订单折后金额还差%.2f元,才满足配送条件,请检查订单。", storeName, diffMoney));
} else {
deliveryFeeResultDTO.setMoneyPassed(true);
}
@ -524,7 +524,7 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
deliveryFeeResultDTO.setMoneyPassed(false);
BigDecimal diffMoney = transport.getMin_delivery_amount().subtract(orderDiscountAmount);
deliveryFeeResultDTO.setDiffMoney(diffMoney);
deliveryFeeResultDTO.setMoneyReason(String.format("应支付订单金额还差%.2f元,才满足配送条件,请检查订单。", diffMoney));
deliveryFeeResultDTO.setMoneyReason(String.format("%s订单应支付金额还差%.2f元,才满足配送条件,请检查订单。", storeName, diffMoney));
} else {
deliveryFeeResultDTO.setMoneyPassed(true);
}
@ -557,21 +557,21 @@ public class ShopStoreSameCityTransportBaseServiceImpl extends BaseServiceImpl<S
}
logger.debug("下单时,根据商家运费设置规则减免{}元运费", reduceDeliveryFee);
logger.debug("下单时,不符合规则的:\n {}\n符合规则的:{}", JSONUtil.toJsonStr(noPassed), JSONUtil.toJsonStr(passed));
logger.debug(storeName + "下单时,根据商家运费设置规则减免{}元运费", reduceDeliveryFee);
logger.debug(storeName + "下单时,不符合规则的:\n {}\n符合规则的:{}", JSONUtil.toJsonStr(noPassed), JSONUtil.toJsonStr(passed));
if (passed.size() == 0 && noPassed.size() > 0) {
// 没有一个满足起送距离和起送金额的规则订单
String canNotDeliveryReason="订单不在配送范围内或订单未达起送金额,请检查!";
String canNotDeliveryReason = storeName + "订单不在配送范围内或未达起送金额,请检查!";
// 根据 level 优先级升序排序
noPassed = CollUtil.sort(noPassed, new FieldsComparator<>(DeliveryFeeResultDTO.class,"level","diffMoney"));
noPassed = CollUtil.sort(noPassed, new FieldsComparator<>(DeliveryFeeResultDTO.class, "level", "diffMoney"));
DeliveryFeeResultDTO deliveryFeeResultNoPassed = noPassed.get(0);
// 优先级显示不符合规定的提示语
if(!deliveryFeeResultNoPassed.getDistancePassed()){
if (!deliveryFeeResultNoPassed.getDistancePassed()) {
canNotDeliveryReason = deliveryFeeResultNoPassed.getDistanceReason();
}else if(!deliveryFeeResultNoPassed.getMoneyPassed()){
} else if (!deliveryFeeResultNoPassed.getMoneyPassed()) {
canNotDeliveryReason = deliveryFeeResultNoPassed.getMoneyReason();
}