From 07a420c1e6a2cfa79d62121b3f6ced6a99648126 Mon Sep 17 00:00:00 2001
From: Jack <46790855@qq.com>
Date: Fri, 26 Sep 2025 00:56:18 +0800
Subject: [PATCH 1/5] =?UTF-8?q?=E5=95=86=E6=88=B7=E5=85=A5=E9=A9=BB?=
=?UTF-8?q?=E5=90=8E=E5=A2=9E=E5=8A=A0=E4=BA=86=E8=AE=BE=E7=BD=AE=E6=8F=90?=
=?UTF-8?q?=E7=8E=B0=E6=A8=A1=E5=BC=8F=EF=BC=9A=E8=87=AA=E5=8A=A8=E7=BB=93?=
=?UTF-8?q?=E7=AE=97=E4=BD=99=E9=A2=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../modules/lakala/LklLedgerMember.java | 1 +
.../impl/ShopBaseCrontabServiceImpl.java | 2 +-
.../quartz/job/UpdateOrderStatusJob.java | 4 +-
.../service/impl/QuartzServiceImpl.java | 8 ++
.../admin/LakalaAdminController.java | 24 +++-
.../controller/mobile/LakalaController.java | 19 +++
.../shop/lakala/service/LakalaApiService.java | 20 +++
.../service/LklLedgerMemberService.java | 9 ++
.../service/impl/LakalaApiServiceImpl.java | 119 +++++++++++++++++-
.../impl/LklLedgerMemberServiceImpl.java | 36 ++++++
.../service/impl/SFExpressApiServiceImpl.java | 63 ++++++----
.../service/impl/ShopMchEntryServiceImpl.java | 3 +
12 files changed, 282 insertions(+), 26 deletions(-)
diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklLedgerMember.java b/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklLedgerMember.java
index adbaf357..d957bbd3 100644
--- a/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklLedgerMember.java
+++ b/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklLedgerMember.java
@@ -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;
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseCrontabServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseCrontabServiceImpl.java
index 96ad6597..e84d23a4 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseCrontabServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseCrontabServiceImpl.java
@@ -125,7 +125,7 @@ public class ShopBaseCrontabServiceImpl extends BaseServiceImpl 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);
+ }
+
+
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java
index 1b28f065..8d1ff881 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java
@@ -309,5 +309,25 @@ 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);
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklLedgerMemberService.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklLedgerMemberService.java
index 6f407c5a..5d607f7b 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklLedgerMemberService.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklLedgerMemberService.java
@@ -55,4 +55,13 @@ public interface LklLedgerMemberService extends IBaseService {
*/
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);
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java
index c04d3518..6f004db7 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java
@@ -682,7 +682,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 +1800,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 +3257,121 @@ 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 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", "处理成功");
+ }
+
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerMemberServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerMemberServiceImpl.java
index be33de34..98dd3a74 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerMemberServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerMemberServiceImpl.java
@@ -125,4 +125,40 @@ public class LklLedgerMemberServiceImpl extends BaseServiceImpl 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;
+ }
+ }
+
+
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java
index 76bb25a3..2e3021f1 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/sfexpress/service/impl/SFExpressApiServiceImpl.java
@@ -106,21 +106,26 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
*
* @param mchId 入驻记录Id, 必填项(mchId 和 storeId 其一必填) 优先
* @param storeId 商家门店ID 必填项(mchId 和 storeId 其一必填)
- * @return
+ * @return Pair 第一个元素表示是否成功,第二个元素表示结果信息或错误信息
*/
@Override
public Pair 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 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;
}
+
/**
* 创建顺丰同城(普通型)店铺
*
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java
index f47f5463..b2d7568e 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java
@@ -1777,6 +1777,9 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl
Date: Fri, 26 Sep 2025 08:58:47 +0800
Subject: [PATCH 2/5] =?UTF-8?q?=E5=95=86=E6=88=B7=E5=85=A5=E9=A9=BB?=
=?UTF-8?q?=E5=90=8E=E5=A2=9E=E5=8A=A0=E4=BA=86=E8=AE=BE=E7=BD=AE=E6=8F=90?=
=?UTF-8?q?=E7=8E=B0=E6=A8=A1=E5=BC=8F=EF=BC=9A=E8=87=AA=E5=8A=A8=E7=BB=93?=
=?UTF-8?q?=E7=AE=97=E4=BD=99=E9=A2=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../service/AccountBaseConfigService.java | 15 ++
.../base/service/ShopBaseDistrictService.java | 29 +++
.../impl/AccountBaseConfigServiceImpl.java | 39 ++++
.../impl/ShopBaseDistrictServiceImpl.java | 202 ++++++++++++++++++
.../service/impl/ShopUserCartServiceImpl.java | 14 +-
.../shop/MallProductApplicationTests.java | 38 ----
6 files changed, 298 insertions(+), 39 deletions(-)
delete mode 100644 mall-shop/src/test/java/com/suisung/mall/shop/MallProductApplicationTests.java
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/AccountBaseConfigService.java b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/AccountBaseConfigService.java
index d3997e94..9256981d 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/AccountBaseConfigService.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/AccountBaseConfigService.java
@@ -50,4 +50,19 @@ public interface AccountBaseConfigService extends IBaseService configs);
boolean saveOrUpdate(AccountBaseConfig config);
+
+ /**
+ * 获取系统配置
+ *
+ * @param configKey
+ * @return
+ */
+ String getSystemConfig(String configKey);
+
+ /**
+ * 获取平台内部最低配送费,单位(分)
+ *
+ * @return
+ */
+ Integer getInnerMinDeliveryFee();
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/ShopBaseDistrictService.java b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/ShopBaseDistrictService.java
index ce71b5fc..970c54d7 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/ShopBaseDistrictService.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/ShopBaseDistrictService.java
@@ -56,4 +56,33 @@ public interface ShopBaseDistrictService extends IBaseService
*/
String joinDistrict(List 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);
+
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/AccountBaseConfigServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/AccountBaseConfigServiceImpl.java
index d97b023d..f6c98682 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/AccountBaseConfigServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/AccountBaseConfigServiceImpl.java
@@ -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
+ * 根据配置键获取对应的配置值,如果配置值为空则返回空字符串。
+ *
+ *
+ * @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 {
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java
index 833187ae..e484a094 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java
@@ -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 implements ShopBaseDistrictService {
@@ -339,4 +341,204 @@ public class ShopBaseDistrictServiceImpl extends BaseServiceImpl 广西壮族自治区/贵港市/桂平市
+ *
+ * @param districtIdPath 省市区ID路径,格式如:"450000/450800/450881"
+ * @return 省市区名称路径,格式如:"广西壮族自治区/贵港市/桂平市"
+ */
+ @Override
+ public String getDistrictNamePathByIdPath(String districtIdPath) {
+ if (StrUtil.isBlank(districtIdPath)) {
+ return "";
+ }
+
+ String[] idStrs = districtIdPath.split("/");
+ List names = new ArrayList<>(idStrs.length);
+ List districts = new ArrayList<>(idStrs.length);
+
+ // 先获取所有地区对象
+ for (String idStr : idStrs) {
+ Integer districtId = Convert.toInt(idStr);
+ if (districtId == null) {
+ log.warn("[地区转换] ID格式不正确: {}", idStr);
+ return "";
+ }
+
+ ShopBaseDistrict district = get(districtId);
+ if (district == null) {
+ log.warn("[地区转换] 未找到对应地区信息, districtId: {}", districtId);
+ return "";
+ }
+
+ districts.add(district);
+ }
+
+ // 按照层级关系重新排序
+ List sortedDistricts = sortDistrictsByHierarchy(districts);
+
+ // 提取名称
+ for (ShopBaseDistrict district : sortedDistricts) {
+ 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 districts = new ArrayList<>(names.length);
+
+ // 先根据名称获取所有地区对象(不考虑顺序)
+ for (String name : names) {
+ if (StrUtil.isBlank(name)) {
+ log.warn("[地区转换] 名称不能为空");
+ return "";
+ }
+
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("district_name", name.trim());
+
+ ShopBaseDistrict district = findOne(queryWrapper);
+ if (district == null) {
+ log.warn("[地区转换] 未找到对应地区信息, name: {}", name);
+ return "";
+ }
+
+ districts.add(district);
+ }
+
+ // 按照层级关系重新排序
+ List sortedDistricts = sortDistrictsByHierarchy(districts);
+
+ // 提取ID
+ List ids = new ArrayList<>(sortedDistricts.size());
+ for (ShopBaseDistrict district : sortedDistricts) {
+ ids.add(district.getDistrict_id().toString());
+ }
+
+ return String.join("/", ids);
+ }
+
+ /**
+ * 根据层级关系对地区进行排序
+ *
+ * @param districts 地区列表
+ * @return 按层级排序后的地区列表
+ */
+ private List sortDistrictsByHierarchy(List districts) {
+ if (districts.size() <= 1) {
+ return districts;
+ }
+
+ // 构建ID到地区的映射
+ Map districtMap = new HashMap<>();
+ for (ShopBaseDistrict district : districts) {
+ districtMap.put(district.getDistrict_id(), district);
+ }
+
+ // 构建层级关系
+ List result = new ArrayList<>(districts.size());
+ Set processedIds = new HashSet<>();
+
+ // 找到最顶级的地区(parent_id为0或者parent不在列表中的)
+ for (ShopBaseDistrict district : districts) {
+ if (district.getDistrict_parent_id() == 0 || !districtMap.containsKey(district.getDistrict_parent_id())) {
+ result.add(district);
+ processedIds.add(district.getDistrict_id());
+ break;
+ }
+ }
+
+ // 逐级查找子地区
+ while (result.size() < districts.size()) {
+ ShopBaseDistrict lastDistrict = result.get(result.size() - 1);
+ boolean found = false;
+
+ for (ShopBaseDistrict district : districts) {
+ if (!processedIds.contains(district.getDistrict_id()) &&
+ district.getDistrict_parent_id().equals(lastDistrict.getDistrict_id())) {
+ result.add(district);
+ processedIds.add(district.getDistrict_id());
+ found = true;
+ break;
+ }
+ }
+
+ // 如果找不到下一级,则添加剩余未处理的地区
+ if (!found) {
+ for (ShopBaseDistrict district : districts) {
+ if (!processedIds.contains(district.getDistrict_id())) {
+ result.add(district);
+ processedIds.add(district.getDistrict_id());
+ }
+ }
+ break;
+ }
+ }
+
+ return result;
+ }
+
+
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/user/service/impl/ShopUserCartServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/user/service/impl/ShopUserCartServiceImpl.java
index 4b38b8c0..2de90dc0 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/user/service/impl/ShopUserCartServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/user/service/impl/ShopUserCartServiceImpl.java
@@ -2653,12 +2653,24 @@ public class ShopUserCartServiceImpl extends BaseServiceImpl
Date: Fri, 26 Sep 2025 10:01:19 +0800
Subject: [PATCH 3/5] =?UTF-8?q?=E5=9C=B0=E5=8C=BA=E5=A2=9E=E5=8A=A0?=
=?UTF-8?q?=E4=BA=86=E4=B8=89=E4=B8=AA=E6=96=B9=E6=B3=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java
index e484a094..7730dc48 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java
@@ -536,7 +536,6 @@ public class ShopBaseDistrictServiceImpl extends BaseServiceImpl
Date: Fri, 26 Sep 2025 15:11:50 +0800
Subject: [PATCH 4/5] =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=20?=
=?UTF-8?q?=E7=98=A6=E8=BA=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ShopOrderBaseServiceImpl.java | 119 ------------------
.../impl/ShopBaseDistrictServiceImpl.java | 118 ++++-------------
.../service/impl/QuartzServiceImpl.java | 93 +++++---------
.../controller/mobile/LakalaController.java | 11 +-
.../store/service/ShopMchEntryService.java | 10 ++
.../service/impl/ShopMchEntryServiceImpl.java | 84 ++++++++++---
.../src/main/resources/bootstrap-dev.yml | 8 ++
.../src/main/resources/bootstrap-local.yml | 8 ++
.../src/main/resources/bootstrap-prod.yml | 8 ++
.../src/main/resources/bootstrap-test.yml | 8 ++
.../src/main/resources/bootstrap-uat.yml | 8 ++
11 files changed, 180 insertions(+), 295 deletions(-)
delete mode 100644 ShopOrderBaseServiceImpl.java
diff --git a/ShopOrderBaseServiceImpl.java b/ShopOrderBaseServiceImpl.java
deleted file mode 100644
index 7de57f26..00000000
--- a/ShopOrderBaseServiceImpl.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * 确认收货处理
- * @param order_ids 订单ID列表
- * @param order_rows 订单数据列表
- * @return 是否处理成功
- */
-public boolean receive(List order_ids, List order_rows) {
- // 检测数据是否合法,过滤允许修改的数据
- if (CollUtil.isEmpty(order_ids)) {
- throw new ApiException(I18nUtil._("请选择需要确认收货的订单!"));
- }
-
- if (CollUtil.isEmpty(order_rows)) {
- order_rows = gets(order_ids);
- }
-
- List 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 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 itemQueryWrapper = new QueryWrapper<>();
- itemQueryWrapper.in("order_id", receive_id_row);
- List order_item_rows = shopOrderItemService.find(itemQueryWrapper);
-
- List item_src_ids = order_item_rows.stream().map(ShopOrderItem::getItem_id).distinct().collect(Collectors.toList());
- if (CollUtil.isNotEmpty(item_src_ids)) {
- QueryWrapper productItemQueryWrapper = new QueryWrapper<>();
- productItemQueryWrapper.in("item_src_id", item_src_ids).eq("store_id", store_id);
- List 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 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;
-}
\ No newline at end of file
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java
index 7730dc48..1ace1af5 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/base/service/impl/ShopBaseDistrictServiceImpl.java
@@ -352,39 +352,37 @@ public class ShopBaseDistrictServiceImpl extends BaseServiceImpl names = new ArrayList<>(idStrs.length);
- List districts = new ArrayList<>(idStrs.length);
- // 先获取所有地区对象
+ // 先获取所有地区对象的名称
for (String idStr : idStrs) {
Integer districtId = Convert.toInt(idStr);
if (districtId == null) {
log.warn("[地区转换] ID格式不正确: {}", idStr);
- return "";
+ names.add(""); // 添加空字符串而不是直接返回
+ continue; // 继续处理下一个
}
ShopBaseDistrict district = get(districtId);
if (district == null) {
log.warn("[地区转换] 未找到对应地区信息, districtId: {}", districtId);
- return "";
+ names.add(""); // 添加空字符串而不是直接返回
+ continue; // 继续处理下一个
}
- districts.add(district);
- }
-
- // 按照层级关系重新排序
- List sortedDistricts = sortDistrictsByHierarchy(districts);
-
- // 提取名称
- for (ShopBaseDistrict district : sortedDistricts) {
names.add(district.getDistrict_name());
}
return String.join("/", names);
}
+
/**
* 根据省市区名称路径获取对应的ID路径
* 例如:广西壮族自治区/贵港市/桂平市 -> 450000/450800/450881
@@ -447,13 +439,14 @@ public class ShopBaseDistrictServiceImpl extends BaseServiceImpl districts = new ArrayList<>(names.length);
+ List ids = new ArrayList<>(names.length);
- // 先根据名称获取所有地区对象(不考虑顺序)
+ // 先根据名称获取所有地区对象的ID
for (String name : names) {
if (StrUtil.isBlank(name)) {
log.warn("[地区转换] 名称不能为空");
- return "";
+ ids.add(""); // 添加空字符串而不是直接返回
+ continue; // 继续处理下一个
}
QueryWrapper queryWrapper = new QueryWrapper<>();
@@ -462,82 +455,15 @@ public class ShopBaseDistrictServiceImpl extends BaseServiceImpl sortedDistricts = sortDistrictsByHierarchy(districts);
-
- // 提取ID
- List ids = new ArrayList<>(sortedDistricts.size());
- for (ShopBaseDistrict district : sortedDistricts) {
ids.add(district.getDistrict_id().toString());
}
return String.join("/", ids);
}
- /**
- * 根据层级关系对地区进行排序
- *
- * @param districts 地区列表
- * @return 按层级排序后的地区列表
- */
- private List sortDistrictsByHierarchy(List districts) {
- if (districts.size() <= 1) {
- return districts;
- }
-
- // 构建ID到地区的映射
- Map districtMap = new HashMap<>();
- for (ShopBaseDistrict district : districts) {
- districtMap.put(district.getDistrict_id(), district);
- }
-
- // 构建层级关系
- List result = new ArrayList<>(districts.size());
- Set processedIds = new HashSet<>();
-
- // 找到最顶级的地区(parent_id为0或者parent不在列表中的)
- for (ShopBaseDistrict district : districts) {
- if (district.getDistrict_parent_id() == 0 || !districtMap.containsKey(district.getDistrict_parent_id())) {
- result.add(district);
- processedIds.add(district.getDistrict_id());
- break;
- }
- }
-
- // 逐级查找子地区
- while (result.size() < districts.size()) {
- ShopBaseDistrict lastDistrict = result.get(result.size() - 1);
- boolean found = false;
-
- for (ShopBaseDistrict district : districts) {
- if (!processedIds.contains(district.getDistrict_id()) &&
- district.getDistrict_parent_id().equals(lastDistrict.getDistrict_id())) {
- result.add(district);
- processedIds.add(district.getDistrict_id());
- found = true;
- break;
- }
- }
-
- // 如果找不到下一级,则添加剩余未处理的地区
- if (!found) {
- for (ShopBaseDistrict district : districts) {
- if (!processedIds.contains(district.getDistrict_id())) {
- result.add(district);
- processedIds.add(district.getDistrict_id());
- }
- }
- break;
- }
- }
- return result;
- }
-
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/components/quartz/service/impl/QuartzServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/components/quartz/service/impl/QuartzServiceImpl.java
index f46dc356..29feab17 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/components/quartz/service/impl/QuartzServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/components/quartz/service/impl/QuartzServiceImpl.java
@@ -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 clazz;
String fullClassName = PATH_PREFIX + cName;
- logger.debug("[Quartz] 尝试加载任务类: {}", fullClassName);
clazz = (Class) Class.forName(fullClassName);
- logger.debug("[Quartz] 成功加载任务类: {}", fullClassName);
// 3. 构建任务详情和触发器
JobKey jobKey = new JobKey(jName, jGroup);
@@ -77,52 +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));
}
- logger.info("Trigger当前状态: {}", scheduler.getTriggerState(triggerKey));
-
- // 在调度器启动检查前添加
- logger.debug("[Quartz] 调度器当前状态 - isStarted: {}, SchedulerName: {}",
- scheduler.isStarted(), scheduler.getSchedulerName());
-
} 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);
}
}
@@ -140,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;
}
}
@@ -170,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);
}
}
@@ -199,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);
}
}
@@ -228,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);
}
}
-
-
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java
index f4403d5c..fbe88173 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java
@@ -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 = "批量发送推送消息 - 测试案例")
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopMchEntryService.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopMchEntryService.java
index 7ceeabc9..f1859fa4 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopMchEntryService.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/ShopMchEntryService.java
@@ -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);
}
\ No newline at end of file
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java
index b2d7568e..cc73839d 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopMchEntryServiceImpl.java
@@ -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 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();
}
@@ -2470,6 +2465,57 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl
Date: Sat, 27 Sep 2025 11:28:02 +0800
Subject: [PATCH 5/5] =?UTF-8?q?=E7=99=BE=E5=BA=A6=E5=9C=B0=E5=9B=BE=20ak?=
=?UTF-8?q?=20=E9=85=8D=E7=BD=AE=E6=9B=B4=E6=94=B9=EF=BC=8C=E6=8B=89?=
=?UTF-8?q?=E5=8D=A1=E6=8B=89=E6=8F=90=E7=8E=B0=E4=BB=A3=E7=A0=81=E5=BC=80?=
=?UTF-8?q?=E5=8F=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../common/modules/lakala/LklOrderDraw.java | 185 +++++++++++++++
.../src/main/resources/application-dev.yml | 4 +-
.../src/main/resources/application-local.yml | 4 +-
.../src/main/resources/application-prod.yml | 4 +-
.../src/main/resources/application-test.yml | 4 +-
.../src/main/resources/application-uat.yml | 4 +-
.../admin/LakalaAdminController.java | 23 +-
.../controller/mobile/LakalaController.java | 19 ++
.../lakala/mapper/LklOrderDrawMapper.java | 19 ++
.../shop/lakala/service/LakalaApiService.java | 21 ++
.../lakala/service/LklOrderDrawService.java | 32 +++
.../service/impl/LakalaApiServiceImpl.java | 213 ++++++++++++++++++
.../service/impl/LklOrderDrawServiceImpl.java | 105 +++++++++
mall-shop/src/main/resources/application.yml | 34 +--
.../src/main/resources/bootstrap-dev.yml | 38 +++-
.../src/main/resources/bootstrap-local.yml | 38 +++-
.../src/main/resources/bootstrap-prod.yml | 38 +++-
.../src/main/resources/bootstrap-test.yml | 38 +++-
.../src/main/resources/bootstrap-uat.yml | 38 +++-
.../mapper/lakala/LklOrderDrawMapper.xml | 8 +
.../src/main/resources/static/diy/js/diy.js | 2 +-
21 files changed, 791 insertions(+), 80 deletions(-)
create mode 100644 mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklOrderDraw.java
create mode 100644 mall-shop/src/main/java/com/suisung/mall/shop/lakala/mapper/LklOrderDrawMapper.java
create mode 100644 mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklOrderDrawService.java
create mode 100644 mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklOrderDrawServiceImpl.java
create mode 100644 mall-shop/src/main/resources/mapper/lakala/LklOrderDrawMapper.xml
diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklOrderDraw.java b/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklOrderDraw.java
new file mode 100644
index 00000000..d41b1abf
--- /dev/null
+++ b/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklOrderDraw.java
@@ -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;
+}
+
diff --git a/mall-common/src/main/resources/application-dev.yml b/mall-common/src/main/resources/application-dev.yml
index e9b9540a..e23eb9cf 100644
--- a/mall-common/src/main/resources/application-dev.yml
+++ b/mall-common/src/main/resources/application-dev.yml
@@ -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: # 个推配置
diff --git a/mall-common/src/main/resources/application-local.yml b/mall-common/src/main/resources/application-local.yml
index 753e7f0d..6c7ca24d 100644
--- a/mall-common/src/main/resources/application-local.yml
+++ b/mall-common/src/main/resources/application-local.yml
@@ -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:
diff --git a/mall-common/src/main/resources/application-prod.yml b/mall-common/src/main/resources/application-prod.yml
index 736778a7..f3d810c5 100644
--- a/mall-common/src/main/resources/application-prod.yml
+++ b/mall-common/src/main/resources/application-prod.yml
@@ -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:
diff --git a/mall-common/src/main/resources/application-test.yml b/mall-common/src/main/resources/application-test.yml
index 82bb8d56..322ead6c 100644
--- a/mall-common/src/main/resources/application-test.yml
+++ b/mall-common/src/main/resources/application-test.yml
@@ -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:
diff --git a/mall-common/src/main/resources/application-uat.yml b/mall-common/src/main/resources/application-uat.yml
index 38e9680d..df4afea2 100644
--- a/mall-common/src/main/resources/application-uat.yml
+++ b/mall-common/src/main/resources/application-uat.yml
@@ -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: # 个推配置
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/admin/LakalaAdminController.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/admin/LakalaAdminController.java
index d57863b4..1eb0afe7 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/admin/LakalaAdminController.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/admin/LakalaAdminController.java
@@ -39,6 +39,27 @@ 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) {
@@ -47,7 +68,7 @@ public class LakalaAdminController extends BaseControllerImpl {
if (paramsJSON == null) {
return CommonResult.failed("请求参数不能为空");
}
-
+
// 执行业务逻辑
Boolean success = lakalaPayService.ewalletSettleProfile(paramsJSON.getStr("mercId"), paramsJSON.getStr("settleType"), paramsJSON.getStr("settleTime"));
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java
index fbe88173..5a100b20 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/controller/mobile/LakalaController.java
@@ -248,6 +248,25 @@ 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 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
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/mapper/LklOrderDrawMapper.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/mapper/LklOrderDrawMapper.java
new file mode 100644
index 00000000..c83d91d9
--- /dev/null
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/mapper/LklOrderDrawMapper.java
@@ -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 {
+
+}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java
index 8d1ff881..49366084 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LakalaApiService.java
@@ -330,4 +330,25 @@ public interface LakalaApiService {
*/
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);
+
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklOrderDrawService.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklOrderDrawService.java
new file mode 100644
index 00000000..8d074ae6
--- /dev/null
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/LklOrderDrawService.java
@@ -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 {
+
+ /**
+ * 新增或更新记录
+ *
+ * @param record
+ * @return
+ */
+ Boolean addOrUpdateByMercIdAndMerOrderNo(LklOrderDraw record);
+
+ /**
+ * 根据拉卡拉对账单流水号和平台订单号查询记录
+ *
+ * @param mercId 商户号
+ * @param merOrderNo 商户订单号
+ * @return
+ */
+ LklOrderDraw getByByMercIdAndMerOrderNo(String mercId, String merOrderNo);
+}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java
index 6f004db7..70dea245 100644
--- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LakalaApiServiceImpl.java
@@ -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;
@@ -3373,5 +3377,214 @@ public class LakalaApiServiceImpl implements LakalaApiService {
.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 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", "系统处理异常");
+ }
+ }
}
diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklOrderDrawServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklOrderDrawServiceImpl.java
new file mode 100644
index 00000000..22e7043c
--- /dev/null
+++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklOrderDrawServiceImpl.java
@@ -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 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 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 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;
+ }
+ }
+}
diff --git a/mall-shop/src/main/resources/application.yml b/mall-shop/src/main/resources/application.yml
index dca587a2..3f0e2695 100644
--- a/mall-shop/src/main/resources/application.yml
+++ b/mall-shop/src/main/resources/application.yml
@@ -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:
diff --git a/mall-shop/src/main/resources/bootstrap-dev.yml b/mall-shop/src/main/resources/bootstrap-dev.yml
index ff304d3a..6245658f 100644
--- a/mall-shop/src/main/resources/bootstrap-dev.yml
+++ b/mall-shop/src/main/resources/bootstrap-dev.yml
@@ -66,13 +66,37 @@ spring:
dashboard: @sentinel.transport.dashboard@
eager: true
quartz:
- # 调度器实例名称
- scheduler-name: mallScheduler
- # 线程池配置
- thread-pool:
- thread-count: 15 # 增加线程数以处理更多并发任务
- # 错过触发器策略
- job-store-type: memory
+ 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:
diff --git a/mall-shop/src/main/resources/bootstrap-local.yml b/mall-shop/src/main/resources/bootstrap-local.yml
index 055e954e..4820f882 100644
--- a/mall-shop/src/main/resources/bootstrap-local.yml
+++ b/mall-shop/src/main/resources/bootstrap-local.yml
@@ -66,13 +66,37 @@ spring:
dashboard: @sentinel.transport.dashboard@
eager: true
quartz:
- # 调度器实例名称
- scheduler-name: mallScheduler
- # 线程池配置
- thread-pool:
- thread-count: 15 # 增加线程数以处理更多并发任务
- # 错过触发器策略
- job-store-type: memory
+ 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:
diff --git a/mall-shop/src/main/resources/bootstrap-prod.yml b/mall-shop/src/main/resources/bootstrap-prod.yml
index bdfb2296..7470b438 100644
--- a/mall-shop/src/main/resources/bootstrap-prod.yml
+++ b/mall-shop/src/main/resources/bootstrap-prod.yml
@@ -73,13 +73,37 @@ spring:
dashboard: @sentinel.transport.dashboard@
eager: true
quartz:
- # 调度器实例名称
- scheduler-name: mallScheduler
- # 线程池配置
- thread-pool:
- thread-count: 15 # 增加线程数以处理更多并发任务
- # 错过触发器策略
- job-store-type: memory
+ 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:
diff --git a/mall-shop/src/main/resources/bootstrap-test.yml b/mall-shop/src/main/resources/bootstrap-test.yml
index 41089593..1500963d 100644
--- a/mall-shop/src/main/resources/bootstrap-test.yml
+++ b/mall-shop/src/main/resources/bootstrap-test.yml
@@ -70,13 +70,37 @@ spring:
dashboard: @sentinel.transport.dashboard@
eager: true
quartz:
- # 调度器实例名称
- scheduler-name: mallScheduler
- # 线程池配置
- thread-pool:
- thread-count: 15 # 增加线程数以处理更多并发任务
- # 错过触发器策略
- job-store-type: memory
+ 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:
diff --git a/mall-shop/src/main/resources/bootstrap-uat.yml b/mall-shop/src/main/resources/bootstrap-uat.yml
index 41089593..1500963d 100644
--- a/mall-shop/src/main/resources/bootstrap-uat.yml
+++ b/mall-shop/src/main/resources/bootstrap-uat.yml
@@ -70,13 +70,37 @@ spring:
dashboard: @sentinel.transport.dashboard@
eager: true
quartz:
- # 调度器实例名称
- scheduler-name: mallScheduler
- # 线程池配置
- thread-pool:
- thread-count: 15 # 增加线程数以处理更多并发任务
- # 错过触发器策略
- job-store-type: memory
+ 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:
diff --git a/mall-shop/src/main/resources/mapper/lakala/LklOrderDrawMapper.xml b/mall-shop/src/main/resources/mapper/lakala/LklOrderDrawMapper.xml
new file mode 100644
index 00000000..d82d81e8
--- /dev/null
+++ b/mall-shop/src/main/resources/mapper/lakala/LklOrderDrawMapper.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+ *
+
+
diff --git a/mall-shop/src/main/resources/static/diy/js/diy.js b/mall-shop/src/main/resources/static/diy/js/diy.js
index 626ebc1e..5eeb33f6 100644
--- a/mall-shop/src/main/resources/static/diy/js/diy.js
+++ b/mall-shop/src/main/resources/static/diy/js/diy.js
@@ -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();