Compare commits
6 Commits
7253649412
...
0f0f4e048c
| Author | SHA1 | Date | |
|---|---|---|---|
| 0f0f4e048c | |||
| 8f39816f36 | |||
| 28478ef8c8 | |||
| 7a96cc7ae4 | |||
| 36c10c53db | |||
| 07a420c1e6 |
@ -1,119 +0,0 @@
|
||||
/**
|
||||
* 确认收货处理
|
||||
* @param order_ids 订单ID列表
|
||||
* @param order_rows 订单数据列表
|
||||
* @return 是否处理成功
|
||||
*/
|
||||
public boolean receive(List<String> order_ids, List<ShopOrderBase> order_rows) {
|
||||
// 检测数据是否合法,过滤允许修改的数据
|
||||
if (CollUtil.isEmpty(order_ids)) {
|
||||
throw new ApiException(I18nUtil._("请选择需要确认收货的订单!"));
|
||||
}
|
||||
|
||||
if (CollUtil.isEmpty(order_rows)) {
|
||||
order_rows = gets(order_ids);
|
||||
}
|
||||
|
||||
List<String> receive_id_row = new ArrayList<>();
|
||||
|
||||
for (ShopOrderBase order_row : order_rows) {
|
||||
// 判断订单是否可以确认收货
|
||||
if (ifReceive(order_row.getOrder_state_id())) {
|
||||
receive_id_row.add(order_row.getOrder_id());
|
||||
|
||||
// 增加积分和经验
|
||||
// todo 目前付款支付积分,此处为收货后发放
|
||||
Integer user_id = order_row.getBuyer_user_id();
|
||||
String order_id = order_row.getOrder_id();
|
||||
Integer store_id = order_row.getStore_id();
|
||||
|
||||
ShopOrderData order_data_row = shopOrderDataService.get(order_id);
|
||||
BigDecimal order_points_add = order_data_row.getOrder_points_add();
|
||||
|
||||
BigDecimal order_points_add_all = order_points_add.add(order_data_row.getOrder_double_points_add());
|
||||
|
||||
// 发放购物积分
|
||||
if (CheckUtil.isNotEmpty(order_points_add_all)) {
|
||||
String desc = String.format(I18nUtil._("购物获取积分 %s,订单号 %s"), order_points_add_all, order_id);
|
||||
if (!payService.points(user_id, order_points_add_all, PointsType.POINTS_TYPE_CONSUME, desc, store_id, null, order_id)) {
|
||||
throw new ApiException(I18nUtil._("积分操作失败!"));
|
||||
}
|
||||
}
|
||||
|
||||
// todo 根据送花郎插件是否开启显示是否需要分钱给不同商户
|
||||
/*
|
||||
boolean hall_enable = accountBaseConfigService.getConfig("hall_enable", false);
|
||||
if (hall_enable) {
|
||||
BigDecimal order_commission_fee = order_data_row.getOrder_commission_fee();
|
||||
sendMoneyForTransfer(order_row, order_commission_fee);
|
||||
}
|
||||
*/
|
||||
|
||||
// 分销功能处理
|
||||
String fx_settle_type = accountBaseConfigService.getConfig("fx_settle_type", "receive");
|
||||
if (StrUtil.equals(fx_settle_type, "receive")) {
|
||||
// todo settleDistributionUserOrder
|
||||
shopDistributionUserOrderService.settleDistributionUserOrder(order_id);
|
||||
}
|
||||
|
||||
// 重要:拉卡拉给平台和代理商分账
|
||||
Pair<Boolean, String> retOrderSeparateRet = lakalaApiService.innerDoOrderSeparate(order_row.getOrder_id(), Convert.toStr(order_row.getStore_id()));
|
||||
if (!retOrderSeparateRet.getFirst()) {
|
||||
throw new ApiException(I18nUtil._("平台或代理商分账失败: " + retOrderSeparateRet.getSecond()));
|
||||
}
|
||||
|
||||
// 统计总营业额
|
||||
ShopStoreAnalytics analytics_row = shopStoreAnalyticsService.get(store_id);
|
||||
BigDecimal order_payment_amount = order_row.getOrder_payment_amount();
|
||||
analytics_row.setStore_trade_amount(NumberUtil.add(analytics_row.getStore_trade_amount(), order_payment_amount));
|
||||
if (!shopStoreAnalyticsService.edit(analytics_row)) {
|
||||
throw new ApiException(ResultCode.FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查是否有符合条件的订单
|
||||
if (CollUtil.isEmpty(receive_id_row)) {
|
||||
throw new ApiException(I18nUtil._("无符合确认收货条件的订单!"));
|
||||
}
|
||||
|
||||
// 修改订单状态, 随机去一个订单获取店铺编号
|
||||
ShopOrderBase shopOrderBase = order_rows.get(0);
|
||||
Integer store_id = shopOrderBase.getStore_id();
|
||||
editNextState(receive_id_row, store_id, StateCode.ORDER_STATE_SHIPPED, order_rows, 0);
|
||||
|
||||
// 如果是商家,且启用供应商,则商家看到供应商店铺商品 store_type = 2
|
||||
boolean ifSupplierMarket = accountBaseConfigService.ifSupplierMarket();
|
||||
UserDto user = getCurrentUser();
|
||||
store_id = user != null ? Convert.toInt(user.getStore_id(), 0) : 0;
|
||||
|
||||
// 处理供应商市场的库存增加逻辑
|
||||
if (ifSupplierMarket && CheckUtil.isNotEmpty(store_id)) {
|
||||
// 供应商商品,增加商家库存
|
||||
QueryWrapper<ShopOrderItem> itemQueryWrapper = new QueryWrapper<>();
|
||||
itemQueryWrapper.in("order_id", receive_id_row);
|
||||
List<ShopOrderItem> order_item_rows = shopOrderItemService.find(itemQueryWrapper);
|
||||
|
||||
List<Long> item_src_ids = order_item_rows.stream().map(ShopOrderItem::getItem_id).distinct().collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(item_src_ids)) {
|
||||
QueryWrapper<ShopProductItem> productItemQueryWrapper = new QueryWrapper<>();
|
||||
productItemQueryWrapper.in("item_src_id", item_src_ids).eq("store_id", store_id);
|
||||
List<ShopProductItem> product_item_rows = shopProductItemService.find(productItemQueryWrapper);
|
||||
|
||||
// 更新供应商商品库存
|
||||
for (ShopProductItem product_item_row : product_item_rows) {
|
||||
String item_src_id = product_item_row.getItem_src_id();
|
||||
Optional<ShopOrderItem> orderItemOpl = order_item_rows.stream().filter(s -> ObjectUtil.equal(s.getItem_id(), item_src_id)).findFirst();
|
||||
if (orderItemOpl.isPresent()) {
|
||||
ShopOrderItem shopOrderItem = orderItemOpl.get();
|
||||
Integer order_item_quantity = shopOrderItem.getOrder_item_quantity();
|
||||
product_item_row.setItem_quantity(product_item_row.getItem_quantity() + order_item_quantity);
|
||||
if (!shopProductItemService.edit(product_item_row)) {
|
||||
throw new ApiException(ResultCode.FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -44,6 +44,7 @@ public class LklLedgerMember implements Serializable {
|
||||
private String ele_contract_no;
|
||||
private String split_launch_mode;
|
||||
private String settle_type;
|
||||
private String settle_type_draw;
|
||||
private String split_rule_source;
|
||||
private String ret_url;
|
||||
private String apply_id;
|
||||
|
||||
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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.modules.lakala;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Accessors(chain = true)
|
||||
@TableName("lkl_order_draw")
|
||||
@ApiModel(value = "拉卡拉订单分账金额提现表实体", description = "拉卡拉订单分账金额提现表实体")
|
||||
public class LklOrderDraw {
|
||||
|
||||
@TableId(value = "id", type = IdType.INPUT)
|
||||
@ApiModelProperty(value = "自增Id", example = "1")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 钱包ID
|
||||
*/
|
||||
@ApiModelProperty(value = "钱包ID", example = "W123456789")
|
||||
private String ewallet_id;
|
||||
|
||||
/**
|
||||
* 请求日期
|
||||
*/
|
||||
@ApiModelProperty(value = "请求日期", example = "20231001")
|
||||
private String req_date;
|
||||
|
||||
/**
|
||||
* 提款流水号
|
||||
*/
|
||||
@ApiModelProperty(value = "提款流水号", example = "DRAW2023100100001")
|
||||
private String draw_jnl;
|
||||
|
||||
/**
|
||||
* 提款金额(单位:元)含手续费
|
||||
*/
|
||||
@ApiModelProperty(value = "提款金额(单位:元)含手续费", example = "1000.00")
|
||||
private String draw_amt;
|
||||
|
||||
/**
|
||||
* 手续费
|
||||
*/
|
||||
@ApiModelProperty(value = "手续费", example = "10.00")
|
||||
private String draw_fee;
|
||||
|
||||
/**
|
||||
* 提款模式
|
||||
*/
|
||||
@ApiModelProperty(value = "提款模式", example = "ONLINE")
|
||||
private String draw_mode;
|
||||
|
||||
/**
|
||||
* 结算模式(01主动提款 02余额自动结算 03 交易自动结算)
|
||||
*/
|
||||
@ApiModelProperty(value = "结算模式(01主动提款 02余额自动结算 03 交易自动结算)", example = "01")
|
||||
private String batch_auto_settle;
|
||||
|
||||
/**
|
||||
* 自动结算批次号
|
||||
*/
|
||||
@ApiModelProperty(value = "自动结算批次号", example = "BATCH20231001001")
|
||||
private String batch_no;
|
||||
|
||||
/**
|
||||
* 结算账户号
|
||||
*/
|
||||
@ApiModelProperty(value = "结算账户号", example = "6222021234567890123")
|
||||
private String acc_no;
|
||||
|
||||
/**
|
||||
* 结算账户名
|
||||
*/
|
||||
@ApiModelProperty(value = "结算账户名", example = "张三")
|
||||
private String acct_name;
|
||||
|
||||
/**
|
||||
* 提款状态:DRAW.ACCEPTED 提款已受理;DRAW.FREEZE 提款冻结;
|
||||
* DRAW.PROCESSING 提款处理中;DRAW.SUCCESS 提款成功;DRAW.FAILED 提款失败
|
||||
*/
|
||||
@ApiModelProperty(value = "提款状态:DRAW.ACCEPTED(提款已受理)、DRAW.FREEZE(提款冻结)、DRAW.PROCESSING(提款处理中)、DRAW.SUCCESS(提款成功)、DRAW.FAILED(提款失败)",
|
||||
example = "DRAW.SUCCESS")
|
||||
private String draw_state;
|
||||
|
||||
/**
|
||||
* 结果信息
|
||||
*/
|
||||
@ApiModelProperty(value = "结果信息", example = "提款成功")
|
||||
private String meno;
|
||||
|
||||
/**
|
||||
* 商户订单号
|
||||
*/
|
||||
@ApiModelProperty(value = "商户订单号", example = "MER2023100100001")
|
||||
private String mer_order_no;
|
||||
|
||||
/**
|
||||
* 结算流水号
|
||||
*/
|
||||
@ApiModelProperty(value = "结算流水号", example = "SETTLE2023100100001")
|
||||
private String settle_no;
|
||||
|
||||
/**
|
||||
* 银行行号
|
||||
*/
|
||||
@ApiModelProperty(value = "银行行号", example = "102100099999")
|
||||
private String bank_no;
|
||||
|
||||
/**
|
||||
* 银行名称
|
||||
*/
|
||||
@ApiModelProperty(value = "银行名称", example = "中国工商银行")
|
||||
private String nbk_name;
|
||||
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
@ApiModelProperty(value = "商户号", example = "M1234567890")
|
||||
private String merc_id;
|
||||
|
||||
/**
|
||||
* 完成时间
|
||||
*/
|
||||
@ApiModelProperty(value = "完成时间", example = "2023-10-01 12:00:00")
|
||||
private String complete_time;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@ApiModelProperty(value = "创建时间", example = "2023-10-01 11:30:00")
|
||||
private String created_time;
|
||||
|
||||
/**
|
||||
* 异步通知地址
|
||||
*/
|
||||
@ApiModelProperty(value = "异步通知地址", example = "https://api.example.com/notify")
|
||||
private String notify_url;
|
||||
|
||||
/**
|
||||
* 异步通知返回的JSON数据
|
||||
*/
|
||||
@ApiModelProperty(value = "异步通知返回的JSON数据", example = "{\"code\":\"0000\",\"msg\":\"success\"}")
|
||||
private String notify_resp;
|
||||
|
||||
@ApiModelProperty(value = "备注信息")
|
||||
private String remark;
|
||||
|
||||
@ApiModelProperty(value = "摘要")
|
||||
private String summary;
|
||||
|
||||
/**
|
||||
* 记录状态:1-有效;2-无效;
|
||||
*/
|
||||
@ApiModelProperty(value = "记录状态:1-有效;2-无效", example = "1")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 新建时间
|
||||
*/
|
||||
@ApiModelProperty(value = "新建时间", example = "2023-10-01 11:30:00")
|
||||
private Date created_at;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@ApiModelProperty(value = "更新时间", example = "2023-10-01 12:00:00")
|
||||
private Date updated_at;
|
||||
}
|
||||
|
||||
@ -30,8 +30,8 @@ redis:
|
||||
|
||||
baidu:
|
||||
map:
|
||||
app_id: 116444176
|
||||
ak: qWKt2xbrqXsp2yK35YYXVBNZgrbiCG5v
|
||||
app_id: 120196890
|
||||
ak: YzRPLAOTYyCFVjvlh2vxnaUnH4jPjufM
|
||||
url: https://api.map.baidu.com/geoconv/v2/?
|
||||
|
||||
getui: # 个推配置
|
||||
|
||||
@ -30,8 +30,8 @@ redis:
|
||||
|
||||
baidu:
|
||||
map:
|
||||
app_id: 116444176
|
||||
ak: qWKt2xbrqXsp2yK35YYXVBNZgrbiCG5v
|
||||
app_id: 120196890
|
||||
ak: YzRPLAOTYyCFVjvlh2vxnaUnH4jPjufM
|
||||
url: https://api.map.baidu.com/geoconv/v2/?
|
||||
getui: # 个推配置
|
||||
push:
|
||||
|
||||
@ -30,8 +30,8 @@ redis:
|
||||
|
||||
baidu:
|
||||
map:
|
||||
app_id: 116444176
|
||||
ak: qWKt2xbrqXsp2yK35YYXVBNZgrbiCG5v
|
||||
app_id: 120196890
|
||||
ak: YzRPLAOTYyCFVjvlh2vxnaUnH4jPjufM
|
||||
url: https://api.map.baidu.com/geoconv/v2/?
|
||||
getui: # 个推配置
|
||||
push:
|
||||
|
||||
@ -30,8 +30,8 @@ redis:
|
||||
|
||||
baidu:
|
||||
map:
|
||||
app_id: 116444176
|
||||
ak: qWKt2xbrqXsp2yK35YYXVBNZgrbiCG5v
|
||||
app_id: 120196890
|
||||
ak: YzRPLAOTYyCFVjvlh2vxnaUnH4jPjufM
|
||||
url: https://api.map.baidu.com/geoconv/v2/?
|
||||
getui: # 个推配置
|
||||
push:
|
||||
|
||||
@ -30,8 +30,8 @@ redis:
|
||||
|
||||
baidu:
|
||||
map:
|
||||
app_id: 116444176
|
||||
ak: qWKt2xbrqXsp2yK35YYXVBNZgrbiCG5v
|
||||
app_id: 120196890
|
||||
ak: YzRPLAOTYyCFVjvlh2vxnaUnH4jPjufM
|
||||
url: https://api.map.baidu.com/geoconv/v2/?
|
||||
|
||||
getui: # 个推配置
|
||||
|
||||
@ -50,4 +50,19 @@ public interface AccountBaseConfigService extends IBaseService<AccountBaseConfig
|
||||
boolean saveOrUpdate(Collection<AccountBaseConfig> configs);
|
||||
|
||||
boolean saveOrUpdate(AccountBaseConfig config);
|
||||
|
||||
/**
|
||||
* 获取系统配置
|
||||
*
|
||||
* @param configKey
|
||||
* @return
|
||||
*/
|
||||
String getSystemConfig(String configKey);
|
||||
|
||||
/**
|
||||
* 获取平台内部最低配送费,单位(分)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Integer getInnerMinDeliveryFee();
|
||||
}
|
||||
|
||||
@ -56,4 +56,33 @@ public interface ShopBaseDistrictService extends IBaseService<ShopBaseDistrict>
|
||||
*/
|
||||
String joinDistrict(List<ShopBaseDistrict> list, Integer joinKey, Boolean hasSeparator, String separator);
|
||||
|
||||
|
||||
/**
|
||||
* 省市区ID路径和名称路径相互转换
|
||||
* 支持根据ID路径获取名称路径,或根据名称路径获取ID路径
|
||||
*
|
||||
* @param areaIds 省市区ID路径,格式如:"450000/450800/450881"
|
||||
* @param areaNames 省市区名称路径,格式如:"广西壮族自治区/贵港市/桂平市"
|
||||
* @return String数组,第一个元素为处理后的ID路径,第二个元素为处理后的名称路径
|
||||
*/
|
||||
String[] convertDistrictPath(String areaIds, String areaNames);
|
||||
|
||||
/**
|
||||
* 根据省市区ID路径获取对应的名称路径
|
||||
* 例如:450000/450800/450881 -> 广西壮族自治区/贵港市/桂平市
|
||||
*
|
||||
* @param districtIdPath 省市区ID路径,格式如:"450000/450800/450881"
|
||||
* @return 省市区名称路径,格式如:"广西壮族自治区/贵港市/桂平市"
|
||||
*/
|
||||
String getDistrictNamePathByIdPath(String districtIdPath);
|
||||
|
||||
/**
|
||||
* 根据省市区名称路径获取对应的ID路径
|
||||
* 例如:广西壮族自治区/贵港市/桂平市 -> 450000/450800/450881
|
||||
*
|
||||
* @param districtNamePath 省市区名称路径,格式如:"省/市/区"
|
||||
* @return 省市区ID路径,格式如:"450000/450800/450881"
|
||||
*/
|
||||
String getDistrictIdPathByNamePath(String districtNamePath);
|
||||
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.constant.CommonConstant;
|
||||
import com.suisung.mall.common.constant.ConfigConstant;
|
||||
import com.suisung.mall.common.constant.RedisConstant;
|
||||
import com.suisung.mall.common.exception.ApiException;
|
||||
@ -341,6 +342,44 @@ public class AccountBaseConfigServiceImpl extends BaseServiceImpl<AccountBaseCon
|
||||
return saveOrUpdate(configs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统配置值
|
||||
* <p>
|
||||
* 根据配置键获取对应的配置值,如果配置值为空则返回空字符串。
|
||||
* </p>
|
||||
*
|
||||
* @param configKey 配置键
|
||||
* @return 配置值,如果找不到或为空则返回空字符串
|
||||
*/
|
||||
@Override
|
||||
public String getSystemConfig(String configKey) {
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(configKey)) {
|
||||
log.warn("[系统配置] 参数校验失败:配置键不能为空");
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
String configValue = accountService.getAccountBaseConfigValue(configKey);
|
||||
return StrUtil.blankToDefault(configValue, "0");
|
||||
} catch (Exception e) {
|
||||
log.error("[系统配置] 获取配置值异常,configKey={}", configKey, e);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取平台内部最低配送费,单位(分)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Integer getInnerMinDeliveryFee() {
|
||||
String v = getSystemConfig(CommonConstant.Inner_Min_DeliveryFee_Key);
|
||||
return NumberUtil.isNumber(v) ? Convert.toInt(v) : 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void run(String... args) throws Exception {
|
||||
|
||||
@ -125,7 +125,7 @@ public class ShopBaseCrontabServiceImpl extends BaseServiceImpl<ShopBaseCrontabM
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取cron 表达式
|
||||
* 获取 cron 表达式
|
||||
*
|
||||
* @param shopBaseCrontab
|
||||
* @return
|
||||
|
||||
@ -13,6 +13,7 @@ import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.base.mapper.ShopBaseDistrictMapper;
|
||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseDistrictService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -30,6 +31,7 @@ import java.util.*;
|
||||
* @author Xinze
|
||||
* @since 2021-06-28
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ShopBaseDistrictServiceImpl extends BaseServiceImpl<ShopBaseDistrictMapper, ShopBaseDistrict> implements ShopBaseDistrictService {
|
||||
|
||||
@ -339,4 +341,129 @@ public class ShopBaseDistrictServiceImpl extends BaseServiceImpl<ShopBaseDistric
|
||||
return district_id_row;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 省市区ID路径和名称路径相互转换
|
||||
* 支持根据ID路径获取名称路径,或根据名称路径获取ID路径
|
||||
*
|
||||
* @param areaIds 省市区ID路径,格式如:"450000/450800/450881"
|
||||
* @param areaNames 省市区名称路径,格式如:"广西壮族自治区/贵港市/桂平市"
|
||||
* @return String数组,第一个元素为处理后的ID路径,第二个元素为处理后的名称路径
|
||||
*/
|
||||
@Override
|
||||
public String[] convertDistrictPath(String areaIds, String areaNames) {
|
||||
// 初始化返回结果
|
||||
String resultAreaIds = "";
|
||||
String resultAreaNames = "";
|
||||
|
||||
try {
|
||||
// 如果两个参数都有值,直接返回原始值
|
||||
if (StrUtil.isNotBlank(areaIds) && StrUtil.isNotBlank(areaNames)) {
|
||||
log.debug("[地区转换] 两个参数都有值,直接返回原始值: areaIds={}, areaNames={}", areaIds, areaNames);
|
||||
return new String[]{areaIds, areaNames};
|
||||
}
|
||||
|
||||
// 如果只有areaIds不为空,根据ID路径获取名称路径
|
||||
if (StrUtil.isNotBlank(areaIds)) {
|
||||
log.debug("[地区转换] 根据ID路径获取名称路径: {}", areaIds);
|
||||
resultAreaNames = getDistrictNamePathByIdPath(areaIds);
|
||||
resultAreaIds = areaIds;
|
||||
}
|
||||
|
||||
// 如果只有areaNames不为空,根据名称路径获取ID路径
|
||||
if (StrUtil.isNotBlank(areaNames)) {
|
||||
log.debug("[地区转换] 根据名称路径获取ID路径: {}", areaNames);
|
||||
resultAreaIds = getDistrictIdPathByNamePath(areaNames);
|
||||
resultAreaNames = areaNames;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[地区转换] 转换过程中发生异常", e);
|
||||
// 发生异常时,保持初始化的空字符串值
|
||||
}
|
||||
|
||||
// 始终返回包含两个元素的数组
|
||||
return new String[]{resultAreaIds, resultAreaNames};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据省市区ID路径获取对应的名称路径
|
||||
* 例如:450000/450800/450881 -> 广西壮族自治区/贵港市/桂平市
|
||||
*
|
||||
* @param districtIdPath 省市区ID路径,格式如:"450000/450800/450881"
|
||||
* @return 省市区名称路径,格式如:"广西壮族自治区/贵港市/桂平市"
|
||||
*/
|
||||
@Override
|
||||
public String getDistrictNamePathByIdPath(String districtIdPath) {
|
||||
if (StrUtil.isBlank(districtIdPath)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String[] idStrs = districtIdPath.split("/");
|
||||
List<String> names = new ArrayList<>(idStrs.length);
|
||||
|
||||
// 先获取所有地区对象的名称
|
||||
for (String idStr : idStrs) {
|
||||
Integer districtId = Convert.toInt(idStr);
|
||||
if (districtId == null) {
|
||||
log.warn("[地区转换] ID格式不正确: {}", idStr);
|
||||
names.add(""); // 添加空字符串而不是直接返回
|
||||
continue; // 继续处理下一个
|
||||
}
|
||||
|
||||
ShopBaseDistrict district = get(districtId);
|
||||
if (district == null) {
|
||||
log.warn("[地区转换] 未找到对应地区信息, districtId: {}", districtId);
|
||||
names.add(""); // 添加空字符串而不是直接返回
|
||||
continue; // 继续处理下一个
|
||||
}
|
||||
|
||||
names.add(district.getDistrict_name());
|
||||
}
|
||||
|
||||
return String.join("/", names);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据省市区名称路径获取对应的ID路径
|
||||
* 例如:广西壮族自治区/贵港市/桂平市 -> 450000/450800/450881
|
||||
*
|
||||
* @param districtNamePath 省市区名称路径,格式如:"省/市/区"
|
||||
* @return 省市区ID路径,格式如:"450000/450800/450881"
|
||||
*/
|
||||
@Override
|
||||
public String getDistrictIdPathByNamePath(String districtNamePath) {
|
||||
if (StrUtil.isBlank(districtNamePath)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String[] names = districtNamePath.split("/");
|
||||
List<String> ids = new ArrayList<>(names.length);
|
||||
|
||||
// 先根据名称获取所有地区对象的ID
|
||||
for (String name : names) {
|
||||
if (StrUtil.isBlank(name)) {
|
||||
log.warn("[地区转换] 名称不能为空");
|
||||
ids.add(""); // 添加空字符串而不是直接返回
|
||||
continue; // 继续处理下一个
|
||||
}
|
||||
|
||||
QueryWrapper<ShopBaseDistrict> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("district_name", name.trim());
|
||||
|
||||
ShopBaseDistrict district = findOne(queryWrapper);
|
||||
if (district == null) {
|
||||
log.warn("[地区转换] 未找到对应地区信息, name: {}", name);
|
||||
ids.add(""); // 添加空字符串而不是直接返回
|
||||
continue; // 继续处理下一个
|
||||
}
|
||||
|
||||
ids.add(district.getDistrict_id().toString());
|
||||
}
|
||||
|
||||
return String.join("/", ids);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ import java.util.List;
|
||||
*/
|
||||
public class UpdateOrderStatusJob extends QuartzJobBean {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(UpdateOrderStatusJob.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(UpdateOrderStatusJob.class);
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
@ -29,6 +29,8 @@ public class UpdateOrderStatusJob extends QuartzJobBean {
|
||||
ShopOrderInfoService shopOrderInfoService = SpringUtil.getBean(ShopOrderInfoService.class);
|
||||
ShopDistributionUserOrderService shopDistributionUserOrderService = SpringUtil.getBean(ShopDistributionUserOrderService.class);
|
||||
|
||||
// 在UpdateOrderStatusJob.execute方法开始添加日志
|
||||
logger.info("UpdateOrderStatusJob 方法开始执行");
|
||||
|
||||
// 自动取消未支付订单
|
||||
//shopOrderBaseService.autoCancelOrder();
|
||||
|
||||
@ -29,32 +29,31 @@ public class QuartzServiceImpl implements QuartzService {
|
||||
*/
|
||||
@Override
|
||||
public void addJob(String jName, String jGroup, String tName, String tGroup, String cron, String cName) {
|
||||
logger.info("[Quartz] 开始添加定时任务: 任务名称={}, 任务组={}, 触发器名称={}, 触发器组={}, cron表达式={}, 类名={}",
|
||||
jName, jGroup, tName, tGroup, cron, cName);
|
||||
logger.info("[Quartz] 添加定时任务: 任务名称={}, cron表达式={}", jName, cron);
|
||||
|
||||
// 1. 参数校验
|
||||
if (jName == null || jName.trim().isEmpty()) {
|
||||
logger.warn("[Quartz] 任务名称不能为空: {}", jName);
|
||||
logger.warn("[Quartz] 任务名称不能为空");
|
||||
throw new ApiException(I18nUtil._("任务名称不能为空!"));
|
||||
}
|
||||
if (jGroup == null || jGroup.trim().isEmpty()) {
|
||||
logger.warn("[Quartz] 任务组不能为空: {}", jGroup);
|
||||
logger.warn("[Quartz] 任务组不能为空");
|
||||
throw new ApiException(I18nUtil._("任务组不能为空!"));
|
||||
}
|
||||
if (tName == null || tName.trim().isEmpty()) {
|
||||
logger.warn("[Quartz] 触发器名称不能为空: {}", tName);
|
||||
logger.warn("[Quartz] 触发器名称不能为空");
|
||||
throw new ApiException(I18nUtil._("触发器名称不能为空!"));
|
||||
}
|
||||
if (tGroup == null || tGroup.trim().isEmpty()) {
|
||||
logger.warn("[Quartz] 触发器组不能为空: {}", tGroup);
|
||||
logger.warn("[Quartz] 触发器组不能为空");
|
||||
throw new ApiException(I18nUtil._("触发器组不能为空!"));
|
||||
}
|
||||
if (cron == null || cron.trim().isEmpty()) {
|
||||
logger.warn("[Quartz] cron表达式不能为空: {}", cron);
|
||||
logger.warn("[Quartz] cron表达式不能为空");
|
||||
throw new ApiException(I18nUtil._("cron表达式不能为空!"));
|
||||
}
|
||||
if (cName == null || cName.trim().isEmpty()) {
|
||||
logger.warn("[Quartz] 任务实现类名称不能为空: {}", cName);
|
||||
logger.warn("[Quartz] 任务实现类名称不能为空");
|
||||
throw new ApiException(I18nUtil._("任务实现类名称不能为空!"));
|
||||
}
|
||||
|
||||
@ -63,9 +62,7 @@ public class QuartzServiceImpl implements QuartzService {
|
||||
Class<Job> clazz;
|
||||
|
||||
String fullClassName = PATH_PREFIX + cName;
|
||||
logger.debug("[Quartz] 尝试加载任务类: {}", fullClassName);
|
||||
clazz = (Class<Job>) Class.forName(fullClassName);
|
||||
logger.debug("[Quartz] 成功加载任务类: {}", fullClassName);
|
||||
|
||||
// 3. 构建任务详情和触发器
|
||||
JobKey jobKey = new JobKey(jName, jGroup);
|
||||
@ -77,44 +74,38 @@ public class QuartzServiceImpl implements QuartzService {
|
||||
CronTrigger trigger = TriggerBuilder.newTrigger()
|
||||
.withIdentity(triggerKey)
|
||||
.startNow()
|
||||
.withSchedule(CronScheduleBuilder.cronSchedule(cron))
|
||||
.withSchedule(CronScheduleBuilder.cronSchedule(cron).withMisfireHandlingInstructionDoNothing())
|
||||
.build();
|
||||
|
||||
logger.debug("[Quartz] 构建任务详情和触发器完成: jobKey={}, triggerKey={}", jobKey, triggerKey);
|
||||
|
||||
// 打印最终执行的 cron 表达式
|
||||
logger.info("[Quartz] 定时任务最终执行表达式: {}", trigger.getCronExpression());
|
||||
|
||||
// 4. 检查任务是否已存在
|
||||
if (scheduler.checkExists(jobKey)) {
|
||||
logger.info("[Quartz] 任务已存在,先删除旧任务: jobKey={}", jobKey);
|
||||
logger.info("[Quartz] 任务已存在,先删除旧任务: {}", jName);
|
||||
scheduler.deleteJob(jobKey);
|
||||
}
|
||||
|
||||
// 5. 调度任务
|
||||
logger.info("[Quartz] 开始调度任务: jobKey={}, triggerKey={}", jobKey, triggerKey);
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
logger.info("[Quartz] 任务调度成功: jobKey={}, triggerKey={}", jobKey, triggerKey);
|
||||
logger.info("[Quartz] 任务调度成功: {}", jName);
|
||||
|
||||
// 6. 启动调度器(如果尚未启动)
|
||||
if (!scheduler.isStarted()) {
|
||||
logger.info("[Quartz] 调度器尚未启动,正在启动...");
|
||||
scheduler.start();
|
||||
logger.info("[Quartz] 调度器启动成功");
|
||||
}
|
||||
|
||||
// 只在异常状态时记录详细信息
|
||||
if (scheduler.getTriggerState(triggerKey) != Trigger.TriggerState.NORMAL) {
|
||||
logger.error("Trigger注册异常,当前状态: {}", scheduler.getTriggerState(triggerKey));
|
||||
logger.error("[Quartz] Trigger注册异常,当前状态: {}", scheduler.getTriggerState(triggerKey));
|
||||
}
|
||||
|
||||
} catch (SchedulerException e) {
|
||||
logger.error("[Quartz] 添加定时任务失败!任务名称={}, 任务组={}, 触发器名称={}, 触发器组={}",
|
||||
jName, jGroup, tName, tGroup, e);
|
||||
logger.error("[Quartz] 添加定时任务失败!任务名称={}", jName, e);
|
||||
throw new ApiException(I18nUtil._("添加定时任务失败!"), e);
|
||||
} catch (ClassNotFoundException e) {
|
||||
logger.error("[Quartz] 定时任务脚本不存在!类名: {}{}", PATH_PREFIX, cName, e);
|
||||
throw new ApiException(I18nUtil._("定时任务脚本不存在!类名: " + PATH_PREFIX + cName), e);
|
||||
} catch (Exception e) {
|
||||
logger.error("[Quartz] 添加定时任务时发生未知异常!任务名称={}, 任务组={}, 触发器名称={}, 触发器组={}",
|
||||
jName, jGroup, tName, tGroup, e);
|
||||
logger.error("[Quartz] 添加定时任务时发生未知异常!任务名称={}", jName, e);
|
||||
throw new ApiException(I18nUtil._("添加定时任务失败!"), e);
|
||||
}
|
||||
}
|
||||
@ -132,23 +123,22 @@ public class QuartzServiceImpl implements QuartzService {
|
||||
*/
|
||||
public boolean addOrUpdateJobFromDatabase(String jobName, String jobGroup, String triggerName,
|
||||
String triggerGroup, String dbCron, String dbJobClass) {
|
||||
logger.info("[Quartz] 尝试从数据库信息添加或更新任务: 任务名称={}, 任务组={}", jobName, jobGroup);
|
||||
|
||||
logger.info("[Quartz] 添加或更新任务: {}", jobName);
|
||||
|
||||
try {
|
||||
JobKey jobKey = new JobKey(jobName, jobGroup);
|
||||
|
||||
// 检查任务是否已存在
|
||||
if (scheduler.checkExists(jobKey)) {
|
||||
logger.debug("[Quartz] 任务已存在于调度器中: jobKey={}", jobKey);
|
||||
return true; // 任务已存在,无需添加
|
||||
}
|
||||
|
||||
// 任务不存在,从数据库信息创建新任务
|
||||
logger.info("[Quartz] 调度器中不存在任务,从数据库信息创建: jobKey={}", jobKey);
|
||||
addJob(jobName, jobGroup, triggerName, triggerGroup, dbCron, dbJobClass);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
logger.error("[Quartz] 从数据库信息添加或更新任务失败: 任务名称={}, 任务组={}", jobName, jobGroup, e);
|
||||
logger.error("[Quartz] 添加或更新任务失败: {}", jobName, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -162,24 +152,22 @@ public class QuartzServiceImpl implements QuartzService {
|
||||
*/
|
||||
@Override
|
||||
public void pauseJob(String jName, String jGroup) {
|
||||
logger.info("[Quartz] 开始暂停定时任务: 任务名称={}, 任务组={}", jName, jGroup);
|
||||
|
||||
logger.info("[Quartz] 暂停定时任务: {}", jName);
|
||||
try {
|
||||
JobKey jobKey = JobKey.jobKey(jName, jGroup);
|
||||
|
||||
// 检查任务是否存在,不存在则记录日志并返回,不抛出异常
|
||||
if (!scheduler.checkExists(jobKey)) {
|
||||
logger.info("[Quartz] 任务不存在,无需暂停: jobKey={},可能任务已手动删除或尚未创建", jobKey);
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler.pauseJob(jobKey);
|
||||
logger.info("[Quartz] 定时任务暂停成功: jobKey={}", jobKey);
|
||||
logger.info("[Quartz] 定时任务暂停成功: {}", jName);
|
||||
} catch (SchedulerException e) {
|
||||
logger.error("[Quartz] 暂停定时任务时发生调度异常!任务名称={}, 任务组={}", jName, jGroup, e);
|
||||
// 即使暂停失败也继续执行,避免阻塞业务流程
|
||||
logger.error("[Quartz] 暂停定时任务时发生调度异常!任务名称={}", jName, e);
|
||||
} catch (Exception e) {
|
||||
logger.error("[Quartz] 暂停定时任务时发生未知异常!任务名称={}, 任务组={}", jName, jGroup, e);
|
||||
// 即使暂停失败也继续执行,避免阻塞业务流程
|
||||
logger.error("[Quartz] 暂停定时任务时发生未知异常!任务名称={}", jName, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,24 +179,22 @@ public class QuartzServiceImpl implements QuartzService {
|
||||
*/
|
||||
@Override
|
||||
public void resumeJob(String jName, String jGroup) {
|
||||
logger.info("[Quartz] 开始继续定时任务: 任务名称={}, 任务组={}", jName, jGroup);
|
||||
|
||||
logger.info("[Quartz] 继续定时任务: {}", jName);
|
||||
try {
|
||||
JobKey jobKey = JobKey.jobKey(jName, jGroup);
|
||||
|
||||
// 检查任务是否存在,不存在则记录日志并返回,不抛出异常
|
||||
if (!scheduler.checkExists(jobKey)) {
|
||||
logger.info("[Quartz] 任务不存在,无需继续: jobKey={},可能任务已手动删除或尚未创建", jobKey);
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler.resumeJob(jobKey);
|
||||
logger.info("[Quartz] 定时任务继续成功: jobKey={}", jobKey);
|
||||
logger.info("[Quartz] 定时任务继续成功: {}", jName);
|
||||
} catch (SchedulerException e) {
|
||||
logger.error("[Quartz] 继续定时任务时发生调度异常!任务名称={}, 任务组={}", jName, jGroup, e);
|
||||
// 即使继续失败也继续执行,避免阻塞业务流程
|
||||
logger.error("[Quartz] 继续定时任务时发生调度异常!任务名称={}", jName, e);
|
||||
} catch (Exception e) {
|
||||
logger.error("[Quartz] 继续定时任务时发生未知异常!任务名称={}, 任务组={}", jName, jGroup, e);
|
||||
// 即使继续失败也继续执行,避免阻塞业务流程
|
||||
logger.error("[Quartz] 继续定时任务时发生未知异常!任务名称={}", jName, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,30 +206,25 @@ public class QuartzServiceImpl implements QuartzService {
|
||||
*/
|
||||
@Override
|
||||
public void deleteJob(String jName, String jGroup) {
|
||||
logger.info("[Quartz] 开始删除定时任务: 任务名称={}, 任务组={}", jName, jGroup);
|
||||
logger.info("[Quartz] 删除定时任务: {}", jName);
|
||||
try {
|
||||
JobKey jobKey = JobKey.jobKey(jName, jGroup);
|
||||
|
||||
// 检查任务是否存在,不存在则记录日志并返回,不抛出异常
|
||||
if (!scheduler.checkExists(jobKey)) {
|
||||
logger.info("[Quartz] 任务不存在,无需删除: jobKey={},可能任务已手动删除或尚未创建", jobKey);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean deleted = scheduler.deleteJob(jobKey);
|
||||
if (deleted) {
|
||||
logger.info("[Quartz] 定时任务删除成功: jobKey={}", jobKey);
|
||||
logger.info("[Quartz] 定时任务删除成功: {}", jName);
|
||||
} else {
|
||||
logger.warn("[Quartz] 定时任务删除失败: jobKey={}", jobKey);
|
||||
logger.warn("[Quartz] 定时任务删除失败: {}", jName);
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
logger.error("[Quartz] 删除定时任务时发生调度异常!任务名称={}, 任务组={}", jName, jGroup, e);
|
||||
// 即使删除失败也继续执行,避免阻塞业务流程
|
||||
logger.error("[Quartz] 删除定时任务时发生调度异常!任务名称={}", jName, e);
|
||||
} catch (Exception e) {
|
||||
logger.error("[Quartz] 删除定时任务时发生未知异常!任务名称={}, 任务组={}", jName, jGroup, e);
|
||||
// 即使删除失败也继续执行,避免阻塞业务流程
|
||||
logger.error("[Quartz] 删除定时任务时发生未知异常!任务名称={}", jName, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ public class LakalaAdminController extends BaseControllerImpl {
|
||||
|
||||
@Resource
|
||||
private LakalaApiService lakalaPayService;
|
||||
|
||||
|
||||
@ApiOperation(value = "查询拉卡拉商户可分账的金额", notes = "查询拉卡拉商户可分账的金额")
|
||||
@RequestMapping(value = "/sacs/queryMchSplitAmt", method = RequestMethod.POST)
|
||||
public CommonResult queryMchCanSplitAmt(@RequestBody JSONObject paramsJSON) {
|
||||
@ -39,4 +39,47 @@ public class LakalaAdminController extends BaseControllerImpl {
|
||||
return CommonResult.failed();
|
||||
}
|
||||
|
||||
@ApiOperation(value = "拉卡拉账户D1提现", notes = "拉卡拉账户D1提现")
|
||||
@RequestMapping(value = "/ewallet/drawD1", method = RequestMethod.POST)
|
||||
public CommonResult ewalletWithDrawD1(@RequestBody JSONObject paramsJSON) {
|
||||
try {
|
||||
// 参数校验
|
||||
if (paramsJSON == null) {
|
||||
return CommonResult.failed("请求参数不能为空");
|
||||
}
|
||||
|
||||
// 执行业务逻辑
|
||||
Boolean success = lakalaPayService.ewalletWithDrawD1(paramsJSON.getStr("mercId"), paramsJSON.getStr("merOrderNo"), paramsJSON.getStr("drawAmt"), paramsJSON.getStr("remark"), paramsJSON.getStr("summary"));
|
||||
if (success) {
|
||||
return CommonResult.success("账户D1提现提交成功");
|
||||
}
|
||||
|
||||
return CommonResult.failed("账户D1提现提交失败");
|
||||
} catch (Exception e) {
|
||||
return CommonResult.failed("系统异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation(value = "提款模式设置", notes = "提款模式设置")
|
||||
@RequestMapping(value = "/ewallet/settleProfile", method = RequestMethod.POST)
|
||||
public CommonResult ewalletSettleProfile(@RequestBody JSONObject paramsJSON) {
|
||||
try {
|
||||
// 参数校验
|
||||
if (paramsJSON == null) {
|
||||
return CommonResult.failed("请求参数不能为空");
|
||||
}
|
||||
|
||||
// 执行业务逻辑
|
||||
Boolean success = lakalaPayService.ewalletSettleProfile(paramsJSON.getStr("mercId"), paramsJSON.getStr("settleType"), paramsJSON.getStr("settleTime"));
|
||||
|
||||
if (success) {
|
||||
return CommonResult.success("提款模式设置成功");
|
||||
}
|
||||
|
||||
return CommonResult.failed("提款模式设置失败");
|
||||
} catch (Exception e) {
|
||||
return CommonResult.failed("系统异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.suisung.mall.common.api.CommonResult;
|
||||
import com.suisung.mall.common.service.impl.BaseControllerImpl;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseDistrictService;
|
||||
import com.suisung.mall.shop.lakala.service.LakalaApiService;
|
||||
import com.suisung.mall.shop.lakala.service.LklLedgerEcService;
|
||||
import com.suisung.mall.shop.library.service.LibraryProductService;
|
||||
@ -23,6 +24,7 @@ import com.suisung.mall.shop.sfexpress.service.SFExpressApiService;
|
||||
import com.suisung.mall.shop.store.service.ShopStoreSameCityTransportBaseService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@ -36,6 +38,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Api(tags = "拉卡拉相关接口 - 前端控制器")
|
||||
@RestController
|
||||
@RequestMapping("/mobile/shop/lakala")
|
||||
@ -80,6 +83,9 @@ public class LakalaController extends BaseControllerImpl {
|
||||
@Resource
|
||||
private LklLedgerEcService lklLedgerEcService;
|
||||
|
||||
@Resource
|
||||
private ShopBaseDistrictService shopBaseDistrictService;
|
||||
|
||||
@ApiOperation(value = "测试案例", notes = "测试案例")
|
||||
@RequestMapping(value = "/testcase", method = RequestMethod.POST)
|
||||
public Object testcase(@RequestBody JSONObject paramsJSON) {
|
||||
@ -118,7 +124,10 @@ public class LakalaController extends BaseControllerImpl {
|
||||
|
||||
// return lakalaApiService.sacsQuery("8226330541100GU", "20250918770188017227140800").toString();
|
||||
|
||||
return lakalaApiService.queryLedgerMer("8226330541100HA");
|
||||
String[] result = shopBaseDistrictService.convertDistrictPath(paramsJSON.getStr("id"), paramsJSON.getStr("name"));
|
||||
log.info("result: " + result[0] + " " + result[1]);
|
||||
|
||||
return ""; //lakalaApiService.queryLedgerMer("8226330541100HA");
|
||||
}
|
||||
|
||||
@ApiOperation(value = "批量发送推送消息 - 测试案例", notes = "批量发送推送消息 - 测试案例")
|
||||
@ -239,4 +248,42 @@ public class LakalaController extends BaseControllerImpl {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 分账结果通知
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=367
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "拉卡拉提现结果通知", notes = "拉卡拉提现结果通知")
|
||||
@RequestMapping(value = "/ewallet/drawNotify", method = RequestMethod.POST)
|
||||
public ResponseEntity<JSONObject> ewalletWithDrawNotify(HttpServletRequest request) {
|
||||
JSONObject resp = lakalaPayService.ewalletWithDrawNotify(request);
|
||||
if (resp != null && "SUCCESS".equals(resp.get("code"))) {
|
||||
return ResponseEntity.ok(resp);
|
||||
}
|
||||
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分账结果通知
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=393
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation(value = "提款模式设置结果通知", notes = "提款模式设置结果通知")
|
||||
@RequestMapping(value = "/ewallet/settleProfileNotify", method = RequestMethod.POST)
|
||||
public ResponseEntity<JSONObject> ewalletSettleProfileNotify(HttpServletRequest request) {
|
||||
JSONObject resp = lakalaPayService.ewalletSettleProfileNotify(request);
|
||||
if (resp != null && "SUCCESS".equals(resp.get("code"))) {
|
||||
return ResponseEntity.ok(resp);
|
||||
}
|
||||
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resp);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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.shop.lakala.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.suisung.mall.common.modules.lakala.LklOrderDraw;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
|
||||
@Repository
|
||||
public interface LklOrderDrawMapper extends BaseMapper<LklOrderDraw> {
|
||||
|
||||
}
|
||||
@ -309,5 +309,46 @@ public interface LakalaApiService {
|
||||
*/
|
||||
Boolean checkAndFixLedgerMerApplyAndBindRelations(ShopMchEntry shopMchEntry);
|
||||
|
||||
/**
|
||||
* 提款模式设置
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=372
|
||||
*
|
||||
* @param mercId 822商户号或receiveNo
|
||||
* @param settleType 提款模式(01主动提款 02余额自动结算 03交易自动结算)
|
||||
* @param settleTime 余额自动结算时间(小时)- 默认值:06。如08:00-09:00到账,则传入08。
|
||||
* @return 设置是否成功
|
||||
*/
|
||||
Boolean ewalletSettleProfile(String mercId, String settleType, String settleTime);
|
||||
|
||||
|
||||
/**
|
||||
* 提款模式设置结果通知
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=372
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
JSONObject ewalletSettleProfileNotify(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 拉卡拉账户D1提现
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=430
|
||||
*
|
||||
* @param mercId 822商户号或receiveNo
|
||||
* @param merOrderNo 商户订单号
|
||||
* @param drawAmt 提现金额(分)
|
||||
* @param remark
|
||||
* @param summary
|
||||
*/
|
||||
Boolean ewalletWithDrawD1(String mercId, String merOrderNo, String drawAmt, String remark, String summary);
|
||||
|
||||
/**
|
||||
* 拉卡拉账户D1提现结果通知
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=367
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
JSONObject ewalletWithDrawNotify(HttpServletRequest request);
|
||||
|
||||
}
|
||||
|
||||
@ -55,4 +55,13 @@ public interface LklLedgerMemberService extends IBaseService<LklLedgerMember> {
|
||||
*/
|
||||
Boolean updateAuditResult(String applyId, String merInnerNo, String merCupNo, String entrustFileName, String entrustFilePath, String auditStatus, String auditStatusText, String remark, String notifyResp);
|
||||
|
||||
|
||||
/**
|
||||
* 更新商户的提现模式
|
||||
*
|
||||
* @param merCupNo 银联商户号
|
||||
* @param settleType 提款模式(01主动提款 02余额自动结算 03交易自动结算)
|
||||
* @return 更新是否成功
|
||||
*/
|
||||
Boolean updateSettleTypeDraw(String merCupNo, String settleType);
|
||||
}
|
||||
|
||||
@ -0,0 +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.shop.lakala.service;
|
||||
|
||||
import com.suisung.mall.common.modules.lakala.LklOrderDraw;
|
||||
import com.suisung.mall.core.web.service.IBaseService;
|
||||
|
||||
public interface LklOrderDrawService extends IBaseService<LklOrderDraw> {
|
||||
|
||||
/**
|
||||
* 新增或更新记录
|
||||
*
|
||||
* @param record
|
||||
* @return
|
||||
*/
|
||||
Boolean addOrUpdateByMercIdAndMerOrderNo(LklOrderDraw record);
|
||||
|
||||
/**
|
||||
* 根据拉卡拉对账单流水号和平台订单号查询记录
|
||||
*
|
||||
* @param mercId 商户号
|
||||
* @param merOrderNo 商户订单号
|
||||
* @return
|
||||
*/
|
||||
LklOrderDraw getByByMercIdAndMerOrderNo(String mercId, String merOrderNo);
|
||||
}
|
||||
@ -57,6 +57,7 @@ import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
@ -145,6 +146,9 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
@Resource
|
||||
private LklOrderSeparateService lklOrderSeparateService;
|
||||
|
||||
@Resource
|
||||
private LklOrderDrawService lklOrderDrawService;
|
||||
|
||||
@Lazy
|
||||
@Resource
|
||||
private ShopOrderBaseService shopOrderBaseService;
|
||||
@ -682,7 +686,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
|
||||
reqData.put("splitLowestRatio", splitLowestRatio); // 商家最低分账比例不低于 20%
|
||||
reqData.put("splitRange", "ALL");
|
||||
reqData.put("settleType", "01"); //01:主动提款 03:交易自动结算 不填默认01
|
||||
reqData.put("settleType", "03"); //01:主动提款 03:交易自动结算 不填默认01
|
||||
|
||||
String postUrl = "";
|
||||
String operationType = ""; // 操作类型,用于日志记录和提示信息
|
||||
@ -1800,6 +1804,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
// 10. 检查商户绑定状态是否完成, 更改总的审核状态
|
||||
shopMchEntryService.checkMerchEntryFinished(mchId);
|
||||
|
||||
|
||||
// 11. 日志记录并返回成功响应
|
||||
log.info("商家绑定分账接收方异步通知处理完成,mchId:{} merCupNo:{}", mchId, merCupNo);
|
||||
return JSONUtil.createObj().set("code", "SUCCESS").set("message", "分账接收方绑定成功");
|
||||
@ -3256,5 +3261,330 @@ public class LakalaApiServiceImpl implements LakalaApiService {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 提款模式设置
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=372
|
||||
*
|
||||
* @param mercId 822商户号或receiveNo
|
||||
* @param settleType 提款模式(01主动提款 02余额自动结算 03交易自动结算)
|
||||
* @param settleTime 余额自动结算时间(小时)- 默认值:06。如08:00-09:00到账,则传入08。
|
||||
* @return 设置是否成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean ewalletSettleProfile(String mercId, String settleType, String settleTime) {
|
||||
// 1. 参数校验
|
||||
if (StrUtil.isBlank(mercId)) {
|
||||
log.warn("[提款模式设置] 参数校验失败:缺少必要参数, mercId={}", mercId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (StrUtil.isBlank(settleType)) {
|
||||
settleType = "02"; // 默认余额自动结算
|
||||
}
|
||||
|
||||
if (StrUtil.isBlank(settleTime)) {
|
||||
settleTime = "06"; // 默认06点结算
|
||||
}
|
||||
|
||||
try {
|
||||
// 2. 配置初始化
|
||||
initLKLSDK();
|
||||
|
||||
// 3. 装配数据
|
||||
V2LaepIndustryEwalletSettleProfileRequest request = new V2LaepIndustryEwalletSettleProfileRequest();
|
||||
request.setBmcpNo(orgCode);
|
||||
request.setMercId(mercId);
|
||||
request.setSettleType(settleType);
|
||||
request.setSettleTime(settleTime);
|
||||
request.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/ewallet/settleProfileNotify");
|
||||
|
||||
log.info("[提款模式设置] 开始设置提款模式, mercId={}, settleType={}, settleTime={}",
|
||||
mercId, settleType, settleTime);
|
||||
|
||||
// 4. 发送请求
|
||||
String responseStr = LKLSDK.httpPost(request);
|
||||
if (StrUtil.isBlank(responseStr)) {
|
||||
log.error("[提款模式设置] 服务器无响应, mercId={}", mercId);
|
||||
return false;
|
||||
}
|
||||
|
||||
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
|
||||
if (lakalaRespJSON == null) {
|
||||
log.error("[提款模式设置] 响应数据解析失败, mercId={}, response={}", mercId, responseStr);
|
||||
return false;
|
||||
}
|
||||
|
||||
String retCode = lakalaRespJSON.getStr("retCode");
|
||||
boolean success = "000000".equals(retCode);
|
||||
|
||||
if (success) {
|
||||
log.info("[提款模式设置] 设置成功, mercId={}", mercId);
|
||||
|
||||
// 更新商户的提现模式
|
||||
lklLedgerMemberService.updateSettleTypeDraw(mercId, settleType);
|
||||
} else {
|
||||
log.warn("[提款模式设置] 设置失败, mercId={}, retCode={}, retMsg={}",
|
||||
mercId, retCode, lakalaRespJSON.getStr("retMsg"));
|
||||
}
|
||||
|
||||
return success;
|
||||
} catch (SDKException e) {
|
||||
log.error("[提款模式设置] SDK调用异常, mercId={}", mercId, e);
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
log.error("[提款模式设置] 设置过程中发生未知异常, mercId={}", mercId, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 提款模式设置结果通知
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=372
|
||||
*
|
||||
* @param request HTTP请求对象,包含拉卡拉回调通知的参数
|
||||
* @return JSONObject 响应结果对象
|
||||
*/
|
||||
@Override
|
||||
public JSONObject ewalletSettleProfileNotify(HttpServletRequest request) {
|
||||
log.info("[提款模式设置通知] 开始处理拉卡拉提款模式设置结果异步回调");
|
||||
|
||||
// 1. 验签处理 - 验证通知来源的合法性
|
||||
Pair<Boolean, String> signCheckResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath, false);
|
||||
if (!signCheckResult.getFirst()) {
|
||||
String errorMsg = "提款模式设置通知验签失败: " + signCheckResult.getSecond();
|
||||
log.warn("[提款模式设置通知] {}", errorMsg);
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", signCheckResult.getSecond());
|
||||
}
|
||||
|
||||
// 2. 解析回调参数
|
||||
JSONObject paramsJSON = JSONUtil.parseObj(signCheckResult.getSecond());
|
||||
if (paramsJSON == null) {
|
||||
log.warn("[提款模式设置通知] 回调参数解析失败");
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", "回调参数解析失败");
|
||||
}
|
||||
|
||||
log.info("[提款模式设置通知] 验签成功,回调参数: {}", paramsJSON);
|
||||
|
||||
// 3. 返回成功响应
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "SUCCESS")
|
||||
.set("message", "处理成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 拉卡拉账户D1提现
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=430
|
||||
*
|
||||
* @param mercId 822商户号或receiveNo
|
||||
* @param merOrderNo 商户订单号
|
||||
* @param drawAmt 提现金额(分)
|
||||
* @param remark 备注信息
|
||||
* @param summary 摘要信息
|
||||
* @return 操作结果,成功返回true,失败返回false
|
||||
*/
|
||||
@Override
|
||||
public Boolean ewalletWithDrawD1(String mercId, String merOrderNo, String drawAmt, String remark, String summary) {
|
||||
// 1. 参数校验
|
||||
if (StrUtil.hasBlank(mercId, merOrderNo, drawAmt)) {
|
||||
log.warn("[D1提现申请] D1提现参数校验失败,关键参数为空: mercId={}, merOrderNo={}, drawAmt={}",
|
||||
mercId, merOrderNo, drawAmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 账号类型(01:收款账户,04:分账接收方账户)
|
||||
String payType = "04";
|
||||
if (StrUtil.startWith(mercId, "822")) {
|
||||
payType = "01";
|
||||
}
|
||||
|
||||
try {
|
||||
// 验证提现金额是否为有效数字
|
||||
BigDecimal drawAmtDecimal = Convert.toBigDecimal(drawAmt);
|
||||
if (drawAmtDecimal == null || drawAmtDecimal.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
log.warn("[D1提现申请] D1提现金额无效,商户号={},订单号={},提现金额={}", mercId, merOrderNo, drawAmt);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
if (StrUtil.isBlank(remark)) {
|
||||
remark = String.format("商户订单:%s 账号类型:%s 分账后立即提现", merOrderNo, payType);
|
||||
}
|
||||
|
||||
log.info("[D1提现申请] 开始处理D1提现,商户号={},订单号={},提现金额={}分", mercId, merOrderNo, drawAmt);
|
||||
|
||||
// 2. 配置初始化
|
||||
initLKLSDK();
|
||||
|
||||
// 3. 装配数据
|
||||
V2LaepIndustryEwalletWithdrawD1Request request = new V2LaepIndustryEwalletWithdrawD1Request();
|
||||
request.setOrgNo(orgCode);
|
||||
request.setMerchantNo(mercId);
|
||||
request.setMerOrderNo(merOrderNo);
|
||||
request.setPayType(payType);
|
||||
|
||||
// 分转元,保留两位小数点,不要四舍五入
|
||||
String drawAmtYuan = drawAmtDecimal.divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN).toString();
|
||||
request.setDrawAmt(drawAmtYuan); // 单位:元
|
||||
request.setRemark(remark);
|
||||
if (StrUtil.isNotBlank(summary)) {
|
||||
request.setSummary(summary);
|
||||
}
|
||||
request.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/ewallet/ewallet/drawNotify");
|
||||
|
||||
// 4. 发送请求
|
||||
String responseStr = LKLSDK.httpPost(request);
|
||||
if (StrUtil.isBlank(responseStr)) {
|
||||
log.error("[D1提现申请] D1提现请求无响应,商户号={},订单号={}", mercId, merOrderNo);
|
||||
return false;
|
||||
}
|
||||
|
||||
JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr);
|
||||
if (lakalaRespJSON == null) {
|
||||
log.error("[D1提现申请] D1提现响应数据解析失败,商户号={},订单号={}", mercId, merOrderNo);
|
||||
return false;
|
||||
}
|
||||
|
||||
String retCode = lakalaRespJSON.getStr("retCode");
|
||||
Object drawJnl = lakalaRespJSON.getByPath("respData.drawJnl");
|
||||
boolean success = "000000".equals(retCode);
|
||||
|
||||
if (success && drawJnl != null) {
|
||||
log.info("[D1提现申请] D1提现请求成功,商户号={},订单号={},流水号={}", mercId, merOrderNo, drawJnl);
|
||||
|
||||
// 5. 保存提现记录
|
||||
LklOrderDraw lklOrderDraw = new LklOrderDraw();
|
||||
lklOrderDraw.setMerc_id(mercId);
|
||||
lklOrderDraw.setMer_order_no(merOrderNo);
|
||||
lklOrderDraw.setDraw_jnl(Convert.toStr(drawJnl));
|
||||
lklOrderDraw.setDraw_amt(drawAmtYuan);
|
||||
lklOrderDraw.setBatch_auto_settle(payType);
|
||||
lklOrderDraw.setNotify_url(request.getNotifyUrl());
|
||||
lklOrderDraw.setNotify_resp(responseStr);
|
||||
lklOrderDraw.setRemark(remark);
|
||||
if (StrUtil.isNotBlank(summary)) {
|
||||
lklOrderDraw.setSummary(summary);
|
||||
}
|
||||
|
||||
boolean saveResult = lklOrderDrawService.addOrUpdateByMercIdAndMerOrderNo(lklOrderDraw);
|
||||
if (saveResult) {
|
||||
log.info("[D1提现申请] D1提现记录保存成功,商户号={},订单号={},流水号={}", mercId, merOrderNo, drawJnl);
|
||||
} else {
|
||||
log.error("[D1提现申请] D1提现记录保存失败,商户号={},订单号={},流水号={}", mercId, merOrderNo, drawJnl);
|
||||
}
|
||||
|
||||
return saveResult;
|
||||
} else {
|
||||
String retMsg = lakalaRespJSON.getStr("retMsg");
|
||||
log.error("[D1提现申请] D1提现失败,商户号={},订单号={},错误码={},错误信息={}",
|
||||
mercId, merOrderNo, retCode, retMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
} catch (SDKException e) {
|
||||
log.error("[D1提现申请] D1提现SDK调用异常,商户号={},订单号={}", mercId, merOrderNo, e);
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
log.error("[D1提现申请] D1提现处理异常,商户号={},订单号={}", mercId, merOrderNo, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 拉卡拉账户D1提现结果通知处理
|
||||
* 参考:https://o.lakala.com/#/home/document/detail?id=367
|
||||
*
|
||||
* @param request HTTP请求对象,包含拉卡拉提现结果通知的参数
|
||||
* @return JSONObject 响应结果对象
|
||||
*/
|
||||
@Override
|
||||
public JSONObject ewalletWithDrawNotify(HttpServletRequest request) {
|
||||
log.debug("[拉卡拉提现结果通知] 开始处理拉卡拉提现结果通知");
|
||||
|
||||
try {
|
||||
// 1. 验签处理 - 验证通知来源的合法性
|
||||
Pair<Boolean, String> signCheckResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath, false);
|
||||
if (!signCheckResult.getFirst()) {
|
||||
log.warn("[LklOrderDraw] 验签失败: {}", signCheckResult.getSecond());
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", signCheckResult.getSecond());
|
||||
}
|
||||
|
||||
// 2. 解析回调参数
|
||||
JSONObject paramsJSON = JSONUtil.parseObj(signCheckResult.getSecond());
|
||||
if (paramsJSON == null) {
|
||||
log.warn("[拉卡拉提现结果通知] 回调参数解析失败");
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", "回调参数解析失败");
|
||||
}
|
||||
|
||||
String drawState = paramsJSON.getStr("drawState");
|
||||
String mercId = paramsJSON.getStr("mercId");
|
||||
String merOrderNo = paramsJSON.getStr("merOrderNo");
|
||||
|
||||
log.info("[拉卡拉提现结果通知] 提现通知参数: drawState={}, mercId={}, merOrderNo={}", drawState, mercId, merOrderNo);
|
||||
|
||||
if (StrUtil.isBlank(mercId) || StrUtil.isBlank(merOrderNo) || StrUtil.isBlank(drawState)) {
|
||||
log.warn("[拉卡拉提现结果通知] 回调参数缺失: drawState={}, mercId={}, merOrderNo={}", drawState, mercId, merOrderNo);
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", "回调参数错误");
|
||||
}
|
||||
|
||||
// 只处理成功的提现状态
|
||||
if (!"DRAW.SUCCESS".equals(drawState)) {
|
||||
log.debug("[拉卡拉提现结果通知] 提现状态未成功,忽略处理: drawState={}", drawState);
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "SUCCESS") // 返回成功,避免重复通知
|
||||
.set("message", "状态未成功,忽略处理");
|
||||
}
|
||||
|
||||
// 3. 转换参数并更新数据
|
||||
String snakeCaseJson = StringUtils.convertCamelToSnake(signCheckResult.getSecond());
|
||||
if (StringUtils.isBlank(snakeCaseJson)) {
|
||||
log.error("[拉卡拉提现结果通知] 回调参数转换失败,mercId={} merOrderNo={}", mercId, merOrderNo);
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", "回调参数转换失败");
|
||||
}
|
||||
|
||||
LklOrderDraw lklOrderDraw = JSONUtil.toBean(snakeCaseJson, LklOrderDraw.class);
|
||||
if (lklOrderDraw == null) {
|
||||
log.error("[拉卡拉提现结果通知] 回调参数转换为对象失败,mercId={} merOrderNo={}", mercId, merOrderNo);
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", "回调参数转换失败");
|
||||
}
|
||||
|
||||
boolean isSuccess = lklOrderDrawService.addOrUpdateByMercIdAndMerOrderNo(lklOrderDraw);
|
||||
if (!isSuccess) {
|
||||
log.error("[拉卡拉提现结果通知] 数据更新失败,mercId={} merOrderNo={}", mercId, merOrderNo);
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", "数据更新失败");
|
||||
}
|
||||
|
||||
log.info("[拉卡拉提现结果通知] 拉卡拉提现结果通知处理成功,mercId={} merOrderNo={}", mercId, merOrderNo);
|
||||
|
||||
// 4. 返回成功响应
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "SUCCESS")
|
||||
.set("message", "处理成功");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[拉卡拉提现结果通知] 处理拉卡拉提现结果通知异常", e);
|
||||
return JSONUtil.createObj()
|
||||
.set("code", "FAIL")
|
||||
.set("message", "系统处理异常");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -125,4 +125,40 @@ public class LklLedgerMemberServiceImpl extends BaseServiceImpl<LklLedgerMemberM
|
||||
return update(updateWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商户的提现模式
|
||||
*
|
||||
* @param merCupNo 银联商户号
|
||||
* @param settleType 提款模式(01主动提款 02余额自动结算 03交易自动结算)
|
||||
* @return 更新是否成功
|
||||
*/
|
||||
@Override
|
||||
public Boolean updateSettleTypeDraw(String merCupNo, String settleType) {
|
||||
// 参数校验
|
||||
if (StrUtil.hasBlank(merCupNo, settleType)) {
|
||||
log.warn("[更新提现模式] 参数校验失败:merCupNo或settleType为空, merCupNo={}, settleType={}", merCupNo, settleType);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
UpdateWrapper<LklLedgerMember> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("mer_cup_no", merCupNo).ne("settle_type_draw", settleType);
|
||||
updateWrapper.set("settle_type_draw", settleType);
|
||||
|
||||
boolean result = update(updateWrapper);
|
||||
|
||||
if (result) {
|
||||
log.info("[更新提现模式] 更新成功, merCupNo={}, settleType={}", merCupNo, settleType);
|
||||
} else {
|
||||
log.warn("[更新提现模式] 未找到匹配记录或更新失败, merCupNo={}, settleType={}", merCupNo, settleType);
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("[更新提现模式] 更新过程中发生异常, merCupNo={}, settleType={}", merCupNo, settleType, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,105 @@
|
||||
package com.suisung.mall.shop.lakala.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.suisung.mall.common.modules.lakala.LklOrderDraw;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.lakala.mapper.LklOrderDrawMapper;
|
||||
import com.suisung.mall.shop.lakala.service.LklOrderDrawService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class LklOrderDrawServiceImpl extends BaseServiceImpl<LklOrderDrawMapper, LklOrderDraw> implements LklOrderDrawService {
|
||||
/**
|
||||
* 新增或更新拉卡拉订单提现记录
|
||||
*
|
||||
* @param record 拉卡拉订单提现记录
|
||||
* @return 操作结果,成功返回true,失败返回false
|
||||
*/
|
||||
@Override
|
||||
public Boolean addOrUpdateByMercIdAndMerOrderNo(LklOrderDraw record) {
|
||||
// 参数校验
|
||||
if (record == null || (StrUtil.isBlank(record.getMer_order_no()) && StrUtil.isBlank(record.getMerc_id()))) {
|
||||
log.warn("[LklOrderDraw] 新增或更新记录参数校验失败,record为空或关键参数缺失");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
log.debug("[LklOrderDraw] 开始处理订单提现记录,商户订单号={},商户号={}",
|
||||
record.getMer_order_no(), record.getMerc_id());
|
||||
|
||||
QueryWrapper<LklOrderDraw> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("mer_order_no", record.getMer_order_no())
|
||||
.eq("merc_id", record.getMerc_id());
|
||||
|
||||
if (StrUtil.isNotBlank(record.getDraw_jnl())) {
|
||||
queryWrapper.eq("draw_jnl", record.getDraw_jnl());
|
||||
}
|
||||
|
||||
LklOrderDraw existsRecord = getOne(queryWrapper);
|
||||
if (existsRecord != null && existsRecord.getId() != null && existsRecord.getId() > 0) {
|
||||
// 更新记录
|
||||
log.info("[LklOrderDraw] 记录已存在,执行更新操作,ID={}", existsRecord.getId());
|
||||
record.setId(existsRecord.getId());
|
||||
boolean updateResult = updateById(record);
|
||||
if (updateResult) {
|
||||
log.debug("[LklOrderDraw] 记录更新成功,ID={}", record.getId());
|
||||
} else {
|
||||
log.error("[LklOrderDraw] 记录更新失败,ID={}", record.getId());
|
||||
}
|
||||
return updateResult;
|
||||
}
|
||||
|
||||
log.info("[LklOrderDraw] 记录不存在,执行新增操作");
|
||||
boolean addResult = add(record);
|
||||
if (addResult) {
|
||||
log.debug("[LklOrderDraw] 记录新增成功,ID={}", record.getId());
|
||||
} else {
|
||||
log.error("[LklOrderDraw] 记录新增失败");
|
||||
}
|
||||
return addResult;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[LklOrderDraw] 处理订单提现记录异常,商户订单号={},商户号={}",
|
||||
record.getMer_order_no(), record.getMerc_id(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商户号和商户订单号查询拉卡拉订单提现记录
|
||||
*
|
||||
* @param mercId 商户号
|
||||
* @param merOrderNo 商户订单号
|
||||
* @return 拉卡拉订单分账记录,未找到返回null
|
||||
*/
|
||||
@Override
|
||||
public LklOrderDraw getByByMercIdAndMerOrderNo(String mercId, String merOrderNo) {
|
||||
// 参数校验
|
||||
if (StrUtil.isBlank(mercId) && StrUtil.isBlank(merOrderNo)) {
|
||||
log.warn("[LklOrderDraw] 查询记录参数校验失败,商户号和商户订单号均为空");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
log.debug("[LklOrderDraw] 开始查询订单提现记录,商户订单号={},商户号={}", merOrderNo, mercId);
|
||||
|
||||
QueryWrapper<LklOrderDraw> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("mer_order_no", merOrderNo).eq("merc_id", mercId);
|
||||
|
||||
LklOrderDraw result = getOne(queryWrapper);
|
||||
if (result != null) {
|
||||
log.debug("[LklOrderDraw] 查询到订单提现记录,ID={}", result.getId());
|
||||
} else {
|
||||
log.debug("[LklOrderDraw] 未查询到订单提现记录");
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("[LklOrderDraw] 查询订单提现记录异常,商户订单号={},商户号={}", merOrderNo, mercId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -106,21 +106,26 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
||||
*
|
||||
* @param mchId 入驻记录Id, 必填项(mchId 和 storeId 其一必填) 优先
|
||||
* @param storeId 商家门店ID 必填项(mchId 和 storeId 其一必填)
|
||||
* @return
|
||||
* @return Pair<Boolean, String> 第一个元素表示是否成功,第二个元素表示结果信息或错误信息
|
||||
*/
|
||||
@Override
|
||||
public Pair<Boolean, String> createSfExpressShop(Long mchId, Integer storeId) {
|
||||
logger.info("[顺丰] 开始创建连锁店铺: mchId={}, storeId={}", mchId, storeId);
|
||||
|
||||
// 参数校验
|
||||
if (ObjectUtil.isEmpty(mchId) && ObjectUtil.isEmpty(storeId)) {
|
||||
if (CheckUtil.isEmpty(mchId) && CheckUtil.isEmpty(storeId)) {
|
||||
logger.error("创建顺丰同店铺:mchId 和 storeId 其一必填");
|
||||
return Pair.of(false, "缺少必填参数");
|
||||
}
|
||||
|
||||
// 获取商家入驻信息
|
||||
ShopMchEntry shopMchEntry;
|
||||
if (ObjectUtil.isEmpty(mchId)) {
|
||||
shopMchEntry = shopMchEntryService.getShopMerchEntryByStoreId(storeId);
|
||||
} else {
|
||||
if (ObjectUtil.isNotEmpty(mchId)) {
|
||||
shopMchEntry = shopMchEntryService.shopMerchEntryById(mchId);
|
||||
logger.debug("[顺丰] 通过mchId获取入驻信息: mchId={}", mchId);
|
||||
} else {
|
||||
shopMchEntry = shopMchEntryService.getShopMerchEntryByStoreId(storeId);
|
||||
logger.debug("[顺丰] 通过storeId获取入驻信息: storeId={}", storeId);
|
||||
}
|
||||
|
||||
if (shopMchEntry == null) {
|
||||
@ -149,39 +154,53 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
|
||||
return Pair.of(false, "联系人姓名不能为空");
|
||||
}
|
||||
|
||||
String contact_mobile = StrUtil.isBlank(shopMchEntry.getLegal_person_mobile()) ?
|
||||
shopMchEntry.getLogin_mobile() : shopMchEntry.getLegal_person_mobile();
|
||||
String contactMobile = StrUtil.isNotBlank(shopMchEntry.getLegal_person_mobile()) ?
|
||||
shopMchEntry.getLegal_person_mobile() : shopMchEntry.getLogin_mobile();
|
||||
|
||||
if (StrUtil.isBlank(contact_mobile)) {
|
||||
if (StrUtil.isBlank(contactMobile)) {
|
||||
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);
|
||||
// 解析城市名称
|
||||
String cityName = "桂平市"; // 默认城市
|
||||
if (StrUtil.isNotBlank(shopMchEntry.getStore_area())) {
|
||||
String[] areaNames = shopMchEntry.getStore_area().split("/");
|
||||
if (areaNames.length > 0) {
|
||||
cityName = areaNames[areaNames.length - 1];
|
||||
} else {
|
||||
cityName = shopMchEntry.getStore_area().replace("/", "");
|
||||
}
|
||||
}
|
||||
|
||||
return createSfExpressShop(
|
||||
// 如果解析后城市名为空,使用默认值
|
||||
if (StrUtil.isBlank(cityName)) {
|
||||
cityName = "桂平市";
|
||||
logger.warn("[顺丰] 城市名为空,使用默认城市: {}", cityName);
|
||||
} else {
|
||||
logger.debug("[顺丰] 解析得到城市名: {}", cityName);
|
||||
}
|
||||
|
||||
// 为了其他顺丰店同名,店铺名称加上[门店ID]; 如:xxxx[xxxx] 聚万家生鲜超市[69]
|
||||
String shopStoreName = String.format("%s[%s]", shopMchEntry.getStore_name(), shopMchEntry.getStore_id());
|
||||
|
||||
// 调用创建店铺方法
|
||||
Pair<Boolean, String> result = createSfExpressShop(
|
||||
Convert.toInt(shopMchEntry.getStore_id()),
|
||||
shopMchEntry.getStore_name(),
|
||||
shopStoreName,
|
||||
cityName,
|
||||
shopMchEntry.getStore_address(),
|
||||
shopMchEntry.getContact_name(),
|
||||
contact_mobile,
|
||||
contactMobile,
|
||||
shopMchEntry.getStore_longitude(),
|
||||
shopMchEntry.getStore_latitude()
|
||||
);
|
||||
|
||||
logger.info("[顺丰] 连锁店铺创建结果: success={}, message={}", result.getFirst(), result.getSecond());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建顺丰同城(普通型)店铺
|
||||
*
|
||||
|
||||
@ -357,4 +357,14 @@ public interface ShopMchEntryService {
|
||||
* @return 分账比例
|
||||
*/
|
||||
BigDecimal getMchEntryRatioOrDefault(Integer mch1stBizCategory, Integer mch2ndBizCategory, BigDecimal srcRatio, BigDecimal defaultRatio);
|
||||
|
||||
/**
|
||||
* 处理店铺省市区信息
|
||||
*
|
||||
* @param storeDistrict 店铺省市区ID路径
|
||||
* @param storeArea 店铺省市区名称路径
|
||||
* @param refStoreAddress 参考店铺地址(用于解析省市区信息)
|
||||
* @return 包含ID路径和名称路径的字符串数组,格式为 [ID路径, 名称路径]
|
||||
*/
|
||||
String[] handleStoreDistrictInfo(String storeDistrict, String storeArea, String refStoreAddress);
|
||||
}
|
||||
@ -29,10 +29,12 @@ import com.suisung.mall.common.modules.account.AccountUserBase;
|
||||
import com.suisung.mall.common.modules.lakala.LklLedgerEc;
|
||||
import com.suisung.mall.common.modules.store.ShopMchEntry;
|
||||
import com.suisung.mall.common.modules.store.ShopStoreEmployee;
|
||||
import com.suisung.mall.common.pojo.to.AddressParseResultTO;
|
||||
import com.suisung.mall.common.utils.*;
|
||||
import com.suisung.mall.common.utils.phone.PhoneNumberUtils;
|
||||
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
|
||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseDistrictService;
|
||||
import com.suisung.mall.shop.base.service.ShopBaseStoreCategoryService;
|
||||
import com.suisung.mall.shop.esign.service.EsignPlatformInfoService;
|
||||
import com.suisung.mall.shop.lakala.service.LklLedgerEcService;
|
||||
@ -91,6 +93,9 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
@Resource
|
||||
private AccountService accountService;
|
||||
|
||||
@Resource
|
||||
private ShopBaseDistrictService shopBaseDistrictService;
|
||||
|
||||
/**
|
||||
* 获取店铺的经营类目列表
|
||||
*
|
||||
@ -952,6 +957,12 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
shopMchEntry.setSettlement_method(1); // 结算类型:0-秒到(不分账);1-次日结算(需要分账)
|
||||
shopMchEntry.setSplit_ratio(splitRatio);
|
||||
|
||||
// 店铺省市区处理
|
||||
String[] result = handleStoreDistrictInfo(shopMchEntry.getStore_district(), shopMchEntry.getStore_area(), shopMchEntry.getStore_address());
|
||||
if (result == null || result.length < 2 || StrUtil.isAllBlank(result[0], result[1])) {
|
||||
return CommonResult.failed("缺少店铺的省市区参数!");
|
||||
}
|
||||
|
||||
// 转换拉卡拉的日期格式 yyyy-MM-dd
|
||||
shopMchEntry = convLklDateFormat(shopMchEntry);
|
||||
|
||||
@ -975,39 +986,23 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
log.debug("开始调用拉卡拉电子合同签署申请,mchId={}", mchId);
|
||||
Pair<Boolean, String> resultPair = lakalaApiService.applyLedgerMerEc(mchId);
|
||||
if (!resultPair.getFirst()) {
|
||||
log.warn("拉卡拉电子合同签署申请失败: {}", resultPair.getSecond());
|
||||
log.warn("拉卡拉入网电子合同提交失败: {}", resultPair.getSecond());
|
||||
return CommonResult.failed(resultPair.getSecond());
|
||||
}
|
||||
|
||||
// 执行更新操作
|
||||
if (!updateMerchEntryApprovalByMchId(shopMchEntry.getId(), null, "入网申请已提交!")) {
|
||||
log.error("系统处理审批出错,请联系管理员!当前记录ID: {}", mchId);
|
||||
log.error("系统处理审批出错,请联系管理员!当前入驻编号: {}", mchId);
|
||||
return CommonResult.failed("系统处理审批出错,请联系管理员!");
|
||||
}
|
||||
|
||||
log.info("商家入驻平台初步审批处理完成,mchId={}", mchId);
|
||||
|
||||
// E签宝暂时停止使用
|
||||
// if (approvalStatus.equals(CommonConstant.Enable)) {
|
||||
// // 多线程执行电子合同生成和填充
|
||||
// taskService.executeTask(() -> {
|
||||
// log.debug("###开始异步执行生成电子合同模版和填充模版数据,并生该商家和平台方签署的未盖章合同文件###");
|
||||
// // 生成电子合同模版和填充模版数据,并生该商家和平台方签署的未盖章合同文件
|
||||
// Boolean genSuccess = esignContractFillingFileService.fillDocTemplate(record.getLogin_mobile(), "");
|
||||
// if (!genSuccess) {
|
||||
// log.error("###商家入驻电子合同生成失败###");
|
||||
// }
|
||||
//
|
||||
// // 发短信通知商家,入驻申请已通过审核
|
||||
// });
|
||||
// }
|
||||
|
||||
return CommonResult.success();
|
||||
} catch (Exception e) {
|
||||
log.error("调用拉卡拉电子合同接口异常", e);
|
||||
return CommonResult.failed("调用拉卡拉服务失败,请稍后重试");
|
||||
}
|
||||
|
||||
return CommonResult.success();
|
||||
}
|
||||
|
||||
|
||||
@ -1777,6 +1772,9 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置商户的提现模式:02余额自动结算,6-7点自动提现
|
||||
lakalaApiService.ewalletSettleProfile(merchantEntry.getLkl_mer_cup_no(), "02", "06");
|
||||
|
||||
return true; // 返回 true,表示入驻流程已全部完成
|
||||
|
||||
} catch (Exception e) {
|
||||
@ -2467,6 +2465,57 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl<ShopMchEntryMapper,
|
||||
return srcRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理店铺省市区信息
|
||||
*
|
||||
* @param storeDistrict 店铺省市区ID路径
|
||||
* @param storeArea 店铺省市区名称路径
|
||||
* @param refStoreAddress 参考店铺地址(用于解析省市区信息)
|
||||
* @return 包含ID路径和名称路径的字符串数组,格式为 [ID路径, 名称路径]
|
||||
*/
|
||||
@Override
|
||||
public String[] handleStoreDistrictInfo(String storeDistrict, String storeArea, String refStoreAddress) {
|
||||
// 当店铺省市区ID和名称都不为空时,直接返回
|
||||
if (StrUtil.isAllNotBlank(storeDistrict, storeArea)) {
|
||||
log.debug("省市区信息已完整,直接返回: ID路径={}, 名称路径={}", storeDistrict, storeArea);
|
||||
return new String[]{storeDistrict, storeArea};
|
||||
}
|
||||
|
||||
// 当店铺省市区ID和名称都为空时,尝试从地址中解析
|
||||
if (StrUtil.isAllBlank(storeDistrict, storeArea)) {
|
||||
if (StrUtil.isBlank(refStoreAddress)) {
|
||||
log.warn("缺少店铺的省市区参数且地址信息为空");
|
||||
return new String[]{"", ""};
|
||||
}
|
||||
|
||||
try {
|
||||
AddressParseResultTO addressParseResultTO = AddressUtil.parseAddress(refStoreAddress);
|
||||
if (addressParseResultTO == null || StrUtil.isBlank(addressParseResultTO.getJoinArea())) {
|
||||
log.warn("地址解析失败,无法获取省市区信息,地址: {}", refStoreAddress);
|
||||
return new String[]{"", ""};
|
||||
}
|
||||
|
||||
String[] result = shopBaseDistrictService.convertDistrictPath("", addressParseResultTO.getJoinArea());
|
||||
log.debug("通过地址解析获取省市区信息: {}", Arrays.toString(result));
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("地址解析异常,地址: {}", refStoreAddress, e);
|
||||
return new String[]{"", ""};
|
||||
}
|
||||
} else {
|
||||
// 当只有省市区ID或名称其中一个有值时,进行转换处理
|
||||
log.debug("省市区信息不完整,storeDistrict={}, storeArea={}", storeDistrict, storeArea);
|
||||
try {
|
||||
String[] result = shopBaseDistrictService.convertDistrictPath(storeDistrict, storeArea);
|
||||
log.debug("转换省市区信息结果: {}", Arrays.toString(result));
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("省市区信息转换异常,storeDistrict={}, storeArea={}", storeDistrict, storeArea, e);
|
||||
return new String[]{"", ""};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -2653,12 +2653,24 @@ public class ShopUserCartServiceImpl extends BaseServiceImpl<ShopUserCartMapper,
|
||||
store_row.put("freight", freight); // 运费金额
|
||||
store_row.put("postFreeBalance", postFreeBalance); // 还需postFreeBalance元即可免邮费
|
||||
|
||||
// 订单的总运费 + 本次订单的运费
|
||||
// 订单的总金额 + 本次订单的运费
|
||||
orderSelFreightAmount = orderSelFreightAmount.add(Convert.toBigDecimal(sameCityDeliveryFeeResp.getDeliveryFee())); // 重要:订单运费金额
|
||||
if (canDelivery) {
|
||||
// 如果能配送,最终支付金额+本次订单的运费。
|
||||
orderSelMoneyAmount = orderSelMoneyAmount.add(freight);// 重要
|
||||
}
|
||||
|
||||
// RMK 平台最低配送费,单位(分)add:2025-09-26
|
||||
Integer innerMinDeliverFee = accountBaseConfigService.getInnerMinDeliveryFee();
|
||||
if (canThrow
|
||||
&& CheckUtil.isNotEmpty(innerMinDeliverFee)
|
||||
&& CheckUtil.isNotEmpty(orderSelMoneyAmount)
|
||||
&& orderSelMoneyAmount.multiply(BigDecimal.valueOf(100)).compareTo(BigDecimal.valueOf(innerMinDeliverFee)) <= 0) {
|
||||
logger.warn("[订单校验] 订单金额低于平台最低配送金额,订单金额:{}分,最低配送金额:{}分",
|
||||
orderSelMoneyAmount.multiply(BigDecimal.valueOf(100)).longValue(), innerMinDeliverFee);
|
||||
throw new ApiException(I18nUtil._("订单低于平台最低配送金额!"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 订单总计运费
|
||||
|
||||
@ -28,38 +28,6 @@ spring:
|
||||
content-type: text/html; charset=utf-8
|
||||
suffix: .html
|
||||
template-loader-path: classpath:/templates/
|
||||
quartz:
|
||||
job-store-type: jdbc
|
||||
jdbc:
|
||||
initialize-schema: always # 每次启动项目都重新清空定时任务
|
||||
properties:
|
||||
org:
|
||||
quartz:
|
||||
scheduler:
|
||||
instanceName: DefaultQuartzScheduler
|
||||
instanceId: AUTO
|
||||
rmi:
|
||||
export: false
|
||||
proxy: false
|
||||
jobStore:
|
||||
class: org.quartz.impl.jdbcjobstore.JobStoreTX
|
||||
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
||||
tablePrefix: QRTZ_
|
||||
isClustered: false
|
||||
useProperties: false
|
||||
misfireThreshold: 60000
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 10
|
||||
threadPriority: 5
|
||||
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||
dataSource:
|
||||
myDS:
|
||||
URL: jdbc:mysql:///test?characterEncoding=utf8&serverTimezone=UTC
|
||||
user: store
|
||||
password: brCnv0qLt8s0VqhI
|
||||
driver: com.mysql.jdbc.Driver
|
||||
maxConnections: 5
|
||||
mybatis-plus:
|
||||
mapper-locations: classpath:/mapper/**/*.xml
|
||||
global-config:
|
||||
@ -100,7 +68,7 @@ ribbon:
|
||||
ConnectTimeout: 60000 #服务请求连接超时时间(毫秒)
|
||||
ReadTimeout: 60000 #服务请求处理超时时间(毫秒)
|
||||
baidu:
|
||||
ak: "uwBrIUOZuTDMHsuRGm0hdmeG9sosN8sQ" # 百度地图ak
|
||||
ak: "YzRPLAOTYyCFVjvlh2vxnaUnH4jPjufM" # 百度地图ak
|
||||
|
||||
# 定时任务列表
|
||||
job:
|
||||
|
||||
@ -65,6 +65,38 @@ spring:
|
||||
transport:
|
||||
dashboard: @sentinel.transport.dashboard@
|
||||
eager: true
|
||||
quartz:
|
||||
job-store-type: jdbc
|
||||
jdbc:
|
||||
initialize-schema: always
|
||||
properties:
|
||||
org:
|
||||
quartz:
|
||||
scheduler:
|
||||
instanceName: DefaultQuartzScheduler
|
||||
instanceId: AUTO
|
||||
rmi:
|
||||
export: false
|
||||
proxy: false
|
||||
jobStore:
|
||||
class: org.quartz.impl.jdbcjobstore.JobStoreTX
|
||||
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
||||
tablePrefix: QRTZ_
|
||||
isClustered: false
|
||||
useProperties: false
|
||||
misfireThreshold: 120000
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 15
|
||||
threadPriority: 5
|
||||
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||
dataSource:
|
||||
myDS:
|
||||
URL: jdbc:mysql://@mysql.host@:@mysql.port@/@mysql.db@?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&&zeroDateTimeBehavior=convertToNull&autoReconnect=true&failOverReadOnly=false&maxReconnects=5
|
||||
user: @mysql.user@
|
||||
password: @mysql.pwd@
|
||||
driver: @mysql.driver@
|
||||
maxConnections: 5
|
||||
upload: # 图片上传配置
|
||||
filepath: @upload.filepath@ # 本地环境静态文件路径
|
||||
seata:
|
||||
|
||||
@ -65,6 +65,38 @@ spring:
|
||||
transport:
|
||||
dashboard: @sentinel.transport.dashboard@
|
||||
eager: true
|
||||
quartz:
|
||||
job-store-type: jdbc
|
||||
jdbc:
|
||||
initialize-schema: always
|
||||
properties:
|
||||
org:
|
||||
quartz:
|
||||
scheduler:
|
||||
instanceName: DefaultQuartzScheduler
|
||||
instanceId: AUTO
|
||||
rmi:
|
||||
export: false
|
||||
proxy: false
|
||||
jobStore:
|
||||
class: org.quartz.impl.jdbcjobstore.JobStoreTX
|
||||
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
||||
tablePrefix: QRTZ_
|
||||
isClustered: false
|
||||
useProperties: false
|
||||
misfireThreshold: 120000
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 15
|
||||
threadPriority: 5
|
||||
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||
dataSource:
|
||||
myDS:
|
||||
URL: jdbc:mysql://@mysql.host@:@mysql.port@/@mysql.db@?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&&zeroDateTimeBehavior=convertToNull&autoReconnect=true&failOverReadOnly=false&maxReconnects=5
|
||||
user: @mysql.user@
|
||||
password: @mysql.pwd@
|
||||
driver: @mysql.driver@
|
||||
maxConnections: 5
|
||||
upload: # 图片上传配置
|
||||
filepath: @upload.filepath@ # 本地环境静态文件路径
|
||||
seata:
|
||||
|
||||
@ -72,6 +72,38 @@ spring:
|
||||
transport:
|
||||
dashboard: @sentinel.transport.dashboard@
|
||||
eager: true
|
||||
quartz:
|
||||
job-store-type: jdbc
|
||||
jdbc:
|
||||
initialize-schema: always
|
||||
properties:
|
||||
org:
|
||||
quartz:
|
||||
scheduler:
|
||||
instanceName: DefaultQuartzScheduler
|
||||
instanceId: AUTO
|
||||
rmi:
|
||||
export: false
|
||||
proxy: false
|
||||
jobStore:
|
||||
class: org.quartz.impl.jdbcjobstore.JobStoreTX
|
||||
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
||||
tablePrefix: QRTZ_
|
||||
isClustered: false
|
||||
useProperties: false
|
||||
misfireThreshold: 120000
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 15
|
||||
threadPriority: 5
|
||||
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||
dataSource:
|
||||
myDS:
|
||||
URL: jdbc:mysql://@mysql.host@:@mysql.port@/@mysql.db@?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&&zeroDateTimeBehavior=convertToNull&autoReconnect=true&failOverReadOnly=false&maxReconnects=5
|
||||
user: @mysql.user@
|
||||
password: @mysql.pwd@
|
||||
driver: @mysql.driver@
|
||||
maxConnections: 5
|
||||
upload: # 图片上传配置
|
||||
filepath: @upload.filepath@ # 本地环境静态文件路径
|
||||
seata:
|
||||
|
||||
@ -69,6 +69,38 @@ spring:
|
||||
transport:
|
||||
dashboard: @sentinel.transport.dashboard@
|
||||
eager: true
|
||||
quartz:
|
||||
job-store-type: jdbc
|
||||
jdbc:
|
||||
initialize-schema: always
|
||||
properties:
|
||||
org:
|
||||
quartz:
|
||||
scheduler:
|
||||
instanceName: DefaultQuartzScheduler
|
||||
instanceId: AUTO
|
||||
rmi:
|
||||
export: false
|
||||
proxy: false
|
||||
jobStore:
|
||||
class: org.quartz.impl.jdbcjobstore.JobStoreTX
|
||||
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
||||
tablePrefix: QRTZ_
|
||||
isClustered: false
|
||||
useProperties: false
|
||||
misfireThreshold: 120000
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 15
|
||||
threadPriority: 5
|
||||
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||
dataSource:
|
||||
myDS:
|
||||
URL: jdbc:mysql://@mysql.host@:@mysql.port@/@mysql.db@?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&&zeroDateTimeBehavior=convertToNull&autoReconnect=true&failOverReadOnly=false&maxReconnects=5
|
||||
user: @mysql.user@
|
||||
password: @mysql.pwd@
|
||||
driver: @mysql.driver@
|
||||
maxConnections: 5
|
||||
upload: # 图片上传配置
|
||||
filepath: @upload.filepath@ # 本地环境静态文件路径
|
||||
seata:
|
||||
|
||||
@ -69,6 +69,38 @@ spring:
|
||||
transport:
|
||||
dashboard: @sentinel.transport.dashboard@
|
||||
eager: true
|
||||
quartz:
|
||||
job-store-type: jdbc
|
||||
jdbc:
|
||||
initialize-schema: always
|
||||
properties:
|
||||
org:
|
||||
quartz:
|
||||
scheduler:
|
||||
instanceName: DefaultQuartzScheduler
|
||||
instanceId: AUTO
|
||||
rmi:
|
||||
export: false
|
||||
proxy: false
|
||||
jobStore:
|
||||
class: org.quartz.impl.jdbcjobstore.JobStoreTX
|
||||
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
|
||||
tablePrefix: QRTZ_
|
||||
isClustered: false
|
||||
useProperties: false
|
||||
misfireThreshold: 120000
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 15
|
||||
threadPriority: 5
|
||||
threadsInheritContextClassLoaderOfInitializingThread: true
|
||||
dataSource:
|
||||
myDS:
|
||||
URL: jdbc:mysql://@mysql.host@:@mysql.port@/@mysql.db@?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&&zeroDateTimeBehavior=convertToNull&autoReconnect=true&failOverReadOnly=false&maxReconnects=5
|
||||
user: @mysql.user@
|
||||
password: @mysql.pwd@
|
||||
driver: @mysql.driver@
|
||||
maxConnections: 5
|
||||
upload: # 图片上传配置
|
||||
filepath: @upload.filepath@ # 本地环境静态文件路径
|
||||
seata:
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.suisung.mall.shop.lakala.mapper.LklOrderDrawMapper">
|
||||
<!-- 通用查询结果列 -->
|
||||
<sql id="Base_Column_List">
|
||||
*
|
||||
</sql>
|
||||
</mapper>
|
||||
@ -20803,7 +20803,7 @@
|
||||
i[_x41903[4478]][_x41903[473]][_x41903[2345]] = e[_x41903[473]][_x41903[688]],
|
||||
c();
|
||||
}, s, o, r)) : 16 == i[_x41903[4420]] ? $[_x41903[39]](i[_x41903[4615]][_x41903[473]], function(e, t) {
|
||||
t[_x41903[124]] == a && (s = r = o = 100, publicFun[_x41903[4586]]($(n[_x41903[476]])[_x41903[217]](_x41903[124]), function(e) {
|
||||
t[_x41903[124]] == a && (s = r = o = 10240, publicFun[_x41903[4586]]($(n[_x41903[476]])[_x41903[217]](_x41903[124]), function(e) {
|
||||
250 == e[_x41903[686]] && $[_x41903[2030]][_x41903[4089]](e[_x41903[4587]] || __(_x41903[4616])),
|
||||
t[_x41903[2345]] = e[_x41903[473]][_x41903[688]],
|
||||
c();
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
package com.suisung.mall.shop;
|
||||
|
||||
import com.suisung.mall.common.constant.MqConstant;
|
||||
import com.suisung.mall.shop.message.service.MqMessageService;
|
||||
import com.suisung.mall.shop.order.service.ShopOrderBaseService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class MallProductApplicationTests {
|
||||
|
||||
@Autowired
|
||||
ShopOrderBaseService shopOrderBaseService;
|
||||
|
||||
@Autowired
|
||||
private MqMessageService mqMessageService;
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动确认收货测试
|
||||
*/
|
||||
@Test
|
||||
public void receiveTest() {
|
||||
shopOrderBaseService.autoReceive();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test01() {
|
||||
mqMessageService.sendMqMsg(MqConstant.SHOP_EXCHANGE, MqConstant.SHOP_MSG_ROUTING_KEY, "你真好看!");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user