From d87cd066de1e52cdbf39754fb79eacf7452fad36 Mon Sep 17 00:00:00 2001 From: DB <2502523450@qq.com> Date: Tue, 16 Jan 2024 22:30:49 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=91=E5=9B=9E=E8=B0=83=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E4=B8=8E=E7=AD=96=E7=95=A5=E8=B0=83=E7=94=A8?= =?UTF-8?q?;=E8=BD=AE=E6=92=AD=E5=9B=BE;=E6=95=B0=E6=8D=AE=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E8=B0=83=E6=95=B4;=E7=99=BD=E5=90=8D=E5=8D=95?= =?UTF-8?q?=E8=B7=AF=E5=BE=84=E8=AF=B7=E6=B1=82=E6=A0=A1=E9=AA=8C;?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=9B=B4=E6=96=B0=E6=A0=A1=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/cloudDb/core/dto/CloudStoreDto.java | 51 ++++++ .../handler/CloudDataImportHandler.java | 18 ++ .../cloudDb/handler/CloudStoreHandler.java | 64 +++++++ .../cpop/core/annontation/SignatureCheck.java | 15 ++ .../annontation/SimpleSignatureCheck.java | 15 ++ .../core/aspect/SignatureCheckAspect.java | 148 ++++++++++++++++ .../aspect/SimpleSignatureCheckAspect.java | 138 +++++++++++++++ .../cpop/core/base/entity/CpopSignBase.java | 33 ++++ .../java/com/cpop/core/utils/RsaUtils.java | 47 ++++- .../src/main/resources/mapper/CoreMapper.xml | 3 + .../com/cpop/generator/CpopGenerator.java | 6 +- .../business/bo/CardTemplateUnionBo.java | 135 +++++++++++++++ .../backstage/CardTemplateController.java | 15 ++ .../backstage/EasyLearnController.java | 5 +- .../jambox/business/entity/CardTemplate.java | 16 +- .../business/service/CardTemplateService.java | 13 +- .../service/EasyLearnOrderService.java | 6 +- .../service/impl/CardTemplateServiceImpl.java | 45 ++++- .../impl/EasyLearnOrderServiceImpl.java | 8 +- .../src/main/resources/application-dev.yml | 9 +- .../mall/web/CpopMallWebApplicationTests.java | 4 +- .../com/cpop/mall/business/bo/CarouselBo.java | 55 ++++++ .../BackstageCarouselController.java | 132 ++++++++++++++ .../mini/MiniProductController.java | 23 +++ .../cpop/mall/business/entity/Carousel.java | 74 ++++++++ .../mall/business/mapper/CarouselMapper.java | 14 ++ .../business/service/CarouselService.java | 41 +++++ .../service/impl/CarouselServiceImpl.java | 79 +++++++++ .../service/impl/ProductServiceImpl.java | 12 +- .../cpop/mall/business/vo/CarouselListVo.java | 41 +++++ .../cpop/mall/business/vo/CarouselPageVo.java | 54 ++++++ .../mall/business/vo/ProductSimpleVo.java | 25 +++ .../main/resources/mapper/CarouselMapper.xml | 7 + .../src/main/resources/application-dev.yml | 4 +- .../java/com/cpop/oam/web/CpopApiTests.java | 12 +- .../java/com/cpop/oam/web/CpopCoreTests.java | 35 +++- .../com/cpop/oam/web/CpopDataSyncTests.java | 62 +++++++ .../com/cpop/oam/web/CpopImportTests.java | 4 +- Cpop-Oam/pom.xml | 4 - .../oam/business/bo/CloudUnionCallbackBo.java | 163 ++++++++++++++++++ .../controller/backstage/WxPayController.java | 1 - .../callback/CloudCallbackController.java | 42 +++++ .../service/impl/BusinessServiceImpl.java | 6 +- .../service/impl/DataImportServiceImpl.java | 21 +-- .../service/impl/TaskServiceImpl.java | 2 +- .../framework/enums/CloudCallbackEnums.java | 50 ++++++ .../strategy/cloud/CloudCallbackStrategy.java | 19 ++ .../CloudDataImportCallbackStrategy.java | 43 +++++ ...CloudSyncBrandOrStoreCallbackStrategy.java | 84 +++++++++ Cpop-System/pom.xml | 4 + .../com/cpop/system/business/bo/StoreBo.java | 60 +++++++ .../cpop/system/business/bo/StoreRenewBo.java | 5 +- .../business/controller/StoreController.java | 15 ++ .../controller/SysCommonController.java | 1 + .../cpop/system/business/entity/Store.java | 4 +- .../system/business/service/StoreService.java | 9 + .../service/impl/StoreRenewServiceImpl.java | 26 ++- .../service/impl/StoreServiceImpl.java | 33 +++- .../cpop/system/business/vo/StorePageVo.java | 6 + 59 files changed, 1966 insertions(+), 100 deletions(-) create mode 100644 Cpop-Api/src/main/java/com/cpop/api/cloudDb/core/dto/CloudStoreDto.java create mode 100644 Cpop-Api/src/main/java/com/cpop/api/cloudDb/handler/CloudDataImportHandler.java create mode 100644 Cpop-Api/src/main/java/com/cpop/api/cloudDb/handler/CloudStoreHandler.java create mode 100644 Cpop-Core/src/main/java/com/cpop/core/annontation/SignatureCheck.java create mode 100644 Cpop-Core/src/main/java/com/cpop/core/annontation/SimpleSignatureCheck.java create mode 100644 Cpop-Core/src/main/java/com/cpop/core/aspect/SignatureCheckAspect.java create mode 100644 Cpop-Core/src/main/java/com/cpop/core/aspect/SimpleSignatureCheckAspect.java create mode 100644 Cpop-Core/src/main/java/com/cpop/core/base/entity/CpopSignBase.java create mode 100644 Cpop-Jambox/src/main/java/com/cpop/jambox/business/bo/CardTemplateUnionBo.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/bo/CarouselBo.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/controller/backstage/BackstageCarouselController.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/entity/Carousel.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/mapper/CarouselMapper.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/service/CarouselService.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/CarouselServiceImpl.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/vo/CarouselListVo.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/vo/CarouselPageVo.java create mode 100644 Cpop-Mall/src/main/java/com/cpop/mall/business/vo/ProductSimpleVo.java create mode 100644 Cpop-Mall/src/main/resources/mapper/CarouselMapper.xml create mode 100644 Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopDataSyncTests.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/business/bo/CloudUnionCallbackBo.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/business/controller/callback/CloudCallbackController.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/framework/enums/CloudCallbackEnums.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudCallbackStrategy.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudDataImportCallbackStrategy.java create mode 100644 Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudSyncBrandOrStoreCallbackStrategy.java create mode 100644 Cpop-System/src/main/java/com/cpop/system/business/bo/StoreBo.java diff --git a/Cpop-Api/src/main/java/com/cpop/api/cloudDb/core/dto/CloudStoreDto.java b/Cpop-Api/src/main/java/com/cpop/api/cloudDb/core/dto/CloudStoreDto.java new file mode 100644 index 0000000..652c48b --- /dev/null +++ b/Cpop-Api/src/main/java/com/cpop/api/cloudDb/core/dto/CloudStoreDto.java @@ -0,0 +1,51 @@ +package com.cpop.api.cloudDb.core.dto; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-15 11:18 + */ +@Data +@Accessors(chain = true) +public class CloudStoreDto { + + /** + * 云校区id + */ + @SerializedName("storeId") + private String storeCloudId; + + /** + * 云品牌id + */ + @SerializedName("brandId") + private String brandCloudId; + + /** + * 云校区名 + */ + @SerializedName("name") + private String storeName; + + /** + * 负责人 + */ + @SerializedName("principalName") + private String personCharge; + + /** + * 手机号 + */ + private String phone; + + /** + * 云校区id + */ + @SerializedName("address") + private String storeAddr; + +} diff --git a/Cpop-Api/src/main/java/com/cpop/api/cloudDb/handler/CloudDataImportHandler.java b/Cpop-Api/src/main/java/com/cpop/api/cloudDb/handler/CloudDataImportHandler.java new file mode 100644 index 0000000..f26fe45 --- /dev/null +++ b/Cpop-Api/src/main/java/com/cpop/api/cloudDb/handler/CloudDataImportHandler.java @@ -0,0 +1,18 @@ +package com.cpop.api.cloudDb.handler; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +/** + * 数据导入 + * @author DB + * @version 1.0.0 + * @since 2024-01-14 11:38 + */ +@Component +public class CloudDataImportHandler { + + @Autowired + private RestTemplate restTemplate; +} diff --git a/Cpop-Api/src/main/java/com/cpop/api/cloudDb/handler/CloudStoreHandler.java b/Cpop-Api/src/main/java/com/cpop/api/cloudDb/handler/CloudStoreHandler.java new file mode 100644 index 0000000..25420ad --- /dev/null +++ b/Cpop-Api/src/main/java/com/cpop/api/cloudDb/handler/CloudStoreHandler.java @@ -0,0 +1,64 @@ +package com.cpop.api.cloudDb.handler; + +import com.alibaba.fastjson.JSONObject; +import com.cpop.api.cloudDb.core.constant.CloudDbUrl; +import com.cpop.api.cloudDb.core.dto.CloudOrderDto; +import com.cpop.api.cloudDb.core.dto.CloudStoreDto; +import com.cpop.common.utils.StringUtils; +import com.cpop.core.base.entity.ExtendPage; +import com.cpop.core.base.exception.UtilException; +import com.mybatisflex.core.paginate.Page; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 云校区工具类 + * @author DB + * @version 1.0.0 + * @since 2024-01-15 11:16 + */ +@Component +public class CloudStoreHandler { + + @Autowired + private RestTemplate restTemplate; + + /** + * 更新校区 + * @author DB + * @since 2024/1/15 + * @param dto 入参 + */ + public void updateStore(CloudStoreDto dto) { + JSONObject jsonBody = new JSONObject(); + jsonBody.put("_type", "storeEdit"); + //云校区id + jsonBody.put("storeId", dto.getStoreCloudId()); + if (StringUtils.isNotBlank(dto.getBrandCloudId())) { + jsonBody.put("brandId", dto.getBrandCloudId()); + } + if (StringUtils.isNotBlank(dto.getStoreName())) { + jsonBody.put("name", dto.getStoreName()); + } + if (StringUtils.isNotBlank(dto.getPersonCharge())) { + jsonBody.put("principalName", dto.getPersonCharge()); + } + if (StringUtils.isNotBlank(dto.getPhone())) { + jsonBody.put("phone", dto.getPhone()); + } + if (StringUtils.isNotBlank(dto.getStoreAddr())) { + jsonBody.put("address", dto.getStoreAddr()); + } + JSONObject jsonObject = restTemplate.postForObject(CloudDbUrl.COMMON_CARD_URL, jsonBody, JSONObject.class); + if (jsonObject != null) { + if (!jsonObject.getBoolean("success")) { + throw new UtilException(jsonObject.getString("error")); + } + } + } +} diff --git a/Cpop-Core/src/main/java/com/cpop/core/annontation/SignatureCheck.java b/Cpop-Core/src/main/java/com/cpop/core/annontation/SignatureCheck.java new file mode 100644 index 0000000..84a1249 --- /dev/null +++ b/Cpop-Core/src/main/java/com/cpop/core/annontation/SignatureCheck.java @@ -0,0 +1,15 @@ +package com.cpop.core.annontation; + +import java.lang.annotation.*; + +/** + * @author: DB + * @Date: 2023/08/08/9:49 + * @Description: 自定义签名校验 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SignatureCheck { + +} diff --git a/Cpop-Core/src/main/java/com/cpop/core/annontation/SimpleSignatureCheck.java b/Cpop-Core/src/main/java/com/cpop/core/annontation/SimpleSignatureCheck.java new file mode 100644 index 0000000..e95d734 --- /dev/null +++ b/Cpop-Core/src/main/java/com/cpop/core/annontation/SimpleSignatureCheck.java @@ -0,0 +1,15 @@ +package com.cpop.core.annontation; + +import java.lang.annotation.*; + +/** + * 简易校验签名 + * @author DB + * @version 1.0.0 + * @since 2024-01-16 10:31 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SimpleSignatureCheck { +} diff --git a/Cpop-Core/src/main/java/com/cpop/core/aspect/SignatureCheckAspect.java b/Cpop-Core/src/main/java/com/cpop/core/aspect/SignatureCheckAspect.java new file mode 100644 index 0000000..20b7b73 --- /dev/null +++ b/Cpop-Core/src/main/java/com/cpop/core/aspect/SignatureCheckAspect.java @@ -0,0 +1,148 @@ +package com.cpop.core.aspect; + +import com.cpop.common.utils.StringUtils; +import com.cpop.core.base.R; +import com.cpop.core.base.exception.ServiceException; +import com.cpop.core.base.exception.UtilException; +import com.cpop.core.utils.RsaUtils; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.DigestUtils; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; + +import javax.servlet.http.HttpServletRequest; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.lang.reflect.Field; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.Key; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 自定义前面校验 + * @author DB + * @version 1.0.0 + * @since 2024-01-16 10:01 + */ +@Aspect +@Component +@Slf4j +public class SignatureCheckAspect { + + @Autowired + private RsaUtils rsaUtils; + + private static final Map APP_IDS = new HashMap() {{ + //数币 + put("1688842965582499840", new String[]{"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"}); + }}; + + @Pointcut("@annotation(com.cpop.core.annontation.SignatureCheck)") + public void signatureCheck() {} + + /** + * 前置通知 + * @author DB + * @since 2024/1/16 + * @param joinPoint 切入点 + */ + @Before(value = "signatureCheck()") + public void beforePointcut(JoinPoint joinPoint) throws IllegalAccessException { + //获取RequestAttributes + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + //从获取RequestAttributes中获取HttpServletRequest的信息 + assert requestAttributes != null; + HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST); + assert request != null; + Object object = joinPoint.getArgs()[0]; + //验签拼接字段 + List signString = new ArrayList(); + //获取父类(公共类必传属性) + Field[] fatherFields = object.getClass().getSuperclass().getDeclaredFields(); + String signature = null; + String appId = null; + for (Field field : fatherFields) { + field.setAccessible(true); + if (StringUtils.equals("signature", field.getName())) { + signature = (String) field.get(object); + continue; + } + if (StringUtils.equals("appId", field.getName())) { + String[] strings = APP_IDS.get((String) field.get(object)); + if (null == strings){ + throw new ServiceException("appId匹配失败,请核实appId"); + } + appId = strings[0]; + } + signString.add(field.getName() + "=" + field.get(object)); + } + if (null == signature){ + throw new ServiceException("签名不存在,请核实签名"); + //return ResultDTO.fail("签名不存在,请核实签名"); + } + //可能为空参 + Field[] fields = object.getClass().getDeclaredFields(); + if (fields.length > 0) { + for (Field field : fields) { + field.setAccessible(true); + if(null == field.get(object)){ + signString.add(field.getName() + "="); + } else { + signString.add(field.getName() + "=" + field.get(object)); + } + } + } + //按照字母排序 + String sign = signString.stream().sorted().collect(Collectors.joining("&")) + appId; + String md5DigestAsHex = DigestUtils.md5DigestAsHex(sign.getBytes()); + if (!StringUtils.equals(md5DigestAsHex,signature)){ + throw new ServiceException("签名匹配失败,请核实签名"); + } + } + + /** + * 环绕通知,不做处理 + * @author DB + * @since 2024/1/16 + * @param joinPoint 请求 + * @return Object + */ + @Around("signatureCheck()") + public Object aroundPointcut(ProceedingJoinPoint joinPoint) throws Throwable { + return joinPoint.proceed(joinPoint.getArgs()); + } + + /** + * 异常通知:目标方法发生异常的时候执行以下代码,此时返回通知不会再触发 + * value 属性:绑定通知的切入点表达式。可以关联切入点声明,也可以直接设置切入点表达式 + * pointcut 属性:绑定通知的切入点表达式,优先级高于 value,默认为 "" + * throwing 属性:与方法中的异常参数名称一致, + * + * @param ex:捕获的异常对象,名称与 throwing 属性值一致 + */ + @AfterThrowing(pointcut = "signatureCheck()", throwing = "ex") + public Object aspectAfterThrowing(JoinPoint jp, Exception ex) { + String methodName = jp.getSignature().getName(); + if (ex instanceof ServiceException) { + log.error("【异常通知】" + methodName + "方法算术异常(ArithmeticException):" + ex.getMessage()); + return R.fail(ex.getMessage()); + } else { + log.error("【异常通知】" + methodName + "方法异常:" + ex.getMessage()); + return R.fail("签名不合法"); + } + } + +} diff --git a/Cpop-Core/src/main/java/com/cpop/core/aspect/SimpleSignatureCheckAspect.java b/Cpop-Core/src/main/java/com/cpop/core/aspect/SimpleSignatureCheckAspect.java new file mode 100644 index 0000000..18ee66b --- /dev/null +++ b/Cpop-Core/src/main/java/com/cpop/core/aspect/SimpleSignatureCheckAspect.java @@ -0,0 +1,138 @@ +package com.cpop.core.aspect; + +import com.cpop.common.utils.StringUtils; +import com.cpop.core.base.R; +import com.cpop.core.base.exception.ServiceException; +import com.cpop.core.base.exception.UtilException; +import com.cpop.core.utils.RsaUtils; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.DigestUtils; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; + +import javax.servlet.http.HttpServletRequest; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.util.HashMap; +import java.util.Map; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-16 10:31 + */ +@Aspect +@Component +@Slf4j +public class SimpleSignatureCheckAspect { + + @Autowired + private RsaUtils rsaUtils; + + private static final Map APP_IDS = new HashMap() {{ + //果酱内部 + put("1747095325571944448", new String[]{"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"}); + //数币 + put("1688842965582499840", new String[]{"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"}); + }}; + + @Pointcut("@annotation(com.cpop.core.annontation.SimpleSignatureCheck)") + public void simpleSignatureCheck() {} + + /** + * 前置通知 + * @author DB + * @since 2024/1/16 + */ + @Before(value = "simpleSignatureCheck()") + public void beforePointcut() { + //获取RequestAttributes + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + //从获取RequestAttributes中获取HttpServletRequest的信息 + assert requestAttributes != null; + HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST); + assert request != null; + String signature = request.getHeader("signature"); + if (StringUtils.isBlank(signature)){ + throw new ServiceException("签名为空,请核实签名"); + } + String appId = request.getHeader("appId"); + if (StringUtils.isBlank(appId)){ + throw new ServiceException("appId为空,请核实签名"); + } + String dateTime = request.getHeader("dateTime"); + if (StringUtils.isBlank(dateTime)){ + throw new ServiceException("时间为空,请核实签名"); + } + String decrypt = rsaUtils.decrypt(signature, stringToKey(APP_IDS.get(appId)[1])); + String sign = appId + dateTime; + String md5DigestAsHex = DigestUtils.md5DigestAsHex(sign.getBytes()); + if (!StringUtils.equals(md5DigestAsHex, decrypt)) { + throw new ServiceException("签名匹配失败,请核实签名"); + } + } + + /** + * 环绕通知,不做处理 + * @author DB + * @since 2024/1/16 + * @param joinPoint 请求 + * @return Object + */ + @Around("simpleSignatureCheck()") + public Object aroundPointcut(ProceedingJoinPoint joinPoint) throws Throwable { + return joinPoint.proceed(joinPoint.getArgs()); + } + + /** + * 异常通知:目标方法发生异常的时候执行以下代码,此时返回通知不会再触发 + * value 属性:绑定通知的切入点表达式。可以关联切入点声明,也可以直接设置切入点表达式 + * pointcut 属性:绑定通知的切入点表达式,优先级高于 value,默认为 "" + * throwing 属性:与方法中的异常参数名称一致, + * + * @param ex:捕获的异常对象,名称与 throwing 属性值一致 + */ + @AfterThrowing(pointcut = "simpleSignatureCheck()", throwing = "ex") + public Object aspectAfterThrowing(JoinPoint jp, Exception ex) { + String methodName = jp.getSignature().getName(); + if (ex instanceof ServiceException) { + log.error("【异常通知】" + methodName + "方法算术异常(ArithmeticException):" + ex.getMessage()); + return R.fail(ex.getMessage()); + } else { + log.error("【异常通知】" + methodName + "方法异常:" + ex.getMessage()); + return R.fail("签名不合法"); + } + + } + + private Key stringToKey(String stringKey) { + byte[] bytes = stringKey.getBytes(StandardCharsets.UTF_8); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + Key key = null; + ObjectInputStream ois = null; + try { + ois = new ObjectInputStream(bais); + key = (Key) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + throw new UtilException(e.getMessage()); + } finally { + try { + assert ois != null; + ois.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return key; + } + +} diff --git a/Cpop-Core/src/main/java/com/cpop/core/base/entity/CpopSignBase.java b/Cpop-Core/src/main/java/com/cpop/core/base/entity/CpopSignBase.java new file mode 100644 index 0000000..50849bd --- /dev/null +++ b/Cpop-Core/src/main/java/com/cpop/core/base/entity/CpopSignBase.java @@ -0,0 +1,33 @@ +package com.cpop.core.base.entity; + +import lombok.Data; + +/** + * 普普签名基础类 + * @author DB + * @version 1.0.0 + * @since 2024-01-16 10:09 + */ +@Data +public class CpopSignBase { + + /** + * 签名 + */ + private String signature; + + /** + * appId + */ + private String appId; + + /** + * 时间(yyyyMMddHHmmss) + */ + private String dateTime; + + /** + * 签名类型 + */ + private String signType; +} diff --git a/Cpop-Core/src/main/java/com/cpop/core/utils/RsaUtils.java b/Cpop-Core/src/main/java/com/cpop/core/utils/RsaUtils.java index e73e662..e0f833a 100644 --- a/Cpop-Core/src/main/java/com/cpop/core/utils/RsaUtils.java +++ b/Cpop-Core/src/main/java/com/cpop/core/utils/RsaUtils.java @@ -86,14 +86,18 @@ public class RsaUtils { * 将密钥对生成到文件中 */ private void generateKeyPairToFiles() { + generateKeyPairToFiles(keyPairConfig.getPublicKeyFile(),keyPairConfig.getPrivateKeyFile()); + } + + private void generateKeyPairToFiles(String publicKeyFile, String privateKeyFile) { ObjectOutputStream oosPublicKey = null; ObjectOutputStream oosPrivateKey = null; try { Map keyPairMap = generateKeyPair(); Key publicKey = keyPairMap.get("publicKey"); Key privateKey = keyPairMap.get("privateKey"); - oosPublicKey = new ObjectOutputStream(Files.newOutputStream(Paths.get(keyPairConfig.getPublicKeyFile()))); - oosPrivateKey = new ObjectOutputStream(Files.newOutputStream(Paths.get(keyPairConfig.getPrivateKeyFile()))); + oosPublicKey = new ObjectOutputStream(Files.newOutputStream(Paths.get(publicKeyFile))); + oosPrivateKey = new ObjectOutputStream(Files.newOutputStream(Paths.get(privateKeyFile))); oosPublicKey.writeObject(publicKey); oosPrivateKey.writeObject(privateKey); } catch (NoSuchAlgorithmException | IOException e) { @@ -111,25 +115,31 @@ public class RsaUtils { } } + + /** * 初始化密钥对文件 * @return 返回密钥对信息【publicKey(公钥字符串)、、privateKey(私钥字符串)】 */ public Map initKeyPair() { + return initKeyPair(keyPairConfig.getPublicKeyFile(),keyPairConfig.getPrivateKeyFile()); + } + + public Map initKeyPair(String publicKeyFile, String privateKeyFile){ Map keyPairMap = new HashMap<>(); - File publicFile = new File(keyPairConfig.getPublicKeyFile()); - File privateFile = new File(keyPairConfig.getPrivateKeyFile()); + File publicFile = new File(publicKeyFile); + File privateFile = new File(privateKeyFile); //判断是否存在公钥和私钥文件 if (!publicFile.exists() || !privateFile.exists()) { - generateKeyPairToFiles(); + generateKeyPairToFiles(publicKeyFile, privateKeyFile); } ObjectInputStream oisPublic = null; ObjectInputStream oisPrivate = null; Key publicKey = null; Key privateKey = null; try { - oisPublic = new ObjectInputStream(Files.newInputStream(Paths.get(keyPairConfig.getPublicKeyFile()))); - oisPrivate = new ObjectInputStream(Files.newInputStream(Paths.get(keyPairConfig.getPrivateKeyFile()))); + oisPublic = new ObjectInputStream(Files.newInputStream(Paths.get(publicKeyFile))); + oisPrivate = new ObjectInputStream(Files.newInputStream(Paths.get(privateKeyFile))); publicKey = (Key) oisPublic.readObject(); privateKey = (Key) oisPrivate.readObject(); byte[] publicKeyBytes = publicKey.getEncoded(); @@ -183,7 +193,28 @@ public class RsaUtils { * @return 解密后的字符串 */ public String decrypt(String source) { - Key privateKey = getKeyFromFile(keyPairConfig.getPrivateKeyFile()); + return decrypt(source,keyPairConfig.getPrivateKeyFile()); + } + + public String decrypt(String source, String privateKeyFile) { + Key privateKey = getKeyFromFile(privateKeyFile); + Base64.Decoder decoder = Base64.getDecoder(); + String decryptSource = null; + try { + //得到Cipher对象对已用公钥加密的数据进行RSA解密 + Cipher cipher = Cipher.getInstance(keyPairConfig.getAlgorithm()); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + //执行解密操作 + byte[] bytes = decoder.decode(source); + decryptSource = new String(cipher.doFinal(bytes), StandardCharsets.UTF_8); + } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | + IllegalBlockSizeException | BadPaddingException e) { + throw new UtilException(e.getMessage()); + } + return decryptSource; + } + + public String decrypt(String source, Key privateKey) { Base64.Decoder decoder = Base64.getDecoder(); String decryptSource = null; try { diff --git a/Cpop-Core/src/main/resources/mapper/CoreMapper.xml b/Cpop-Core/src/main/resources/mapper/CoreMapper.xml index 474be7d..18a4fa5 100644 --- a/Cpop-Core/src/main/resources/mapper/CoreMapper.xml +++ b/Cpop-Core/src/main/resources/mapper/CoreMapper.xml @@ -295,6 +295,9 @@ password = #{password}, + + rsa_password = #{rsaPassword}, + nick_name = #{nickName}, diff --git a/Cpop-Generator/src/main/java/com/cpop/generator/CpopGenerator.java b/Cpop-Generator/src/main/java/com/cpop/generator/CpopGenerator.java index 8276257..6c85a8c 100644 --- a/Cpop-Generator/src/main/java/com/cpop/generator/CpopGenerator.java +++ b/Cpop-Generator/src/main/java/com/cpop/generator/CpopGenerator.java @@ -40,17 +40,17 @@ public class CpopGenerator { /** * 输出路径 */ - private static final String EXPORT_URL = "/Cpop-Oam"; + private static final String EXPORT_URL = "/Cpop-Mall"; /** * 模块 */ - private static final String EXPORT_ITEM = "oam"; + private static final String EXPORT_ITEM = "mall"; /** * 表前缀 */ - private static final String TABLE_PREFIX = "cp_oam_"; + private static final String TABLE_PREFIX = "cp_mall_"; /** * 主入口 diff --git a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/bo/CardTemplateUnionBo.java b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/bo/CardTemplateUnionBo.java new file mode 100644 index 0000000..c051c11 --- /dev/null +++ b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/bo/CardTemplateUnionBo.java @@ -0,0 +1,135 @@ +package com.cpop.jambox.business.bo; + +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-16 16:29 + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "CardTemplateUnionBo对象", description = "课卡模板统一入口") +public class CardTemplateUnionBo { + + /** + * 主键 + */ + @ApiModelProperty(value = "主键") + private String id; + + /** + * 云品牌id + */ + @ApiModelProperty(value = "云品牌id") + private String brandCloudId; + + /** + * 云校区id + */ + @ApiModelProperty(value = "云校区id") + private String storeCloudId; + + /** + * 模板名 + */ + @NotBlank(message = "模板名不能为空") + @ApiModelProperty(value = "模板名",required = true) + private String name; + + /** + * 有效日期数 + */ + @ApiModelProperty(value = "有效日期数") + private Integer validDay; + + /** + * 开始日期 + */ + @ApiModelProperty(value = "开始日期") + private LocalDate startDate; + + /** + * 结束日期 + */ + @ApiModelProperty(value = "结束日期") + private LocalDate endDate; + + /** + * 价格 + */ + @NotNull(message = "价格不能为空") + @ApiModelProperty(value = "价格") + private BigDecimal price; + + /** + * 课时 + */ + @ApiModelProperty("课时") + private Integer classNumber; + + /** + * 周预约数 + */ + @ApiModelProperty(value = "周预约数") + private Integer weekAppointment; + + /** + * 日预约数 + */ + @ApiModelProperty(value = "日预约数") + private Integer dayAppointment; + + /** + * 缓冲天数 + */ + @ApiModelProperty(value = "缓冲天数") + private Integer bufferDay; + + /** + * 模板类型(0:课时卡,1:时限卡,2:储值卡) + */ + @ApiModelProperty(value = "模板类型(0:课时卡,1:时限卡,2:储值卡)") + private Integer templateType; + + /** + * 使用范围 + */ + @ApiModelProperty(value = "使用范围(旧Type字段)") + private String scopeUse; + + /** + * 支付类型(0:微信支付;1:微信先学后付;2:放心学合约支付;3:数字人民币支付;4:线下支付) + */ + @NotNull(message = "支付类型不能为空") + @ApiModelProperty(value = "支付类型(0:微信支付;1:微信先学后付;2:放心学合约支付;3:数字人民币支付;4:线下支付") + private Integer payType; + + /** + * 是否是会员(0否1是) + */ + @ApiModelProperty(value = "是否是会员(0否1是)") + private Boolean isMember; + + /** + * 先学后付支付 + */ + @ApiModelProperty("先学后付支付(次付)") + private LearnNowPayLaterPlanBo learnNowPayLaterPay; + + /** + * 先学后付支付 + */ + @ApiModelProperty("先学后付(月付)") + private LearnNowPayLaterPlanBo learnNowPayLaterMonthPay; +} diff --git a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/controller/backstage/CardTemplateController.java b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/controller/backstage/CardTemplateController.java index c1a9e34..fdf9653 100644 --- a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/controller/backstage/CardTemplateController.java +++ b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/controller/backstage/CardTemplateController.java @@ -1,5 +1,6 @@ package com.cpop.jambox.business.controller.backstage; +import com.cpop.jambox.business.bo.CardTemplateUnionBo; import com.mybatisflex.core.paginate.Page; import com.cpop.core.base.R; import com.cpop.jambox.business.entity.CardTemplate; @@ -9,8 +10,10 @@ import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; import java.io.Serializable; import java.util.List; @@ -28,4 +31,16 @@ public class CardTemplateController { @Autowired private CardTemplateService cardTemplateService; + /** + * 添加课卡模板(整合) + * @author DB + * @since 2023/10/07 9:59 + * @param bo 请求参数 + */ + @ApiOperation(value = "添加课卡模板(整合)") + @PostMapping("/insertCardTemplateUnion") + public R insertCardTemplateUnion(@RequestBody @Validated CardTemplateUnionBo bo) { + String templateId = cardTemplateService.insertCardTemplateUnion(bo); + return R.ok(templateId); + } } diff --git a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/controller/backstage/EasyLearnController.java b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/controller/backstage/EasyLearnController.java index 7ba054f..ee232f0 100644 --- a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/controller/backstage/EasyLearnController.java +++ b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/controller/backstage/EasyLearnController.java @@ -2,10 +2,7 @@ package com.cpop.jambox.business.controller.backstage; import com.alibaba.excel.EasyExcel; import com.cpop.core.base.R; -import com.cpop.jambox.business.bo.EasyLearnPageBo; -import com.cpop.jambox.business.bo.EasyLearnUnifiedPayBo; -import com.cpop.jambox.business.bo.EasyLearnUnionPayBo; -import com.cpop.jambox.business.bo.OncePlaceOrderBo; +import com.cpop.jambox.business.bo.*; import com.cpop.jambox.business.dto.EasyLearnPageDto; import com.cpop.jambox.business.service.EasyLearnOrderService; import com.cpop.jambox.business.vo.EasyLearnPageVo; diff --git a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/entity/CardTemplate.java b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/entity/CardTemplate.java index 9d5ce00..f84b5bf 100644 --- a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/entity/CardTemplate.java +++ b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/entity/CardTemplate.java @@ -41,14 +41,14 @@ public class CardTemplate extends BaseEntity implements Serializable { private String oldTemplateId; /** - * 云品牌id + * 品牌id */ - private String cloudBrandId; + private String brandId; /** - * 云校区id + * 校区id */ - private String cloudStoreId; + private String storeId; /** * 是否使用(0否1是) @@ -113,7 +113,7 @@ public class CardTemplate extends BaseEntity implements Serializable { /** * 支付类型(0:微信支付;1:微信先学后付;2:放心学合约支付;3:数字人民币支付;4:线下支付) */ - private String payType; + private Integer payType; /** * 太阳码 @@ -125,12 +125,6 @@ public class CardTemplate extends BaseEntity implements Serializable { */ private Boolean isMember; - /** - * 模板类型(0:课时卡,1:时限卡,2:储值卡) - */ - @Column(ignore = true) - private String oldTemplateType; - /** * 逻辑删除(0否1是) */ diff --git a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/CardTemplateService.java b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/CardTemplateService.java index 4aae0c0..5431941 100644 --- a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/CardTemplateService.java +++ b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/CardTemplateService.java @@ -1,5 +1,7 @@ package com.cpop.jambox.business.service; +import com.cpop.jambox.business.bo.CardTemplateUnionBo; +import com.mybatisflex.core.row.Row; import com.mybatisflex.core.service.IService; import com.cpop.jambox.business.entity.CardTemplate; import com.cpop.jambox.business.vo.CardTemplateListVo; @@ -22,5 +24,14 @@ public interface CardTemplateService extends IService { * @param brandId 品牌id * @return: com.cpop.jambox.business.entity.CardTemplate */ - CardTemplate getOldTemplateInfo(String oldTemplateId, String brandId); + Row getOldTemplateInfo(String oldTemplateId, String brandId); + + /** + * 添加课卡模板(整合) + * @author DB + * @since 2024/1/16 + * @param bo 请求参数 + * @return String 旧模板id + */ + String insertCardTemplateUnion(CardTemplateUnionBo bo); } diff --git a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/EasyLearnOrderService.java b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/EasyLearnOrderService.java index 0f16640..10d2035 100644 --- a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/EasyLearnOrderService.java +++ b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/EasyLearnOrderService.java @@ -1,9 +1,6 @@ package com.cpop.jambox.business.service; -import com.cpop.jambox.business.bo.EasyLearnPageBo; -import com.cpop.jambox.business.bo.EasyLearnUnifiedPayBo; -import com.cpop.jambox.business.bo.EasyLearnUnionPayBo; -import com.cpop.jambox.business.bo.OncePlaceOrderBo; +import com.cpop.jambox.business.bo.*; import com.cpop.jambox.business.dto.EasyLearnPageDto; import com.cpop.jambox.business.entity.EasyLearnOrder; import com.cpop.jambox.business.vo.EasyLearnPageVo; @@ -77,4 +74,5 @@ public interface EasyLearnOrderService extends IService { * @return Object */ Object unifiedPay(EasyLearnUnifiedPayBo bo); + } diff --git a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/impl/CardTemplateServiceImpl.java b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/impl/CardTemplateServiceImpl.java index 360ee24..71ee595 100644 --- a/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/impl/CardTemplateServiceImpl.java +++ b/Cpop-Jambox/src/main/java/com/cpop/jambox/business/service/impl/CardTemplateServiceImpl.java @@ -1,11 +1,18 @@ package com.cpop.jambox.business.service.impl; +import com.cpop.common.utils.StringUtils; +import com.cpop.common.utils.bean.BeanUtils; import com.cpop.core.utils.SpringUtils; +import com.cpop.jambox.business.bo.CardTemplateUnionBo; import com.cpop.jambox.business.entity.BrandExtend; import com.cpop.jambox.business.entity.CardTemplate; +import com.cpop.jambox.business.entity.StoreExtend; import com.cpop.jambox.business.mapper.CardTemplateMapper; import com.cpop.jambox.business.service.BrandExtendService; import com.cpop.jambox.business.service.CardTemplateService; +import com.cpop.jambox.business.service.StoreExtendService; +import com.cpop.system.business.entity.Store; +import com.cpop.system.business.service.StoreService; import com.mybatisflex.core.datasource.DataSourceKey; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.row.Db; @@ -19,6 +26,7 @@ import java.util.List; import static com.cpop.jambox.business.entity.table.BrandExtendTableDef.BRAND_EXTEND; import static com.cpop.jambox.business.entity.table.CardTemplateTableDef.CARD_TEMPLATE; +import static com.cpop.jambox.business.entity.table.StoreExtendTableDef.STORE_EXTEND; /** * 果酱-课卡模板 服务层实现。 @@ -38,24 +46,43 @@ public class CardTemplateServiceImpl extends ServiceImpl keyPairMap = rsaUtils.initKeyPair(); + String publicFileUrl = "E:\\Cpop\\Cpop-Union\\Cpop-Mall\\Cpop-Mall-Web\\src\\main\\resources\\static\\keyPair\\publicKey"; + String privateFileUrl = "E:\\Cpop\\Cpop-Union\\Cpop-Mall\\Cpop-Mall-Web\\src\\main\\resources\\static\\keyPair\\privateKey"; + Map keyPairMap = rsaUtils.initKeyPair(publicFileUrl,privateFileUrl); String publicKey = keyPairMap.get("publicKey"); String privateKey = keyPairMap.get("privateKey"); System.out.println("公钥:"); diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/CarouselBo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/CarouselBo.java new file mode 100644 index 0000000..8063de1 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/CarouselBo.java @@ -0,0 +1,55 @@ +package com.cpop.mall.business.bo; + +import com.mybatisflex.annotation.Id; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-15 13:44 + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "商城轮播图对象") +public class CarouselBo { + + /** + * 主键 + */ + @ApiModelProperty(value = "主键") + private String id; + + /** + * 产品id + */ + @NotBlank(message = "产品id不能为空") + @ApiModelProperty(value = "产品id",required = true) + private String productId; + + /** + * 图片地址 + */ + @ApiModelProperty(value = "图片地址",required = true) + @NotBlank(message = "图片地址不能为空") + private String picUrl; + + /** + * 排序 + */ + @NotNull(message = "排序不能为空") + @ApiModelProperty(value = "排序",required = true) + private Integer orderNo; + + /** + * 上架状态(0:下架;1:上架) + */ + @NotNull(message = "上架状态不能为空") + @ApiModelProperty(value = "上架状态(0:下架;1:上架)",required = true) + private Boolean upStatus; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/backstage/BackstageCarouselController.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/backstage/BackstageCarouselController.java new file mode 100644 index 0000000..58a582a --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/backstage/BackstageCarouselController.java @@ -0,0 +1,132 @@ +package com.cpop.mall.business.controller.backstage; + +import com.cpop.core.base.R; +import com.cpop.core.utils.SpringUtils; +import com.cpop.mall.business.bo.CarouselBo; +import com.cpop.mall.business.service.ProductService; +import com.cpop.mall.business.vo.CarouselPageVo; +import com.cpop.mall.business.vo.ProductInfoVo; +import com.cpop.mall.business.vo.ProductSimpleVo; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Autowired; +import com.cpop.mall.business.entity.Carousel; +import com.cpop.mall.business.service.CarouselService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.io.Serializable; +import java.util.List; + +import static com.cpop.mall.business.entity.table.CarouselTableDef.CAROUSEL; +import static com.cpop.mall.business.entity.table.ProductTableDef.PRODUCT; + +/** + * 商城轮播图 控制层。 + * + * @author DB + * @since 2024-01-15 + */ +@RestController +@Api(tags = "商城轮播图接口") +@RequestMapping("/carousel") +public class BackstageCarouselController { + + @Autowired + private CarouselService carouselService; + + /** + * 分页查询商城轮播图 + * @author DB + * @since 2024/1/15 + * @param upStatus 上架状态 + * @return R> + */ + @GetMapping("/getCarouselPage") + @ApiOperation("分页查询商城轮播图") + public R> getCarouselPage(@ApiParam("上架状态") @RequestParam(value = "upStatus", required = false) Boolean upStatus) { + Page page = carouselService.getCarouselPage(upStatus); + return R.ok(page); + } + + /** + * 新增轮播图 + * @author DB + * @since 2024/1/15 + * @param bo 请求参数 + * @return R + */ + @PostMapping("/insertCarousel") + @ApiOperation("新增商城轮播图") + public R insertCarousel(@RequestBody CarouselBo bo) { + carouselService.insertCarousel(bo); + return R.ok(); + } + + /** + * 更新轮播图 + * + * @param bo 请求参数 + * @return R + * @author DB + * @since 2024/1/15 + */ + @PutMapping("/updateCarousel") + @ApiOperation("修改商城轮播图") + public R updateCarousel(@RequestBody CarouselBo bo) { + carouselService.updateCarousel(bo); + return R.ok(); + } + + /** + * 轮播图上下架 + * @param id 主键 + * @return R + * @author DB + * @since 2024/1/15 + */ + @PutMapping("/carouselUnmount/{id}") + @ApiOperation("轮播图上下架") + public R carouselUnmount(@PathVariable String id) { + carouselService.updateChain() + .setRaw(CAROUSEL.UP_STATUS, "if(up_status = 0, 1, 0)") + .where(CAROUSEL.ID.eq(id)) + .update(); + return R.ok(); + } + + /** + * 删除轮播图 + * + * @param id 主键 + * @return R + * @author DB + * @since 2024/1/15 + */ + @DeleteMapping("/removeCarouselById/{id}") + @ApiOperation("删除轮播图") + public R removeCarouselById(@PathVariable String id) { + carouselService.updateChain().where(CAROUSEL.ID.eq(id)).remove(); + return R.ok(); + } + + /** + * 获取上架商品 + * @author DB + * @since 2024/1/15 + * @param brandId 品牌id + * @return R> + */ + @GetMapping("/getUpProductList") + @ApiOperation("获取上架商品") + public R> getUpProductList(@ApiParam("品牌id") @RequestParam(value = "brandId", required = false) String brandId) { + List productSimpleVos = SpringUtils.getBean(ProductService.class).listAs(QueryWrapper.create() + .select(PRODUCT.ID, PRODUCT.PRODUCT_NAME) + .where(PRODUCT.BRAND_ID.eq(brandId)) + .and(PRODUCT.IS_UP.eq(true)) + , ProductSimpleVo.class); + return R.ok(productSimpleVos); + } + +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniProductController.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniProductController.java index a40bc68..34d0bc3 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniProductController.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniProductController.java @@ -1,9 +1,12 @@ package com.cpop.mall.business.controller.mini; +import com.alibaba.fastjson.JSONObject; import com.cpop.common.utils.bean.BeanUtils; import com.cpop.core.base.R; +import com.cpop.core.utils.SecurityUtils; import com.cpop.core.utils.SpringUtils; import com.cpop.mall.business.bo.ProductPageBo; +import com.cpop.mall.business.service.CarouselService; import com.cpop.mall.business.service.ProductService; import com.cpop.mall.business.vo.*; import com.cpop.system.business.entity.Store; @@ -12,12 +15,15 @@ import com.mybatisflex.core.paginate.Page; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; +import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.Arrays; import java.util.List; +import static com.cpop.mall.business.entity.table.CarouselTableDef.CAROUSEL; + /** * 商城-商品表 控制层。 * @@ -32,6 +38,9 @@ public class MiniProductController { @Autowired private ProductService productService; + @Autowired + private CarouselService carouselService; + /** * @descriptions 分页查询商城-商品 * @author DB @@ -117,4 +126,18 @@ public class MiniProductController { return R.ok(info); } + /** + * 获取商城轮播图 + * @author DB + * @since 2024/1/15 + * @return R> + */ + @GetMapping("/getCarouselList") + @ApiOperation("获取商城轮播图") + public R> getCarouselList() { + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + List vos = carouselService.queryChain().where(CAROUSEL.BRAND_ID.eq(loginUserInfo.getString("brandId")) + .and(CAROUSEL.UP_STATUS.eq(true))).listAs(CarouselListVo.class); + return R.ok(vos); + } } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/entity/Carousel.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/entity/Carousel.java new file mode 100644 index 0000000..1a9f4e2 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/entity/Carousel.java @@ -0,0 +1,74 @@ +package com.cpop.mall.business.entity; + +import com.cpop.core.base.entity.BaseEntity; +import com.cpop.core.base.entity.BaseInsertListener; +import com.cpop.core.base.entity.BaseUpdateListener; +import com.mybatisflex.annotation.Column; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; +import java.io.Serializable; +import java.time.LocalDateTime; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.*; +import lombok.experimental.Accessors; + +/** + * 商城轮播图 实体类。 + * + * @author DB + * @since 2024-01-15 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +@Table(value = "cp_mall_carousel", onInsert = BaseInsertListener.class, onUpdate = BaseUpdateListener.class, mapperGenerateEnable = false) +public class Carousel extends BaseEntity implements Serializable { + + /** + * 主键 + */ + @Id + private String id; + + /** + * 产品id + */ + @Id + private String productId; + + /** + * 品牌id + */ + @Id + private String brandId; + + /** + * 图片地址 + */ + private String picUrl; + + /** + * 排序 + */ + private Integer orderNo; + + /** + * 上架状态(0:下架;1:上架) + */ + private Boolean upStatus; + + + + + + /** + * 逻辑删除(0否1是) + */ + @Column(isLogicDelete = true) + private Boolean isDelete; + +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/mapper/CarouselMapper.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/mapper/CarouselMapper.java new file mode 100644 index 0000000..17f1ed1 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/mapper/CarouselMapper.java @@ -0,0 +1,14 @@ +package com.cpop.mall.business.mapper; + +import com.mybatisflex.core.BaseMapper; +import com.cpop.mall.business.entity.Carousel; + +/** + * 商城轮播图 映射层。 + * + * @author DB + * @since 2024-01-15 + */ +public interface CarouselMapper extends BaseMapper { + +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/CarouselService.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/CarouselService.java new file mode 100644 index 0000000..dedae33 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/CarouselService.java @@ -0,0 +1,41 @@ +package com.cpop.mall.business.service; + +import com.cpop.mall.business.bo.CarouselBo; +import com.cpop.mall.business.vo.CarouselPageVo; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.service.IService; +import com.cpop.mall.business.entity.Carousel; + +/** + * 商城轮播图 服务层。 + * + * @author DB + * @since 2024-01-15 + */ +public interface CarouselService extends IService { + + /** + * 分页查询商城轮播图 + * @author DB + * @since 2024/1/15 + * @param upStatus 上架状态 + * @return Page + */ + Page getCarouselPage(Boolean upStatus); + + /** + * 新增轮播图 + * @author DB + * @since 2024/1/15 + * @param bo 请求参数 + */ + void insertCarousel(CarouselBo bo); + + /** + * 修改轮播图 + * @author DB + * @since 2024/1/15 + * @param bo 请求参数 + */ + void updateCarousel(CarouselBo bo); +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/CarouselServiceImpl.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/CarouselServiceImpl.java new file mode 100644 index 0000000..2f1bdc6 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/CarouselServiceImpl.java @@ -0,0 +1,79 @@ +package com.cpop.mall.business.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.cpop.common.utils.bean.BeanUtils; +import com.cpop.core.base.entity.PageDomain; +import com.cpop.core.utils.SecurityUtils; +import com.cpop.core.utils.sql.SqlUtils; +import com.cpop.mall.business.bo.CarouselBo; +import com.cpop.mall.business.vo.CarouselPageVo; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.spring.service.impl.ServiceImpl; +import com.cpop.mall.business.entity.Carousel; +import com.cpop.mall.business.mapper.CarouselMapper; +import com.cpop.mall.business.service.CarouselService; +import org.springframework.stereotype.Service; + +import static com.cpop.mall.business.entity.table.CarouselTableDef.CAROUSEL; +import static com.cpop.mall.business.entity.table.ProductTableDef.PRODUCT; + +/** + * 商城轮播图 服务层实现。 + * + * @author DB + * @since 2024-01-15 + */ +@Service("carouselService") +public class CarouselServiceImpl extends ServiceImpl implements CarouselService { + + /** + * 分页查询商城轮播图 + * @author DB + * @since 2024/1/15 + * @param upStatus 上架状态 + * @return Page + */ + @Override + public Page getCarouselPage(Boolean upStatus) { + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + PageDomain pageDomain = SqlUtils.getInstance().getPageDomain(); + return this.pageAs(Page.of(pageDomain.getPageNum(), pageDomain.getPageSize()), + QueryWrapper.create() + .select(CAROUSEL.ID,CAROUSEL.PRODUCT_ID,CAROUSEL.PIC_URL,CAROUSEL.ORDER_NO,CAROUSEL.UP_STATUS) + .select(PRODUCT.PRODUCT_NAME) + .leftJoin(PRODUCT).on(PRODUCT.ID.eq(CAROUSEL.PRODUCT_ID)) + .where(CAROUSEL.BRAND_ID.eq(loginUserInfo.getString("brandId"))) + .and(CAROUSEL.UP_STATUS.eq(upStatus)) + .orderBy(CAROUSEL.ORDER_NO.asc()), + CarouselPageVo.class); + } + + /** + * 新增轮播图 + * @author DB + * @since 2024/1/15 + * @param bo 请求参数 + */ + @Override + public void insertCarousel(CarouselBo bo) { + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + Carousel carousel = BeanUtils.mapToClass(bo, Carousel.class); + carousel.setBrandId(loginUserInfo.getString("brandId")); + this.save(carousel); + } + + /** + * 修改轮播图 + * @author DB + * @since 2024/1/15 + * @param bo 请求参数 + */ + @Override + public void updateCarousel(CarouselBo bo) { + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + Carousel carousel = BeanUtils.mapToClass(bo, Carousel.class); + carousel.setBrandId(loginUserInfo.getString("brandId")); + this.updateById(carousel); + } +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ProductServiceImpl.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ProductServiceImpl.java index 05b3979..1f6857b 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ProductServiceImpl.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/ProductServiceImpl.java @@ -217,18 +217,18 @@ public class ProductServiceImpl extends ServiceImpl impl //判断当前传入的是否是课卡 if (bo.getProductType() == 0) { //获取模板相关信息 - CardTemplate oldTemplateInfo = SpringUtils.getBean(CardTemplateService.class).getOldTemplateInfo(bo.getCardTemplateId(), product.getBrandId()); - product.setMaxConsume(oldTemplateInfo.getPrice()).setMinConsume(oldTemplateInfo.getPrice()); + Row oldTemplateInfo = SpringUtils.getBean(CardTemplateService.class).getOldTemplateInfo(bo.getCardTemplateId(), product.getBrandId()); + product.setMaxConsume(oldTemplateInfo.getBigDecimal("price")).setMinConsume(oldTemplateInfo.getBigDecimal("price")); this.save(product); //课卡模板获取固定规格 ProductSpecification productSpecification = new ProductSpecification(); - productSpecification.setSpecificationNames(oldTemplateInfo.getName()); + productSpecification.setSpecificationNames(oldTemplateInfo.getString("name")); productSpecifications = new ArrayList(); productSpecifications.add(productSpecification); //记录 recordList = new ArrayList(); ProductRecord productRecord = new ProductRecord(); - productRecord.setRecordNum(2147483647).setRecordNames(productSpecification.getSpecificationNames()).setRecordPrice(oldTemplateInfo.getPrice()).setRecordPoints(0); + productRecord.setRecordNum(2147483647).setRecordNames(productSpecification.getSpecificationNames()).setRecordPrice(oldTemplateInfo.getBigDecimal("price")).setRecordPoints(0); recordList.add(productRecord); } else { //积分支付 @@ -449,8 +449,8 @@ public class ProductServiceImpl extends ServiceImpl impl if (productInfoVo.getProductType() == 0){ try { DataSourceKey.use("jambox"); - CardTemplate cardTemplate = SpringUtils.getBean(CardTemplateService.class).getOldTemplateInfo(productInfoVo.getCardTemplateId(), loginUserInfo.getString("brandId")); - productInfoVo.setCardTemplateName(cardTemplate.getName()); + Row cardTemplate = SpringUtils.getBean(CardTemplateService.class).getOldTemplateInfo(productInfoVo.getCardTemplateId(), loginUserInfo.getString("brandId")); + productInfoVo.setCardTemplateName(cardTemplate.getString("name")); } finally { DataSourceKey.clear(); } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/CarouselListVo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/CarouselListVo.java new file mode 100644 index 0000000..ddcb820 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/CarouselListVo.java @@ -0,0 +1,41 @@ +package com.cpop.mall.business.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-15 14:51 + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "Brand对象", description = "品牌表") +public class CarouselListVo { + + /** + * 主键 + */ + @ApiModelProperty(value = "主键") + private String id; + + /** + * 产品id + */ + @ApiModelProperty(value = "产品id") + private String productId; + + /** + * 图片地址 + */ + @ApiModelProperty(value = "图片地址") + private String picUrl; + + /** + * 排序 + */ + @ApiModelProperty(value = "排序") + private Integer orderNo; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/CarouselPageVo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/CarouselPageVo.java new file mode 100644 index 0000000..6788069 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/CarouselPageVo.java @@ -0,0 +1,54 @@ +package com.cpop.mall.business.vo; + +import com.mybatisflex.annotation.Id; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-15 12:54 + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "Brand对象", description = "品牌表") +public class CarouselPageVo { + + /** + * 主键 + */ + @ApiModelProperty(value = "主键") + private String id; + + /** + * 产品id + */ + @ApiModelProperty(value = "产品id") + private String productId; + + /** + * 产品名称 + */ + @ApiModelProperty(value = "产品名称") + private String productName; + + /** + * 图片地址 + */ + @ApiModelProperty(value = "图片地址") + private String picUrl; + + /** + * 排序 + */ + @ApiModelProperty(value = "排序") + private Integer orderNo; + + /** + * 上架状态(0:下架;1:上架) + */ + @ApiModelProperty(value = "上架状态(0:下架;1:上架)") + private Boolean upStatus; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/ProductSimpleVo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/ProductSimpleVo.java new file mode 100644 index 0000000..053acce --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/ProductSimpleVo.java @@ -0,0 +1,25 @@ +package com.cpop.mall.business.vo; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-15 14:06 + */ +@Data +public class ProductSimpleVo { + + /** + * 主键 + */ + @ApiModelProperty(value = "主键") + private String id; + + /** + * 商品名称 + */ + @ApiModelProperty(value = "商品名称") + private String productName; +} diff --git a/Cpop-Mall/src/main/resources/mapper/CarouselMapper.xml b/Cpop-Mall/src/main/resources/mapper/CarouselMapper.xml new file mode 100644 index 0000000..a28e3f1 --- /dev/null +++ b/Cpop-Mall/src/main/resources/mapper/CarouselMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-dev.yml b/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-dev.yml index 5c8cafc..c79cd5f 100644 --- a/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-dev.yml +++ b/Cpop-Oam/Cpop-Oam-Web/src/main/resources/application-dev.yml @@ -43,7 +43,9 @@ spring: mongodb: host: localhost port: 27017 - database: cpop-union + database: cpop-dev + username: Cpop + password: Admin@123 server: port: 9420 diff --git a/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopApiTests.java b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopApiTests.java index 43bc145..b13e32e 100644 --- a/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopApiTests.java +++ b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopApiTests.java @@ -1,6 +1,8 @@ package com.cpop.oam.web; import com.cpop.api.tencent.wxWork.handler.WebHookSendHandler; +import com.cpop.core.utils.RsaUtils; +import com.cpop.core.utils.SpringUtils; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -14,7 +16,7 @@ import java.util.List; * @createTime 2023/09/15 17:44 * @description */ -@SpringBootTest +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class CpopApiTests { @Autowired @@ -36,4 +38,12 @@ public class CpopApiTests { throw new RuntimeException(e); } } + + @Test + public void rsaDecrypt(){ + RsaUtils rsaUtils = SpringUtils.getBean(RsaUtils.class); + String jambox0831 = rsaUtils.encrypt("jambox0831"); + String decrypt = rsaUtils.decrypt(jambox0831); + System.out.println(decrypt); + } } diff --git a/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopCoreTests.java b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopCoreTests.java index d3837ad..f82d89c 100644 --- a/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopCoreTests.java +++ b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopCoreTests.java @@ -1,5 +1,6 @@ package com.cpop.oam.web; +import cn.hutool.core.util.IdUtil; import com.cpop.core.base.entity.LoginUser; import com.cpop.core.base.enums.OperationLogEnum; import com.cpop.core.base.enums.UserType; @@ -7,6 +8,7 @@ import com.cpop.core.service.CoreService; import com.cpop.core.utils.PasswordEncoder; import com.cpop.core.utils.RsaUtils; import com.cpop.core.utils.SpringUtils; +import com.cpop.core.utils.uuid.IdUtils; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -84,5 +86,36 @@ public class CpopCoreTests { System.out.println("encode加密:"+encode); } - + /** + * 初始化密钥对 + */ + @Test + public void initPublicOrPrivateKey() { + String snowflakeNextIdStr = IdUtil.getSnowflakeNextIdStr(); + String baseKeyRepository = "E:\\KeyRepository\\"; + String publicKeyFile = baseKeyRepository + "publicKey" + snowflakeNextIdStr; + String privateKeyFile = baseKeyRepository + "privateKey" + snowflakeNextIdStr; + Map keyPairMap = rsaUtils.initKeyPair(publicKeyFile, privateKeyFile); + String publicKey = keyPairMap.get("publicKey"); + String privateKey = keyPairMap.get("privateKey"); + System.out.println("公钥:"); + System.out.println(publicKey); + System.out.println(); + System.out.println("私钥:"); + System.out.println(privateKey); + System.out.println(); + String source = "Admin@123"; + System.out.println("待加密字符串:" + source); + System.out.println(); + String strEncrypt = rsaUtils.encrypt(source); + System.out.println("加密后的字符串:"); + System.out.println(strEncrypt); + System.out.println(); + String strDecrypt = rsaUtils.decrypt(strEncrypt); + System.out.println("解密后的字符串:"); + System.out.println(strDecrypt); + //加密 + String encode = SpringUtils.getBean(PasswordEncoder.class).encode("Admin@123"); + System.out.println("encode加密:" + encode); + } } diff --git a/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopDataSyncTests.java b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopDataSyncTests.java new file mode 100644 index 0000000..1b5818a --- /dev/null +++ b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopDataSyncTests.java @@ -0,0 +1,62 @@ +package com.cpop.oam.web; + +import com.alibaba.fastjson.JSONArray; +import com.cpop.common.utils.StringUtils; +import com.cpop.core.utils.SpringUtils; +import com.cpop.jambox.business.entity.Plug; +import com.cpop.jambox.business.entity.StoreExtend; +import com.cpop.jambox.business.service.PlugService; +import com.cpop.jambox.business.service.StoreExtendService; +import com.cpop.system.business.entity.Store; +import com.cpop.system.business.service.StoreService; +import com.mybatisflex.core.datasource.DataSourceKey; +import com.mybatisflex.core.row.DbChain; +import com.mybatisflex.core.row.Row; +import com.mybatisflex.core.row.RowUtil; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-16 17:17 + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class CpopDataSyncTests { + + /** + * 同步校区缺失数据 + * @author DB + * @since 2024/1/16 + */ + @Test + public void syncStoreInfo(){ + List rowList; + try { + DataSourceKey.use("jambox"); + rowList = DbChain.table("t_mechanism_info") + .select("tmi.store_id as storeCloudId") + .from("t_mechanism_info").as("tmi") + .leftJoin("t_signContract_mechanism").as("tsm").on("tsm.store_id = tmi.store_id") + .where("tmi.deleted = 1") + .and("DATEDIFF(\n" + + "\tDATE_FORMAT( tsm.end_time, '%Y-%m-%d' ),\n" + + "\tDATE_FORMAT( tmi.creation_time, '%Y-%m-%d' ))>= 300") + .list(); + } finally { + DataSourceKey.clear(); + } + //获取所有校区 + Map storeMap = SpringUtils.getBean(StoreExtendService.class).list().stream().collect(Collectors.toMap(StoreExtend::getStoreCloudId, StoreExtend::getStoreId)); + rowList.forEach(item -> { + item.set("id", storeMap.get(item.getString("storeCloudId"))); + item.set("have_active", true); + }); + List storeList = RowUtil.toEntityList(rowList, Store.class).stream().filter(item -> StringUtils.isNotBlank(item.getId())).collect(Collectors.toList()); + SpringUtils.getBean(StoreService.class).updateBatch(storeList); + } +} diff --git a/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopImportTests.java b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopImportTests.java index 65af0a4..8e9a782 100644 --- a/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopImportTests.java +++ b/Cpop-Oam/Cpop-Oam-Web/src/test/java/com/cpop/oam/web/CpopImportTests.java @@ -1578,18 +1578,16 @@ public class CpopImportTests { @Test public void batchUpdateStaffPassword(){ List cpSysUser = DbChain.table("cp_sys_user") - .select("id","phone_number","password") + .select("id","phone_number") .where("user_type = 'OAM_USER'") .and("is_delete = 0") .list(); List entityList = RowUtil.toEntityList(cpSysUser, SysUser.class); //加密 - PasswordEncoder passwordEncoder = SpringUtils.getBean(PasswordEncoder.class); RsaUtils rsaUtils = SpringUtils.getBean(RsaUtils.class); entityList.forEach(item -> { if (!StringUtils.equals("1", item.getId())) { String lastFourChars = "jambox" + item.getPhoneNumber().substring(item.getPhoneNumber().length() - 4); - item.setPassword(passwordEncoder.encode(lastFourChars)); item.setRsaPassword(rsaUtils.encrypt(lastFourChars)); } }); diff --git a/Cpop-Oam/pom.xml b/Cpop-Oam/pom.xml index ee8b262..5e2d5d8 100644 --- a/Cpop-Oam/pom.xml +++ b/Cpop-Oam/pom.xml @@ -19,10 +19,6 @@ com.cpop Cpop-Core - - com.cpop - Cpop-Api - com.cpop Cpop-Jambox diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/CloudUnionCallbackBo.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/CloudUnionCallbackBo.java new file mode 100644 index 0000000..20eda29 --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/bo/CloudUnionCallbackBo.java @@ -0,0 +1,163 @@ +package com.cpop.oam.business.bo; + +import com.cpop.system.business.bo.StoreBo; +import com.cpop.system.business.bo.SyncBrandAndStoreBo; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import java.sql.Date; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-16 11:35 + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "CloudUnionCallbackBo对象", description = "云回调统一入参") +public class CloudUnionCallbackBo { + + /** + * 回调枚举(DATA_IMPORT_CALLBACK:数据导入回调) + */ + @NotBlank(message = "回调枚举不能为空") + @ApiModelProperty(value = "回调枚举(DATA_IMPORT_CALLBACK:数据导入回调;SYNC_BRAND_AND_STORE_CALLBACK:同步品牌与校区)",required = true) + private String callbackEnum; + + /** + * 主要id + */ + @ApiModelProperty(value = "主要id") + private String mainId; + + /** + * 同步品牌与校区相关参数 + */ + @ApiModelProperty(value = "同步品牌与校区相关参数") + private SyncBrandAndStore syncBrandAndStore; + + @Data + @ApiModel("同步品牌与校区") + public class SyncBrandAndStore { + + /** + * 品牌 + */ + @ApiModelProperty(value = "品牌") + private SyncBrandAndStoreBo.BrandInfo brandInfo; + + /** + * 校区 + */ + @ApiModelProperty(value = "校区") + private SyncBrandAndStoreBo.StoreInfo storeInfo; + + + /** + * 品牌信息 + */ + @Data + public class BrandInfo { + + /** + * 云品牌id + */ + @ApiModelProperty(value = "云品牌id") + private String brandCloudId; + + /** + * 品牌名 + */ + @ApiModelProperty(value = "品牌名") + private String brandName; + } + + /** + * 校区信息 + */ + @Data + public class StoreInfo { + + /** + * 云品牌id + */ + @ApiModelProperty(value = "云校区id") + private String storeCloudId; + + /** + * 店铺/校区名 + */ + @ApiModelProperty(value = "店铺/校区名") + private String storeName; + + /** + * 店铺/校区地址 + */ + @ApiModelProperty(value = "店铺/校区地址") + private String storeAddr; + + /** + * 负责人 + */ + @ApiModelProperty(value = "负责人") + private String personCharge; + + /** + * 手机号 + */ + @ApiModelProperty(value = "手机号") + private String phone; + + /** + * 营业执照地址 + */ + @ApiModelProperty(value = "营业执照地址") + private String licenseAddr; + + /** + * 营业执照日期 + */ + @ApiModelProperty(value = "营业执照日期") + private Date licenseDate; + + /** + * 营业执照公司名 + */ + @ApiModelProperty(value = "营业执照公司名") + private String licenseName; + + /** + * 营业执照证书码 + */ + @ApiModelProperty(value = "营业执照证书码") + private String licenseCode; + + /** + * 营业执照法人名 + */ + @ApiModelProperty(value = "营业执照法人名") + private String licenseUserName; + + /** + * 营业执照图片地址 + */ + @ApiModelProperty(value = "营业执照图片地址") + private String licensePicUrl; + + /** + * 经度 + */ + @ApiModelProperty(value = "经度") + private String longitude; + + /** + * 纬度 + */ + @ApiModelProperty(value = "纬度") + private String latitude; + } + } +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/backstage/WxPayController.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/backstage/WxPayController.java index 032ba35..541bdbe 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/backstage/WxPayController.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/backstage/WxPayController.java @@ -52,7 +52,6 @@ public class WxPayController { * @date 2023/11/15 11:06 * @return: com.cpop.core.base.R */ - @PreAuthorize("@aps.hasPermission('brandStore:brand:update')") @ApiOperation("开通微信分账") @PutMapping("/changeBrandSharing") public R changeBrandSharing(@RequestBody @Validated ChangeWechatSharingBo bo) { diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/callback/CloudCallbackController.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/callback/CloudCallbackController.java new file mode 100644 index 0000000..aac0545 --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/controller/callback/CloudCallbackController.java @@ -0,0 +1,42 @@ +package com.cpop.oam.business.controller.callback; + +import com.cpop.core.annontation.SimpleSignatureCheck; +import com.cpop.core.base.R; +import com.cpop.oam.business.bo.CloudUnionCallbackBo; +import com.cpop.oam.framework.enums.CloudCallbackEnums; +import com.cpop.oam.framework.strategy.cloud.CloudCallbackStrategy; +import com.cpop.system.business.vo.SysFileVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-16 11:28 + */ +@Api(tags = "云回调controller") +@RestController +@RequestMapping("/cloudCallback") +public class CloudCallbackController { + + /** + * 云联合回调 + * @author DB + * @since 2024/1/16 + * @param callback 回调参数 + * @return R + */ + //@SimpleSignatureCheck + @ApiOperation("云联合回调") + @PostMapping("/cloudUnionCallback") + public R cloudUnionCallback(@RequestBody @Validated CloudUnionCallbackBo callback) { + CloudCallbackStrategy cloudCallbackStrategy = CloudCallbackEnums.valueOf(callback.getCallbackEnum()).getCloudCallbackStrategy(); + cloudCallbackStrategy.callback(callback); + return R.ok(); + } +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/BusinessServiceImpl.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/BusinessServiceImpl.java index 2347477..909dfad 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/BusinessServiceImpl.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/BusinessServiceImpl.java @@ -393,11 +393,7 @@ public class BusinessServiceImpl extends ServiceImpl i storeSign.setSignStaffId(loginUserInfo.getString("id")); storeSignService.save(storeSign); } - /*storeSign.setSignStaffId(loginUserInfo.getString("id")); - StoreRenewService storeRenewService = SpringUtils.getBean(StoreRenewService.class); - StoreRenewBo storeRenewBo = new StoreRenewBo(); - storeRenewBo.setStoreId(bo.getStoreId()).setRenewType(1).setRenewDesc("机构签约自动续费一年").setRenewDate(LocalDate.now().plusYears(1)); - storeRenewService.storeRenew(storeRenewBo);*/ + } } } diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/DataImportServiceImpl.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/DataImportServiceImpl.java index 2711ee8..cd0f146 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/DataImportServiceImpl.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/DataImportServiceImpl.java @@ -34,12 +34,14 @@ import com.cpop.oam.business.mapper.DataImportMapper; import com.cpop.oam.business.service.DataImportService; import com.qcloud.cos.model.UploadResult; import lombok.extern.slf4j.Slf4j; +import org.apache.http.conn.ConnectTimeoutException; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; +import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.List; @@ -106,6 +108,12 @@ public class DataImportServiceImpl extends ServiceImpl(), - "==========有一条校区数据导入失败==========\n" + - "导入id:" + dataImport.getId() + "\n" + - "校区id:" + dataImport.getStoreId() + "\n", - true); - } catch (IOException ex) { - throw new ServiceException("发送消息通知失败!"); - } + log.info("数据导入超时,导入id为:{}", dataImport.getId()); } } diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/TaskServiceImpl.java b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/TaskServiceImpl.java index 22cd726..9252054 100644 --- a/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/TaskServiceImpl.java +++ b/Cpop-Oam/src/main/java/com/cpop/oam/business/service/impl/TaskServiceImpl.java @@ -741,7 +741,7 @@ public class TaskServiceImpl extends ServiceImpl implements Ta //所有技术员工信息 Map staffMap = SpringUtils.getBean(StaffService.class).queryChain() .leftJoin(SYS_USER).on(SYS_USER.ID.eq(STAFF.USER_ID)) - .where(STAFF.STAFF_TYPE.eq(0)) + .where(STAFF.STAFF_TYPE.in(0, 2)) .and(SYS_USER.STATUS.eq(1)) .list() .stream().collect(Collectors.toMap(Staff::getId, item -> item)); diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/framework/enums/CloudCallbackEnums.java b/Cpop-Oam/src/main/java/com/cpop/oam/framework/enums/CloudCallbackEnums.java new file mode 100644 index 0000000..ec8cefb --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/framework/enums/CloudCallbackEnums.java @@ -0,0 +1,50 @@ +package com.cpop.oam.framework.enums; + +import com.cpop.core.utils.SpringUtils; +import com.cpop.oam.framework.strategy.cloud.CloudCallbackStrategy; +import com.cpop.oam.framework.strategy.cloud.CloudDataImportCallbackStrategy; +import com.cpop.oam.framework.strategy.cloud.CloudSyncBrandOrStoreCallbackStrategy; +import lombok.Getter; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-16 11:38 + */ +@Getter +public enum CloudCallbackEnums { + + /** + * 数据导入回调 + */ + DATA_IMPORT_CALLBACK(0, "dataImportCallback", SpringUtils.getBean(CloudDataImportCallbackStrategy.class)), + /** + * 同步品牌与校区回调 + */ + SYNC_BRAND_AND_STORE_CALLBACK(1, "syncBrandAndStoreCallback", SpringUtils.getBean(CloudSyncBrandOrStoreCallbackStrategy.class)) + ; + + CloudCallbackEnums(Integer code, String name, CloudCallbackStrategy cloudCallbackStrategy) { + this.code = code; + this.name = name; + this.cloudCallbackStrategy = cloudCallbackStrategy; + } + + private Integer code; + + private String name; + + private CloudCallbackStrategy cloudCallbackStrategy; + + public void setCode(Integer code) { + this.code = code; + } + + public void setName(String name) { + this.name = name; + } + + public void setCloudCallbackStrategy(CloudCallbackStrategy cloudCallbackStrategy) { + this.cloudCallbackStrategy = cloudCallbackStrategy; + } +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudCallbackStrategy.java b/Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudCallbackStrategy.java new file mode 100644 index 0000000..860fb32 --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudCallbackStrategy.java @@ -0,0 +1,19 @@ +package com.cpop.oam.framework.strategy.cloud; + +import com.cpop.oam.business.bo.CloudUnionCallbackBo; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-16 11:42 + */ +public interface CloudCallbackStrategy { + + /** + * 回调 + * @author DB + * @since 2024/1/16 + */ + void callback(CloudUnionCallbackBo callback); + +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudDataImportCallbackStrategy.java b/Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudDataImportCallbackStrategy.java new file mode 100644 index 0000000..5f49680 --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudDataImportCallbackStrategy.java @@ -0,0 +1,43 @@ +package com.cpop.oam.framework.strategy.cloud; + +import com.cpop.api.tencent.wxWork.handler.WebHookSendHandler; +import com.cpop.core.base.exception.ServiceException; +import com.cpop.core.utils.SpringUtils; +import com.cpop.oam.business.bo.CloudUnionCallbackBo; +import com.cpop.oam.business.entity.DataImport; +import com.cpop.oam.business.service.DataImportService; +import com.cpop.oam.framework.constant.WebHookKeyConstant; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.ArrayList; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-16 11:44 + */ +@Component +public class CloudDataImportCallbackStrategy implements CloudCallbackStrategy { + + /** + * 回调策略 + */ + @Override + public void callback(CloudUnionCallbackBo callback) { + DataImportService dataImportService = SpringUtils.getBean(DataImportService.class); + DataImport dataImport = dataImportService.getById(callback.getMainId()); + //数据导入异常通知 + try { + SpringUtils.getBean(WebHookSendHandler.class) + .webHookSendText(WebHookKeyConstant.PRODUCT_BOT, + new ArrayList<>(), + "==========有一条校区数据导入失败==========\n" + + "导入id:" + dataImport.getId() + "\n" + + "校区id:" + dataImport.getStoreId() + "\n", + true); + } catch (IOException ex) { + throw new ServiceException("发送消息通知失败!"); + } + } +} diff --git a/Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudSyncBrandOrStoreCallbackStrategy.java b/Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudSyncBrandOrStoreCallbackStrategy.java new file mode 100644 index 0000000..2ae39fd --- /dev/null +++ b/Cpop-Oam/src/main/java/com/cpop/oam/framework/strategy/cloud/CloudSyncBrandOrStoreCallbackStrategy.java @@ -0,0 +1,84 @@ +package com.cpop.oam.framework.strategy.cloud; + +import com.cpop.common.utils.bean.BeanUtils; +import com.cpop.core.base.entity.LoginUser; +import com.cpop.core.base.enums.SourceType; +import com.cpop.core.utils.SecurityUtils; +import com.cpop.core.utils.SpringUtils; +import com.cpop.oam.business.bo.CloudUnionCallbackBo; +import com.cpop.system.business.bo.SyncBrandAndStoreBo; +import com.cpop.system.business.entity.Brand; +import com.cpop.system.business.entity.Store; +import com.cpop.system.business.entity.StoreLicense; +import com.cpop.system.business.service.BrandService; +import com.cpop.system.business.service.StoreLicenseService; +import com.cpop.system.business.service.StoreService; +import com.mybatisflex.core.row.Db; +import com.mybatisflex.core.row.DbChain; +import com.mybatisflex.core.row.Row; +import com.mybatisflex.core.row.RowKey; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * + * @author DB + * @version 1.0.0 + * @since 2024-01-16 14:37 + */ +@Component +public class CloudSyncBrandOrStoreCallbackStrategy implements CloudCallbackStrategy{ + + /** + * 回调策略 + * @author DB + * @since 2024/1/16 + * @param callback 回调参数 + */ + @Override + public void callback(CloudUnionCallbackBo callback) { + SyncBrandAndStoreBo.BrandInfo brandInfo = callback.getSyncBrandAndStore().getBrandInfo(); + //查询品牌 + Row brandExtend = DbChain.table("cp_j_brand_extend").where("brand_cloud_id = ?", brandInfo.getBrandCloudId()).one(); + Brand brand; + LocalDateTime now = LocalDateTime.now(); + LoginUser loginUser = SecurityUtils.getInstance().getLoginUser(); + BrandService brandService = SpringUtils.getBean(BrandService.class); + if (brandExtend.isEmpty()) { + brand = new Brand(); + brand.setBrandName(brandInfo.getBrandName()).setSourceType(SourceType.JAMBOX.toString()); + brandService.save(brand); + //保存拓展 + RowKey brandKey = RowKey.SNOW_FLAKE_ID; + DbChain.table("cp_j_brand_extend") + .setId(brandKey) + .set("brand_id", brand.getId()) + .set("brand_cloud_id", brandInfo.getBrandCloudId()) + .set("create_time", now) + .set("update_time", now) + .set("create_user_id", loginUser == null ? "1" : loginUser.getUserId()) + .set("update_user_id", loginUser == null ? "1" : loginUser.getUserId()) + .save(); + }else { + brand = brandService.getById(brandExtend.getString("brandId")); + } + SyncBrandAndStoreBo.StoreInfo storeInfo = callback.getSyncBrandAndStore().getStoreInfo(); + Store store = BeanUtils.mapToClass(storeInfo, Store.class); + store.setBrandId(brand.getId()).setSourceType(SourceType.JAMBOX.toString()); + SpringUtils.getBean(StoreService.class).save(store); + //拓展 + Row row = Row.ofKey(RowKey.SNOW_FLAKE_ID); + row.set("store_cloud_id", storeInfo.getStoreCloudId()); + row.set("store_id", store.getId()); + row.set("create_time", now); + row.set("update_time", now); + row.set("create_user_id", loginUser == null ? "1" : loginUser.getUserId()); + row.set("update_user_id", loginUser == null ? "1" : loginUser.getUserId()); + Db.insert("cp_j_store_extend",row); + //营业执照 + StoreLicense storeLicense = BeanUtils.mapToClass(storeInfo, StoreLicense.class); + storeLicense.setStoreId(store.getId()); + SpringUtils.getBean(StoreLicenseService.class).save(storeLicense); + } +} diff --git a/Cpop-System/pom.xml b/Cpop-System/pom.xml index 16be23f..710365c 100644 --- a/Cpop-System/pom.xml +++ b/Cpop-System/pom.xml @@ -24,6 +24,10 @@ org.springframework.boot spring-boot-starter-websocket + + com.cpop + Cpop-Api + diff --git a/Cpop-System/src/main/java/com/cpop/system/business/bo/StoreBo.java b/Cpop-System/src/main/java/com/cpop/system/business/bo/StoreBo.java new file mode 100644 index 0000000..85c5c38 --- /dev/null +++ b/Cpop-System/src/main/java/com/cpop/system/business/bo/StoreBo.java @@ -0,0 +1,60 @@ +package com.cpop.system.business.bo; + +import com.mybatisflex.annotation.Id; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; + +/** + * @author DB + * @version 1.0.0 + * @since 2024-01-15 11:04 + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "StoreBo对象") +public class StoreBo { + + /** + * 店铺/校区id + */ + @ApiModelProperty(value = "店铺/校区id") + private String id; + + /** + * 品牌id + */ + @ApiModelProperty(value = "品牌id") + private String brandId; + + /** + * 店铺/校区名 + */ + @NotBlank(message = "不能为空") + @ApiModelProperty(value = "店铺/校区名",required = true) + private String storeName; + + /** + * 负责人 + */ + @NotBlank(message = "负责人不能为空") + @ApiModelProperty(value = "负责人",required = true) + private String personCharge; + + /** + * 手机号 + */ + @NotBlank(message = "手机号不能为空") + @ApiModelProperty(value = "手机号",required = true) + private String phone; + + /** + * 微信商户id + */ + @ApiModelProperty(value = "微信商户id") + private String wxMchId; + +} diff --git a/Cpop-System/src/main/java/com/cpop/system/business/bo/StoreRenewBo.java b/Cpop-System/src/main/java/com/cpop/system/business/bo/StoreRenewBo.java index 000b252..a333d60 100644 --- a/Cpop-System/src/main/java/com/cpop/system/business/bo/StoreRenewBo.java +++ b/Cpop-System/src/main/java/com/cpop/system/business/bo/StoreRenewBo.java @@ -37,9 +37,8 @@ public class StoreRenewBo { /** * 续费日期 */ - @NotNull(message = "不能为空") @DateTimeFormat(pattern = "yyyy-MM-dd") - @ApiModelProperty(value = "续费日期", required = true) + @ApiModelProperty(value = "续费日期") private LocalDate renewDate; /** @@ -60,6 +59,6 @@ public class StoreRenewBo { * 类型(0:续费;1:延期) */ @NotNull(message = "类型不能为空") - @ApiModelProperty(value = "类型(0:续费;1:延期)", required = true) + @ApiModelProperty(value = "类型(0:续费;1:延期;2:激活)", required = true) private Integer renewType; } diff --git a/Cpop-System/src/main/java/com/cpop/system/business/controller/StoreController.java b/Cpop-System/src/main/java/com/cpop/system/business/controller/StoreController.java index b6bdcb4..54e04ec 100644 --- a/Cpop-System/src/main/java/com/cpop/system/business/controller/StoreController.java +++ b/Cpop-System/src/main/java/com/cpop/system/business/controller/StoreController.java @@ -1,6 +1,7 @@ package com.cpop.system.business.controller; import com.cpop.core.base.R; +import com.cpop.system.business.bo.StoreBo; import com.cpop.system.business.bo.StorePageBo; import com.cpop.system.business.bo.StoreRenewBo; import com.cpop.system.business.service.StoreRenewService; @@ -59,4 +60,18 @@ public class StoreController { storeRenewService.storeRenew(bo); return R.ok(); } + + /** + * 更新校区 + * @author DB + * @since 2024/1/15 + * @param bo 请求参数 + * @return R + */ + @ApiOperation("更新校区") + @PutMapping("/updateStore") + public R updateStore(@RequestBody @Validated StoreBo bo) { + storeService.updateStore(bo); + return R.ok(); + } } diff --git a/Cpop-System/src/main/java/com/cpop/system/business/controller/SysCommonController.java b/Cpop-System/src/main/java/com/cpop/system/business/controller/SysCommonController.java index e123bf1..89c9f31 100644 --- a/Cpop-System/src/main/java/com/cpop/system/business/controller/SysCommonController.java +++ b/Cpop-System/src/main/java/com/cpop/system/business/controller/SysCommonController.java @@ -96,6 +96,7 @@ public class SysCommonController { * @param bo 请求参数 * @return R */ + @Deprecated @ApiOperation("小程序同步品牌和校区") @PostMapping("/miniSyncBrandAndStore") public R miniSyncBrandAndStore(@RequestBody SyncBrandAndStoreBo bo) { diff --git a/Cpop-System/src/main/java/com/cpop/system/business/entity/Store.java b/Cpop-System/src/main/java/com/cpop/system/business/entity/Store.java index 7dc4bc2..7499213 100644 --- a/Cpop-System/src/main/java/com/cpop/system/business/entity/Store.java +++ b/Cpop-System/src/main/java/com/cpop/system/business/entity/Store.java @@ -55,12 +55,12 @@ public class Store extends BaseEntity implements Serializable { /** * 是否有顾问 */ - private String haveCounselor; + private Boolean haveCounselor; /** * 是否激活 */ - private String haveActive; + private Boolean haveActive; /** * 品牌id diff --git a/Cpop-System/src/main/java/com/cpop/system/business/service/StoreService.java b/Cpop-System/src/main/java/com/cpop/system/business/service/StoreService.java index b23e2a0..9da5be5 100644 --- a/Cpop-System/src/main/java/com/cpop/system/business/service/StoreService.java +++ b/Cpop-System/src/main/java/com/cpop/system/business/service/StoreService.java @@ -1,5 +1,6 @@ package com.cpop.system.business.service; +import com.cpop.system.business.bo.StoreBo; import com.cpop.system.business.bo.StorePageBo; import com.cpop.system.business.bo.SyncBrandAndStoreBo; import com.cpop.system.business.vo.StorePageVo; @@ -30,4 +31,12 @@ public interface StoreService extends IService { * @param bo 请求参数 */ void miniSyncBrandAndStore(SyncBrandAndStoreBo bo); + + /** + * 更新校区 + * @author DB + * @since 2024/1/15 + * @param bo 请求参数 + */ + void updateStore(StoreBo bo); } diff --git a/Cpop-System/src/main/java/com/cpop/system/business/service/impl/StoreRenewServiceImpl.java b/Cpop-System/src/main/java/com/cpop/system/business/service/impl/StoreRenewServiceImpl.java index 052dec6..7f5603e 100644 --- a/Cpop-System/src/main/java/com/cpop/system/business/service/impl/StoreRenewServiceImpl.java +++ b/Cpop-System/src/main/java/com/cpop/system/business/service/impl/StoreRenewServiceImpl.java @@ -15,6 +15,7 @@ import com.cpop.system.framework.constant.SystemRedisKey; import com.mybatisflex.core.datasource.DataSourceKey; import com.mybatisflex.core.row.DbChain; import com.mybatisflex.core.row.Row; +import com.mybatisflex.core.row.RowKey; import com.mybatisflex.spring.service.impl.ServiceImpl; import com.cpop.system.business.entity.StoreRenew; import com.cpop.system.business.mapper.StoreRenewMapper; @@ -30,6 +31,7 @@ import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisClientConfig; import javax.annotation.Resource; +import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.concurrent.TimeUnit; @@ -54,19 +56,22 @@ public class StoreRenewServiceImpl extends ServiceImpl implements public Page getStorePage(StorePageBo bo) { PageDomain pageDomain = SqlUtils.getInstance().getPageDomain(); return this.getMapper().paginateAs(Page.of(pageDomain.getPageNum(), pageDomain.getPageSize()), - QueryWrapper.create().select(STORE.ID, STORE.STORE_NAME, STORE.SOURCE_TYPE, STORE.CREATE_TIME, STORE.STORE_ADDR, STORE.PERSON_CHARGE, STORE.PHONE, STORE.HAVE_ACTIVE, STORE.HAVE_COUNSELOR) + QueryWrapper.create().select(STORE.ID, STORE.STORE_NAME, STORE.SOURCE_TYPE, STORE.CREATE_TIME, STORE.STORE_ADDR, STORE.PERSON_CHARGE, STORE.PHONE, STORE.HAVE_ACTIVE, + STORE.HAVE_COUNSELOR, STORE.WX_MCH_ID) .select(STORE_SIGN.EXPIRE_DATE) - .select(BRAND.BRAND_NAME,BRAND.ID.as(StorePageVo::getBrandId)) + .select(BRAND.BRAND_NAME, BRAND.ID.as(StorePageVo::getBrandId)) .select("cp_j_store_extend.store_cloud_id as storeCloudId") .from(STORE) .leftJoin(STORE_SIGN).on(STORE_SIGN.STORE_ID.eq(STORE.ID)) @@ -124,4 +128,29 @@ public class StoreServiceImpl extends ServiceImpl implements storeLicense.setStoreId(store.getId()); SpringUtils.getBean(StoreLicenseService.class).save(storeLicense); } + + /** + * 更新校区 + * @author DB + * @since 2024/1/15 + * @param bo 请求参数 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStore(StoreBo bo) { + Store store = BeanUtils.mapToClass(bo, Store.class); + this.updateById(store); + //获取云信息 + Row row = Db.selectOneByQuery("cp_j_store_extend", QueryWrapper.create() + .select("cjse.store_cloud_id", "cjbe.brand_cloud_id") + .from("cp_j_store_extend").as("cjse") + .leftJoin("cp_sys_store").as("css").on("css.id = cjse.store_id") + .leftJoin("cp_j_brand_extend").as("cjbe").on("cjbe.brand_id = css.brand_id") + .where("cjse.store_id = ?", store.getId())); + CloudStoreDto cloudStoreDto = BeanUtils.mapToClass(store, CloudStoreDto.class); + cloudStoreDto.setBrandCloudId(row.getString("brandCloudId")); + cloudStoreDto.setStoreCloudId(row.getString("storeCloudId")); + //云更新 + SpringUtils.getBean(CloudStoreHandler.class).updateStore(cloudStoreDto); + } } diff --git a/Cpop-System/src/main/java/com/cpop/system/business/vo/StorePageVo.java b/Cpop-System/src/main/java/com/cpop/system/business/vo/StorePageVo.java index a7069ee..f399feb 100644 --- a/Cpop-System/src/main/java/com/cpop/system/business/vo/StorePageVo.java +++ b/Cpop-System/src/main/java/com/cpop/system/business/vo/StorePageVo.java @@ -101,4 +101,10 @@ public class StorePageVo implements Serializable { @ApiModelProperty("是否激活") private Boolean haveActive; + /** + * 微信商户号 + */ + @ApiModelProperty("微信商户号") + private String wxMchId; + }