From 7b369442ffafee58177af2081aff0d60c25dfc91 Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Wed, 20 Aug 2025 00:17:15 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=85=A5=E9=A9=BB=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/common/utils/DateTimeUtils.java | 39 +++++++++++++++ .../common/utils/RestTemplateHttpUtil.java | 42 +++++++++------- .../service/impl/LakalaApiServiceImpl.java | 6 +-- .../service/impl/LklLedgerEcServiceImpl.java | 6 ++- .../lakala/service/impl/LklTkServiceImpl.java | 48 ++++++++++--------- .../mobile/ShopMchEntryController.java | 2 +- .../service/impl/ShopMchEntryServiceImpl.java | 34 +++++++++---- 7 files changed, 123 insertions(+), 54 deletions(-) diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/DateTimeUtils.java b/mall-common/src/main/java/com/suisung/mall/common/utils/DateTimeUtils.java index d9a17194..336dcf89 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/utils/DateTimeUtils.java +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/DateTimeUtils.java @@ -1,6 +1,7 @@ package com.suisung.mall.common.utils; import lombok.extern.slf4j.Slf4j; +import org.springframework.data.util.Pair; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -51,6 +52,12 @@ public class DateTimeUtils { * 特殊值:空值、"长期"、"永久" 转9999-12-31 */ public static String convertLklDate(String dateStr) { + // 先验证是否符合格式,符合直接返回,不符合,进行处理返回符合的格式 + Pair isValid = isValidDateFormat(dateStr); + if (isValid.getFirst()) { + return isValid.getSecond(); + } + String DEFAULT_FUTURE_DATE = "9999-12-31"; if (dateStr == null || dateStr.trim().isEmpty()) { return DEFAULT_FUTURE_DATE; @@ -153,6 +160,37 @@ public class DateTimeUtils { } } + /** + * 判断字符串是否符合 yyyy-MM-dd 格式,将"长期"、"永久"、"9999-12-31"列入白名单 + * + * @param dateStr 日期字符串 + * @return true: 符合格式或在白名单中, false: 不符合格式 + */ + public static Pair isValidDateFormat(String dateStr) { + // 空值检查 + if (dateStr == null || dateStr.trim().isEmpty()) { + return Pair.of(false, ""); + } + + // 白名单检查 + if ("长期".equals(dateStr) || "永久".equals(dateStr) || "9999-12-31".equals(dateStr)) { + return Pair.of(true, "9999-12-31"); + } + + // 格式检查 (yyyy-MM-dd) 长度为10,第5位和第8位为'-' + if (dateStr.length() != 10 || dateStr.charAt(4) != '-' || dateStr.charAt(7) != '-') { + return Pair.of(false, dateStr); + } + + try { + // 使用 LocalDate.parse 验证日期有效性 + LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE); + return Pair.of(true, dateStr); + } catch (DateTimeException e) { + return Pair.of(false, dateStr); + } + } + /** * 计算字符串中某个字符的出现次数 */ @@ -179,6 +217,7 @@ public class DateTimeUtils { System.out.println(convertLklDate("25.1.2")); // 2025-01-02 System.out.println(convertLklDate("25.01.02")); // 2025-01-02 System.out.println(convertLklDate("长期")); // 9999-12-31 + System.out.println(convertLklDate("永久")); // 9999-12-31 System.out.println(convertLklDate(null)); // 9999-12-31 System.out.println(convertLklDate("2025.2.30")); // 9999-12-31(无效日期) } diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/RestTemplateHttpUtil.java b/mall-common/src/main/java/com/suisung/mall/common/utils/RestTemplateHttpUtil.java index 91c35d15..de99feb6 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/utils/RestTemplateHttpUtil.java +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/RestTemplateHttpUtil.java @@ -8,8 +8,11 @@ package com.suisung.mall.common.utils; +import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.*; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -19,6 +22,7 @@ import java.util.Map; public class RestTemplateHttpUtil { private static final RestTemplate restTemplate = new RestTemplate(); + private static final Logger log = LoggerFactory.getLogger(RestTemplateHttpUtil.class); /** * 发送 GET 请求 @@ -200,33 +204,34 @@ public class RestTemplateHttpUtil { // 处理成功的响应 if (response.getStatusCode() == HttpStatus.OK) { JSONObject result = new JSONObject(); - result.set("retCode", "000000"); - result.set("retMsg", "请求成功"); - // 如果响应体是JSONObject类型,解析其中的retCode和retMsg - if (response.getBody() instanceof JSONObject) { - JSONObject responseBody = (JSONObject) response.getBody(); - // 尝试获取返回码和消息 - String[] codeFields = {"retCode", "ret_code", "code", "code"}; - String[] msgFields = {"retMsg", "ret_msg", "msg", "message"}; + // 统一处理响应体 + Object body = response.getBody(); + JSONObject responseBody = (body instanceof JSONObject) ? (JSONObject) body : JSONUtil.parseObj(body); - String retCode = findFirstNonNullValue(responseBody, codeFields); - String retMsg = findFirstNonNullValue(responseBody, msgFields); - if (retCode != null) result.set("retCode", retCode); - if (retMsg != null) result.set("retMsg", retMsg); + log.info("####拉卡拉接口响应结果: {}", responseBody); - result.set("respData", responseBody); - } else if (response.getBody() != null) { - result.set("respData", response.getBody().toString()); - } + // 尝试获取返回码、消息和数据 + String[] codeFields = {"retCode", "ret_code", "code"}; + String[] msgFields = {"retMsg", "ret_msg", "msg", "message"}; + String[] dataFields = {"respData", "resp_data", "data"}; + String retCode = findFirstNonNullValue(responseBody, codeFields); + String retMsg = findFirstNonNullValue(responseBody, msgFields); + String respData = findFirstNonNullValue(responseBody, dataFields); + + result.set("retCode", StrUtil.isBlank(retCode) ? "000000" : retCode); + result.set("retMsg", StrUtil.isBlank(retMsg) ? "" : retMsg); + result.set("respData", StrUtil.isBlank(respData) ? null : JSONUtil.parseObj(respData)); + result.set("rawData", responseBody); return result; } else { // 处理其他HTTP状态码 JSONObject result = new JSONObject(); result.set("retCode", String.valueOf(response.getStatusCode().value())); result.set("retMsg", "HTTP状态码: " + response.getStatusCode().getReasonPhrase()); + result.set("rawData", response.getBody()); return result; } } catch (org.springframework.web.client.HttpClientErrorException e) { @@ -240,6 +245,7 @@ public class RestTemplateHttpUtil { JSONObject result = new JSONObject(); result.set("retCode", "500"); result.set("retMsg", "请求异常: " + e.getMessage()); + result.set("rawData", ""); return result; } } @@ -296,14 +302,16 @@ public class RestTemplateHttpUtil { result.set("retMsg", cn.hutool.core.util.StrUtil.isNotBlank(retMsg) ? retMsg : "请求失败: " + e.getStatusText()); // 保留原始错误信息 - result.set("rawError", errorResponse); + result.set("rawData", errorResponse); } else { result.set("retCode", statusCode); result.set("retMsg", "请求失败: " + e.getStatusText()); + result.set("rawData", ""); } } catch (Exception parseException) { result.set("retCode", statusCode); result.set("retMsg", "请求失败,无法解析错误响应: " + e.getMessage()); + result.set("rawData", ""); } return result; 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 ad8a5e7c..81ee7e60 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 @@ -493,7 +493,6 @@ public class LakalaApiServiceImpl implements LakalaApiService { reqBody.put("req_data", reqData); String reqUrl = serverUrl + "/api/v3/mms/open_api/ec/apply"; - //"/api/v3/mms/open_api/ec/apply"; "/api/v2/mms/openApi/ec/apply"; String privateKey = LakalaUtil.getResourceFile(priKeyPath, false, true); String authorization = LakalaUtil.genAuthorization(privateKey, appId, serialNo, reqBody.toString()); @@ -523,7 +522,7 @@ public class LakalaApiServiceImpl implements LakalaApiService { // 商家入网申请电子合同处理数据 // 先写入本地数据库表中 LklLedgerEc record = new LklLedgerEc(); - record.setMch_id(shopMchEntry.getId()); + record.setMch_id(mchId); record.setMch_mobile(contractMobile); record.setReq_params(reqBody.toString()); record.setNotify_url(retUrl); @@ -540,7 +539,7 @@ public class LakalaApiServiceImpl implements LakalaApiService { } // 更新拉卡拉的电子合同信息到商家入驻表中 - shopMchEntryService.updateMerchEntryEcResultUrlByMchId(shopMchEntry.getId(), ecResultUrl); + shopMchEntryService.updateMerchEntryEcResultUrlByMchId(mchId, ecResultUrl); // 发短信给商家,及时签署合同 SMS_488465246 // 【小发同城商家】恭喜您的开店入驻申请已审核通过!请尽快登录APP平台签署电子合同,签署链接24小时内有效(逾期需重新提交申请)。如有疑问请联系客服,感谢您的支持! @@ -1035,6 +1034,7 @@ public class LakalaApiServiceImpl implements LakalaApiService { // 更新商家分账申请状态为已申请(hasApplySplit=1) shopMchEntryService.updateMulStatus(lklLedgerMember.getMch_id(), "", merCupNo, 0, 0, 0, 1, 0, 0, CommonConstant.MCH_APPR_STA_LKL_PADDING); + shopMchEntryService.updateMerchEntryApprovalByMchId(lklLedgerMember.getMch_id(), null, "分账业务开通成功"); log.debug("商户分账业务申请回调:处理成功,applyId={}", applyId); return JSONUtil.createObj().put("code", "SUCCESS").put("message", "操作成功!"); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerEcServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerEcServiceImpl.java index 3eb530fa..dc95704b 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerEcServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerEcServiceImpl.java @@ -19,6 +19,8 @@ import com.suisung.mall.shop.lakala.mapper.LklLedgerEcMapper; import com.suisung.mall.shop.lakala.service.LklLedgerEcService; import org.springframework.stereotype.Service; +import java.util.Date; + @Service public class LklLedgerEcServiceImpl extends BaseServiceImpl implements LklLedgerEcService { @@ -35,12 +37,14 @@ public class LklLedgerEcServiceImpl extends BaseServiceImpl queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("mch_id", record.getMch_id()).eq("status", CommonConstant.Enable); + queryWrapper.eq("mch_id", record.getMch_id()) + .eq("status", CommonConstant.Enable); queryWrapper.orderByDesc("id"); LklLedgerEc existsRecord = findOne(queryWrapper); if (existsRecord != null && existsRecord.getId() > 0) { // 更新记录 + record.setUpdated_at(new Date()); record.setId(existsRecord.getId()); return updateById(record); } 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 d9be4e41..4b08c280 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 @@ -402,8 +402,8 @@ public class LklTkServiceImpl { reqJsonBody.put("accountIdCard", shopMchEntry.getLegal_person_id_number());//结算⼈证件号码(身份证) Integer SettlementMethod = shopMchEntry.getSettlement_method(); - if (SettlementMethod == null || SettlementMethod < 0 || SettlementMethod > 10) { - SettlementMethod = 0; + if (SettlementMethod == null || SettlementMethod < 0 || SettlementMethod > 1) { + SettlementMethod = 0; // 结算类型: 0-秒到;1-次日结算 } String settleType = String.format("D%d", SettlementMethod); reqJsonBody.put("settleType", settleType); //结算类型,D0秒到,D1次日结算 @@ -523,23 +523,27 @@ public class LklTkServiceImpl { JSONObject response = RestTemplateHttpUtil.sendLklPost(buildLklTkUrl(urlPath), header, reqJsonBody, JSONObject.class); logger.debug("拉卡拉进件响应参数:{}", response); - JSONObject respData = response.getJSONObject("respData"); - if (ObjectUtil.isEmpty(response) || respData == null) { - String errMsg = response.getStr("retMsg") == null ? "拉卡拉进件出现未知错误" : response.getStr("retMsg"); + if (ObjectUtil.isEmpty(response) + || response.get("retCode") == null + || !"000000".equals(response.getStr("retCode"))) { + String errMsg = response.getStr("retMsg") == null ? "拉卡拉发生未知错误" : response.getStr("retMsg"); shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_NOPASS, "进件失败:" + errMsg); return Pair.of(false, "提交进件失败:" + errMsg); } - String lklMerInnerNo = respData.getStr("merchantNo"); //拉卡拉内部商户号 + // {"merchantNo": "100132349","status": "WAIT_AUDI","state": "1"} + JSONObject rawData = response.getJSONObject("rawData"); // 进件这个接口比较特殊,不安装常规返回数据 + String lklMerInnerNo = rawData.getStr("merchantNo"); //拉卡拉内部商户号 // 表中的内部外部商户号暂时都传同一个内部商户号,以便异步通知更改记录 - Boolean success = shopMchEntryService.updateMerchEntryLklMerCupNo(mchId, CommonConstant.Disable2, lklMerInnerNo, lklMerInnerNo, reqJsonBody.toString(), respData.toString()); + Boolean success = shopMchEntryService.updateMerchEntryLklMerCupNo(mchId, CommonConstant.Disable2, lklMerInnerNo, lklMerInnerNo, reqJsonBody.toString(), rawData.toString()); if (!success) { shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_NOPASS, "进件成功,但更新商户号失败!"); return Pair.of(false, "提交进件成功,但更新商户号失败!"); + } } catch (Exception e) { @@ -550,7 +554,7 @@ public class LklTkServiceImpl { } - shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_NOPASS, "商户进件:提交进件成功,请等待审核!"); + shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_PADDING, "商户进件:提交进件成功,请等待审核!"); return Pair.of(true, "提交进件成功,请等待审核!"); } @@ -606,7 +610,13 @@ public class LklTkServiceImpl { 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 + "内部商户号入驻信息不存在"); + } + // 校验审核状态 if (!"SUCCESS".equals(auditStatus) && !"REVIEW_PASS".equals(auditStatus)) { @@ -617,17 +627,11 @@ public class LklTkServiceImpl { // RMK 拉卡拉进价提交成功,边处理周边的数据,边等待审核异步通知 - // 给商家入驻表增加拉卡拉的商户号和拉卡拉返回的数据 - - if (shopMchEntry == null) { - logger.error("拉卡拉进件异步通知:{}内部商户号入驻信息不存在!", merInnerNo); - return new JSONObject().put("code", "500").put("message", merInnerNo + "内部商户号入驻信息不存在"); - } - Boolean success = shopMchEntryService.updateMerchEntryLklAuditStatusByLklMerCupNo( merInnerNo, merCupNo, termNos, CommonConstant.Enable, null, data); if (!success) { + shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_NOPASS, "进件时更新商户号失败"); return new JSONObject().set("code", "500").set("message", "更新商户号失败"); } @@ -649,25 +653,19 @@ public class LklTkServiceImpl { if (success && StrUtil.isNotBlank(shopMchEntry.getContract_download_url())) { // TODO 新建一个正式的已审核通过的店铺, 新建之前判断是否已经新建过了? - // 新建一个正式的已审核通过的店铺,不要抛异常,使用补偿机制,可以独立初始化店铺 ShopMchEntry shopEntry = shopMchEntryService.getShopMerchEntryByMerCupNo(merCupNo); if (shopEntry != null && !CommonConstant.Enable.equals(shopEntry.getStore_status())) { Long mchId = shopEntry.getId(); + // 新建一个正式的已审核通过的店铺,不要抛异常,使用补偿机制,可以独立初始化店铺 // 重要:包含了更改 merchEntryInfo 的状态 TODO 用法人、小微个人的手机号注册商家账号,作为店铺的管理员 Pair retPair = shopStoreBaseService.covMerchEntryInfo2StoreInfo(mchId, false); if (retPair.getFirst() <= 0) { + shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), null, "进件时初始化店铺失败"); logger.error("初始化店铺失败: mchId={}, reason={}", mchId, retPair.getSecond()); } logger.info("初始化店铺成功!mchId={}", mchId); - -// boolean updateSuccess = shopMchEntryService.updateMulStatus(mchMobile, "", 0, 0, 1, 0, 0, 0, CommonConstant.MCH_APPR_STA_LKL_PADDING); -// if (!updateSuccess) { -// logger.warn("更新店铺状态失败: mchMobile={}", mchMobile); -// } else { -// logger.info("商家进件:初始化店铺成功!mchMobile={}", mchMobile); -// } } // 1、(电子合同)给商家申请分账功能使用;务必检查是否申请过?申请过忽略 @@ -678,21 +676,25 @@ public class LklTkServiceImpl { // 统一处理分账申请结果 if (retPair.getFirst() && genSuccess) { + shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_PADDING, "成功申请分账功能"); return new JSONObject().put("code", "200").put("message", "处理成功"); } if (!retPair.getFirst()) { String message = "商家申请分账功能失败:" + retPair.getSecond(); logger.error(message); + shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), null, message); return new JSONObject().set("code", "500").set("message", message); } if (!genSuccess) { logger.error("申请分账接收方失败"); + shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), null, "申请分账接收方失败"); return new JSONObject().set("code", "500").set("message", "申请分账接收方失败"); } } + shopMchEntryService.updateMerchEntryApprovalByMchId(shopMchEntry.getId(), CommonConstant.MCH_APPR_STA_LKL_NOPASS, "进件回调处理失败"); return new JSONObject().set("code", "500").set("message", "进件回调处理失败"); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopMchEntryController.java b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopMchEntryController.java index d429a5e9..2aa1bf4f 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopMchEntryController.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/store/controller/mobile/ShopMchEntryController.java @@ -53,7 +53,7 @@ public class ShopMchEntryController extends BaseControllerImpl { return shopMchEntryService.storeBusinessCategoryList(); } - @ApiOperation(value = "商家申请入驻商城平台", notes = "商家申请入驻商城平台") + @ApiOperation(value = "商家申请入驻小发同城平台", notes = "商家申请入驻小发同城平台") @RequestMapping(value = "/apply", method = RequestMethod.POST) public CommonResult shopMerchEntryApply(@RequestBody JSONObject shopMerchEntryJSON) { return shopMchEntryService.shopMerchEntryApply(shopMerchEntryJSON); 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 5e5a1bee..ee33e9eb 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 @@ -262,7 +262,6 @@ public class ShopMchEntryServiceImpl extends BaseServiceImpl updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("id", mchId) // 根据商家入驻申请 ID 进行匹配 - .set("lkl_ec_result_url", lklEcResultUrl); // 设置拉卡拉电子合同结果 URL + .set("lkl_ec_result_url", lklEcResultUrl) // 设置拉卡拉电子合同结果 URL + .set("approval_remark", "请引导商家签署电子合同!"); // 执行更新操作 return update(updateWrapper);