增加了创建顺丰同城店铺接口(补偿机制)

This commit is contained in:
Jack 2025-09-02 17:45:07 +08:00
parent 6235112c4b
commit 9f3101fca7
12 changed files with 208 additions and 69 deletions

View File

@ -2994,7 +2994,7 @@ public class AccountUserBaseServiceImpl extends BaseServiceImpl<AccountUserBaseM
// 找出手机对应的绑定用户
// 是否为手机号注册密码6位随机数
CommonResult result = doMobileBindLogin(verifyMobile, CommonConstant.USER_TYPE_MCH, cid, osType);
if (result.getStatus() == 200) {
if (result.getStatus() == 200L) {
// 登录成功之后异步检查并修复商户店铺信息
asyncTaskService.checkAndFixMchStoreInfo(PhoneNumberUtils.cleanPhoneNumber(user_mobile));
}

View File

@ -31,6 +31,7 @@ public class AsyncTaskService {
@Async
public Boolean checkAndFixMchStoreInfo(String loginMobile) {
try {
logger.info("开始检查并修复商户店铺信息,手机号: {}", loginMobile);
// 调用shop服务检查并修复商户店铺信息
Boolean result = shopService.checkAndFixMchStoreInfo(loginMobile);
// 记录处理结果日志

View File

@ -129,7 +129,7 @@ public class StateCode {
public static final int ORDER_STATE_RECEIVED = 2050; //已签收
public static final int ORDER_STATE_FINISH = 2060; //已完成
public static final int ORDER_STATE_CANCEL = 2070; //已取消
public static final int ORDER_STATE_SELF_PICKUP = 2080; //自提 - 虚拟映射 交易关闭 交易关闭
public static final int ORDER_STATE_SELF_PICKUP = 2080; //自提 - 虚拟映射
public static final int ORDER_STATE_ERROR = 2090; //异常订单
public static final int ORDER_STATE_RETURN = 2091; //退回订单 - 虚拟映射

View File

@ -1,13 +1,11 @@
package com.suisung.mall.shop.config;
import com.suisung.mall.common.constant.MqConstant;
import com.suisung.mall.shop.message.service.MqMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.support.converter.SimpleMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -18,48 +16,8 @@ import java.util.Map;
@Slf4j
public class RabbitMqConfig {
@Autowired
private MqMessageService mqMessageService;
/**
* 序列化
*/
// @Bean
// public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
//
// RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
// // 消息抵达确认通知
// rabbitTemplate.setConfirmCallback((data, ack, cause) -> {
// if (ack) {
// String msgId = data.getId();
// mqMessageService.setMessageStatus(msgId, MqConstant.DELIVERED);
// } else {
// log.error("消息未能发送成功,消息编号:{},失败原因:{}", data.getId(), cause);
//
// String msgId = data.getId();
// mqMessageService.setMessageStatus(msgId, MqConstant.FAILURE);
// }
// });
// // 消息投递失败通知
// rabbitTemplate.setReturnCallback((msg, respCode, respText, exchange, routingKey) -> {
// log.error("交换机抵达队列失败,消息编号:{},状态码:{},失败原因:{},当前交换机:{},当前路由键: {}", msg, respCode, respText, exchange, routingKey);
// String msgId = msg.getMessageProperties().getMessageId();
// mqMessageService.setMessageStatus(msgId, MqConstant.FAILURE);
// });
//
// // 配置序列化配置
// // rabbitTemplate.setMessageConverter(new SimpleMessageConverter());
//
// Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
// converter.setAssumeSupportedContentType(true);
// rabbitTemplate.setMessageConverter(converter);
//
// return rabbitTemplate;
// }
/**
* 反序列化
* 配置监听容器工厂
*/
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
@ -75,24 +33,6 @@ public class RabbitMqConfig {
return new SimpleMessageConverter();
}
// @Bean
// public Jackson2JsonMessageConverter jackson2JsonMessageConverter() {
// return new Jackson2JsonMessageConverter();
// }
/**
* 反序列化
*/
// @Bean
// public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
// SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
// factory.setConnectionFactory(connectionFactory);
// factory.setMessageConverter(new SimpleMessageConverter());
// factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
// return factory;
// }
/**
* 默认交换机
*
@ -178,7 +118,6 @@ public class RabbitMqConfig {
null);
}
/**
* 声明延迟交换机
*/
@ -248,5 +187,4 @@ public class RabbitMqConfig {
.to(deadLetterExchange())
.with(MqConstant.DEAD_LETTER_ROUTING_KEY);
}
}

View File

@ -89,6 +89,13 @@ public class OrderPayedListener {
int order_state_id = orderInfoOld.getOrder_state_id().intValue();
logger.info("#### 当前订单状态: {} ####", order_state_id);
// 检查订单是否已经处理过幂等性检查
// if (isOrderPaid(orderInfoOld)) {
// logger.info("订单已支付无需重复处理订单ID: {}", orderId);
// flag = true;
// continue;
// }
if (order_state_id == StateCode.ORDER_STATE_WAIT_PAY) {
// 待支付状态
logger.info("#### 待支付业务分支 ####");
@ -183,5 +190,20 @@ public class OrderPayedListener {
}
}
/**
* 检查订单是否已经支付幂等性检查
*
* @param orderInfo 订单信息
* @return 是否已支付
*/
private boolean isOrderPaid(ShopOrderInfo orderInfo) {
// public static final int ORDER_PAID_STATE_NO = 3010; //未付款
// public static final int ORDER_PAID_STATE_FINANCE_REVIEW = 3011; //待付款审核
// public static final int ORDER_PAID_STATE_PART = 3012; //部分付款
// public static final int ORDER_PAID_STATE_YES = 3013; //已付款
return orderInfo.getOrder_is_paid() != null &&
orderInfo.getOrder_is_paid().equals(StateCode.ORDER_PAID_STATE_YES);
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2024. 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.shop.sfexpress.controller.admin;
import cn.hutool.json.JSONObject;
import com.suisung.mall.common.api.CommonResult;
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.data.util.Pair;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@Api(tags = "顺丰同城Api端")
@RestController
@RequestMapping("/admin/shop/sf-express")
public class SFExpressAdminController {
@Autowired
private SFExpressApiService sfExpressApiService;
@ApiOperation(value = "创建顺丰同城店铺", notes = "创建顺丰同城店铺")
@RequestMapping(value = "/create-shop", method = RequestMethod.POST)
public CommonResult createSfExpressShopNotify(@RequestBody JSONObject requestBody) {
Pair<Boolean, String> result = sfExpressApiService.createSfExpressShop(requestBody.getLong("mch_id"), requestBody.getInt("store_id"));
if (result.getFirst()) {
Map<String, Object> data = new HashMap<>();
data.put("shop_id", result.getSecond());
return CommonResult.success(data, "创建成功!");
}
return CommonResult.failed(result.getSecond());
}
}

View File

@ -20,7 +20,6 @@ import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/shop/sf-express")
public class SFExpressApiController {
@Lazy
@Autowired
private SFExpressApiService sfExpressApiService;

View File

@ -16,6 +16,15 @@ import java.util.Map;
public interface SFExpressApiService {
/**
* 创建顺丰同店铺-连锁店铺
*
* @param mchId 入驻记录Id, 必填项(mchId storeId 其中一个必填)
* @param storeId 商家门店ID 必填项(mchId storeId 其中一个必填)
* @return
*/
Pair<Boolean, String> createSfExpressShop(Long mchId, Integer storeId);
/**
* 创建顺丰同店铺-连锁店铺
*
@ -31,6 +40,7 @@ public interface SFExpressApiService {
*/
Pair<Boolean, String> createSfExpressShop(Integer storeId, String shopName, String cityName, String shopAddress, String contactName, String contactPhone, String longitude, String latitude);
/**
* 创建顺丰同城店铺-连锁店铺回调
*

View File

@ -19,6 +19,7 @@ import com.suisung.mall.common.api.StateCode;
import com.suisung.mall.common.constant.CommonConstant;
import com.suisung.mall.common.constant.SFExpressConstant;
import com.suisung.mall.common.exception.ApiException;
import com.suisung.mall.common.modules.store.ShopMchEntry;
import com.suisung.mall.common.modules.store.ShopStoreSameCityTransportBase;
import com.suisung.mall.common.modules.store.ShopStoreSfOrder;
import com.suisung.mall.common.pojo.req.*;
@ -32,6 +33,7 @@ import com.suisung.mall.shop.order.service.ShopOrderBaseService;
import com.suisung.mall.shop.order.service.ShopOrderInfoService;
import com.suisung.mall.shop.order.service.ShopOrderReturnService;
import com.suisung.mall.shop.sfexpress.service.SFExpressApiService;
import com.suisung.mall.shop.store.service.ShopMchEntryService;
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService;
import com.suisung.mall.shop.store.service.ShopStoreSfOrderService;
import com.suisung.mall.shop.wechat.service.WxOrderShippingService;
@ -89,11 +91,97 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
@Autowired
private WxOrderShippingService wxOrderShippingService;
@Lazy
@Autowired
private ShopMchEntryService shopMchEntryService;
@Lazy
@Autowired
private PushMessageService pushMessageService;
/**
* 创建顺丰同店铺-连锁店铺
*
* @param mchId 入驻记录Id, 必填项(mchId storeId 其一必填) 优先
* @param storeId 商家门店ID 必填项(mchId storeId 其一必填)
* @return
*/
@Override
public Pair<Boolean, String> createSfExpressShop(Long mchId, Integer storeId) {
// 参数校验
if (ObjectUtil.isEmpty(mchId) && ObjectUtil.isEmpty(storeId)) {
logger.error("创建顺丰同店铺mchId 和 storeId 其一必填");
return Pair.of(false, "缺少必填参数");
}
ShopMchEntry shopMchEntry;
if (ObjectUtil.isEmpty(mchId)) {
shopMchEntry = shopMchEntryService.shopMerchEntryByStoreId(storeId);
} else {
shopMchEntry = shopMchEntryService.shopMerchEntryById(mchId);
}
if (shopMchEntry == null) {
logger.error("创建顺丰同店铺:入驻信息不能为空");
return Pair.of(false, "入驻信息不能为空");
}
// 校验必要字段
if (shopMchEntry.getStore_id() == null || StrUtil.isBlank(shopMchEntry.getStore_id())) {
logger.error("创建顺丰同店铺门店ID无效storeId: {}", shopMchEntry.getStore_id());
return Pair.of(false, "门店ID无效");
}
if (StrUtil.isBlank(shopMchEntry.getStore_name())) {
logger.error("创建顺丰同店铺:门店名称不能为空");
return Pair.of(false, "门店名称不能为空");
}
if (StrUtil.isBlank(shopMchEntry.getStore_address())) {
logger.error("创建顺丰同店铺:门店地址不能为空");
return Pair.of(false, "门店地址不能为空");
}
if (StrUtil.isBlank(shopMchEntry.getContact_name())) {
logger.error("创建顺丰同店铺:联系人姓名不能为空");
return Pair.of(false, "联系人姓名不能为空");
}
String contact_mobile = StrUtil.isBlank(shopMchEntry.getLegal_person_mobile()) ?
shopMchEntry.getLogin_mobile() : shopMchEntry.getLegal_person_mobile();
if (StrUtil.isBlank(contact_mobile)) {
logger.error("创建顺丰同店铺:联系人手机号不能为空");
return Pair.of(false, "联系人手机号不能为空");
}
// shopMchEntry.getStore_area() == 广西壮族自治区/贵港市/桂平市 or 广西壮族自治区/贵港市
String[] areaNames = StrUtil.isNotBlank(shopMchEntry.getStore_area()) ?
shopMchEntry.getStore_area().split("/") : new String[0];
String cityName = areaNames.length > 0 ?
areaNames[areaNames.length - 1] :
shopMchEntry.getStore_area() != null ? shopMchEntry.getStore_area().replace("/", "") : "";
// 如果城市名为空使用默认值
if (StrUtil.isBlank(cityName)) {
cityName = "桂平市"; // 默认城市
logger.warn("城市名为空,使用默认城市: {}", cityName);
}
return createSfExpressShop(
Convert.toInt(shopMchEntry.getStore_id()),
shopMchEntry.getStore_name(),
cityName,
shopMchEntry.getStore_address(),
shopMchEntry.getContact_name(),
contact_mobile,
shopMchEntry.getStore_longitude(),
shopMchEntry.getStore_latitude()
);
}
/**
* 创建顺丰同城普通型店铺
*

View File

@ -108,6 +108,14 @@ public interface ShopMchEntryService {
*/
ShopMchEntry shopMerchEntryById(Long mchId);
/**
* 根据店铺 ID 获取商户入驻信息
*
* @param storeId
* @return
*/
ShopMchEntry shopMerchEntryByStoreId(Integer storeId);
/**
* 根据商家手机号营业执照审批状态获取有效的商家入驻申请记录

View File

@ -1103,6 +1103,34 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
}
}
/**
* 根据店铺 ID 获取商户入驻信息
*
* @param storeId
* @return
*/
@Override
public ShopMchEntry shopMerchEntryByStoreId(Integer storeId) {
// 1. 参数校验商户ID不能为空
if (ObjectUtil.isEmpty(storeId)) {
return null;
}
try {
// 2. 构建查询条件只查询有效状态的记录
QueryWrapper<ShopMchEntry> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("store_id", storeId) // 修正字段名应为"id"而非"mch_id"
.eq("status", CommonConstant.Enable).orderByDesc("id");
// 3. 执行查询并返回结果
return findOne(queryWrapper);
} catch (Exception e) {
// 4. 异常处理记录异常信息避免程序中断
log.error("根据商户ID获取商户入驻信息时发生异常, storeId: {}", storeId, e);
return null; // 发生异常时返回null
}
}
/**
* 根据商家手机号营业执照审批状态获取有效的商家入驻申请记录
*

View File

@ -3329,9 +3329,9 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
// storeSameCityTransportBaseService.initDefaultSameCityTransport(storeId);
// 立即创建顺丰店铺附带初始化同城配送默认设置
String[] areaNames = StrUtil.isNotBlank(shopStoreBase.getStore_area()) ? shopStoreBase.getStore_area().split("/") : new String[0];
String cityName = areaNames.length > 0 ? areaNames[areaNames.length - 1] : shopStoreBase.getStore_area().replace("/", "");
sfExpressApiService.createSfExpressShop(storeId, shopStoreBase.getStore_name(), cityName, shopStoreBase.getStore_address(), shopMchEntry.getContact_name(), contact_mobile, shopStoreBase.getStore_longitude(), shopStoreBase.getStore_longitude());
String[] areaNames = StrUtil.isNotBlank(shopMchEntry.getStore_area()) ? shopMchEntry.getStore_area().split("/") : new String[0];
String cityName = areaNames.length > 0 ? areaNames[areaNames.length - 1] : shopMchEntry.getStore_area().replace("/", "");
sfExpressApiService.createSfExpressShop(storeId, shopMchEntry.getStore_name(), cityName, shopMchEntry.getStore_address(), shopMchEntry.getContact_name(), contact_mobile, shopMchEntry.getStore_longitude(), shopMchEntry.getStore_longitude());
return Pair.of(storeId, "新增成功");
} catch (Exception e) {