commit fcffced7184a04f15fa95aa47c0e2dfcbc0dbad4 Author: eric <465889110@qq.com> Date: Sun Aug 17 14:11:08 2025 +0800 no message diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d7f4db --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ +logs/ +src/main/resources/rebel.xml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fd863fa --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +# 使用 OpenJDK 8 镜像构建 +FROM openjdk:8-jdk +# 添加作者信息 +LABEL maintainer="123879394@qq.com" + +WORKDIR /app +# 复制 jar 包 +COPY target/*.jar app.jar +# 设置 JVM 参数和启动命令 +ENTRYPOINT ["java", "-jar", "-Xms64m", "-Xmx128m", "app.jar"] \ No newline at end of file diff --git a/Dockerfile.buildagent b/Dockerfile.buildagent new file mode 100644 index 0000000..f893f6c --- /dev/null +++ b/Dockerfile.buildagent @@ -0,0 +1,15 @@ +# 使用 JDK 8 作为构建环境 +FROM openjdk:8-jdk + +# 使用阿里云的 apt 镜像源(Debian 11 bullseye) +RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && \ + sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list + +# 更新包列表并安装 Maven 和 Git +RUN apt update && \ + apt install -y maven git && \ + mvn --version && \ + git --version + +# 设置工作目录 +WORKDIR /home/jenkins/workspace \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..c65a3ea --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,85 @@ +pipeline { + agent any +// tools { +// maven 'M3' // 必须在 Jenkins → Manage Jenkins → Global Tool Configuration 中配置过 +// } + environment { + APP_NAME = "sczx_sync" + DOCKER_IMAGE = "${APP_NAME}:latest" + CONTAINER_NAME = "${APP_NAME}-container" + } + + stages { +// stage('Checkout') { +// steps { +// echo "📦 正在拉取代码..." +// git branch: 'main', url: 'http://115.190.8.52:3000/sczx_group/sczx_order.git' +// } +// } + + stage('Build with Maven in JDK 8') { + agent { + dockerfile { + filename "Dockerfile.buildagent" + } + } + steps { + echo "🛠️ 正在使用 Maven 构建..." + sh 'mvn clean package -s settings.xml' + } + } + + stage('Check Jar File') { + agent any + steps { + sh 'ls -la target/' // 确保 jar 文件存在 + } + } + + stage('Build Docker Image') { + agent any + steps { + echo "🐋 正在构建 Docker 镜像..." + sh 'docker build -t "$DOCKER_IMAGE" .' + } + } + + stage('Stop Old Container') { + agent any + steps { + echo "🛑 正在停止旧的容器(如果存在)..." + sh ''' + if [ "$(docker ps -f 'name=sczx_sync-container' --format '{{.Status}}')" ]; then + docker stop sczx_sync-container + docker rm sczx_sync-container + fi + ''' + } + } + + stage('Run New Container') { + agent any + steps { + echo "🟢 正在运行新的容器..." + sh """ + docker run -d \ + --name \${CONTAINER_NAME} \ + --network sczx-net \ + -p 8016:8016 \ + -e JAVA_OPTS="-Xms256m -Xmx512m -Duser.timezone=Asia/Shanghai" \ + --restart always \ + \${DOCKER_IMAGE} + """ + } + } + } + + post { + success { + echo "🎉 构建成功!" + } + failure { + echo "❌ 构建失败,请检查日志!" + } + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ea786ff --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +readme \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..af8a580 --- /dev/null +++ b/pom.xml @@ -0,0 +1,234 @@ + + + 4.0.0 + + com.sczx + sczx_sync + 1.0.0 + jar + + sczx_sync + sczx_sync service + + + 1.8 + 2.3.12.RELEASE + Hoxton.SR12 + 2.2.9.RELEASE + + + + + org.springframework.boot + spring-boot-starter-parent + 2.3.12.RELEASE + + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + com.alibaba.cloud + spring-cloud-alibaba-dependencies + ${spring-cloud-alibaba.version} + pom + import + + + + + + + + + org.springframework.boot + spring-boot-starter + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + org.springframework.boot + spring-boot-configuration-processor + + + + org.springframework.cloud + spring-cloud-commons + + + + + org.projectlombok + lombok + 1.18.30 + + + + + + org.springframework.retry + spring-retry + 1.3.1 + + + + org.springframework.boot + spring-boot-starter-aop + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.3.1 + + + + + com.baomidou + mybatis-plus-boot-starter + 3.5.3.1 + + + + + + mysql + mysql-connector-java + 8.0.33 + + + + + io.springfox + springfox-swagger2 + 2.9.2 + + + + io.springfox + springfox-swagger-ui + 2.9.2 + + + + + javax.xml.bind + jaxb-api + 2.3.1 + + + + io.projectreactor + reactor-core + 3.2.2.RELEASE + + + + + org.mapstruct + mapstruct + 1.5.5.Final + + + + + org.mapstruct + mapstruct-processor + 1.5.5.Final + provided + + + + + com.alibaba + fastjson + 1.2.83 + + + + + + sczx_sync + + + src/main/resources + + *.yml + + true + + + src/main/resources + + *.yml + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + + \ No newline at end of file diff --git a/settings.xml b/settings.xml new file mode 100644 index 0000000..06004f8 --- /dev/null +++ b/settings.xml @@ -0,0 +1,12 @@ + + + + aliyun-maven + * + Aliyun Maven + https://maven.aliyun.com/repository/public + + + \ No newline at end of file diff --git a/src/main/java/com/sczx/sync/Application.java b/src/main/java/com/sczx/sync/Application.java new file mode 100644 index 0000000..f307db1 --- /dev/null +++ b/src/main/java/com/sczx/sync/Application.java @@ -0,0 +1,29 @@ +package com.sczx.sync; + +import com.sczx.sync.utils.ComputerInfo; +import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.Environment; +import org.springframework.retry.annotation.EnableRetry; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import java.io.IOException; + +@Slf4j +@SpringBootApplication +@EnableDiscoveryClient // 启用服务注册与发现 +@EnableRetry +@EnableTransactionManagement +@MapperScan("com.sczx.sync.mapper") // 扫描 Mapper 接口 +public class Application { + + public static void main(String[] args) throws IOException { + ConfigurableApplicationContext context = SpringApplication.run(Application.class, args); + Environment environment = context.getBean(Environment.class); + log.info("启动成功,后端服务API地址:http://{}:{}/swagger-ui.html", ComputerInfo.getIpAddr(), environment.getProperty("server.port")); + } +} diff --git a/src/main/java/com/sczx/sync/common/IApiCode.java b/src/main/java/com/sczx/sync/common/IApiCode.java new file mode 100644 index 0000000..5243b0f --- /dev/null +++ b/src/main/java/com/sczx/sync/common/IApiCode.java @@ -0,0 +1,12 @@ +package com.sczx.sync.common; + +/** + * @Author: 张黎 + * @Date: 2025/07/09/20:20 + * @Description: + */ +public interface IApiCode { + String getCode(); + + String getMsg(); +} diff --git a/src/main/java/com/sczx/sync/common/Result.java b/src/main/java/com/sczx/sync/common/Result.java new file mode 100644 index 0000000..9126fd9 --- /dev/null +++ b/src/main/java/com/sczx/sync/common/Result.java @@ -0,0 +1,123 @@ +package com.sczx.sync.common; + + + + +import com.sczx.sync.common.enums.ApiErrorCode; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; +import org.apache.commons.lang.StringUtils; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** + * @Author: 张黎 + * @Date: 2025/07/09/20:25 + * @Description: + */ +@ApiModel(value = "公共返回结果") +@Builder +@Data +public class Result implements Serializable { + private static final long serialVersionUID = 1331134667810352183L; + @ApiModelProperty(value = "成功标识") + private boolean success; + @ApiModelProperty(value = "返回编码") + private String code; + @ApiModelProperty(value = "返回信息说明") + private String msg; + private String issue; + @ApiModelProperty(value = "返回数据") + private T data; + + public Result(boolean success, String code, String msg, String issue, T data) { + this.success = success; + this.code = code; + this.msg = msg; + this.issue = issue; + this.data = data; + } + + public static Result result(IApiCode apiCode) { + return result(apiCode, (Object)null); + } + + public static Result result(IApiCode apiCode, Object data) { + return result(apiCode, apiCode.getMsg(), data); + } + + public static Result result(IApiCode apiCode, String issue, Object data) { + return result((IApiCode)apiCode, (String)null, issue, data); + } + + public static Result result(IApiCode apiCode, String msg, String issue, Object data) { + String message = apiCode.getMsg(); + if (StringUtils.isNotBlank(msg)) { + message = msg; + } + + return result(apiCode.getCode(), message, issue, data); + } + + public static Result result(String code, String msg, String issue, Object data) { + return builder().code(code).success("0".equals(code)).msg(msg).issue(issue).data(data).build(); + } + + public static Result ok() { + return ok((Object)null); + } + + public static Result ok(Object data) { + return result(ApiErrorCode.SUCCESS, data); + } + + public static Result ok(String key, Object value) { + Map map = new HashMap(1); + map.put(key, value); + return ok(map); + } + + public static Result fail(String msg) { + return result((IApiCode)ApiErrorCode.FAIL, msg, msg, (Object)null); + } + + public static Result fail(IApiCode apiCode) { + return result(apiCode, (Object)null); + } + + public static Result fail(IApiCode apiCode, String issue) { + return result(apiCode, issue, (Object)null); + } + + public static Result fail(String code, String msg) { + return result((String)code, msg, msg, (Object)null); + } + + public static Result fail(String code, String msg, String issue) { + return result((String)code, msg, issue, (Object)null); + } + + public static Result fail(String code, String msg, String issue, Object data) { + return result(code, msg, issue, data); + } + + public static Result fail(IApiCode apiCode, String issue, Object data) { + if (ApiErrorCode.SUCCESS == apiCode) { + throw new RuntimeException("失败结果状态码不能为" + ApiErrorCode.SUCCESS.getCode()); + } else { + return result(apiCode, issue, data); + } + } + + public static Result fail(String key, Object value) { + Map map = new HashMap(); + map.put(key, value); + return result(ApiErrorCode.FAIL, map); + } + public Result() { + } +} diff --git a/src/main/java/com/sczx/sync/common/enums/ApiErrorCode.java b/src/main/java/com/sczx/sync/common/enums/ApiErrorCode.java new file mode 100644 index 0000000..a3e2256 --- /dev/null +++ b/src/main/java/com/sczx/sync/common/enums/ApiErrorCode.java @@ -0,0 +1,55 @@ +package com.sczx.sync.common.enums; + + +import com.sczx.sync.common.IApiCode; + +/** + * @Author: 张黎 + * @Date: 2025/07/09/20:22 + * @Description: + */ +public enum ApiErrorCode implements IApiCode { + SUCCESS("0", "操作成功"), + ARG_ERROR("401000", "参数错误"), + NOT_PERMISSION("401001", "没有权限"), + HTTP_MEDIA_TYPE_NOT_SUPPORTED_ERROR("401002", "media类型出错"), + HTTP_METHOD_NOT_ALLOW_ERROR("401003", "http请求method错误"), + BODY_NOT_MATCH("401004", "请求的数据格式不符!"), + NOT_FOUND("404000", "你请求的路径不存在"), + UNAUTHORIZED("404001", "非法访问"), + FAIL("500000", "操作失败"), + INNER_ERROR("500001", "服务器内部异常"); + + private final String code; + private final String msg; + + private ApiErrorCode(String code, String msg) { + this.code = code; + this.msg = msg; + } + + public static ApiErrorCode getApiCode(String code) { + ApiErrorCode[] ecs = values(); + ApiErrorCode[] var2 = ecs; + int var3 = ecs.length; + + for(int var4 = 0; var4 < var3; ++var4) { + ApiErrorCode ec = var2[var4]; + if (ec.getCode().equals(code)) { + return ec; + } + } + + return SUCCESS; + } + + @Override + public String getCode() { + return this.code; + } + + @Override + public String getMsg() { + return this.msg; + } +} diff --git a/src/main/java/com/sczx/sync/common/enums/MiniProgramTypeEnum.java b/src/main/java/com/sczx/sync/common/enums/MiniProgramTypeEnum.java new file mode 100644 index 0000000..d906938 --- /dev/null +++ b/src/main/java/com/sczx/sync/common/enums/MiniProgramTypeEnum.java @@ -0,0 +1,19 @@ +package com.sczx.sync.common.enums; + +import lombok.Getter; + +/** + * 小程序类型枚举 + */ +@Getter +public enum MiniProgramTypeEnum { + WECHAT("wechat"), + ALIPAY("alipay"); + + private final String type; + + MiniProgramTypeEnum(String type) { + this.type = type; + } + +} diff --git a/src/main/java/com/sczx/sync/common/enums/YesOrNoEnum.java b/src/main/java/com/sczx/sync/common/enums/YesOrNoEnum.java new file mode 100644 index 0000000..7e8bb9d --- /dev/null +++ b/src/main/java/com/sczx/sync/common/enums/YesOrNoEnum.java @@ -0,0 +1,20 @@ +package com.sczx.sync.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @Author: 张黎 + * @Date: 2024/03/08/17:42 + * @Description: 报考场次:统考unified,区域专场areaSpecial + */ +@AllArgsConstructor +@Getter +public enum YesOrNoEnum { + YES(1, "是"), + NO(0, "否"), + ; + private final Integer code; + + private final String msg; +} diff --git a/src/main/java/com/sczx/sync/config/AsyncConfig.java b/src/main/java/com/sczx/sync/config/AsyncConfig.java new file mode 100644 index 0000000..3821d74 --- /dev/null +++ b/src/main/java/com/sczx/sync/config/AsyncConfig.java @@ -0,0 +1,54 @@ +package com.sczx.sync.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 异步配置类 + * + * @author sczx + */ +@Configuration +@EnableAsync +public class AsyncConfig { + + /** + * 异步任务执行器 + */ + @Bean("taskExecutor") + public Executor taskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + + // 核心线程数 + executor.setCorePoolSize(10); + + // 最大线程数 + executor.setMaxPoolSize(20); + + // 队列容量 + executor.setQueueCapacity(500); + + // 线程空闲时间 + executor.setKeepAliveSeconds(60); + + // 线程名前缀 + executor.setThreadNamePrefix("async-task-"); + + // 拒绝策略 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + + // 等待所有任务结束后再关闭线程池 + executor.setWaitForTasksToCompleteOnShutdown(true); + + // 等待时间 + executor.setAwaitTerminationSeconds(60); + + executor.initialize(); + return executor; + } +} diff --git a/src/main/java/com/sczx/sync/config/MyBatisPlusConfig.java b/src/main/java/com/sczx/sync/config/MyBatisPlusConfig.java new file mode 100644 index 0000000..a97e3f0 --- /dev/null +++ b/src/main/java/com/sczx/sync/config/MyBatisPlusConfig.java @@ -0,0 +1,18 @@ +package com.sczx.sync.config; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MyBatisPlusConfig { + + + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + return interceptor; + } +} diff --git a/src/main/java/com/sczx/sync/config/SwaggerConfig.java b/src/main/java/com/sczx/sync/config/SwaggerConfig.java new file mode 100644 index 0000000..4b9bcfb --- /dev/null +++ b/src/main/java/com/sczx/sync/config/SwaggerConfig.java @@ -0,0 +1,47 @@ +package com.sczx.sync.config; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.ParameterBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.schema.ModelRef; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import java.util.Arrays; + +@Configuration +@EnableSwagger2 +public class SwaggerConfig { + @Bean + public Docket createRestApi() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .select() + .apis(RequestHandlerSelectors.basePackage("com.sczx.sync.controller")) // 修改为你的 controller 包路径 + .paths(PathSelectors.any()) + .build() + .globalOperationParameters(Arrays.asList( + new ParameterBuilder() + .name("Authorization") + .description("Bearer Token") + .modelRef(new ModelRef("string")) + .parameterType("header") + .required(true) + .build() + )); + } + + private ApiInfo apiInfo() { + return new ApiInfoBuilder() + .title("订单服务接口文档") + .description("sczx_order订单服务接口文档") + .version("1.0") + .build(); + } +} diff --git a/src/main/java/com/sczx/sync/config/ThirdPartyConfig.java b/src/main/java/com/sczx/sync/config/ThirdPartyConfig.java new file mode 100644 index 0000000..692763b --- /dev/null +++ b/src/main/java/com/sczx/sync/config/ThirdPartyConfig.java @@ -0,0 +1,25 @@ +package com.sczx.sync.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * 第三方平台配置实体 + * + * @author sczx + */ +@Component +public class ThirdPartyConfig { + + @Value("${third-party.platform.app-id}") + private String appId; + @Value("${third-party.platform.access-token}") + private String accessToken; + @Value("${third-party.platform.api-url}") + private String apiUrl; + @Value("${third-party.platform.timeout}") + private int timeOut; + @Value("${third-party.platform.retry-times}") + private int retryTimes; + +} diff --git a/src/main/java/com/sczx/sync/controller/ReceiveBatteryController.java b/src/main/java/com/sczx/sync/controller/ReceiveBatteryController.java new file mode 100644 index 0000000..bb9bd51 --- /dev/null +++ b/src/main/java/com/sczx/sync/controller/ReceiveBatteryController.java @@ -0,0 +1,49 @@ +package com.sczx.sync.controller; + + +import com.sczx.sync.common.Result; +import com.sczx.sync.common.enums.ApiErrorCode; +import com.sczx.sync.dto.DataRceiveReq; +import com.sczx.sync.dto.ReceiveMealReq; +import com.sczx.sync.mapper.CompanyStoreMapper; +import com.sczx.sync.service.ReceiveService; +import com.sczx.sync.service.SendDataService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +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; +import static com.sczx.sync.common.enums.ApiErrorCode.NOT_PERMISSION; + +/** + * 数据同步控制器 + * + * @author sczx + */ +@Api(value = "租电平台推送数据至租车平台", tags = "租电平台推送数据至租车平台") +@Slf4j +@RestController +@RequestMapping("/b2c") +public class ReceiveBatteryController { + + + @Autowired + private ReceiveService receiveService; + + @ApiOperation(value = "接收租电数据接口") + @PostMapping("/batterymeal") + public Result batterymeal(@RequestBody String receiveMealReq){ + Boolean bool = receiveService.recceiveMeals(receiveMealReq); + if (!bool.booleanValue()){ + return Result.fail(NOT_PERMISSION); + } + return Result.ok(); + } + + + + +} diff --git a/src/main/java/com/sczx/sync/controller/SendDataController.java b/src/main/java/com/sczx/sync/controller/SendDataController.java new file mode 100644 index 0000000..56e00a6 --- /dev/null +++ b/src/main/java/com/sczx/sync/controller/SendDataController.java @@ -0,0 +1,86 @@ +package com.sczx.sync.controller; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.TypeReference; +import com.sczx.sync.common.Result; +import com.sczx.sync.dto.DataRceiveReq; +import com.sczx.sync.mapper.CompanyStoreMapper; +import com.sczx.sync.service.SendDataService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +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; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +/** + * 数据同步控制器 + * + * @author sczx + */ +@Api(value = "接收平台同步数据接口", tags = "接收平台同步数据接口") +@Slf4j +@RestController +@RequestMapping("/send") +public class SendDataController { + + @Autowired + private SendDataService sendDataService; + + @Autowired + private CompanyStoreMapper companyStoreMapper; + + @ApiOperation(value = "接收需同步数据接口") + @PostMapping("/dataToBattery") + public Result sendDataToBattery(@RequestBody DataRceiveReq dataRceiveReq){ + return Result.ok(sendDataService.recAndSend(dataRceiveReq)); + } + +// @ApiOperation(value = "c2btest") +// @PostMapping("/json") +// public Result json(@RequestBody String dataRceiveReq){ +// +// Map returnMap = new HashMap<>(); +// +// JSONObject jsonObject=JSON.parseObject(dataRceiveReq.toString()); +// jsonObject.remove("status"); +// jsonObject.remove("msg"); +// JSONObject jsonObj = JSON.parseObject(jsonObject.toJSONString()); +// for (Map.Entry entry : jsonObj.entrySet()) { +// String keyStr = entry.getKey(); +// switch (keyStr){ +// case "order_no": +// System.out.println(entry.getValue()); +// long numberLong3 = Long.parseLong(entry.getValue().toString()); +// int vv3 = 30; +// long ll3 = vv3; +// companyStoreMapper.updateOdId(numberLong3,vv3); +// break; +// case "store_id": +// System.out.println(entry.getValue().getClass()); +// long numberLong = Long.parseLong(entry.getValue().toString()); +// int vv = 55; +// long ll = vv; +// companyStoreMapper.updateStoreId(numberLong,vv); +// break; +// case "operator_id": +// System.out.println(entry.getValue()) ; +// long numberLong2 = Long.parseLong(entry.getValue().toString()); +// int vv2 = 10; +// long ll2 = vv2; +// companyStoreMapper.updateOpeId(numberLong2,vv2); +// break; +// } +// } +// +// } + +} diff --git a/src/main/java/com/sczx/sync/dto/DataRceiveReq.java b/src/main/java/com/sczx/sync/dto/DataRceiveReq.java new file mode 100644 index 0000000..2aa3b17 --- /dev/null +++ b/src/main/java/com/sczx/sync/dto/DataRceiveReq.java @@ -0,0 +1,22 @@ +package com.sczx.sync.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Map; + +@Data +@ApiModel +public class DataRceiveReq { + + @ApiModelProperty("传入数据类型") + private String dataType; + + @ApiModelProperty("租车平台对应表主键ID") + private Long Cid; + + @ApiModelProperty("传入数据Map") + private Map businessData; + +} diff --git a/src/main/java/com/sczx/sync/dto/ReceiveMealReq.java b/src/main/java/com/sczx/sync/dto/ReceiveMealReq.java new file mode 100644 index 0000000..420f6a4 --- /dev/null +++ b/src/main/java/com/sczx/sync/dto/ReceiveMealReq.java @@ -0,0 +1,22 @@ +package com.sczx.sync.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.Map; + +@Data +@ApiModel +public class ReceiveMealReq { + + @ApiModelProperty("APPID") + private String appid; + + @ApiModelProperty("租车平台对应表主键ID") + private String access_token; + + @ApiModelProperty("传入数据Map") + private Map Data; + +} diff --git a/src/main/java/com/sczx/sync/entity/Response.java b/src/main/java/com/sczx/sync/entity/Response.java new file mode 100644 index 0000000..a07f9c4 --- /dev/null +++ b/src/main/java/com/sczx/sync/entity/Response.java @@ -0,0 +1,31 @@ +package com.sczx.sync.entity; + +public class Response { + private String status; + private String msg; + private T data; + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getMessage() { + return msg; + } + + public void setMessage(String message) { + this.msg = message; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} \ No newline at end of file diff --git a/src/main/java/com/sczx/sync/exception/BizException.java b/src/main/java/com/sczx/sync/exception/BizException.java new file mode 100644 index 0000000..7e7bab7 --- /dev/null +++ b/src/main/java/com/sczx/sync/exception/BizException.java @@ -0,0 +1,85 @@ +package com.sczx.sync.exception; + + +import com.sczx.sync.common.IApiCode; +import com.sczx.sync.common.enums.ApiErrorCode; + +/** + * + * @author zhangli + */ +public class BizException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** + * 错误码 + */ + protected String errorCode; + /** + * 错误信息 + */ + protected String errorMsg; + + public BizException() { + super(); + } + + public BizException(IApiCode apiCode) { + super(apiCode.getCode()); + this.errorCode = apiCode.getCode(); + this.errorMsg = apiCode.getMsg(); + } + + public BizException(IApiCode apiCode, Throwable cause) { + super(apiCode.getCode(), cause); + this.errorCode = apiCode.getCode(); + this.errorMsg = apiCode.getMsg(); + } + + public BizException(String errorMsg) { + super(errorMsg); + this.errorCode = ApiErrorCode.FAIL.getCode(); + this.errorMsg = errorMsg; + } + + public BizException(String errorCode, String errorMsg) { + super(errorCode); + this.errorCode = errorCode; + this.errorMsg = errorMsg; + } + + public BizException(String errorCode, String errorMsg, Throwable cause) { + super(errorCode, cause); + this.errorCode = errorCode; + this.errorMsg = errorMsg; + } + + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } + + @Override + public String getMessage() { + return errorMsg; + } + + @Override + public Throwable fillInStackTrace() { + return this; + } + +} diff --git a/src/main/java/com/sczx/sync/exception/GlobalExceptionHandler.java b/src/main/java/com/sczx/sync/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..f41b100 --- /dev/null +++ b/src/main/java/com/sczx/sync/exception/GlobalExceptionHandler.java @@ -0,0 +1,50 @@ +package com.sczx.sync.exception; + + + +import com.sczx.sync.common.Result; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; + + +/** + * @author zhangli + */ +@Slf4j +@ControllerAdvice +public class GlobalExceptionHandler { + + + /** + * 处理自定义的业务异常 + * + * @param req + * @param e + * @return + */ + @ExceptionHandler(value = BizException.class) + @ResponseBody + public Result bizExceptionHandler(HttpServletRequest req, BizException e) { + log.warn("发生业务异常!原因是:{}", e.getErrorMsg(), e); + return Result.fail(e.getErrorCode(), e.getErrorMsg()); + } + + @ExceptionHandler(value = InnerException.class) + @ResponseBody + public Result innerExceptionHandler(HttpServletRequest req, InnerException e) { + log.error("发生服务内部异常!原因是:{}", e.getErrorMsg(), e); + return Result.fail(e.getErrorCode(), e.getErrorMsg()); + } + + @ExceptionHandler(value = Exception.class) + @ResponseBody + public Result exceptionHandler(HttpServletRequest req, Exception e) { + log.error("意料外异常!原因是:{}", e.getMessage(), e); + return Result.fail("99999", "系统内部异常"); + } + +} diff --git a/src/main/java/com/sczx/sync/exception/InnerException.java b/src/main/java/com/sczx/sync/exception/InnerException.java new file mode 100644 index 0000000..dc412aa --- /dev/null +++ b/src/main/java/com/sczx/sync/exception/InnerException.java @@ -0,0 +1,86 @@ +package com.sczx.sync.exception; + + +import com.sczx.sync.common.IApiCode; +import com.sczx.sync.common.enums.ApiErrorCode; + +/** + * + * @author zhangli + + */ +public class InnerException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** + * 错误码 + */ + protected String errorCode; + /** + * 错误信息 + */ + protected String errorMsg; + + public InnerException() { + super(); + } + + public InnerException(IApiCode apiCode) { + super(apiCode.getCode()); + this.errorCode = apiCode.getCode(); + this.errorMsg = apiCode.getMsg(); + } + + public InnerException(IApiCode apiCode, Throwable cause) { + super(apiCode.getCode(), cause); + this.errorCode = apiCode.getCode(); + this.errorMsg = apiCode.getMsg(); + } + + public InnerException(String errorMsg) { + super(errorMsg); + this.errorCode = ApiErrorCode.INNER_ERROR.getCode(); + this.errorMsg = errorMsg; + } + + public InnerException(String errorCode, String errorMsg) { + super(errorCode); + this.errorCode = errorCode; + this.errorMsg = errorMsg; + } + + public InnerException(String errorCode, String errorMsg, Throwable cause) { + super(errorCode, cause); + this.errorCode = errorCode; + this.errorMsg = errorMsg; + } + + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } + + @Override + public String getMessage() { + return errorMsg; + } + + @Override + public Throwable fillInStackTrace() { + return this; + } + +} diff --git a/src/main/java/com/sczx/sync/mapper/BatteryMealMapper.java b/src/main/java/com/sczx/sync/mapper/BatteryMealMapper.java new file mode 100644 index 0000000..27e6e47 --- /dev/null +++ b/src/main/java/com/sczx/sync/mapper/BatteryMealMapper.java @@ -0,0 +1,13 @@ +package com.sczx.sync.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sczx.sync.po.SyncDataInfo; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BatteryMealMapper extends BaseMapper { + + int insertZcRentBatteyRule(SyncDataInfo syncDataInfo); + + int updateBatteryRule(SyncDataInfo syncDataInfo); +} diff --git a/src/main/java/com/sczx/sync/mapper/CompanyStoreMapper.java b/src/main/java/com/sczx/sync/mapper/CompanyStoreMapper.java new file mode 100644 index 0000000..7558b4c --- /dev/null +++ b/src/main/java/com/sczx/sync/mapper/CompanyStoreMapper.java @@ -0,0 +1,13 @@ +package com.sczx.sync.mapper; + +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface CompanyStoreMapper { + + int updateStoreId(long bpStoreId, long cId); + + int updateOpeId(long bOpId, long cId); + + int updateOdId(long bOdId, long cId); +} diff --git a/src/main/java/com/sczx/sync/mapper/DataReceiveRecordMapper.java b/src/main/java/com/sczx/sync/mapper/DataReceiveRecordMapper.java new file mode 100644 index 0000000..de2dedb --- /dev/null +++ b/src/main/java/com/sczx/sync/mapper/DataReceiveRecordMapper.java @@ -0,0 +1,14 @@ +package com.sczx.sync.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sczx.sync.po.DataReceivePo; +import org.apache.ibatis.annotations.Mapper; + +/** + * 数据接收记录Mapper接口 + * + * @author sczx + */ +@Mapper +public interface DataReceiveRecordMapper extends BaseMapper { +} diff --git a/src/main/java/com/sczx/sync/po/DataReceivePo.java b/src/main/java/com/sczx/sync/po/DataReceivePo.java new file mode 100644 index 0000000..fc2a507 --- /dev/null +++ b/src/main/java/com/sczx/sync/po/DataReceivePo.java @@ -0,0 +1,101 @@ +package com.sczx.sync.po; + +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 数据接收记录实体 + * + * @author sczx + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("data_receive_record") +public class DataReceivePo { + + /** + * 主键ID + */ + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @TableField("app_id") + private String appId; + + @TableField("access_token") + private String accessToken; + + /** + * 接口数据类型 + */ + @TableField("data_type") + private String dataType; + + @TableField("c_id") + private Long Cid; + + + /** + * 请求数据 + */ + @TableField("request_data") + private String requestData; + + /** + * 请求时间 + */ + @TableField("request_time") + private LocalDateTime requestTime; + + /** + * 状态:0-待转发,1-转发中,2-转发成功,3-转发失败 + */ + @TableField("status") + private Integer status; + + /** + * 转发时间 + */ + @TableField("forward_time") + private LocalDateTime forwardTime; + + /** + * 响应数据 + */ + @TableField("response_data") + private String responseData; + + /** + * 错误信息 + */ + @TableField("error_message") + private String errorMessage; + + /** + * 重试次数 + */ + @TableField("retry_count") + private Integer retryCount; + + /** + * 创建时间 + */ + @TableField(value = "create_time", fill = FieldFill.INSERT) + private LocalDateTime createTime; + + /** + * 更新时间 + */ + @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + /** + * 是否删除 + */ + @TableLogic + @TableField("deleted") + private Integer deleted; +} diff --git a/src/main/java/com/sczx/sync/po/SyncDataInfo.java b/src/main/java/com/sczx/sync/po/SyncDataInfo.java new file mode 100644 index 0000000..8d705b0 --- /dev/null +++ b/src/main/java/com/sczx/sync/po/SyncDataInfo.java @@ -0,0 +1,150 @@ +package com.sczx.sync.po; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@TableName("zc_rent_battey_rule") +public class SyncDataInfo implements Serializable { + private static final long serialVersionUID = 1L; + @TableField("id") + private Long id; + @TableField("meal_id") + private Integer mealId; + @TableField("title") + private String title; + @TableField("detail") + private String detail; + @TableField("voltage") + private Integer voltage; + @TableField("ah") + private Integer ah; + @TableField("rent_price") + private Double rentPrice; + @TableField("duration_type") + private Integer durationType; + @TableField("duration") + private Integer duration; + @TableField("city_id") + private Integer cityId; + @TableField("province_id") + private Integer provinceId; + @TableField("category_id") + private Integer categoryId; + @TableField("operator_id") + private Integer operatorId; + + public LocalDateTime getSyncTime() { + return syncTime; + } + + public void setSyncTime(LocalDateTime syncTime) { + this.syncTime = syncTime; + } + + private LocalDateTime syncTime; + + // Getters and Setters + public void setId(Long id) { this.id = id;} + + public Long getId() { return id; } + + public Integer getMealId() { + return mealId; + } + + public void setMealId(Integer mealId) { + this.mealId = mealId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getDetail() { + return detail; + } + + public void setDetail(String detail) { + this.detail = detail; + } + + public Integer getVoltage() { + return voltage; + } + + public void setVoltage(Integer voltage) { + this.voltage = voltage; + } + + public Integer getAh() { + return ah; + } + + public void setAh(Integer ah) { + this.ah = ah; + } + + public Double getRentPrice() { + return rentPrice; + } + + public void setRentPrice(Double rentPrice) { + this.rentPrice = rentPrice; + } + + public Integer getDurationType() { + return durationType; + } + + public void setDurationType(Integer durationType) { + this.durationType = durationType; + } + + public Integer getDuration() { + return duration; + } + + public void setDuration(Integer duration) { + this.duration = duration; + } + + public Integer getCityId() { + return cityId; + } + + public void setCityId(Integer cityId) { + this.cityId = cityId; + } + + public Integer getProvinceId() { + return provinceId; + } + + public void setProvinceId(Integer provinceId) { + this.provinceId = provinceId; + } + + public Integer getCategoryId() { + return categoryId; + } + + public void setCategoryId(Integer categoryId) { + this.categoryId = categoryId; + } + + public Integer getOperatorId() { + return operatorId; + } + + public void setOperatorId(Integer operatorId) { + this.operatorId = operatorId; + } + +} \ No newline at end of file diff --git a/src/main/java/com/sczx/sync/po/SyncRequest.java b/src/main/java/com/sczx/sync/po/SyncRequest.java new file mode 100644 index 0000000..ed252fe --- /dev/null +++ b/src/main/java/com/sczx/sync/po/SyncRequest.java @@ -0,0 +1,42 @@ +package com.sczx.sync.po; + +import com.baomidou.mybatisplus.annotation.TableField; +import java.io.Serializable; + +public class SyncRequest implements Serializable { + private static final long serialVersionUID = 1L; + + private String appid; + + private String accessToken; + + @TableField("Data") + private SyncDataInfo data; + + // Getters and Setters + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public SyncDataInfo getData() { + return data; + } + + public void setData(SyncDataInfo data) { + this.data = data; + } + + +} \ No newline at end of file diff --git a/src/main/java/com/sczx/sync/service/ReceiveService.java b/src/main/java/com/sczx/sync/service/ReceiveService.java new file mode 100644 index 0000000..3163edc --- /dev/null +++ b/src/main/java/com/sczx/sync/service/ReceiveService.java @@ -0,0 +1,8 @@ +package com.sczx.sync.service; + + +import com.sczx.sync.dto.ReceiveMealReq; + +public interface ReceiveService { + boolean recceiveMeals(String request); +} diff --git a/src/main/java/com/sczx/sync/service/SendDataService.java b/src/main/java/com/sczx/sync/service/SendDataService.java new file mode 100644 index 0000000..1417d89 --- /dev/null +++ b/src/main/java/com/sczx/sync/service/SendDataService.java @@ -0,0 +1,28 @@ +package com.sczx.sync.service; + +import com.sczx.sync.dto.DataRceiveReq; + +public interface SendDataService { + + /** + * 接收数据并异步转发 + * + * @param request 数据接收请求 + * @return 是否接收成功 + */ + boolean recAndSend(DataRceiveReq request); + + /** + * 异步转发数据到第三方平台 + * + * @param recordId 记录ID + */ + void forwardToThirdParty(Long recordId,String url); + + /** + * 重试失败的数据转发 + * + * @param recordId 记录ID + */ + void retryForward(Long recordId); +} diff --git a/src/main/java/com/sczx/sync/service/ThirdPartyForwardService.java b/src/main/java/com/sczx/sync/service/ThirdPartyForwardService.java new file mode 100644 index 0000000..e8b47f8 --- /dev/null +++ b/src/main/java/com/sczx/sync/service/ThirdPartyForwardService.java @@ -0,0 +1,12 @@ +package com.sczx.sync.service; + + +/** + * 第三方平台转发服务接口 + * + * @author sczx + */ +public interface ThirdPartyForwardService { + + String forwardData(String datatype,String data); +} diff --git a/src/main/java/com/sczx/sync/service/impl/ReceiveServiceImpl.java b/src/main/java/com/sczx/sync/service/impl/ReceiveServiceImpl.java new file mode 100644 index 0000000..f227830 --- /dev/null +++ b/src/main/java/com/sczx/sync/service/impl/ReceiveServiceImpl.java @@ -0,0 +1,65 @@ +package com.sczx.sync.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.sczx.sync.dto.DataRceiveReq; +import com.sczx.sync.dto.ReceiveMealReq; +import com.sczx.sync.mapper.BatteryMealMapper; +import com.sczx.sync.mapper.CompanyStoreMapper; +import com.sczx.sync.mapper.DataReceiveRecordMapper; +import com.sczx.sync.po.DataReceivePo; +import com.sczx.sync.po.SyncDataInfo; +import com.sczx.sync.po.SyncRequest; +import com.sczx.sync.service.ReceiveService; +import com.sczx.sync.service.ThirdPartyForwardService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.Map; + +@Slf4j +@Service +@Component +public class ReceiveServiceImpl implements ReceiveService { + + + @Autowired + private BatteryMealMapper batteryMealMapper; + + + @Value("${battery-platform.appid}") + private String appId; + @Value("${battery-platform.access-token}") + private String accessToken; + + @Override + public boolean recceiveMeals(String request) { + + SyncRequest meals = JSON.parseObject(request, SyncRequest.class); + + if(!meals.getAppid().equals(appId)||!meals.getAccessToken().equals(accessToken)){ + return false; + } + SyncDataInfo syncDataInfo = meals.getData(); + syncDataInfo.setSyncTime(LocalDateTime.now()); + QueryWrapper syncDataInfoQueryWrapper = new QueryWrapper<>(); + QueryWrapper eq = syncDataInfoQueryWrapper.eq("meal_id", meals.getData().getMealId()); + if(batteryMealMapper.selectOne(eq)!=null){ + + batteryMealMapper.updateBatteryRule(syncDataInfo); + }else { + batteryMealMapper.insertZcRentBatteyRule(syncDataInfo); + } + + + + return true; + } +} diff --git a/src/main/java/com/sczx/sync/service/impl/SendDataServiceImpl.java b/src/main/java/com/sczx/sync/service/impl/SendDataServiceImpl.java new file mode 100644 index 0000000..6d83c6e --- /dev/null +++ b/src/main/java/com/sczx/sync/service/impl/SendDataServiceImpl.java @@ -0,0 +1,197 @@ +package com.sczx.sync.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.sczx.sync.dto.DataRceiveReq; + +import com.sczx.sync.mapper.CompanyStoreMapper; +import com.sczx.sync.mapper.DataReceiveRecordMapper; +import com.sczx.sync.po.DataReceivePo; +import com.sczx.sync.service.SendDataService; +import com.sczx.sync.service.ThirdPartyForwardService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; +import java.util.Map; + +@Slf4j +@Service +@Component +public class SendDataServiceImpl implements SendDataService { + + @Autowired + private DataReceiveRecordMapper dataReceiveRecordMapper; + + @Autowired + private CompanyStoreMapper companyStoreMapper; + + @Autowired + private ThirdPartyForwardService thirdPartyForwardService; + + @Value("${third-party.platform.api-url}") + private String URL; + @Value("${third-party.platform.app-id}") + private String appId; + @Value("${third-party.platform.access-token}") + private String accessToken; + + + @Override + @Transactional + public boolean recAndSend(DataRceiveReq dataRceiveReq) { + String dataType = dataRceiveReq.getDataType(); + + System.out.println("dataType "+dataType); + + switch (dataType){ + case "userinfo": + + return saveRecord(dataRceiveReq,URL+"/"+dataType); + case "companyinfo": + return saveRecord(dataRceiveReq,URL+"/"+dataType); + + case "storeinfo": + return saveRecord(dataRceiveReq,URL+"/"+dataType); + + case "batteryorder": + return saveRecord(dataRceiveReq,URL+"/"+dataType); + + } + + return false; + } + + @Override + @Async + public void forwardToThirdParty(Long recordId,String url) { + try { + // 更新状态为转发中 + DataReceivePo record = dataReceiveRecordMapper.selectById(recordId); + if (record == null) { + log.error("记录不存在,ID: {}", recordId); + return; + } + + record.setStatus(1); // 转发中 + dataReceiveRecordMapper.updateById(record); + + String dataType = record.getDataType(); + // 转发数据 + String response = thirdPartyForwardService.forwardData(dataType,record.getRequestData()); + + modifyData(dataType,record.getCid(),response); + + // 更新记录状态 + record.setStatus(2); // 转发成功 + record.setForwardTime(LocalDateTime.now()); + record.setResponseData(response); + dataReceiveRecordMapper.updateById(record); + + log.info("数据转发成功,记录ID: {}", recordId); + } catch (Exception e) { + log.error("数据转发失败,记录ID: {}", recordId, e); + updateRecordStatus(recordId, 3, e.getMessage()); + } + } + + @Override + @Async + public void retryForward(Long recordId) { + try { + DataReceivePo record = dataReceiveRecordMapper.selectById(recordId); + if (record == null) { + log.error("记录不存在,ID: {}", recordId); + return; + } + + // 检查重试次数 + if (record.getRetryCount() >= 3) { + log.warn("重试次数已达上限,记录ID: {}", recordId); + return; + } + + // 增加重试次数 + record.setRetryCount(record.getRetryCount() + 1); + dataReceiveRecordMapper.updateById(record); + // 重新转发 + forwardToThirdParty(recordId,URL+"/"+record.getDataType()); + } catch (Exception e) { + log.error("重试转发失败,记录ID: {}", recordId, e); + } + } + + /** + * 更新记录状态 + */ + private void updateRecordStatus(Long recordId, Integer status, String errorMessage) { + try { + DataReceivePo record = new DataReceivePo(); + record.setId(recordId); + record.setStatus(status); + record.setErrorMessage(errorMessage); + record.setUpdateTime(LocalDateTime.now()); + dataReceiveRecordMapper.updateById(record); + } catch (Exception e) { + log.error("更新记录状态失败,记录ID: {}", recordId, e); + } + } + + private boolean saveRecord(DataRceiveReq request,String url) { + System.out.println(url); + + try { + + // 保存接收记录 + DataReceivePo record = new DataReceivePo(); + record.setDataType(request.getDataType()); + record.setCid(request.getCid()); + record.setRequestData(JSON.toJSONString(request.getBusinessData())); + record.setRequestTime(LocalDateTime.now()); + record.setStatus(0); // 待转发 + record.setRetryCount(0); + + dataReceiveRecordMapper.insert(record); + + // 异步转发数据 + forwardToThirdParty(record.getId(),url); + + log.info("数据接收成功,记录ID: {}", record.getId()); + return true; + } catch (Exception e) { + log.error("数据接收失败", e); + return false; + } + } + + private void modifyData(String dataType,Long Cid,String response){ + + JSONObject jsonObject=JSON.parseObject(response.toString()); + jsonObject.remove("status"); + jsonObject.remove("msg"); + JSONObject jsonObj = JSON.parseObject(jsonObject.toJSONString()); + for (Map.Entry entry : jsonObj.entrySet()) { + System.out.println(entry.getKey() + ":" + entry.getValue()); + String keyStr = entry.getKey(); + long bId = Long.parseLong(entry.getValue().toString()); + switch (keyStr){ + case "order_no": + companyStoreMapper.updateOdId(bId,Cid); + break; + case "store_id": + companyStoreMapper.updateStoreId(bId,Cid); + break; + case "operator_id": + companyStoreMapper.updateOpeId(bId,Cid); + break; + } + } + + } + +} diff --git a/src/main/java/com/sczx/sync/service/impl/ThirdPartyForwardServiceImpl.java b/src/main/java/com/sczx/sync/service/impl/ThirdPartyForwardServiceImpl.java new file mode 100644 index 0000000..8ad2965 --- /dev/null +++ b/src/main/java/com/sczx/sync/service/impl/ThirdPartyForwardServiceImpl.java @@ -0,0 +1,112 @@ +package com.sczx.sync.service.impl; + +import com.alibaba.fastjson.JSON; +import com.sczx.sync.config.ThirdPartyConfig; +import com.sczx.sync.service.ThirdPartyForwardService; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpEntity; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +/** + * 第三方平台转发服务实现类 + * + * @author sczx + */ +@Slf4j +@Service +public class ThirdPartyForwardServiceImpl implements ThirdPartyForwardService { + + @Value("${third-party.platform.api-url}") + private String URL; + @Value("${third-party.platform.app-id}") + private String appId; + @Value("${third-party.platform.access-token}") + private String accessToken; + @Value("${third-party.platform.api-url}") + private String apiUrl; + @Value("${third-party.platform.timeout}") + private int timeOut; + @Value("${third-party.platform.retry-times}") + private int retryTimes; + + @Override + public String forwardData(String datatype,String data) { + CloseableHttpClient httpClient = null; + CloseableHttpResponse response = null; + + + + try { + // 创建HTTP客户端 + httpClient = HttpClients.createDefault(); + String url = URL+'/'+datatype; + // 创建POST请求 + HttpPost httpPost = new HttpPost(url); + + // 设置请求头 + httpPost.setHeader("Content-Type", "application/json;charset=UTF-8"); + httpPost.setHeader("User-Agent", "SczxSync/1.0"); + + // 构建请求体 + Map requestBody = new HashMap<>(); + requestBody.put("appId", appId); + requestBody.put("accessToken",accessToken); + requestBody.put("data", JSON.parse(data)); + requestBody.put("timestamp", System.currentTimeMillis()); + + StringEntity entity = new StringEntity(JSON.toJSONString(requestBody), StandardCharsets.UTF_8); + httpPost.setEntity(entity); + + // 设置超时配置 + RequestConfig requestConfig = RequestConfig.custom() + .setConnectTimeout(timeOut) + .setSocketTimeout(timeOut) + .build(); + httpPost.setConfig(requestConfig); + + log.info("开始转发数据到第三方平台: {}, 数据: {}", url, data); + + // 执行请求 + response = httpClient.execute(httpPost); + HttpEntity responseEntity = response.getEntity(); + String responseBody = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8); + + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == 200) { + log.info("数据转发成功,响应: {}", responseBody); + return responseBody; + } else { + log.error("数据转发失败,状态码: {}, 响应: {}", statusCode, responseBody); + throw new RuntimeException("第三方平台响应异常,状态码: " + statusCode); + } + + } catch (Exception e) { + log.error("数据转发异常", e); + throw new RuntimeException("数据转发异常: " + e.getMessage(), e); + } finally { + // 关闭资源 + try { + if (response != null) { + response.close(); + } + if (httpClient != null) { + httpClient.close(); + } + } catch (Exception e) { + log.error("关闭HTTP客户端异常", e); + } + } + } +} diff --git a/src/main/java/com/sczx/sync/utils/ComputerInfo.java b/src/main/java/com/sczx/sync/utils/ComputerInfo.java new file mode 100644 index 0000000..75a88a3 --- /dev/null +++ b/src/main/java/com/sczx/sync/utils/ComputerInfo.java @@ -0,0 +1,159 @@ +package com.sczx.sync.utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/* + * <取网卡物理地址-- + * 1.在Windows,Linux系统下均可用; + * 2.通过ipconifg,ifconfig获得计算机信息; + * 3.再用模式匹配方式查找MAC地址,与操作系统的语言无关> + * + * //* Description: <取计算机名--从环境变量中取> + * abstract 限制继承/创建实例 + */ +public abstract class ComputerInfo { + private static String macAddressStr = null; + private static String computerName = System.getenv().get("COMPUTERNAME"); + + private static final String[] windowsCommand = { "ipconfig", "/all" }; + private static final String[] linuxCommand = { "/sbin/ifconfig", "-a" }; + private static final String[] macCommand = { "ifconfig", "-a" }; + private static final Pattern macPattern = Pattern.compile(".*((:?[0-9a-f]{2}[-:]){5}[0-9a-f]{2}).*", + Pattern.CASE_INSENSITIVE); + + /** + * 获取多个网卡地址 + * + * @return + * @throws IOException + */ + private final static List getMacAddressList() throws IOException { + final ArrayList macAddressList = new ArrayList(); + final String os = System.getProperty("os.name"); + final String command[]; + + if (os.startsWith("Windows")) { + command = windowsCommand; + } else if (os.startsWith("Linux")) { + command = linuxCommand; + } else if (os.startsWith("Mac")){ + command = macCommand; + } + else { + throw new IOException("Unknow operating system:" + os); + } + // 执行命令 + final Process process = Runtime.getRuntime().exec(command); + + BufferedReader bufReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + for (String line = null; (line = bufReader.readLine()) != null;) { + Matcher matcher = macPattern.matcher(line); + if (matcher.matches()) { + macAddressList.add(matcher.group(1)); + // macAddressList.add(matcher.group(1).replaceAll("[-:]", + // ""));//去掉MAC中的“-” + } + } + + process.destroy(); + bufReader.close(); + return macAddressList; + } + + /** + * 获取一个网卡地址(多个网卡时从中获取一个) + * + * @return + */ + public static String getMacAddress() { + if (macAddressStr == null || macAddressStr.equals("")) { + StringBuffer sb = new StringBuffer(); // 存放多个网卡地址用,目前只取一个非0000000000E0隧道的值 + try { + List macList = getMacAddressList(); + for (Iterator iter = macList.iterator(); iter.hasNext();) { + String amac = iter.next(); + if (!"0000000000E0".equals(amac)) { + sb.append(amac); + break; + } + } + } catch (IOException e) { + e.printStackTrace(); + } + + macAddressStr = sb.toString(); + + } + + return macAddressStr; + } + + /** + * 获取电脑名 + * + * @return + */ + public static String getComputerName() { + if (computerName == null || computerName.equals("")) { + computerName = System.getenv().get("COMPUTERNAME"); + } + return computerName; + } + + /** + * 获取客户端IP地址 + * + * @return + */ + public static String getIpAddrAndName() throws IOException { + return InetAddress.getLocalHost().toString(); + } + + /** + * 获取客户端IP地址 + * + * @return + */ + public static String getIpAddr() throws IOException { + return InetAddress.getLocalHost().getHostAddress().toString(); + } + + /** + * 获取电脑唯一标识 + * + * @return + */ + public static String getComputerID() { + String id = getMacAddress(); + if (id == null || id.equals("")) { + try { + id = getIpAddrAndName(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return computerName; + } + + /** + * 限制创建实例 + */ + private ComputerInfo() { + + } + + public static void main(String[] args) throws IOException { + System.out.println(ComputerInfo.getMacAddress()); + System.out.println(ComputerInfo.getComputerName()); + System.out.println(ComputerInfo.getIpAddr()); + System.out.println(ComputerInfo.getIpAddrAndName()); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..4884c45 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,69 @@ + +server: + port: 8016 + +spring: + application: + name: sczx-sync # 微服务名称 + http: + encoding: + charset: UTF-8 + enabled: true + force: true + mvc: + async: + request-timeout: -1 + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + cloud: + nacos: + discovery: + server-addr: 115.190.8.52:8848 # Nacos 地址 + group: DEFAULT_GROUP + metadata: + version: 1.0.0 + env: dev + lifecycle: + timeout-per-shutdown-phase: 30s # 设置优雅停机时间 + datasource: + url: jdbc:mysql://115.190.8.52:3306/sczx?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true + username: sczx_user + password: Sczx123@ + driver-class-name: com.mysql.cj.jdbc.Driver + hikari: + maximum-pool-size: 10 + auto-commit: true + +management: + endpoints: + web: + exposure: + include: "*" # 暴露所有监控端点 + endpoint: + health: + show-details: always + + + + +mybatis-plus: + mapper-locations: classpath*:mapper/**/*.xml + type-aliases-package: com.sczx.sync.po # 实体类包路径 + configuration: + mapUnderscoreToCamelCase: true + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印 SQL(调试用) + + +# 第三方平台配置 +third-party: + platform: + app-id: 111 + access-token: 111 + api-url: 127.0.0.1:8081/api/ddd + timeout: 30000 + retry-times: 3 + +battery-platform: + appid: 12312321 + access_token: 23213213 \ No newline at end of file diff --git a/src/main/resources/doc/dbInit.sql b/src/main/resources/doc/dbInit.sql new file mode 100644 index 0000000..314c3de --- /dev/null +++ b/src/main/resources/doc/dbInit.sql @@ -0,0 +1,40 @@ +CREATE TABLE `zc_order_main` ( + `order_id` bigint NOT NULL AUTO_INCREMENT COMMENT '订单ID(主键)', + `order_no` varchar(50) NOT NULL COMMENT '订单编号', + `order_status` varchar(20) NOT NULL COMMENT '订单状态:下单未提车、租赁中、已结束-自动、已结束-手动', + `operator_id` bigint NOT NULL COMMENT '所属运营商ID', + `store_id` bigint NOT NULL COMMENT '所属门店ID', + `vehicle_id` bigint DEFAULT NULL COMMENT '车辆ID', + `car_model_id` bigint NOT NULL COMMENT '车型ID', + `customer_id` bigint NOT NULL COMMENT '客户id', + `customer_name` varchar(50) NOT NULL COMMENT '客户姓名', + `customer_phone` varchar(20) NOT NULL COMMENT '客户联系电话', + `battery_type` varchar(50) DEFAULT '' COMMENT '选择的电池类型(48V标准版/100km,48V超长版/200km等)', + `rental_type` varchar(20) NOT NULL COMMENT '租赁类型(时租/日租/按天数/以租代售)', + `rental_days` int DEFAULT NULL COMMENT '租赁天数(当类型为"按天数"时使用)', + `rental_price` decimal(10,2) NOT NULL COMMENT '租车价格(元)', + `deposit_price` decimal(10,2) NOT NULL COMMENT '押金价格(元)', + `overdue_fee` decimal(10,2) NOT NULL COMMENT '逾期金额(元)', + `overdue_type` varchar(10) DEFAULT '按日计费' COMMENT '逾期计费类型(按日计费/按月计费)', + `is_deposit_free` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否开通免押', + `is_auto_deduct` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否开通代扣', + `first_order_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '首次下单时间', + `start_rent_time` datetime DEFAULT NULL COMMENT '开始计费时间', + `end_rent_time` datetime DEFAULT NULL COMMENT '预计还车时间', + `req_end_rent_time` datetime DEFAULT NULL COMMENT '申请还车时间', + `act_end_rent_time` datetime DEFAULT NULL COMMENT '实际还车时间', + `overdue_days` int NOT NULL DEFAULT '0' COMMENT '逾期天数', + `renewal_times` int NOT NULL DEFAULT '0' COMMENT '续租次数', + `charge_times` int NOT NULL DEFAULT '0' COMMENT '充电次数', + `rent_car_rule_id` bigint DEFAULT NULL COMMENT '租车套餐id', + `rent_battey_rule_id` bigint DEFAULT NULL COMMENT '租电套餐id', + `end_order_time` datetime DEFAULT NULL COMMENT '订单结束时间', + `del_flag` char(1) DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`order_id`), + KEY `idx_order_no` (`order_no`), + KEY `idx_customer_id` (`customer_id`), + KEY `idx_operator_id` (`operator_id`), + KEY `idx_store_id` (`store_id`) +) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='租车订单信息'; \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..e594345 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,53 @@ + + + + + + + + + ${PATTERN} + + + + + + ${LOG_FILE_PATH}/${hostname}/info.%d{yyyy-MM-dd}.log + 31 + + + + ${PATTERN} + + + + WARN + DENY + NEUTRAL + + + ERROR + DENY + NEUTRAL + + + + + + WARN + + ${LOG_FILE_PATH}/${hostname}/warn.log + true + + ${PATTERN} + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/BatteryMeal.xml b/src/main/resources/mapper/BatteryMeal.xml new file mode 100644 index 0000000..df2cfd8 --- /dev/null +++ b/src/main/resources/mapper/BatteryMeal.xml @@ -0,0 +1,59 @@ + + + + + + insert into zc_rent_battey_rule + + title, + detail, + + voltage, + ah, + + rent_price, + duration_type, + duration, + city_id, + operator_id, + province_id, + category_id, + meal_id, + sync_time, + + + #{title}, + #{detail}, + #{voltage}, + #{ah}, + #{rentPrice}, + #{durationType}, + #{duration}, + #{cityId}, + #{operatorId}, + #{provinceId}, + #{categoryId}, + #{mealId}, + #{syncTime}, + + + + + update zc_rent_battey_rule + + title = #{title}, + detail = #{detail}, + voltage = #{voltage}, + ah = #{ah}, + rent_price = #{rentPrice}, + duration_type = #{durationType}, + duration = #{duration}, + city_id = #{cityId}, + operator_id = #{operatorId}, + province_id = #{provinceId}, + category_id = #{categoryId}, + sync_time = #{syncTime}, + + where meal_id = #{mealId} + + diff --git a/src/main/resources/mapper/CompanyStoreMapper.xml b/src/main/resources/mapper/CompanyStoreMapper.xml new file mode 100644 index 0000000..4d8b555 --- /dev/null +++ b/src/main/resources/mapper/CompanyStoreMapper.xml @@ -0,0 +1,18 @@ + + + + + + update zc_company_store set bp_store_id = #{bpStoreId} where id =#{cId} + + + + update zc_company set b_op_id = #{bOpId} where id =#{cId} + + + + update zc_order_sub set b_order_id = #{bOdId} where order_id =#{cId} and suborder_type = "RENTBATTEY" + + + +