From 5da423e50b21215fd7ec307b3bbfa5efddc56e94 Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Sat, 13 Sep 2025 21:31:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E9=A1=BA=E4=B8=B0=E9=80=80?= =?UTF-8?q?=E6=AC=BE=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C=E5=85=A8=E9=83=A8?= =?UTF-8?q?=E9=80=80=E6=AC=BE=E6=88=96=E9=80=80=E9=83=A8=E5=88=86=E6=AC=BE?= =?UTF-8?q?=E5=BF=85=E9=A1=BB=E5=8F=AF=E7=94=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/modules/order/ShopOrderLkl.java | 2 + mall-shop/pom.xml | 2 + .../service/impl/LakalaApiServiceImpl.java | 104 +++++-- .../lakala/service/impl/LklTkServiceImpl.java | 259 ++++++++++------ .../admin/ShopOrderReturnController.java | 2 +- .../impl/ShopOrderBaseServiceImpl.java | 4 +- .../service/impl/ShopOrderLklServiceImpl.java | 7 +- .../impl/ShopOrderReturnServiceImpl.java | 280 ++++++++++++------ .../service/impl/SFExpressApiServiceImpl.java | 29 +- .../impl/ShopStoreBaseServiceImpl.java | 20 +- .../impl/SnsUserMessageServiceImpl.java | 82 ++--- pom.xml | 3 - 12 files changed, 497 insertions(+), 297 deletions(-) diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/order/ShopOrderLkl.java b/mall-common/src/main/java/com/suisung/mall/common/modules/order/ShopOrderLkl.java index 9399741e..6cd02679 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/modules/order/ShopOrderLkl.java +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/order/ShopOrderLkl.java @@ -74,6 +74,8 @@ public class ShopOrderLkl implements Serializable { private String lkl_term_no; + private String wx_transaction_id; // 微信用户交易单号, 确认收货时使用 + private String notify_url; private String receive_notify_url; diff --git a/mall-shop/pom.xml b/mall-shop/pom.xml index 24993e94..06a6df00 100644 --- a/mall-shop/pom.xml +++ b/mall-shop/pom.xml @@ -473,10 +473,12 @@ true + com.spotify docker-maven-plugin + maven-resources-plugin 3.1.0 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 16a83c06..22ab0e8e 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 @@ -569,36 +569,47 @@ public class LakalaApiServiceImpl implements LakalaApiService { /** * 商户分账业务开通申请 * - * @param merCupNo - * @return + *

向拉卡拉提交商户分账业务开通申请,包括上传分账授权委托书等必要文件。 + * + * @param merCupNo 拉卡拉商户号(银联商户号) + * @return Pair对象,第一个元素表示操作是否成功,第二个元素为操作结果信息 */ @Override public Pair innerApplyLedgerMer(String merCupNo) { - log.debug("商户分账业务申请开始"); + log.info("开始执行商户分账业务申请流程,商户号: {}", merCupNo); + // 参数校验 if (StringUtils.isBlank(merCupNo)) { + log.warn("商户分账业务申请失败:商户号不能为空"); return Pair.of(false, I18nUtil._("商户号不能为空!")); } // 获取商户入驻记录 + log.debug("开始查询商户入驻信息,商户号: {}", merCupNo); ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByMerCupNo(merCupNo); if (shopMchEntry == null) { + log.warn("商户分账业务申请失败:商家入驻信息不存在,商户号: {}", merCupNo); return Pair.of(false, I18nUtil._("商家入驻信息不存在!")); } // 判断是否已经申请过? + log.debug("检查商户是否已申请过分账业务,商户号: {}", merCupNo); LklLedgerMember lklLedgerMember = lklLedgerMemberService.getByMerCupNo(merCupNo); - if (lklLedgerMember != null && lklLedgerMember.getAudit_status() == 1) { + if (lklLedgerMember != null && Integer.valueOf(1).equals(lklLedgerMember.getAudit_status())) { + log.info("商户已申请过分账业务,无需重复申请,商户号: {}", merCupNo); return Pair.of(true, I18nUtil._("商家已经申请过了!")); } // 检查更新店铺初始化状态 + log.debug("检查并更新店铺初始化状态,商户ID: {}", shopMchEntry.getId()); shopMchEntryService.checkMchEntryStoreStatus(shopMchEntry.getId(), shopMchEntry); // 1. 配置初始化 + log.debug("初始化拉卡拉SDK"); initLKLSDK(); //2. 装配数据 + log.debug("装配分账业务申请请求参数"); V2MmsOpenApiLedgerApplyLedgerMerRequest req = new V2MmsOpenApiLedgerApplyLedgerMerRequest(); req.setVersion("2.0"); req.setOrderNo(StringUtils.genLklOrderNo(8));// 14位年月日时(24小时制)分秒+8位的随机数 @@ -624,26 +635,32 @@ public class LakalaApiServiceImpl implements LakalaApiService { String retUrl = domain + "/mobile/shop/lakala/ledger/applyLedgerMerNotify"; req.setRetUrl(retUrl); - log.debug("商户分账业务申请请求参数:{}", JSONUtil.toJsonStr(req)); + log.debug("商户分账业务申请请求参数: {}", JSONUtil.toJsonStr(req)); try { //3. 发送请求 + log.info("开始向拉卡拉提交分账业务申请,订单号: {}", req.getOrderNo()); String responseStr = LKLSDK.httpPost(req); if (StrUtil.isBlank(responseStr)) { + log.error("申请拉卡拉分账业务无返回值,订单号: {}", req.getOrderNo()); return Pair.of(false, I18nUtil._("申请拉卡拉分账业务无返回值!")); } - log.debug("商户分账业务申请响应数据:{}", responseStr); + log.debug("商户分账业务申请响应数据: {}", responseStr); // 成功返回示例:{'retCode':'000000','retMsg':'申请已受理,请等待审核结果','respData':{'version':'1.0','orderNo':'KFPT20230223181025407788734','orgCode':'1','applyId':681201215598657536}} JSONObject lakalaRespJSON = JSONUtil.parseObj(responseStr); if (lakalaRespJSON == null) { + log.error("申请拉卡拉分账业务返回值异常,订单号: {}", req.getOrderNo()); return Pair.of(false, I18nUtil._("申请拉卡拉分账业务返回值异常!")); } Object applyId = lakalaRespJSON.getByPath("respData.applyId"); - if (!lakalaRespJSON.getStr("retCode").equals(lklSuccessCode) || applyId == null) { - return Pair.of(false, lakalaRespJSON.getStr("retMsg")); + if (!lklSuccessCode.equals(lakalaRespJSON.getStr("retCode")) || applyId == null) { + String retMsg = lakalaRespJSON.getStr("retMsg"); + log.warn("拉卡拉分账业务申请被拒绝,订单号: {},返回码: {},返回信息: {}", + req.getOrderNo(), lakalaRespJSON.getStr("retCode"), retMsg); + return Pair.of(false, retMsg); } JSONObject paramsJSON = new JSONObject(); @@ -670,15 +687,21 @@ public class LakalaApiServiceImpl implements LakalaApiService { // 新增数据 // 将 JSON 对象的键名转换为下划线命名 + log.debug("准备保存分账业务申请记录"); LklLedgerMember lklLedgerMemberNew = JSONUtil.toBean(StringUtils.convertCamelToSnake(paramsJSON.toString()), LklLedgerMember.class); if (!lklLedgerMemberService.addOrUpdateByMerCupNo(lklLedgerMemberNew)) { + log.error("新增或更改拉卡拉分账业务申请信息失败,订单号: {}", req.getOrderNo()); return Pair.of(false, I18nUtil._("新增或更改拉卡拉分账业务申请信息失败!")); } + log.info("商户分账业务申请提交成功,等待审核,订单号: {},申请ID: {}", req.getOrderNo(), applyId); return Pair.of(true, I18nUtil._("商户申请拉卡拉分账业务,提交成功,待审核中!")); } catch (SDKException e) { - log.error("申请拉卡拉分账业务出错:", e); + log.error("申请拉卡拉分账业务出错,订单号: {}", req.getOrderNo(), e); return Pair.of(false, I18nUtil._("申请拉卡拉分账业务出错!")); + } catch (Exception e) { + log.error("申请拉卡拉分账业务出现未预期异常,订单号: {}", req.getOrderNo(), e); + return Pair.of(false, I18nUtil._("申请拉卡拉分账业务出现未预期异常!")); } } @@ -1359,49 +1382,56 @@ public class LakalaApiServiceImpl implements LakalaApiService { /** * 内部调用分账关系绑定申请(优化版) - * 参考:https://o.lakala.com/#/home/document/detail?id=386 * - * @param paramsJSON 包含绑定参数的JSON对象 {merCupNo} - * @return 操作结果及提示信息 - */ - /** - * 内部调用分账关系绑定申请(优化版) - * 参考:https://o.lakala.com/#/home/document/detail?id=386 + *

参考:https://o.lakala.com/#/home/document/detail?id=386 + * 为商户绑定分账接收方,包括平台方和代理商(如有)。 * * @param paramsJSON 包含绑定参数的JSON对象 {merCupNo} - * @return 操作结果及提示信息 + * @return Pair对象,第一个元素表示操作是否成功,第二个元素为操作结果信息 */ public Pair innerApplyLedgerMerReceiverBind(JSONObject paramsJSON) { - log.debug("商家绑定分账接收方申请开始:{}", paramsJSON); + log.info("开始执行商家绑定分账接收方申请"); // 1. 参数校验(提前失败) if (paramsJSON == null) { + log.warn("商家绑定分账接收方申请失败:绑定参数为空"); return Pair.of(false, I18nUtil._("绑定参数为空")); } String merCupNo = paramsJSON.getStr("merCupNo"); if (StrUtil.isBlank(merCupNo)) { + log.warn("商家绑定分账接收方申请失败:商户号(merCupNo)为空"); return Pair.of(false, I18nUtil._("商户号(merCupNo)为空")); } + log.debug("商家绑定分账接收方申请参数:{}", paramsJSON); + // 2. 基础数据查询(提前失败) + log.debug("开始查询商户入驻信息,商户号: {}", merCupNo); ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByMerCupNo(merCupNo); if (shopMchEntry == null) { + log.warn("商家绑定分账接收方申请失败:商户入驻记录不存在,商户号: {}", merCupNo); return Pair.of(false, I18nUtil._("商户入驻记录不存在")); } // 进件记录 + log.debug("开始查询分账业务申请记录,商户号: {}", merCupNo); LklLedgerMember lklLedgerMember = lklLedgerMemberService.getByMerCupNo(merCupNo); if (lklLedgerMember == null || !CommonConstant.Enable.equals(lklLedgerMember.getAudit_status())) { + log.warn("商家绑定分账接收方申请失败:商家尚未申请分账业务或审核未通过,商户号: {}", merCupNo); return Pair.of(false, I18nUtil._("商家尚未申请分账业务")); } // 分账接收方列表 + log.debug("开始查询分账接收方列表"); List receiverList = lklLedgerReceiverService.selectPlatformAnDistributorList(); if (CollectionUtil.isEmpty(receiverList)) { + log.warn("商家绑定分账接收方申请失败:分账接收方信息为空"); return Pair.of(false, I18nUtil._("分账接收方信息为空")); } + log.info("获取到 {} 个分账接收方,开始处理绑定申请", receiverList.size()); + // 3. 公共参数准备(避免循环内重复计算) // 正式上线的时候,调整 api 地址 String domain = projectDomain; @@ -1418,19 +1448,26 @@ public class LakalaApiServiceImpl implements LakalaApiService { int totalCount = receiverList.size(); // 5. 初始化SDK(建议移至类初始化或统一配置) + log.debug("初始化拉卡拉SDK"); initLKLSDK(); // 4. 循环处理接收方绑定 for (LklLedgerReceiver receiver : receiverList) { try { + log.debug("开始处理分账接收方绑定,接收方编号: {}", receiver.getReceiver_no()); + // 跳过已存在的绑定关系 - if (lklLedgerMerReceiverBindService.getByCondition(merCupNo, receiver.getReceiver_no()) != null) { - log.warn("分账绑定关系已存在:merCupNo={}, receiverNo={}", merCupNo, receiver.getReceiver_no()); + LklLedgerMerReceiverBind existingBind = lklLedgerMerReceiverBindService.getByCondition(merCupNo, receiver.getReceiver_no()); + if (existingBind != null) { + log.info("分账绑定关系已存在,跳过处理:merCupNo={}, receiverNo={}", merCupNo, receiver.getReceiver_no()); + successCount++; // 已存在的绑定视为成功 continue; } // 6. 构建请求参数 String orderNo = StringUtils.genLklOrderNo(8); + log.debug("生成订单号: {}", orderNo); + V2MmsOpenApiLedgerApplyBindRequest request = new V2MmsOpenApiLedgerApplyBindRequest(); request.setOrderNo(orderNo); request.setOrgCode(orgCode); @@ -1443,17 +1480,23 @@ public class LakalaApiServiceImpl implements LakalaApiService { request.setRetUrl(retUrl); // 7. 记录请求参数 - log.debug("商家绑定分账接收方参数:{}", JSONUtil.toJsonStr(request)); + log.debug("商家绑定分账接收方请求参数:{}", JSONUtil.toJsonStr(request)); // 8. 发送请求并处理响应 + log.info("向拉卡拉提交分账接收方绑定申请,订单号: {},商户号: {},接收方: {}", + orderNo, merCupNo, receiver.getReceiver_no()); String responseStr = LKLSDK.httpPost(request); JSONObject respJson = JSONUtil.parseObj(responseStr); if (respJson == null || !lklSuccessCode.equals(respJson.getStr("retCode"))) { - log.error("绑定接收方拉卡拉响应失败:{}", respJson != null ? respJson.getStr("retMsg") : "无响应数据"); + String errorMsg = respJson != null ? respJson.getStr("retMsg") : "无响应数据"; + log.error("绑定接收方拉卡拉响应失败,订单号: {},错误信息: {}", orderNo, errorMsg); continue; // 单个失败不影响其他接收方处理 } + log.info("拉卡拉分账接收方绑定申请提交成功,订单号: {},申请ID: {}", + orderNo, respJson.getByPath("respData.applyId")); + // 9. 更新参数并保存记录 paramsJSON.set("orderNo", orderNo); paramsJSON.set("apply_id", respJson.getByPath("respData.applyId")); @@ -1468,20 +1511,25 @@ public class LakalaApiServiceImpl implements LakalaApiService { String snakeJson = StringUtils.convertCamelToSnake(paramsJSON.toString()); LklLedgerMerReceiverBind bindRecord = JSONUtil.toBean(snakeJson, LklLedgerMerReceiverBind.class); + log.debug("准备保存分账绑定记录"); if (lklLedgerMerReceiverBindService.addOrUpdateByMerCupNoReceiverNo(bindRecord)) { successCount++; + log.info("分账绑定记录保存成功,订单号: {}", orderNo); } else { - log.warn("绑定记录保存失败:merCupNo={}, receiverNo={}", merCupNo, receiver.getReceiver_no()); + log.warn("分账绑定记录保存失败,订单号: {},商户号: {},接收方: {}", + orderNo, merCupNo, receiver.getReceiver_no()); } } catch (Exception e) { - log.error("处理分账绑定失败:merCupNo={}, receiverNo={}", merCupNo, receiver.getReceiver_no(), e); + log.error("处理分账绑定异常,商户号: {},接收方: {}", merCupNo, receiver.getReceiver_no(), e); // 单个接收方处理失败,继续处理其他接收方 } } // 10. 返回结果 + log.info("分账接收方绑定处理完成,成功: {},总数: {}", successCount, totalCount); if (successCount == 0) { + log.error("商家绑定分账接收方全部失败"); if (lklLedgerMember != null) { shopMchEntryService.updateMerchEntryApprovalByMchId( lklLedgerMember.getMch_id(), CommonConstant.MCH_APPR_STA_NOPASS, "商家绑定分账接收方失败" @@ -1489,9 +1537,13 @@ public class LakalaApiServiceImpl implements LakalaApiService { } return Pair.of(false, "商家绑定分账接收方失败"); } else if (successCount < totalCount) { - return Pair.of(true, "商家绑定分账接收方,部分提交成功(" + successCount + "/" + totalCount + "),待审核通知"); + String message = "商家绑定分账接收方,部分提交成功(" + successCount + "/" + totalCount + "),待审核通知"; + log.info(message); + return Pair.of(true, message); } else { - return Pair.of(true, "商家绑定分账接收方,全部提交成功,待审核通知"); + String message = "商家绑定分账接收方,全部提交成功,待审核通知"; + log.info(message); + return Pair.of(true, message); } } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklTkServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklTkServiceImpl.java index 09a628ae..c98c2c58 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklTkServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklTkServiceImpl.java @@ -318,44 +318,54 @@ public class LklTkServiceImpl { } /** - * (重要) 请求拉卡拉进件, - * TODO 已经进件过了,一般不涉及更改企业(小微)的信息,可以不要重新进件了 - *

- * 参考拉卡拉给的独立文档:2、拓客SAAS商户管理接口(新).docx + * (重要) 请求拉卡拉进件 * - * @param mchId 入驻商家自增Id - * @return + *

此方法用于向拉卡拉提交商户进件申请,包括完整的商户信息和相关附件。 + * 已经进件过的商户一般不涉及更改企业(小微)的信息,可以不要重新进件。 + * + *

参考拉卡拉给的独立文档:2、拓客SAAS商户管理接口(新).docx + * + * @param mchId 入驻商家自增Id,不能为空 + * @return Pair对象,第一个元素表示操作是否成功,第二个元素为操作结果信息 */ public Pair registrationMerchant(Long mchId) { + logger.info("开始执行拉卡拉商户进件流程,商户ID: {}", mchId); + + // 参数校验 if (ObjectUtil.isEmpty(mchId)) { + logger.warn("商户进件失败:入驻商户Id不能为空"); return Pair.of(false, "入驻商户Id不能为空"); } String authorization = getLklTkAuthorization(); if (StrUtil.isBlank(authorization)) { + logger.error("商户进件失败:获取拉卡拉token失败"); return Pair.of(false, "获取拉卡拉token失败"); } JSONObject header = new JSONObject(); - header.put("Authorization", getLklTkAuthorization()); + header.put("Authorization", authorization); // 获取商家入驻信息,组成请求参数 ShopMchEntry shopMchEntry = shopMchEntryService.shopMerchEntryById(mchId); if (ObjectUtil.isEmpty(shopMchEntry)) { + logger.warn("商户进件失败:商家入驻信息不存在,商户ID: {}", mchId); return Pair.of(false, "商家入驻信息不存在"); } if (!CommonConstant.Enable.equals(shopMchEntry.getHas_ec_signed()) || StrUtil.isBlank(shopMchEntry.getContract_download_url())) { + logger.warn("商户进件失败:商家未签署合同,商户ID: {}", mchId); return Pair.of(false, "商家先签署合同,再来进件!"); } // 判断是否已经进件过?进件过,执行下一步操作(进件异步通知的相关操作) - - //密集操作:进件审核通过之后,要下一步流程操作:申请分账业务、创建分账接收方 - if (CommonConstant.Enable.equals(shopMchEntry.getHas_apply_mer()) && CheckUtil.isNotEmpty(shopMchEntry.getDistributor_id()) + // 密集操作:进件审核通过之后,要下一步流程操作:申请分账业务、创建分账接收方 + if (CommonConstant.Enable.equals(shopMchEntry.getHas_apply_mer()) + && CheckUtil.isNotEmpty(shopMchEntry.getDistributor_id()) && StrUtil.isAllNotBlank(shopMchEntry.getLkl_mer_cup_no(), shopMchEntry.getLkl_term_no())) { // 已经进件过了,执行下一步操作 + logger.info("商户已进件,执行后续操作,商户ID: {}", mchId); registrationMerchantAfterHook(mchId, shopMchEntry.getLkl_mer_cup_no(), shopMchEntry.getDistributor_id()); return Pair.of(true, "请勿重复提交,拉卡拉已进件成功了,准备提交分账业务申请!"); } @@ -475,60 +485,87 @@ public class LklTkServiceImpl { reqJsonBody.put("bizContent", bizContent); // 附件文件相关开始 + logger.debug("开始处理商户附件文件,商户ID: {}", mchId); JSONArray attachments = new JSONArray(); - if (isQy) { + if (Boolean.TRUE.equals(isQy)) { JSONObject SETTLE_ID_CARD_FRONT = updatePhoto(shopMchEntry.getLegal_person_id_images(), "FR_ID_CARD_FRONT", false); if (SETTLE_ID_CARD_FRONT != null) { attachments.put(SETTLE_ID_CARD_FRONT); // 法人身份证正面 + logger.debug("成功添加法人身份证正面图片"); + } else { + logger.warn("法人身份证正面图片添加失败"); } JSONObject SETTLE_ID_CARD_BEHIND = updatePhoto(shopMchEntry.getLegal_person_id_images2(), "FR_ID_CARD_BEHIND", false); if (SETTLE_ID_CARD_BEHIND != null) { attachments.put(SETTLE_ID_CARD_BEHIND); // 法人身份证国徽面 + logger.debug("成功添加法人身份证国徽面图片"); + } else { + logger.warn("法人身份证国徽面图片添加失败"); } JSONObject BUSINESS_LICENCE = updatePhoto(shopMchEntry.getBiz_license_image(), "BUSINESS_LICENCE", false); if (BUSINESS_LICENCE != null) { attachments.put(BUSINESS_LICENCE); // 营业执照 + logger.debug("成功添加营业执照图片"); + } else { + logger.warn("营业执照图片添加失败"); } } else { JSONObject ID_CARD_FRONT = updatePhoto(shopMchEntry.getIndividual_id_images(), "ID_CARD_FRONT", false); if (ID_CARD_FRONT != null) { attachments.put(ID_CARD_FRONT); // 身份证正面 + logger.debug("成功添加身份证正面图片"); + } else { + logger.warn("身份证正面图片添加失败"); } JSONObject ID_CARD_BEHIND = updatePhoto(shopMchEntry.getIndividual_id_images2(), "ID_CARD_BEHIND", false); if (ID_CARD_BEHIND != null) { attachments.put(ID_CARD_BEHIND); // 身份证国徽面 + logger.debug("成功添加身份证国徽面图片"); + } else { + logger.warn("身份证国徽面图片添加失败"); } } JSONObject SHOP_OUTSIDE_IMG = updatePhoto(shopMchEntry.getFront_facade_image(), "SHOP_OUTSIDE_IMG", false); if (SHOP_OUTSIDE_IMG != null) { attachments.put(SHOP_OUTSIDE_IMG); // 门店门面图片 + logger.debug("成功添加门店门面图片"); + } else { + logger.warn("门店门面图片添加失败"); } JSONObject SHOP_INSIDE_IMG = updatePhoto(shopMchEntry.getEnvironment_image(), "SHOP_INSIDE_IMG", false); if (SHOP_INSIDE_IMG != null) { attachments.put(SHOP_INSIDE_IMG); // 门店内部图片 + logger.debug("成功添加门店内部图片"); + } else { + logger.warn("门店内部图片添加失败"); } JSONObject BANK_CARD = updatePhoto(shopMchEntry.getBank_image(), "BANK_CARD", false); if (BANK_CARD != null) { attachments.put(BANK_CARD); // 银行卡图片 + logger.debug("成功添加银行卡图片"); + } else { + logger.warn("银行卡图片添加失败"); } reqJsonBody.put("attchments", attachments); + logger.debug("商户附件文件处理完成,共添加 {} 个附件", attachments.size()); // 附件文件相关结束 String urlPath = "/sit/htkregistration/merchant"; - if (isLklProd) { + if (Boolean.TRUE.equals(isLklProd)) { // 生产环境启用 urlPath = "/registration/merchant"; } try { - logger.info("进件请求参数:{}", JSONUtil.toJsonStr(reqJsonBody)); + logger.info("准备提交拉卡拉进件请求,商户ID: {}", mchId); + logger.debug("进件请求参数:{}", JSONUtil.toJsonStr(reqJsonBody)); JSONObject response = RestTemplateHttpUtil.sendLklPost(buildLklTkUrl(urlPath), header, reqJsonBody, JSONObject.class); logger.debug("拉卡拉进件响应参数:{}", response); @@ -538,6 +575,7 @@ public class LklTkServiceImpl { || !"000000".equals(response.getStr("retCode"))) { String errMsg = response.getStr("retMsg") == null ? "提交拉卡拉进件,出现未知错误" : response.getStr("retMsg"); + logger.error("拉卡拉进件失败,商户ID: {},错误信息: {}", mchId, errMsg); shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_NOPASS, "提交拉卡拉进件失败:" + errMsg); return Pair.of(false, "提交拉卡拉进件失败:" + errMsg); @@ -546,19 +584,24 @@ public class LklTkServiceImpl { // {"merchantNo": "100132349","status": "WAIT_AUDI","state": "1"} JSONObject rawData = response.getJSONObject("rawData"); // 进件这个接口比较特殊,不按照常规返回数据 String lklMerInnerNo = rawData.getStr("merchantNo"); //拉卡拉内部商户号 + + logger.info("拉卡拉进件成功,商户ID: {},拉卡拉商户号: {}", mchId, lklMerInnerNo); + // 表中的内部外部商户号暂时都传同一个内部商户号,以便异步通知更改记录 Boolean success = shopMchEntryService.updateMerchEntryLklMerCupNo(mchId, CommonConstant.Disable2, lklMerInnerNo, lklMerInnerNo, reqJsonBody.toString(), rawData.toString()); - if (!success) { + if (!Boolean.TRUE.equals(success)) { + logger.error("进件成功但更新商户号失败,商户ID: {}", mchId); shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_NOPASS, "进件成功,但更新商户号失败!"); return Pair.of(false, "提交进件成功,但更新商户号失败!"); } } catch (Exception e) { - logger.error("拉卡拉进件异常:{}", e.getMessage()); + logger.error("拉卡拉进件异常,商户ID: {}", mchId, e); shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_NOPASS, "进件失败:" + e.getMessage()); return Pair.of(false, "提交拉卡拉进件失败:" + e.getMessage()); } + logger.info("拉卡拉进件提交成功,等待审核,商户ID: {}", mchId); shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_PADDING, "提交拉卡拉进件成功,正进一步审核!"); return Pair.of(true, "提交拉卡拉进件成功,正进一步审核!"); } @@ -566,91 +609,117 @@ public class LklTkServiceImpl { /** * (重要)拉卡拉进件异步通知 * - * @param request - * @return + *

处理拉卡拉平台发送的商户进件结果异步通知,包括解密通知数据、更新商户状态等操作。 + * + * @param request HTTP请求对象,包含拉卡拉发送的异步通知数据 + * @return JSONObject 响应结果,包含处理状态码和消息 */ -// @Transactional public JSONObject registrationMerchantNotify(HttpServletRequest request) { - logger.debug("拉卡拉进件异步通知开始"); + logger.info("开始处理拉卡拉进件异步通知"); - // 解密请求参数 - String requestBody = LakalaUtil.getBody(request); - logger.debug("拉卡拉进件异步通知返回参数:{}", requestBody); + try { + // 解密请求参数 + String requestBody = LakalaUtil.getBody(request); + logger.debug("拉卡拉进件异步通知原始参数:{}", requestBody); - if (StrUtil.isBlank(requestBody)) { - return new JSONObject().set("code", "400").set("message", "返回参数为空"); + if (StrUtil.isBlank(requestBody)) { + logger.warn("拉卡拉进件异步通知参数为空"); + return new JSONObject().set("code", "400").set("message", "返回参数为空"); + } + + JSONObject reqBodyJSON = JSONUtil.parseObj(requestBody); + if (reqBodyJSON.isEmpty() || reqBodyJSON.get("data") == null) { + logger.warn("拉卡拉进件异步通知参数格式有误,无法解析: {}", requestBody); + return new JSONObject().set("code", "400").set("message", "参数格式有误,无法解析"); + } + + String srcData = reqBodyJSON.getStr("data"); + if (StrUtil.isBlank(srcData)) { + logger.warn("拉卡拉进件异步通知关键参数为空值"); + return new JSONObject().set("code", "400").set("message", "关键参数为空值"); + } + + // 公钥解密出来的数据 + logger.debug("开始解密拉卡拉通知数据"); + String notifyPubKey = LakalaUtil.getResourceFile(notifyPubKeyPath, false, false); + String data = LakalaUtil.decryptNotifyData(notifyPubKey, srcData); + if (StrUtil.isBlank(data)) { + logger.error("拉卡拉进件异步通知数据解密失败"); + return new JSONObject().set("code", "400").set("message", "数据解密出错!"); + } + + logger.info("拉卡拉进件异步通知数据解密成功,开始处理业务逻辑"); + + // 逻辑处理 + JSONObject dataJSON = JSONUtil.parseObj(data); + String auditStatus = dataJSON.getStr("status"); + String merCupNo = dataJSON.getStr("externalCustomerNo"); //拉卡拉外部商户号 + String merInnerNo = dataJSON.getStr("customerNo"); //拉卡拉内部商户号 + String termNos = dataJSON.getStr("termNos"); //拉卡拉分配的业务终端号 + + logger.debug("解析通知数据完成 - 审核状态: {},外部商户号: {},内部商户号: {},终端号: {}", + auditStatus, merCupNo, merInnerNo, termNos); + + // 合并参数校验 + if (dataJSON.isEmpty() || + StrUtil.isBlank(auditStatus) || + StrUtil.isBlank(merCupNo) || + StrUtil.isBlank(merInnerNo)) { + logger.warn("拉卡拉进件异步通知参数解析出错,数据: {}", data); + return new JSONObject().set("code", "500").set("message", "参数解析出错"); + } + + // 给商家入驻表增加拉卡拉的商户号和拉卡拉返回的数据 + logger.debug("开始查询商户入驻信息,内部商户号: {}", merInnerNo); + ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByMerInnerNo(merInnerNo); + if (shopMchEntry == null) { + logger.error("拉卡拉进件异步通知:{}内部商户号入驻信息不存在!", merInnerNo); + return new JSONObject().put("code", "500").put("message", merInnerNo + "内部商户号入驻信息不存在"); + } + + Long mchId = shopMchEntry.getId(); + logger.info("找到商户入驻信息,商户ID: {}", mchId); + + // 校验审核状态 + logger.debug("校验审核状态: {}", auditStatus); + if (!"SUCCESS".equals(auditStatus) && !"REVIEW_PASS".equals(auditStatus)) { + String remark = dataJSON.getStr("remark"); + logger.warn("拉卡拉进件审核未通过,审核状态: {},备注: {}", auditStatus, remark); + shopMchEntryService.updateMerchEntryApprovalByMchId(mchId, CommonConstant.MCH_APPR_STA_LKL_NOPASS, "进件失败:" + remark); + return new JSONObject().set("code", "FAIL").set("message", "返回审核状态有误"); + } + + logger.info("拉卡拉进件审核通过,商户ID: {},开始更新商户信息", mchId); + + // RMK 拉卡拉进价提交成功,边处理周边的数据,边等待审核异步通知 + + // 更新已进件成功的商户号和设备号 + logger.debug("开始更新商户拉卡拉审核状态"); + Boolean success = shopMchEntryService.updateMerchEntryLklAuditStatusByLklMerCupNo( + merInnerNo, merCupNo, termNos, CommonConstant.Enable, null, data); + + if (!Boolean.TRUE.equals(success)) { + logger.error("拉卡拉进件审核通过但更新商户号失败,商户ID: {}", mchId); + shopMchEntryService.updateMerchEntryApprovalByMchId(mchId, CommonConstant.MCH_APPR_STA_LKL_NOPASS, "进件时更新商户号失败"); + return new JSONObject().set("code", "500").set("message", "更新商户号失败"); + } + + logger.info("商户拉卡拉审核状态更新成功,商户ID: {}", mchId); + + shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_PADDING, + "进件、申请分账业务、创建分账接收方均已成功,等待拉卡拉审核分账业务请求!"); + + //密集操作:进件审核通过之后,要下一步流程操作:申请分账业务、创建分账接收方 + logger.info("开始执行进件后续操作,商户ID: {},拉卡拉商户号: {}", mchId, merCupNo); + registrationMerchantAfterHook(mchId, merCupNo, shopMchEntry.getDistributor_id()); + + logger.info("拉卡拉进件异步通知处理完成,商户ID: {}", mchId); + return new JSONObject().set("code", "200").set("message", "处理成功"); + + } catch (Exception e) { + logger.error("处理拉卡拉进件异步通知异常", e); + return new JSONObject().set("code", "500").set("message", "处理异常:" + e.getMessage()); } - - JSONObject reqBodyJSON = JSONUtil.parseObj(requestBody); - if (reqBodyJSON.isEmpty() || reqBodyJSON.get("data") == null) { - return new JSONObject().set("code", "400").set("message", "参数格式有误,无法解析"); - } - - String srcData = reqBodyJSON.getStr("data"); - if (StrUtil.isBlank(srcData)) { - return new JSONObject().set("code", "400").set("message", "关键参数为空值"); - } - - // 公钥解密出来的数据 - String notifyPubKey = LakalaUtil.getResourceFile(notifyPubKeyPath, false, false); - String data = LakalaUtil.decryptNotifyData(notifyPubKey, srcData); - if (StrUtil.isBlank(data)) { - return new JSONObject().set("code", "400").set("message", "数据解密出错!"); - } - - logger.debug("拉卡拉进件异步通知data解密成功,开始处理逻辑"); - - // 逻辑处理 - JSONObject dataJSON = JSONUtil.parseObj(data); - String auditStatus = dataJSON.getStr("status"); - String merCupNo = dataJSON.getStr("externalCustomerNo"); //拉卡拉外部商户号 - String merInnerNo = dataJSON.getStr("customerNo"); //拉卡拉内部商户号 - String termNos = dataJSON.getStr("termNos"); //拉卡拉分配的业务终端号 - - // 合并参数校验 - if (dataJSON.isEmpty() || - StrUtil.isBlank(auditStatus) || - StrUtil.isBlank(merCupNo) || - StrUtil.isBlank(merInnerNo)) { - return new JSONObject().set("code", "500").set("message", "参数解析出错"); - } - - // 给商家入驻表增加拉卡拉的商户号和拉卡拉返回的数据 - ShopMchEntry shopMchEntry = shopMchEntryService.getShopMerchEntryByMerInnerNo(merInnerNo); - if (shopMchEntry == null) { - logger.error("拉卡拉进件异步通知:{}内部商户号入驻信息不存在!", merInnerNo); - return new JSONObject().put("code", "500").put("message", merInnerNo + "内部商户号入驻信息不存在"); - } - - Long mchId = shopMchEntry.getId(); - - - // 校验审核状态 - if (!"SUCCESS".equals(auditStatus) && !"REVIEW_PASS".equals(auditStatus)) { - logger.debug("返回的审核状态:{}", auditStatus); - shopMchEntryService.updateMerchEntryApprovalByMchId(mchId, CommonConstant.MCH_APPR_STA_LKL_NOPASS, "进件失败:" + dataJSON.getStr("remark")); - return new JSONObject().set("code", "FAIL").set("message", "返回审核状态有误"); - } - - // RMK 拉卡拉进价提交成功,边处理周边的数据,边等待审核异步通知 - - // 更新已进件成功的商户号和设备号 - Boolean success = shopMchEntryService.updateMerchEntryLklAuditStatusByLklMerCupNo( - merInnerNo, merCupNo, termNos, CommonConstant.Enable, null, data); - - if (!success) { - shopMchEntryService.updateMerchEntryApprovalByMchId(mchId, CommonConstant.MCH_APPR_STA_LKL_NOPASS, "进件时更新商户号失败"); - return new JSONObject().set("code", "500").set("message", "更新商户号失败"); - } - - - shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_PADDING, - "进件、申请分账业务、创建分账接收方均已成功,等待拉卡拉审核分账业务请求!"); - - //密集操作:进件审核通过之后,要下一步流程操作:申请分账业务、创建分账接收方 - registrationMerchantAfterHook(mchId, merCupNo, shopMchEntry.getDistributor_id()); - - return new JSONObject().set("code", "200").set("message", "处理成功"); } /** diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/controller/admin/ShopOrderReturnController.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/controller/admin/ShopOrderReturnController.java index 91184391..c57db39e 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/controller/admin/ShopOrderReturnController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/controller/admin/ShopOrderReturnController.java @@ -211,7 +211,7 @@ public class ShopOrderReturnController extends BaseControllerImpl { * {"order_id":"DD-20250701-1","reason":"商家协商退款","order_return_vo":{"order_id":"DD-20250701-1","return_items":[{"order_item_id":1,"return_item_num":1,"return_refund_amount":"0.01"}]}} * @return CommonResult 处理结果 */ - @ApiOperation(value = "商家退货退款", notes = "商家退货退款,支持整单或个别商品退货") + @ApiOperation(value = "商家退款", notes = "商家退款,支持整单或个别商品退货") @RequestMapping(value = "/mch/order/doRefund", method = RequestMethod.POST) public CommonResult doRefundForMch(@RequestBody JSONObject params) { return shopOrderReturnService.doRefundForMch(params); diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java index e9f78848..3f2deda2 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/order/service/impl/ShopOrderBaseServiceImpl.java @@ -764,7 +764,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl order_item_ids = orderReturnInputVo.getReturn_items().stream().map(OrderReturnItemInputVo::getOrder_item_id).distinct().collect(Collectors.toList()); - ShopOrderInfo shopOrderInfo = shopOrderInfoService.get(order_id); + List order_item_ids = orderReturnInputVo.getReturn_items().stream() + .map(OrderReturnItemInputVo::getOrder_item_id) + .distinct() + .collect(Collectors.toList()); + ShopOrderInfo shopOrderInfo = shopOrderInfoService.get(order_id); if (shopOrderInfo == null) { throw new ApiException(I18nUtil._("此订单信息数据有误!")); } ShopOrderBase orderBase = shopOrderBaseService.get(order_id); - if (orderBase == null) { throw new ApiException(I18nUtil._("此订单详细信息数据有误!")); } - // 判断此订单商品是否有正在审核的退款单。 + // 判断此订单商品是否有正在审核的退款单 QueryWrapper returnQueryWrapper = new QueryWrapper<>(); - returnQueryWrapper.eq("order_id", order_id).eq("return_state_id", StateCode.RETURN_PROCESS_CHECK); + returnQueryWrapper.eq("order_id", order_id) + .eq("return_state_id", StateCode.RETURN_PROCESS_CHECK); List order_return_rows = find(returnQueryWrapper); if (CollUtil.isNotEmpty(order_return_rows)) { - List return_ids = order_return_rows.stream().map(ShopOrderReturn::getReturn_id).collect(Collectors.toList()); + List return_ids = order_return_rows.stream() + .map(ShopOrderReturn::getReturn_id) + .collect(Collectors.toList()); QueryWrapper returnItemQueryWrapper = new QueryWrapper<>(); returnItemQueryWrapper.in("order_item_id", order_item_ids) @@ -471,13 +481,14 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl shopOrderReturnItems = new ArrayList<>(); for (OrderReturnItemInputVo returnItemInputVo : orderReturnInputVo.getReturn_items()) { + // 获取订单商品信息 ShopOrderItem shopOrderItem = shopOrderItemService.get(returnItemInputVo.getOrder_item_id()); - if (shopOrderItem == null) { throw new ApiException(I18nUtil._("此订单商品订单数据有误!")); } - ShopProductIndex shopProductIndex = shopProductIndexService.get(shopOrderItem.getProduct_id()); + // 获取商品索引信息 + ShopProductIndex shopProductIndex = shopProductIndexService.get(shopOrderItem.getProduct_id()); if (shopProductIndex == null) { throw new ApiException(I18nUtil._("此订单商品数据有误!")); } + // 检查是否允许退货 boolean is_denyreturn = ifDenyReturn(shopOrderInfo, shopOrderItem, shopProductIndex); if (is_denyreturn) { throw new ApiException(I18nUtil._("此商品不允许退货!")); } + + // 构建退款单明细 ShopOrderReturnItem orderReturnItem = new ShopOrderReturnItem(); Integer return_item_num = returnItemInputVo.getReturn_item_num(); @@ -536,61 +552,43 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl return_ids, Integer store_id, Integer return_state_id, List return_rows, Integer return_next_state_id) { @@ -1434,15 +1439,17 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl orderItemQueryWrapper = new QueryWrapper<>(); orderItemQueryWrapper.eq("order_id", order_id); List orderItemList = shopOrderItemService.find(orderItemQueryWrapper); + // 累计订单项支付总金额 - BigDecimal order_item_payment_amount = orderItemList.stream().map(s -> s.getOrder_item_payment_amount()).reduce(BigDecimal::add).get(); + BigDecimal order_item_payment_amount = BigDecimal.ZERO; + if (CollUtil.isNotEmpty(orderItemList)) { + order_item_payment_amount = orderItemList.stream() + .map(ShopOrderItem::getOrder_item_payment_amount) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } // 当前已经同意退款额度 = 所有单品退款额度 QueryWrapper returnItemQueryWrapper = new QueryWrapper<>(); - returnItemQueryWrapper.eq("order_id", order_id).in("return_state_id", StateCode.RETURN_PROCESS_RECEIVED, StateCode.RETURN_PROCESS_REFUND, StateCode.RETURN_PROCESS_RECEIPT_CONFIRMATION, StateCode.RETURN_PROCESS_FINISH); + returnItemQueryWrapper.eq("order_id", order_id) + .in("return_state_id", Arrays.asList( + StateCode.RETURN_PROCESS_RECEIVED, + StateCode.RETURN_PROCESS_REFUND, + StateCode.RETURN_PROCESS_RECEIPT_CONFIRMATION, + StateCode.RETURN_PROCESS_FINISH)); List returnItemList = orderReturnItemService.find(returnItemQueryWrapper); - BigDecimal return_item_subtotal = returnItemList.stream().map(s -> s.getReturn_item_subtotal()).reduce(BigDecimal::add).get(); + + BigDecimal return_item_subtotal = BigDecimal.ZERO; + if (CollUtil.isNotEmpty(returnItemList)) { + return_item_subtotal = returnItemList.stream() + .map(ShopOrderReturnItem::getReturn_item_subtotal) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + } // 订单所有商品退款的情况 - if (ObjectUtil.compare(order_item_payment_amount, return_item_subtotal) == 0) { + if (order_item_payment_amount.compareTo(return_item_subtotal) == 0) { + logger.debug("订单所有商品均已退款,订单ID: {}", order_id); ShopOrderData shopOrderData = new ShopOrderData(); shopOrderData.setOrder_id(order_id); shopOrderData.setOrder_refund_status(2); //退款状态:0-是无退款;1-是部分退款;2-是全部退款 if (!shopOrderDataService.edit(shopOrderData)) { + logger.error("修改订单退款状态失败!订单ID: {}", order_id); throw new ApiException(ResultCode.FAILED); } // 取消订单 ShopOrderInfo info_row = shopOrderInfoService.get(order_id); + if (info_row == null) { + logger.error("获取订单信息失败!订单ID: {}", order_id); + throw new ApiException(I18nUtil._("订单信息不存在!")); + } + // 当前订单状态 Integer order_state_id = info_row.getOrder_state_id(); // 没有发货没有完成订单之前,允许取消订单和退运费 - if (!Arrays.asList(StateCode.ORDER_STATE_SHIPPED, StateCode.ORDER_STATE_RECEIVED, StateCode.ORDER_STATE_FINISH).contains(order_state_id)) { - + List forbiddenStates = Arrays.asList( + StateCode.ORDER_STATE_SHIPPED, + StateCode.ORDER_STATE_RECEIVED, + StateCode.ORDER_STATE_FINISH); + if (order_state_id != null && !forbiddenStates.contains(order_state_id)) { // 取消订单,更改订单的状态为已取消 shopOrderBaseService.cancel(order_id, info_row, false); - // logger.info("全部退款完成,取消订单:{}", order_id); + logger.info("全部退款完成,订单已取消:{}", order_id); // 未发货,退运费 - 判断运费是否存在 ShopOrderData order_data_row = shopOrderDataService.get(order_id); // 如果有打包费,最后的退款订单的退款金额加上 打包费 - if (order_data_row != null && order_data_row.getPacking_fee().compareTo(BigDecimal.ZERO) > 0) { + if (order_data_row != null && + order_data_row.getPacking_fee() != null && + order_data_row.getPacking_fee().compareTo(BigDecimal.ZERO) > 0) { // 退款金额+打包费 - BigDecimal order_refund_amount_add_fee = NumberUtil.add(order_data_row.getOrder_refund_amount(), order_data_row.getPacking_fee()); + BigDecimal order_refund_amount_add_fee = NumberUtil.add( + order_data_row.getOrder_refund_amount(), + order_data_row.getPacking_fee()); // 最后一个退款订单如果有打包费,加上打包费 return_row.setReturn_refund_amount(order_refund_amount_add_fee); + logger.debug("已添加打包费到退款金额,订单ID: {}", order_id); } // 有运费的订单 - if (order_data_row != null && order_data_row.getOrder_shipping_fee().compareTo(BigDecimal.ZERO) > 0) { + if (order_data_row != null && + order_data_row.getOrder_shipping_fee() != null && + order_data_row.getOrder_shipping_fee().compareTo(BigDecimal.ZERO) > 0) { // 运费大于0的, 执行退运费操作, 有两种方案,1、生成退运费售后服务单; 2、直接执行退款 // 1、生成独立退运费售后服务单,需注意运费是退给运费代理商的,需要获取代理商的交易单号 @@ -1544,8 +1595,8 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl returnOrder = new ArrayList<>(); - returnOrder.addAll(return_rows); + if (return_rows != null) { + returnOrder.addAll(return_rows); + } if (return_order_shipping_fee_row != null) { returnOrder.add(return_order_shipping_fee_row); } + // 重要:执行退款操作 if (!payService.doRefund(returnOrder)) { + logger.error("执行退款操作失败!退单列表: {}", return_ids); throw new ApiException(ResultCode.FAILED); } + logger.info("退款操作执行成功,退单列表: {}", return_ids); + + // 更新退货单的退款完成状态和完成时间 + ShopOrderReturn updateRefundStatus = new ShopOrderReturn(); + updateRefundStatus.setReturn_is_paid(1); // 0-退货未完成;1-退货完成 + updateRefundStatus.setReturn_finish_time(now); + + QueryWrapper updateWrapper = new QueryWrapper<>(); + updateWrapper.in("return_id", return_ids); + if (!edit(updateRefundStatus, updateWrapper)) { + logger.error("更新退货单退款状态失败!退货单列表: {}", return_ids); + throw new ApiException(ResultCode.FAILED); + } + } return true; @@ -2195,7 +2268,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl itemQueryWrapper = new QueryWrapper<>(); itemQueryWrapper.eq("order_id", orderId); List allOrderItems = shopOrderItemService.find(itemQueryWrapper); if (CollectionUtil.isEmpty(allOrderItems)) { + logger.warn("订单剩余商品退款申请失败:订单商品表为空,订单ID: {}", orderId); throw new ApiException(I18nUtil._("订单商品表为空!")); } + logger.info("获取订单商品列表成功,共 {} 个商品,订单ID: {}", allOrderItems.size(), orderId); + // 获取已申请退款的商品ID列表 - Set refundedItemIds = getRefundedItemIds(orderId); + logger.debug("开始查询已退款商品ID列表,订单ID: {}", orderId); + Set refundedItemIds = getRefundFinishedItemIds(orderId); + logger.debug("已退款商品数量: {},订单ID: {}", refundedItemIds.size(), orderId); // 筛选出尚未申请退款的商品 + logger.debug("筛选未退款商品,订单ID: {}", orderId); List remainingItems = allOrderItems.stream() .filter(item -> !refundedItemIds.contains(item.getOrder_item_id())) .collect(Collectors.toList()); if (CollectionUtil.isEmpty(remainingItems)) { + logger.warn("订单剩余商品退款申请失败:订单中所有商品均已申请退款,订单ID: {}", orderId); throw new ApiException(I18nUtil._("订单中所有商品均已申请退款!")); } + logger.info("筛选出未退款商品 {} 个,准备创建退款申请,订单ID: {}", remainingItems.size(), orderId); + // 生成退款单 + logger.debug("构建退款申请参数,订单ID: {}", orderId); OrderReturnInputVo orderReturnInputVo = new OrderReturnInputVo(); orderReturnInputVo.setOrder_id(orderId); orderReturnInputVo.setReturn_tel(""); @@ -2254,6 +2351,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl 已申请退款的商品ID集合 */ - private Set getRefundedItemIds(String orderId) { + private Set getRefundFinishedItemIds(String orderId) { Set refundedItemIds = new HashSet<>(); // 查询该订单所有未取消的退款单 QueryWrapper returnQueryWrapper = new QueryWrapper<>(); returnQueryWrapper.eq("order_id", orderId) - .ne("return_state_id", StateCode.RETURN_PROCESS_CANCEL); + .eq("return_state_id", StateCode.RETURN_PROCESS_FINISH); List shopOrderReturns = find(returnQueryWrapper); if (CollectionUtil.isNotEmpty(shopOrderReturns)) { 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 124aee9c..322b6039 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 @@ -826,37 +826,37 @@ public class SFExpressApiServiceImpl implements SFExpressApiService { public ThirdApiRes receiveCancelOrderNotify(String jsonData, String sign) { // 参数校验 if (StrUtil.isBlank(jsonData) || StrUtil.isBlank(sign)) { - logger.warn("[顺丰订单取消回调] 缺少必要参数: jsonData或sign为空"); + logger.warn("[顺丰订单取消回调通知] 缺少必要参数: jsonData或sign为空"); return new ThirdApiRes().fail(1003, "缺少必要参数!"); } // 签名校验 if (!checkOpenSign(sign, jsonData)) { - logger.warn("[顺丰订单取消回调] 请求签名sign校验失败"); + logger.warn("[顺丰订单取消回调通知] 请求签名sign校验失败"); return new ThirdApiRes().fail(2002, "请求签名sign校验失败!"); } - logger.info("[顺丰订单取消回调] 接收回调数据: {}", jsonData); + logger.info("[顺丰订单取消回调通知] 接收回调数据: {}", jsonData); try { // 解析并更新顺丰同城订单状态 ShopStoreSfOrder shopStoreSfOrder = toShopStoreSfOrder(jsonData); if (shopStoreSfOrder == null) { - logger.error("[顺丰订单取消回调] 解析订单数据失败: jsonData={}", jsonData); + logger.error("[顺丰订单取消回调通知] 解析订单数据失败: jsonData={}", jsonData); return new ThirdApiRes().fail(-1, "订单数据解析失败!"); } String shopOrderId = shopStoreSfOrder.getShop_order_id(); String sfOrderId = shopStoreSfOrder.getSf_order_id(); - logger.info("[顺丰订单取消回调] 处理订单取消: shopOrderId={} sfOrderId={}", shopOrderId, sfOrderId); + logger.info("[顺丰订单取消回调通知] 处理订单取消: shopOrderId={} sfOrderId={}", shopOrderId, sfOrderId); // 判断订单的状态,是否已经取消了?已取消,不再执行 ShopStoreSfOrder shopStoreSfOrderExist = shopStoreSfOrderService.getBySfOrderId(sfOrderId); if (shopStoreSfOrderExist != null && shopStoreSfOrderExist.getOrder_status() != null && (ObjectUtil.equal(shopStoreSfOrderExist.getOrder_status(), StateCode.SF_ORDER_STATUS_CANCELED) || ObjectUtil.equal(shopStoreSfOrderExist.getOrder_status(), StateCode.SF_ORDER_STATUS_CANCELING))) { - logger.info("[顺丰订单取消回调] 订单已处于取消状态,无需重复处理: sfOrderId={} status={}", + logger.info("[顺丰订单取消回调通知] 订单已处于取消状态,无需重复处理: sfOrderId={} status={}", sfOrderId, shopStoreSfOrderExist.getOrder_status()); return new ThirdApiRes().success("success"); } @@ -864,18 +864,18 @@ public class SFExpressApiServiceImpl implements SFExpressApiService { // 更新顺丰订单状态 Boolean success = shopStoreSfOrderService.updateShopStoreSfOrderStatus(shopStoreSfOrder); if (!success) { - logger.error("[顺丰订单取消回调] 更新顺丰订单状态失败: sfOrderId={}", sfOrderId); + logger.error("[顺丰订单取消回调通知] 更新顺丰订单状态失败: sfOrderId={}", sfOrderId); return new ThirdApiRes().fail(-1, "状态处理失败!"); } - logger.debug("[顺丰订单取消回调] 顺丰订单状态更新成功: sfOrderId={}", sfOrderId); + logger.debug("[顺丰订单取消回调通知] 顺丰订单状态更新成功: sfOrderId={}", sfOrderId); // 重要:更改商城订单状态为:已取消,注意事务问题 success = shopOrderReturnService.sfExpressExpiredForceRefund(shopOrderId); if (!success) { - logger.error("[顺丰订单取消回调] 取消商城订单业务处理失败: shopOrderId={}", shopOrderId); + logger.error("[顺丰订单取消回调通知] 取消商城订单业务处理失败: shopOrderId={}", shopOrderId); return new ThirdApiRes().fail(-1, "取消订单业务处理失败!"); } - logger.debug("[顺丰订单取消回调] 商城订单取消处理成功: shopOrderId={}", shopOrderId); + logger.debug("[顺丰订单取消回调通知] 商城订单取消处理成功: shopOrderId={}", shopOrderId); // 获取顺丰同城的物流轨迹 Map params = new HashMap<>(); @@ -885,7 +885,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService { JSONObject result = JSONUtil.parseObj(feedRes.getResult()); if (result != null && result.get("feed") != null) { shopStoreSfOrder.setFeed(JSONUtil.toJsonStr(result.get("feed"))); - logger.debug("[顺丰订单取消回调] 获取物流轨迹成功: sfOrderId={}", sfOrderId); + logger.debug("[顺丰订单取消回调通知] 获取物流轨迹成功: sfOrderId={}", sfOrderId); } } @@ -894,12 +894,11 @@ public class SFExpressApiServiceImpl implements SFExpressApiService { payload.put("category", CommonConstant.PUSH_MSG_CATE_MCH_ORDER_DETAIL); payload.put("orderId", shopOrderId); pushMessageService.noticeMerchantEmployeeOrderAction(null, shopOrderId, "您有一笔取消订单", "您有一笔取消订单[" + shopOrderId + "],请及时处理。", payload); - logger.info("[顺丰订单取消回调] 推送消息完成: shopOrderId={}", shopOrderId); - - logger.info("[顺丰订单取消回调] 处理完成: shopOrderId={} sfOrderId={}", shopOrderId, sfOrderId); + + logger.info("[顺丰订单取消回调通知] 处理完成: shopOrderId={} sfOrderId={}", shopOrderId, sfOrderId); return new ThirdApiRes().success("success"); } catch (Exception e) { - logger.error("[顺丰订单取消回调] 处理过程中发生异常", e); + logger.error("[顺丰订单取消回调通知] 处理过程中发生异常", e); return new ThirdApiRes().fail(-1, "系统处理异常: " + e.getMessage()); } } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreBaseServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreBaseServiceImpl.java index 5a4a8066..d073d415 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreBaseServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/service/impl/ShopStoreBaseServiceImpl.java @@ -2375,7 +2375,7 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl 0) { @@ -2385,9 +2385,11 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl 0) { @@ -2556,6 +2553,13 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl redisTemplate; +// @Autowired +// private RedisTemplate redisTemplate; @Override public Map getMsgCount() { @@ -88,30 +87,22 @@ public class SnsUserMessageServiceImpl extends BaseServiceImpl queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("user_id", userId).eq("message_kind", 2).eq("message_is_read", 0); - unreadCount = count(queryWrapper); - // 设置计数器,过期时间1小时 - redisTemplate.opsForValue().set(counterKey, unreadCount, 3600, TimeUnit.SECONDS); - } + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("user_id", userId).eq("message_kind", 2).eq("message_is_read", 0); + long num = count(queryWrapper); - rs.put("num", unreadCount); + rs.put("num", num); // 构造最后一个用户聊天网址 - if (unreadCount > 0) { + if (num > 0) { QueryWrapper messageQuery = new QueryWrapper<>(); messageQuery.orderByAsc("message_is_read").orderByDesc("message_time") .eq("user_id", userId).eq("message_is_read", 0).eq("message_kind", 2); @@ -132,8 +123,8 @@ public class SnsUserMessageServiceImpl extends BaseServiceImpl messagesToUpdate = find(queryWrapper); - long unreadToUpdate = messagesToUpdate.stream() - .filter(m -> m.getMessage_is_read() == 0) - .count(); - SnsUserMessage userMessage = new SnsUserMessage(); userMessage.setMessage_is_read(1); - boolean result = saveOrUpdate(userMessage, queryWrapper); - - // 更新未读计数器和缓存 - if (result && unreadToUpdate > 0) { - String counterKey = "sns:user:message:unread:counter:" + user_id; - String cacheKey = "sns:user:message:unread:" + user_id; - - // 减少计数器 - redisTemplate.opsForValue().increment(counterKey, -unreadToUpdate); - // 删除缓存,下次请求会重新生成 - redisTemplate.delete(cacheKey); - } - - return result; + saveOrUpdate(userMessage, queryWrapper); + return true; } @Override @@ -737,11 +712,14 @@ public class SnsUserMessageServiceImpl extends BaseServiceImplopenjdk:8-jre - - - ["sh", "-c", "mkdir -p /tmp /app/temp /root/nacos/naming/public && chmod -R 777 /tmp /app/temp /root/nacos && java -Djava.io.tmpdir=/app/temp -Dnacos.naming.cache.dir=/root/nacos/naming -jar -Xms256m -Xmx512m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseContainerSupport -XX:MaxRAMPercentage=60.0 -XX:+UseSerialGC -XX:MinHeapFreeRatio=40 -XX:MaxHeapFreeRatio=60 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:./gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M -Dspring.profiles.active=${spring.profile} -Duser.timezone=Asia/Shanghai /${project.build.finalName}.jar"]