店铺分类 sql fix bug

This commit is contained in:
Jack 2025-05-28 20:35:58 +08:00
parent 60e4019900
commit 6dda9f6f97
4 changed files with 157 additions and 243 deletions

View File

@ -1278,6 +1278,10 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
// 敏感头信息脱敏打印
logger.debug("拉卡拉支付异步通知回调 body:{} \n authorization: {}", body, authorization);
// 异步通知返回的json数据{"out_trade_no":"202203151637334864280014","trade_no":"2022031566210203291925","log_no":"66210203291925",
// "acc_trade_no":"2022031522001483661454130929 ","trade_status":"SUCCESS","trade_state":"SUCCESS","total_amount":"1",
// "payer_amount":"1","acc_settle_amount":"1","trade_time":"20220315163808","user_id1":"app***@163.com",
// "user_id2":"2088432881453660","notify_url":"https://www.baidu.com","account_type":"ALIPAY","card_type":"99"}
// 解析JSON格式响应
params = Convert.toMap(String.class, String.class, JSONUtil.parseObj(body));
@ -1343,6 +1347,8 @@ public class PayUserPayServiceImpl extends BaseServiceImpl<PayUserPayMapper, Pay
throw new ApiException(e.getMessage());
}
// TODO 分账指令 写入 MQ 定时执行
return lklNotifyMsg(true, "执行成功");
} catch (Exception e) {
logger.error("通知处理发生异常:{}", e.getMessage(), e);

View File

@ -1381,7 +1381,9 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 9. 更新参数并保存记录
paramsJSON.set("orderNo", orderNo);
paramsJSON.set("apply_id", respJson.getByPath("respData.applyId"));
paramsJSON.set("org_code", orgCode);
paramsJSON.set("receiver_no", receiver.getReceiver_no());
paramsJSON.set("ret_url", retUrl);
paramsJSON.set("remark", respJson.getStr("retMsg"));
paramsJSON.set("platform_id", receiver.getPlatform_id());
@ -1796,166 +1798,6 @@ public class LakalaApiServiceImpl implements LakalaApiService {
}
}
public Pair<Boolean, String> innerDoOrderSeparateTemp(String orderId) {
if (StrUtil.isBlank(orderId)) {
return Pair.of(false, "订单号不能为空");
}
try {
// 1. 配置初始化
initLKLSDK();
// 获取订单信息店铺信息商户信息分账信息
List<ShopOrderLkl> shopOrderLklList = shopOrderLklService.selectByOrderId(orderId, "");
if (CollectionUtil.isEmpty(shopOrderLklList)) {
return Pair.of(false, "订单不存在");
}
int successCnt = 0;
// 一个订单里包含了多个商家的时候需要处理
for (ShopOrderLkl shopOrderLkl : shopOrderLklList) {
String merchantNo = shopOrderLkl.getMerchant_no();
// 分账总金额
Integer paymentAmount = shopOrderLkl.getTotal_amt();
Integer shoppingFee = shopOrderLkl.getShopping_fee();
BigDecimal splitRatioMch = shopOrderLkl.getSplit_ratio();
// 应付款金额大于零并且大于运费
if (paymentAmount <= 0
|| (shoppingFee != null && paymentAmount - shoppingFee <= 0)) {
log.error("店铺{}订单{}金额有误或运费高于分账金额,不会进行分账", shopOrderLkl.getStore_id(), orderId);
continue;
}
// 平台和代理商的分成比例
BigDecimal splitRatioNoMch = new BigDecimal("100").subtract(shopOrderLkl.getSplit_ratio());
LklLedgerMerReceiverBind platform = lklLedgerMerReceiverBindService.getPlatformByMerCupNo(merchantNo);
List<LklLedgerMerReceiverBind> distributorList = lklLedgerMerReceiverBindService.selectDistributorByMerCupNo(merchantNo);
if (platform == null) {
log.error("店铺{}订单{}未绑定平台方,不会进行分账", shopOrderLkl.getStore_id(), orderId);
continue;
}
boolean canSplit = true; // 能分账并扣运费
if (splitRatioMch == null || splitRatioMch.compareTo(new BigDecimal("100")) >= 0) {
log.warn("店铺{}分账比例为0只扣运费不会进行分账", shopOrderLkl.getStore_id());
canSplit = false; //不分账只扣运费
}
V3SacsSeparateRequest req = new V3SacsSeparateRequest();
req.setMerchantNo(merchantNo); // 拉卡拉商户号
req.setLogNo(shopOrderLkl.getLog_no());
req.setLogDate(shopOrderLkl.getLog_date());
req.setOutSeparateNo(orderId); // 暂时传入平台订单Id
req.setTotalAmt(shopOrderLkl.getTotal_amt().toString());
req.setLklOrgNo(orgCode);
req.setCalType("0"); // 0- 按照指定金额1- 按照指定比例默认 0
req.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/sacs/separateNotify");
List<V3SacsSeparateRecvDatas> recvDatas = new ArrayList<>();
// 平台先代扣掉运费
if (shoppingFee != null && shoppingFee > 0) {
V3SacsSeparateRecvDatas recvData = new V3SacsSeparateRecvDatas();
recvData.setRecvNo(platform.getReceiver_no());
recvData.setSeparateValue(shoppingFee.toString()); // 分账金额单位分分账金额不能大于订单金额分账金额不能小于0
recvDatas.add(recvData);
}
if (canSplit) { //扣完运费后还能能分账
// 应付款扣除运费后得出实际分账的金额,单位
Integer splitAmount = paymentAmount - shoppingFee;
if (!CollectionUtils.isEmpty(distributorList)
&& (splitRatioMch != null && splitRatioNoMch.compareTo(BigDecimal.ONE) > 0)) { // 有平台和代理商并且分账比例大于1的情况
// 平台方分账
BigDecimal platformSeparateValue = CommonUtil.DecimalRoundHalfDown(new BigDecimal(splitAmount).multiply(new BigDecimal("0.01"))); // 平台收取1%手续费
if (platformSeparateValue.compareTo(BigDecimal.ZERO) > 0) {
V3SacsSeparateRecvDatas recvData = new V3SacsSeparateRecvDatas();
recvData.setRecvNo(platform.getReceiver_no());
recvData.setSeparateValue(platformSeparateValue.toString()); // 分账金额单位分分账金额不能大于订单金额分账金额不能小于0
recvDatas.add(recvData);
}
// TODO: 一级以上的代理商以后做处理
// 一级代理方分账 分账比例扣掉1%的平台方费其余都是代理商的
BigDecimal splitRatioDistributor = splitRatioNoMch.subtract(new BigDecimal("1")).divide(new BigDecimal(100));
BigDecimal distributorSeparateValue = CommonUtil.DecimalRoundHalfDown(new BigDecimal(splitAmount).multiply(splitRatioDistributor));
if (distributorSeparateValue.compareTo(BigDecimal.ZERO) > 0) {
V3SacsSeparateRecvDatas recvData2 = new V3SacsSeparateRecvDatas();
recvData2.setRecvNo(distributorList.get(0).getReceiver_no());
recvData2.setSeparateValue(distributorSeparateValue.toString()); // 分账金额单位分分账金额不能大于订单金额分账金额不能小于0
recvDatas.add(recvData2);
}
} else {
// 仅平台方一方分账
BigDecimal splitRatioPlatform = CommonUtil.DecimalRoundHalfDown(splitRatioNoMch.divide(new BigDecimal(100)));
BigDecimal separateValue = new BigDecimal(splitAmount).multiply(splitRatioPlatform);
if (separateValue.compareTo(BigDecimal.ZERO) > 0) {
V3SacsSeparateRecvDatas recvData = new V3SacsSeparateRecvDatas();
recvData.setRecvNo(platform.getReceiver_no());
recvData.setSeparateValue(separateValue.toString()); // 分账金额单位分分账金额不能大于订单金额分账金额不能小于0
recvDatas.add(recvData);
}
}
}
req.setRecvDatas(recvDatas);
log.debug("分账执行请求参数:{}", JSONUtil.toJsonStr(req));
//3. 发送请求
String responseStr = LKLSDK.httpPost(req);
if (StrUtil.isBlank(responseStr)) {
log.error("服务器无返回值!");
continue;
}
log.debug("分账执行响应参数:{}", responseStr);
JSONObject lklRespJSON = JSONUtil.parseObj(responseStr);
if (lklRespJSON == null
|| !lklSacsSuccessCode.equals(lklRespJSON.getStr("code"))
|| lklRespJSON.getJSONObject("resp_data") == null) {
log.error("分账返回值有误!");
continue;
}
JSONObject respData = lklRespJSON.getJSONObject("resp_data");
// 4. 处理返回结果等待异步通知
LklOrderSeparate record = new LklOrderSeparate();
record.setSeparate_no(respData.getStr("separate_no")); // 必填参数
record.setOut_separate_no(req.getOutSeparateNo());// 必填参数
record.setMerchant_no(merchantNo);
record.setLog_no(shopOrderLkl.getLog_no());
record.setLog_date(shopOrderLkl.getLog_date());
record.setOrder_id(shopOrderLkl.getOrder_id());
record.setTotal_amt(shopOrderLkl.getTotal_amt().toString());
record.setNotify_url(req.getNotifyUrl());
record.setLkl_org_no(req.getLklOrgNo());
record.setRecv_datas(JSONUtil.toJsonStr(req.getRecvDatas()));
record.setStatus(respData.getStr("status"));
lklOrderSeparateService.addOrUpdateByReceiverNo(record);
successCnt++;
}
if (successCnt <= 0) {
return Pair.of(false, "分账失败");
} else if (successCnt != shopOrderLklList.size()) {
return Pair.of(true, "部分订单分账执行成功,处理中");
}
return Pair.of(true, "全部订单分账执行成功,处理中");
} catch (SDKException e) {
log.error("分账发生错误:", e);
return Pair.of(false, "分账发生错误");
}
}
/**
* 分账结果通知
* 参考https://o.lakala.com/#/home/document/detail?id=393

View File

@ -18,13 +18,13 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
/***
* 支付成功后微信和支付宝发出异步通知消息到 mqmq监听到消息执行更改订单状态已支付
/**
* 支付成功后微信和支付宝发出异步通知消息到 RabbitMQ
* 这里 MQ 监听到消息后执行更改订单状态为已支付
*/
@Service
@Slf4j
@ -32,103 +32,169 @@ import java.util.List;
public class OrderPayedListener {
private static final Logger logger = LoggerFactory.getLogger(OrderPayedListener.class);
@Autowired
private ShopOrderBaseService shopOrderBaseService;
@Autowired
private ShopOrderInfoService shopOrderInfoService;
// @Autowired
// private ShopStorePrinterService shopStorePrinterService;
// @Autowired
// private MqMessageService mqMessageService;
@Autowired
private SFExpressApiService sfExpressApiService;
/**
* RabbitMQ 消息监听入口方法
*
* @param data 消息体包含订单 ID 列表
* @param channel 当前 Channel
* @param message 消息对象
* @throws IOException IO 异常
*/
@RabbitHandler
public void listener(String data, Channel channel, Message message) throws IOException, InterruptedException {
String messageId = message.getMessageProperties().getMessageId();
public void listener(String data, Channel channel, Message message) throws IOException {
List<String> orderIdList = Convert.toList(String.class, data);
boolean flag = false;
List<String> order_id_row = Convert.toList(String.class, data);
try {
boolean flag = false;
logger.info("收到微信异步通知消息data:{}-chanel:{}-message:{},订单ID:{}", data, channel, message, order_id_row);
// 1. 记录接收到的消息内容
logger.info("收到微信异步通知消息data:{}-channel:{}-message:{},订单ID:{}", data, channel, message, orderIdList);
for (String orderId : order_id_row) {
//判断是否为线下支付订单
ShopOrderInfo orderInfoOld = shopOrderInfoService.get(orderId);
if (orderInfoOld == null) {
continue;
}
// 订单状态
int order_state_id = orderInfoOld.getOrder_state_id().intValue();
logger.info("#### 当前订单状态: {} ####", order_state_id);
if (order_state_id == StateCode.ORDER_STATE_WAIT_PAY) {
// 待支付状态
logger.info("#### 待支付业务分支 ####");
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
} else {
//判断是否线下支付
if (StateCode.PAYMENT_TYPE_OFFLINE == orderInfoOld.getPayment_type_id().intValue()) {
//线下支付直接处理订单支付状态 不处理订单状态
logger.info("#### 线下业务分支 ####");
ShopOrderInfo orderInfo = new ShopOrderInfo();
orderInfo.setOrder_id(orderId);
orderInfo.setOrder_is_paid(StateCode.ORDER_PAID_STATE_YES);
flag = shopOrderInfoService.edit(orderInfo);
} else {
logger.info("#### 非线下业务分支 ####");
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
}
}
logger.info("#### 支付异步通知回调处理是否成功:{} ####", flag);
// 生成取单号和打印小票
if (flag) {
// TODO 以下仅处理下单打印的情况还需要处理退单打印分支
// 原始状态 2010-待付款;2011--待订单审核;2013-待财务审核 变成 2020-待配货2016-已经付款 的时候
// 生成取单号打票机打印订单向顺丰同城下单
if (order_state_id == StateCode.ORDER_STATE_WAIT_PAY
|| order_state_id == StateCode.ORDER_STATE_WAIT_REVIEW
|| order_state_id == StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW) {
// 已支付的订单生成取单号打票机并打印订单
Long orderPickupNum = shopOrderInfoService.isPaidOrderGenPickNumAndPrint(orderInfoOld.getStore_id(), orderId);
// 如果配送方式是 顺丰同城下单
if (orderInfoOld.getDelivery_type_id() != null && orderInfoOld.getDelivery_type_id().equals(StateCode.DELIVERY_TYPE_SAME_CITY)
&& orderPickupNum > 0) {
// 发送顺丰同城快递
Pair<Boolean, String> pairCreateSfOrder = sfExpressApiService.innerCreateSfExpressOrder(orderId, orderPickupNum);
if (pairCreateSfOrder == null) {
logger.error("顺丰同城下单失败pairCreateSfOrder 返回空值");
return;
}
if (!pairCreateSfOrder.getFirst()) {
logger.error("顺丰同城下单失败:{}", pairCreateSfOrder.getSecond());
return;
}
logger.info("顺丰同城下单成功");
}
}
}
}
// 2. 执行订单状态更新逻辑支持批量处理
flag = updateOrderStatusBatch(orderIdList);
if (flag) {
// 操作成功标记消息消费成功
// 3. 若订单更新成功执行后续操作取单号生成打票机打印顺丰下单等
handlePostPaymentActions(orderIdList);
}
// 4. 根据执行结果确认或拒绝消息
if (flag) {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} else {
log.error("消息消费失败执行setPaidYes异常当前订单编号{}", order_id_row);
log.warn("订单状态更新失败,拒绝消息:{}", orderIdList);
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
Thread.sleep(1000);
}
} catch (Exception e) {
log.error("消息消费失败执行setPaidYes异常当前订单编号{},失败原因:", order_id_row, e);
// 5. 捕获异常并记录日志
log.error("消费消息失败:{},失败原因:", orderIdList, e);
// 6. 拒绝消息并重新入队
channel.basicReject(message.getMessageProperties().getDeliveryTag(), true);
Thread.sleep(1000);
}
}
/**
* 批量更新订单状态为已支付
*
* @param orderIdList 订单 ID 列表
* @return 是否全部更新成功
*/
private boolean updateOrderStatusBatch(List<String> orderIdList) {
if (orderIdList == null || orderIdList.isEmpty()) {
return false;
}
boolean flag = false;
for (String orderId : orderIdList) {
ShopOrderInfo orderInfoOld = shopOrderInfoService.get(orderId);
if (orderInfoOld == null) {
continue;
}
int order_state_id = orderInfoOld.getOrder_state_id().intValue();
logger.debug("#### 当前订单状态: {} ####", order_state_id);
// 如果是待支付状态则调用 setPaidYes
if (order_state_id == StateCode.ORDER_STATE_WAIT_PAY) {
logger.debug("#### 待支付业务分支 ####");
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
}
// 非待支付状态判断是否为线下支付
else if (StateCode.PAYMENT_TYPE_OFFLINE == orderInfoOld.getPayment_type_id().intValue()) {
logger.debug("#### 线下业务分支 ####");
ShopOrderInfo orderInfo = new ShopOrderInfo();
orderInfo.setOrder_id(orderId);
orderInfo.setOrder_is_paid(StateCode.ORDER_PAID_STATE_YES);
flag = shopOrderInfoService.edit(orderInfo);
}
// 其他情况也调用 setPaidYes
else {
logger.debug("#### 非线下业务分支 ####");
flag = shopOrderBaseService.setPaidYes(Collections.singletonList(orderId));
}
logger.info("#### 支付异步通知回调处理是否成功:{} ####", flag);
if (!flag) {
break; // 任意一个失败则中断处理
}
}
return flag;
}
/**
* 处理支付完成后需要执行的操作
* - 生成取单号
* - 打印小票
* - 顺丰同城下单等
*
* @param orderIdList 订单 ID 列表
*/
/**
* 处理支付完成后需要执行的操作
* - 生成取单号
* - 打印小票
* - 顺丰同城下单等
*
* @param orderIdList 订单 ID 列表
*/
private void handlePostPaymentActions(List<String> orderIdList) {
if (orderIdList == null || orderIdList.isEmpty()) {
return;
}
for (String orderId : orderIdList) {
ShopOrderInfo orderInfoOld = shopOrderInfoService.get(orderId);
if (orderInfoOld == null) {
continue;
}
int order_state_id = orderInfoOld.getOrder_state_id().intValue();
// 只处理特定状态的订单待支付待审核待财务审核
if (!(order_state_id == StateCode.ORDER_STATE_WAIT_PAY ||
order_state_id == StateCode.ORDER_STATE_WAIT_REVIEW ||
order_state_id == StateCode.ORDER_STATE_WAIT_FINANCE_REVIEW)) {
continue;
}
Long orderPickupNum = shopOrderInfoService.isPaidOrderGenPickNumAndPrint(orderInfoOld.getStore_id(), orderId);
if (orderPickupNum == null || orderPickupNum <= 0) {
continue;
}
// 判断是否为顺丰同城配送方式
if (orderInfoOld.getDelivery_type_id() == null ||
!orderInfoOld.getDelivery_type_id().equals(StateCode.DELIVERY_TYPE_SAME_CITY)) {
continue;
}
Pair<Boolean, String> pairCreateSfOrder = sfExpressApiService.innerCreateSfExpressOrder(orderId, orderPickupNum);
if (pairCreateSfOrder == null) {
logger.error("顺丰同城下单失败pairCreateSfOrder 返回空值");
continue;
}
if (!pairCreateSfOrder.getFirst()) {
logger.error("顺丰同城下单失败:{}", pairCreateSfOrder.getSecond());
continue;
}
logger.debug("顺丰同城下单成功");
}
}

View File

@ -45,8 +45,8 @@
c.category_image AS child_category_image
FROM shop_base_store_category p
LEFT JOIN
shop_base_store_category c ON p.store_category_parent_id = c.store_category_id and c.category_is_enable = 1
WHERE p.store_category_parent_id = 0 and p.category_is_enable = 1
shop_base_store_category c ON c.store_category_parent_id = p.store_category_id and c.category_is_enable = 1
WHERE p.category_is_enable = 1 and p.store_category_parent_id = 0
<if test="keyword != null and keyword != ''">
AND (p.store_category_name LIKE CONCAT('%', #{keyword}, '%')
OR p.description LIKE CONCAT('%', #{keyword}, '%')