Преглед изворни кода

Merge branch 'develop' into develop-kjf

Pota1ovO пре 2 година
родитељ
комит
3972937746
29 измењених фајлова са 1735 додато и 8 уклоњено
  1. 30 0
      kxs-common/kxs-common-core/src/main/java/com/kxs/common/core/valid/Sn.java
  2. 36 0
      kxs-common/kxs-common-core/src/main/java/com/kxs/common/core/valid/impl/SnValidator.java
  3. 49 0
      kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/dto/kxsapp/gd/GdReportDTO.java
  4. 79 0
      kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/dto/kxsapp/gd/GdReportPutDTO.java
  5. 157 0
      kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/model/KxsGdReport.java
  6. 35 0
      kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/req/gd/GdQueryCardOrderReq.java
  7. 18 0
      kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/res/gd/GdCommRes.java
  8. 102 0
      kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/res/gd/GdQueryOrderRes.java
  9. 50 0
      kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/vo/kxsapp/gd/GdDotNumVO.java
  10. 77 0
      kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/vo/kxsapp/gd/GdReportListVO.java
  11. 4 0
      kxs-product/kxs-product-biz/pom.xml
  12. 2 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/KxsProductApplication.java
  13. 52 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/config/RsaProperties.java
  14. 33 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/constant/enums/GdReportEnum.java
  15. 78 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/controller/admin/SysGdController.java
  16. 104 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/controller/kxsapp/GdController.java
  17. 30 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/mapper/KxsGdReportMapper.java
  18. 77 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/KxsGdReportService.java
  19. 33 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/KxsGdService.java
  20. 157 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/impl/KxsGdReportServiceImpl.java
  21. 109 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/impl/KxsGdServiceImpl.java
  22. 0 1
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/impl/KxsMachineServiceImpl.java
  23. 284 0
      kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/util/GdRsaUtils.java
  24. 38 0
      kxs-product/kxs-product-biz/src/main/resources/mapper/KxsGdReportMapper.xml
  25. 8 0
      kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/feign/RemoteKxsUserService.java
  26. 0 5
      kxs-user/kxs-user-biz/pom.xml
  27. 13 0
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/controller/kxsapp/KxsAppController.java
  28. 5 2
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/service/impl/KxsUserServiceImpl.java
  29. 75 0
      kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/util/SmsUtils.java

+ 30 - 0
kxs-common/kxs-common-core/src/main/java/com/kxs/common/core/valid/Sn.java

@@ -0,0 +1,30 @@
+package com.kxs.common.core.valid;
+
+import com.kxs.common.core.valid.impl.PhoneValidator;
+import com.kxs.common.core.valid.impl.SnValidator;
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+
+import java.lang.annotation.*;
+
+/**
+ * 手机号验证正则
+ * @author mac
+ */
+@Target({ElementType.FIELD,ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Constraint(validatedBy = {SnValidator.class})// 指定约束处理器
+public @interface Sn {
+
+    String pattern() default "^[a-zA-Z0-9]+$";
+
+    String message() default "SN格式非法";
+
+    Class<?>[] groups() default { }; // groups用来指定分组,可以让校验采取不同的机制,当前默认未指定任何分组机制,默认每次都要进行校验
+
+    Class<? extends Payload>[] payload() default { };
+
+
+}
+

+ 36 - 0
kxs-common/kxs-common-core/src/main/java/com/kxs/common/core/valid/impl/SnValidator.java

@@ -0,0 +1,36 @@
+package com.kxs.common.core.valid.impl;
+
+import com.kxs.common.core.valid.Sn;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * sn格式校验器
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-11
+ */
+public class SnValidator implements ConstraintValidator<Sn, String> {
+
+    // 注解对象
+    private Sn sn;
+
+    // 初始化【Phone】对象
+    @Override
+    public void initialize(Sn constraintAnnotation) {
+        sn = constraintAnnotation;
+    }
+
+    @Override
+    public boolean isValid(String value, ConstraintValidatorContext context) {
+        // 获取【Phone】对象的手机格式验证表达式
+        String pattern = sn.pattern();
+        Pattern compile = Pattern.compile(pattern);
+        Matcher matcher = compile.matcher(value);
+        return matcher.matches();
+    }
+}
+

+ 49 - 0
kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/dto/kxsapp/gd/GdReportDTO.java

@@ -0,0 +1,49 @@
+package com.kxs.product.api.dto.kxsapp.gd;
+
+import com.kxs.common.core.valid.Phone;
+import com.kxs.common.core.valid.Sn;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+
+/**
+ * 广电报备-提交报备-dto
+ *
+ * @author 系统
+ * @date 2024-04-23 10:44:27
+ */
+@Data
+public class GdReportDTO {
+
+    /**
+     * 主键ID
+     */
+    @Schema(description = "主键ID")
+    @NotNull(message = "报备ID不能为空")
+    private Integer id;
+
+
+    /**
+     * sn码
+     */
+    @Schema(description = "sn码")
+    @NotBlank(message = "sn码不能为空")
+    @Sn
+    private String gdSn;
+
+
+    /**
+     * 广电手机号码
+     */
+    @Schema(description = "广电手机号码")
+    @NotBlank(message = "广电手机号码不能为空")
+    @Phone
+    private String gdMobile;
+
+
+
+
+
+}

+ 79 - 0
kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/dto/kxsapp/gd/GdReportPutDTO.java

@@ -0,0 +1,79 @@
+package com.kxs.product.api.dto.kxsapp.gd;
+
+import com.kxs.common.core.valid.Phone;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+
+/**
+ * 广电报备-提交工单-dto
+ *
+ * @author 系统
+ * @date 2024-04-23 10:44:27
+ */
+@Data
+public class GdReportPutDTO {
+
+    /**
+     * 创客姓名
+     */
+    @Schema(description = "创客姓名")
+    @NotBlank(message = "创客姓名不能为空")
+    private String username;
+
+
+    /**
+     * 创客编号
+     */
+    @Schema(description = "创客编号")
+    @NotBlank(message = "创客编号不能为空")
+    private String userCode;
+
+
+    /**
+     * 报备省份
+     */
+    @Schema(description = "报备省份")
+    @NotBlank(message = "报备省份不能为空")
+    private String province;
+
+
+    /**
+     * 报备城市
+     */
+    @Schema(description = "报备城市")
+    @NotBlank(message = "报备城市不能为空")
+    private String city;
+
+
+    /**
+     * 入网姓名
+     */
+    @Schema(description = "入网姓名")
+    @NotBlank(message = "入网姓名不能为空")
+    private String putName;
+
+
+    /**
+     * 入网手机号
+     */
+    @Schema(description = "入网手机号")
+    @NotBlank(message = "入网手机号不能为空")
+    @Phone
+    private String putMobile;
+
+
+    /**
+     * 验证码
+     */
+    @Schema(description = "验证码")
+    @NotBlank(message = "验证码不能为空")
+    @Length(min = 6,max = 6, message = "验证码错误")
+    private String code;
+
+
+
+
+}

+ 157 - 0
kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/model/KxsGdReport.java

@@ -0,0 +1,157 @@
+package com.kxs.product.api.model;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 广电报备入网表(KxsGdReport)表实体类
+ *
+ * @author 系统
+ * @since 2024-04-23 10:44:23
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class KxsGdReport extends Model<KxsGdReport> implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    
+    
+    /**
+     * 主键ID
+     */
+    @Schema(description = "主键ID")
+    @TableId(type = IdType.AUTO)
+    private Integer id;
+
+
+    /**
+     * 新增时间
+     */
+    @TableField(fill = FieldFill.INSERT)
+    @Schema(description = "新增时间")
+    private LocalDateTime createTime;
+
+
+    /**
+     * 更新时间
+     */
+    @TableField(fill = FieldFill.UPDATE)
+    @Schema(description = "更新时间")
+    private LocalDateTime updateTime;
+
+
+    /**
+     * 删除标记,0未删除,1已删除
+     */
+    @Schema(description = "删除标记,0未删除,1已删除")
+    private Integer delFlag;
+
+
+    /**
+     * 版本
+     */
+    @Schema(description = "版本")
+    private Integer version;
+
+
+    /**
+     * 创客ID
+     */
+    @Schema(description = "创客ID")
+    private Integer userId;
+
+
+    /**
+     * 创客姓名
+     */
+    @Schema(description = "创客姓名")
+    private String username;
+
+
+    /**
+     * 创客编号
+     */
+    @Schema(description = "创客编号")
+    private String userCode;
+
+
+    /**
+     * 报备省份
+     */
+    @Schema(description = "报备省份")
+    private String province;
+
+
+    /**
+     * 报备城市
+     */
+    @Schema(description = "报备城市")
+    private String city;
+
+
+    /**
+     * 入网姓名
+     */
+    @Schema(description = "入网姓名")
+    private String putName;
+
+
+    /**
+     * 入网手机号
+     */
+    @Schema(description = "入网手机号")
+    private String putMobile;
+
+
+    /**
+     * 备注
+     */
+    @Schema(description = "备注")
+    private String remark;
+
+
+    /**
+     * 状态 未处理=0 已作废=-1 报备成功=1
+     */
+    @Schema(description = "状态 未处理=0 已作废=-1 报备成功=1")
+    private Integer status;
+
+
+    /**
+     * sn码
+     */
+    @Schema(description = "sn码")
+    private String gdSn;
+
+
+    /**
+     * 广电手机号码
+     */
+    @Schema(description = "广电手机号码")
+    private String gdMobile;
+
+
+    /**
+     * 匹配状态
+     */
+    @Schema(description = "匹配状态")
+    private Integer isCheck;
+
+
+
+
+}
+

+ 35 - 0
kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/req/gd/GdQueryCardOrderReq.java

@@ -0,0 +1,35 @@
+package com.kxs.product.api.req.gd;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * 查询开卡订单数据
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-23
+ */
+@Data
+@Builder
+public class GdQueryCardOrderReq {
+
+    /**
+     * 签名
+     */
+    private String sign;
+    /**
+     * 查询开始时间
+     */
+    private String queryBeginTime;
+    /**
+     * 查询结束时间
+     */
+    private String queryEndTime;
+    private String pageNo;
+    private String pageSize;
+    /**
+     * 机构号
+     */
+    private String brhNo;
+    private String timestamp;
+}

+ 18 - 0
kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/res/gd/GdCommRes.java

@@ -0,0 +1,18 @@
+package com.kxs.product.api.res.gd;
+
+import lombok.Data;
+
+/**
+ * 广电公共返回参数
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-23
+ */
+@Data
+public class GdCommRes<T> {
+
+    private T data;
+    private int resultCode;
+    private int errorCode;
+    private String errorDesc;
+}

+ 102 - 0
kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/res/gd/GdQueryOrderRes.java

@@ -0,0 +1,102 @@
+package com.kxs.product.api.res.gd;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 广电开卡订单数据返回
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-23
+ */
+@Data
+public class GdQueryOrderRes {
+
+    private int total;
+    private int size;
+    private int current;
+    private int pages;
+    private List<GdQueryOrder> records;
+
+
+    /**
+     * 订单数据
+     *
+     * @author 没秃顶的码农
+     * @date 2024-04-23
+     */
+    @Data
+    public class GdQueryOrder{
+
+        /**
+         * 订单号
+         */
+        private String orderNo;
+        /**
+         * 订单创建时间
+         */
+        private String orderCreateTime;
+        /**
+         * 用户选择号码
+         */
+        private String phoneNo;
+        /**
+         * 是否首充(中文):是,否
+         */
+        private String firstCharge;
+        /**
+         * 首充金额(元)
+         */
+        private BigDecimal initialChargeAmount;
+        /**
+         * 省
+         */
+        private String province;
+        /**
+         * 城市
+         */
+        private String city;
+        /**
+         * 商品名称
+         */
+        private String productName;
+        /**
+         * 促销活动名称
+         */
+        private String promotionName;
+        /**
+         * 商品类型名称
+         */
+        private String productTypeName;
+        /**
+         * 实付金额(元)
+         */
+        private BigDecimal paidInAmount;
+        /**
+         * 订单状态(中文):待
+         * 激活、已完成、退款
+         * 中、未知
+         */
+        private String orderStatus;
+        /**
+         * 激活状态(中文):待激活、已激活、未知
+         */
+        private String activationStatusName;
+        /**
+         * 激活时间
+         */
+        private String activationTime;
+        /**
+         * 开卡人工号
+         */
+        private String jobId;
+        /**
+         * SIM 卡号
+         */
+        private String iccId;
+    }
+
+
+}

+ 50 - 0
kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/vo/kxsapp/gd/GdDotNumVO.java

@@ -0,0 +1,50 @@
+package com.kxs.product.api.vo.kxsapp.gd;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * 广电报备-数量接口vo
+ *
+ * @author 系统
+ * @date 2024-04-23 10:44:27
+ */
+@Data
+@Schema(description = "广电报备-数量接口返回实体")
+public class GdDotNumVO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 待处理
+     */
+    @Schema(description = "待处理")
+    private Object pendNum;
+
+
+    /**
+     * 已报备
+     */
+    @Schema(description = "已报备")
+    private Object reportNum;
+
+
+    /**
+     * 已作废
+     */
+    @Schema(description = "已作废")
+    private Object cancelNum;
+
+
+
+
+
+	
+
+}

+ 77 - 0
kxs-product/kxs-product-api/src/main/java/com/kxs/product/api/vo/kxsapp/gd/GdReportListVO.java

@@ -0,0 +1,77 @@
+package com.kxs.product.api.vo.kxsapp.gd;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 广电报备-列表vo
+ *
+ * @author 系统
+ * @date 2024-04-23 10:44:27
+ */
+@Data
+@Schema(description = "广电报备-列表返回实体")
+public class GdReportListVO implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 1L;
+
+
+    /**
+     * 主键ID
+     */
+    @Schema(description = "主键ID")
+    private Integer id;
+
+
+    /**
+     * 新增时间
+     */
+    @Schema(description = "新增时间")
+    private LocalDateTime createTime;
+
+
+    /**
+     * 入网姓名
+     */
+    @Schema(description = "入网姓名")
+    private String putName;
+
+
+    /**
+     * 入网手机号
+     */
+    @Schema(description = "入网手机号")
+    private String putMobile;
+
+    /**
+     * 广电手机号
+     */
+    @Schema(description = "广电手机号")
+    private String gdMobile;
+
+    /**
+     * 广电sn
+     */
+    @Schema(description = "广电sn")
+    private String gdSn;
+
+
+    /**
+     * 状态 未处理=0 已作废=-1 报备成功=1
+     */
+    @Schema(description = "状态 未处理=0 已作废=-1 报备成功=1")
+    private Integer status;
+
+
+
+
+
+	
+
+}

+ 4 - 0
kxs-product/kxs-product-biz/pom.xml

@@ -75,6 +75,10 @@
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-crypto</artifactId>
         </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-json</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 2 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/KxsProductApplication.java

@@ -4,6 +4,7 @@ import com.kxs.common.security.annotation.EnableAuthResourceServer;
 import com.kxs.common.swagger.annotation.EnableKxsDoc;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
 
 
 /**
@@ -15,6 +16,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 @SpringBootApplication
 @EnableAuthResourceServer
 @EnableKxsDoc(value = "product")
+@EnableAsync
 public class KxsProductApplication {
 
 	public static void main(String[] args) {

+ 52 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/config/RsaProperties.java

@@ -0,0 +1,52 @@
+
+package com.kxs.product.biz.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.stereotype.Component;
+
+/**
+ * 广电 配置信息
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-18
+ */
+@Data
+@Component
+@RefreshScope
+@ConfigurationProperties("rsa")
+public class RsaProperties {
+
+	/**
+	 * 广电配置信息
+	 */
+	private GdProperties gd = new GdProperties();
+
+	@Data
+	public static class GdProperties {
+
+		/**
+		 * 请求地址
+		 */
+		private String url;
+
+		/**
+		 * 机构号
+		 */
+		private String brhNo;
+
+		/**
+		 * 公钥
+		 */
+		private String publicKey;
+
+		/**
+		 * 私钥
+		 */
+		private String privateKey;
+
+	}
+
+
+}

+ 33 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/constant/enums/GdReportEnum.java

@@ -0,0 +1,33 @@
+package com.kxs.product.biz.constant.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 商户模块枚举类
+ *
+ * @author Lxq
+ * @date 2023-10-25
+ */
+@Getter
+@AllArgsConstructor
+public enum GdReportEnum {
+
+    /**
+     * 报备状态
+     */
+    PENDING(0, "待处理"),
+    REPORT(1, "已报备"),
+    CANCEL(-1, "已作废"),
+
+    /**
+     * 匹配状态
+     */
+    CHECK_NO(0, "未匹配"),
+    CHECK_SUC(1, "匹配成功");
+
+    //状态码
+    private final Integer type;
+    //状态码码描述
+    private final String description;
+}

+ 78 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/controller/admin/SysGdController.java

@@ -0,0 +1,78 @@
+package com.kxs.product.biz.controller.admin;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.kxs.common.core.util.R;
+import com.kxs.product.api.model.KxsGdReport;
+import com.kxs.product.biz.service.KxsGdReportService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 产品模块(SysGd)控制层
+ *
+ * @author 系统
+ * @since 2024-04-23 10:44:27
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("sysGd")
+public class SysGdController {
+
+    /**
+     * 服务对象
+     */
+    private final KxsGdReportService kxsGdReportService;
+
+
+
+    /**
+     * 广电报备-列表
+     *
+     * @param page 分页对象
+     * @param param 查询实体
+     * @return 广电报备-列表
+     */
+    @GetMapping("/page")
+    public R page(Page<KxsGdReport> page, KxsGdReport param) {
+        return R.ok(kxsGdReportService.page(page,
+                Wrappers.<KxsGdReport>lambdaQuery().eq(StrUtil.isNotBlank(param.getGdSn()),KxsGdReport::getGdSn, param.getGdSn())
+                        .eq(StrUtil.isNotBlank(param.getGdMobile()),KxsGdReport::getGdMobile, param.getGdMobile())
+                        .eq(StrUtil.isNotBlank(param.getUserCode()),KxsGdReport::getUserCode, param.getUserCode())
+                        .eq(param.getIsCheck() != null, KxsGdReport::getIsCheck, param.getIsCheck())
+                ));
+    }
+
+
+    /**
+     * 广电报备-编辑
+     *
+     * @param param 实体对象
+     * @return 广电报备-编辑
+     */
+    @PutMapping("/update")
+    public R update(@RequestBody KxsGdReport param) {
+
+        return R.ok(kxsGdReportService.updateData(param));
+    }
+
+    /**
+     * 广电报备-匹配数据
+     *
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 广电报备-编辑
+     */
+    @GetMapping("/check")
+    public R check(@RequestParam("startTime") String startTime, @RequestParam("endTime") String endTime) {
+
+        return kxsGdReportService.checkGdData(startTime, endTime);
+    }
+
+
+
+
+
+}
+

+ 104 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/controller/kxsapp/GdController.java

@@ -0,0 +1,104 @@
+package com.kxs.product.biz.controller.kxsapp;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.kxs.common.core.util.R;
+import com.kxs.common.security.annotation.Inner;
+import com.kxs.product.api.dto.kxsapp.gd.GdReportDTO;
+import com.kxs.product.api.dto.kxsapp.gd.GdReportPutDTO;
+import com.kxs.product.api.model.KxsGdReport;
+import com.kxs.product.api.vo.kxsapp.gd.GdReportListVO;
+import com.kxs.product.biz.service.KxsGdReportService;
+import jakarta.validation.Valid;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 产品模块(Gd)控制层
+ *
+ * @author 系统
+ * @since 2024-04-23 10:44:27
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("gd")
+public class GdController {
+
+    /**
+     * 服务对象
+     */
+    private final KxsGdReportService kxsGdReportService;
+
+
+
+    /**
+     * 广电报备-提交工单
+     *
+     * @param param 实体对象
+     * @return 广电报备-提交工单
+     */
+    @Inner(value = false)
+    @PostMapping("/add")
+    public R add(@RequestBody @Valid GdReportPutDTO param) {
+
+        return R.ok(kxsGdReportService.addReport(param));
+    }
+
+
+    /**
+     * 广电报备-列表
+     *
+     * @param page 分页对象
+     * @param status 状态
+     * @param keyword 关键字
+     * @return 广电报备-列表
+     */
+    @GetMapping("/page")
+    public R page(Page<GdReportListVO> page, @RequestParam("status") Integer status, @RequestParam(value = "keyword", required = false) String keyword) {
+
+        return R.ok(kxsGdReportService.getByPage(page, status, keyword));
+    }
+
+
+    /**
+     * 广电报备-数量接口
+     *
+     * @return 广电报备-数量接口
+     */
+    @GetMapping("/dot")
+    public R dot() {
+
+        return R.ok(kxsGdReportService.dotNum());
+    }
+
+
+    /**
+     * 广电报备-作废
+     *
+     * @param param 实体对象
+     * @return 广电报备-作废
+     */
+    @PutMapping("/cancel")
+    public R cancel(@RequestBody KxsGdReport param) {
+
+        return R.ok(kxsGdReportService.cancelReport(param));
+    }
+
+
+    /**
+     * 广电报备-报备
+     *
+     * @param param 实体对象
+     * @return 广电报备-报备
+     */
+    @PutMapping("/report")
+    public R report(@RequestBody @Valid GdReportDTO param) {
+
+        return R.ok(kxsGdReportService.report(param));
+    }
+
+
+
+
+
+}
+

+ 30 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/mapper/KxsGdReportMapper.java

@@ -0,0 +1,30 @@
+package com.kxs.product.biz.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.kxs.product.api.model.KxsGdReport;
+import com.kxs.product.api.vo.kxsapp.gd.GdReportListVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 广电报备入网表(KxsGdReport)表数据库访问层
+ *
+ * @author 系统
+ * @since 2024-04-23 10:44:23
+ */
+@Mapper
+public interface KxsGdReportMapper extends BaseMapper<KxsGdReport> {
+
+    /**
+     * app分页
+     *
+     * @param page    页
+     * @param userId 用户ID
+     * @param keyword 关键词
+     * @return {@link IPage}<{@link GdReportListVO}>
+     */
+    IPage<GdReportListVO> getByPage(Page<GdReportListVO> page, @Param("userId") Long userId, @Param("status") Integer status, @Param("keyword") String keyword);
+}
+

+ 77 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/KxsGdReportService.java

@@ -0,0 +1,77 @@
+package com.kxs.product.biz.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.kxs.common.core.util.R;
+import com.kxs.product.api.dto.kxsapp.gd.GdReportDTO;
+import com.kxs.product.api.dto.kxsapp.gd.GdReportPutDTO;
+import com.kxs.product.api.model.KxsGdReport;
+import com.kxs.product.api.vo.kxsapp.gd.GdDotNumVO;
+import com.kxs.product.api.vo.kxsapp.gd.GdReportListVO;
+
+/**
+ * 广电报备入网表(KxsGdReport)表服务接口
+ *
+ * @author 系统
+ * @since 2024-04-23 10:44:23
+ */
+public interface KxsGdReportService extends IService<KxsGdReport> {
+
+    /**
+     * 入网报备信息增加
+     *
+     * @param param 参数
+     */
+    Boolean addReport(GdReportPutDTO param);
+
+    /**
+     * app分页
+     *
+     * @param page    页
+     * @param keyword 关键词
+     * @return {@link IPage}<{@link GdReportListVO}>
+     */
+    IPage<GdReportListVO> getByPage(Page<GdReportListVO> page,  Integer status, String keyword);
+
+    /**
+     * 数量接口
+     *
+     * @return {@link GdDotNumVO}
+     */
+    GdDotNumVO dotNum();
+
+    /**
+     * 广电报备-作废
+     *
+     * @param param 参数
+     * @return {@link Object}
+     */
+    Boolean cancelReport(KxsGdReport param);
+
+    /**
+     * 报备
+     *
+     * @param param 参数
+     * @return {@link Boolean}
+     */
+    Boolean report(GdReportDTO param);
+
+    /**
+     * sys更新数据
+     *
+     * @param param 参数
+     * @return {@link Boolean}
+     */
+    Boolean updateData(KxsGdReport param);
+
+    /**
+     * 匹配 GD 数据
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @return {@link R}
+     */
+    R checkGdData(String startTime, String endTime);
+}
+

+ 33 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/KxsGdService.java

@@ -0,0 +1,33 @@
+package com.kxs.product.biz.service;
+
+import com.kxs.product.api.res.gd.GdQueryOrderRes;
+
+import java.util.List;
+
+/**
+ * KXS 广电 服务
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-23
+ */
+public interface KxsGdService {
+
+
+    /**
+     * 查询开卡订单数据
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @param pageNo
+     * @param pageSize
+     */
+    List<GdQueryOrderRes.GdQueryOrder> queryCardOrders(String startTime, String endTime, int pageNo, int pageSize);
+
+    /**
+     * 匹配 广电 开卡数据
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     */
+    void checkGdAsyncData(String startTime, String endTime);
+}

+ 157 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/impl/KxsGdReportServiceImpl.java

@@ -0,0 +1,157 @@
+package com.kxs.product.biz.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.kxs.common.core.constant.CommonConstants;
+import com.kxs.common.core.constant.SecurityConstants;
+import com.kxs.common.core.constant.enums.ErrorTypeEnum;
+import com.kxs.common.core.exception.GlobalCustomerException;
+import com.kxs.common.core.util.R;
+import com.kxs.common.core.util.RetOps;
+import com.kxs.common.security.util.SecurityUtils;
+import com.kxs.product.api.dto.kxsapp.gd.GdReportDTO;
+import com.kxs.product.api.dto.kxsapp.gd.GdReportPutDTO;
+import com.kxs.product.api.model.KxsGdReport;
+import com.kxs.product.api.res.gd.GdQueryOrderRes;
+import com.kxs.product.api.vo.kxsapp.gd.GdDotNumVO;
+import com.kxs.product.api.vo.kxsapp.gd.GdReportListVO;
+import com.kxs.product.biz.constant.enums.GdReportEnum;
+import com.kxs.product.biz.mapper.KxsGdReportMapper;
+import com.kxs.product.biz.service.KxsGdReportService;
+import com.kxs.product.biz.service.KxsGdService;
+import com.kxs.user.api.feign.RemoteKxsUserService;
+import com.kxs.user.api.model.KxsUser;
+import lombok.RequiredArgsConstructor;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * 广电报备入网表(KxsGdReport)表服务实现类
+ *
+ * @author 系统
+ * @since 2024-04-23 10:44:23
+ */
+@Service("kxsGdReportService")
+@RequiredArgsConstructor
+public class KxsGdReportServiceImpl extends ServiceImpl<KxsGdReportMapper, KxsGdReport> implements KxsGdReportService {
+
+    private final RemoteKxsUserService remoteKxsUserService;
+
+    private final KxsGdService kxsGdService;
+
+
+    @Override
+    public Boolean addReport(GdReportPutDTO param) {
+
+
+        R<Boolean> booleanR = remoteKxsUserService.checkMobileCode(param.getPutMobile(), param.getCode(), SecurityConstants.FROM_IN);
+        if(booleanR.getStatus() != CommonConstants.SUCCESS || !booleanR.getData()){
+            throw new GlobalCustomerException(booleanR.getMsg());
+        }
+        R<KxsUser> kxsUserR = remoteKxsUserService.loadUserByCode(param.getUserCode(), SecurityConstants.FROM_IN);
+        KxsUser user = RetOps.of(kxsUserR)
+                .getData()
+                .orElseThrow(() -> new GlobalCustomerException(ErrorTypeEnum.USER_NOT_FOUND.getDescription()));
+
+        KxsGdReport kxsGdReport = new KxsGdReport();
+        BeanUtil.copyProperties(param, kxsGdReport);
+        kxsGdReport.setUserId(user.getId());
+        return this.save(kxsGdReport);
+    }
+
+    @Override
+    public IPage<GdReportListVO> getByPage(Page<GdReportListVO> page, Integer status, String keyword) {
+
+        Long userId = SecurityUtils.getUser().getId();
+        return baseMapper.getByPage(page, userId, status, keyword);
+    }
+
+    @Override
+    public GdDotNumVO dotNum() {
+
+        Long userId = SecurityUtils.getUser().getId();
+        GdDotNumVO gdDotNumVO = new GdDotNumVO();
+        gdDotNumVO.setPendNum(Optional.of(this.count(Wrappers.<KxsGdReport>lambdaQuery().eq(KxsGdReport::getUserId, userId).eq(KxsGdReport::getStatus, GdReportEnum.PENDING.getType()))).orElse(0L));
+        gdDotNumVO.setReportNum(Optional.of(this.count(Wrappers.<KxsGdReport>lambdaQuery().eq(KxsGdReport::getUserId, userId).eq(KxsGdReport::getStatus, GdReportEnum.REPORT.getType()))).orElse(0L));
+        gdDotNumVO.setCancelNum(Optional.of(this.count(Wrappers.<KxsGdReport>lambdaQuery().eq(KxsGdReport::getUserId, userId).eq(KxsGdReport::getStatus, GdReportEnum.CANCEL.getType()))).orElse(0L));
+
+        return gdDotNumVO;
+    }
+
+    @Override
+    public Boolean cancelReport(KxsGdReport param) {
+
+        Optional.ofNullable(param.getId()).orElseThrow(() -> new GlobalCustomerException("参数错误"));
+        KxsGdReport kxsGdReport = this.getById(param.getId());
+        Optional.ofNullable(kxsGdReport).orElseThrow(() -> new GlobalCustomerException("参数错误"));
+        if(Objects.equals(kxsGdReport.getStatus(), GdReportEnum.REPORT.getType())){
+            throw new GlobalCustomerException("该工单已报备,无法作废");
+        }
+
+        kxsGdReport.setStatus(GdReportEnum.CANCEL.getType());
+
+        return this.updateById(kxsGdReport);
+    }
+
+    @Override
+    public Boolean report(GdReportDTO param) {
+
+        KxsGdReport kxsGdReport = this.getById(param.getId());
+
+        Optional.ofNullable(kxsGdReport).orElseThrow(() -> new GlobalCustomerException("参数错误"));
+        if(!Objects.equals(kxsGdReport.getStatus(), GdReportEnum.PENDING.getType())){
+            throw new GlobalCustomerException("该工单状态错误");
+        }
+        //判断sn是否重复
+        KxsGdReport report = this.getOne(Wrappers.<KxsGdReport>lambdaQuery().eq(KxsGdReport::getGdSn, param.getGdSn()));
+        if(report != null){
+            throw new GlobalCustomerException("该工单sn已报备");
+        }
+
+
+        kxsGdReport.setStatus(GdReportEnum.REPORT.getType());
+        kxsGdReport.setGdMobile(param.getGdMobile());
+        kxsGdReport.setGdSn(param.getGdSn());
+
+        return this.updateById(kxsGdReport);
+    }
+
+    @Override
+    public Boolean updateData(KxsGdReport param) {
+
+        Optional.ofNullable(param.getId()).orElseThrow(() -> new GlobalCustomerException("参数错误"));
+        KxsGdReport kxsGdReport = this.getById(param.getId());
+        Optional.ofNullable(kxsGdReport).orElseThrow(() -> new GlobalCustomerException("参数错误"));
+
+        if(Objects.equals(kxsGdReport.getIsCheck(), GdReportEnum.CHECK_SUC.getType())){
+            throw new GlobalCustomerException("该工单已匹配,无法更新");
+        }
+
+
+        return this.update(Wrappers.<KxsGdReport>lambdaUpdate()
+                .eq(KxsGdReport::getId, param.getId())
+                .set(KxsGdReport::getPutName, param.getPutName())
+                .set(KxsGdReport::getGdSn, param.getGdSn())
+                .set(KxsGdReport::getGdMobile, param.getGdMobile()));
+    }
+
+    @Override
+    public R checkGdData(String startTime, String endTime) {
+
+        kxsGdService.checkGdAsyncData(startTime, endTime);
+
+        return R.ok();
+    }
+
+
+
+}
+

+ 109 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/impl/KxsGdServiceImpl.java

@@ -0,0 +1,109 @@
+package com.kxs.product.biz.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.lang.TypeReference;
+import cn.hutool.http.Header;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.kxs.common.core.exception.GlobalCustomerException;
+import com.kxs.product.api.model.KxsGdReport;
+import com.kxs.product.api.req.gd.GdQueryCardOrderReq;
+import com.kxs.product.api.res.gd.GdCommRes;
+import com.kxs.product.api.res.gd.GdQueryOrderRes;
+import com.kxs.product.biz.config.RsaProperties;
+import com.kxs.product.biz.constant.enums.GdReportEnum;
+import com.kxs.product.biz.mapper.KxsGdReportMapper;
+import com.kxs.product.biz.service.KxsGdService;
+import com.kxs.product.biz.util.GdRsaUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * KXS 广电 服务实现
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-23
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class KxsGdServiceImpl implements KxsGdService {
+
+    private final RsaProperties rsaProperties;
+
+    private final KxsGdReportMapper kxsGdReportMapper;
+
+    @Async("getAsyncExecutor")
+    public void checkGdAsyncData(String startTime, String endTime){
+        int pageNo = 1;
+        int pageSize = 50;
+
+        do {
+            List<GdQueryOrderRes.GdQueryOrder> list = this.queryCardOrders(startTime, endTime, pageNo, pageSize);
+            if (list.isEmpty()) {
+                pageNo = -1;
+            }else{
+                for (GdQueryOrderRes.GdQueryOrder gdQueryOrder : list) {
+                    if("已激活".equals(gdQueryOrder.getActivationStatusName())){
+                        KxsGdReport kxsGdReport = kxsGdReportMapper.selectOne(Wrappers.<KxsGdReport>lambdaQuery()
+                                        .eq(KxsGdReport::getGdSn, gdQueryOrder.getIccId())
+                                .eq(KxsGdReport::getGdMobile, gdQueryOrder.getPhoneNo()));
+                        if(kxsGdReport != null){
+                            kxsGdReportMapper.update(null, Wrappers.<KxsGdReport>lambdaUpdate().eq(KxsGdReport::getId, kxsGdReport.getId())
+                                            .set(KxsGdReport::getIsCheck, GdReportEnum.CHECK_SUC.getType())
+                                            .set(KxsGdReport::getGdMobile, gdQueryOrder.getPhoneNo()));
+                            //TODO 调用激活接口
+
+                        }
+                    }
+                }
+                pageNo++;
+            }
+        }while (pageNo != -1);
+
+    }
+
+    @Override
+    public List<GdQueryOrderRes.GdQueryOrder> queryCardOrders(String startTime, String endTime, int pageNo, int pageSize) {
+
+        try {
+            String url = "https://" + rsaProperties.getGd().getUrl() + "/ycsim-business/openapi/query_card_order_info";
+
+            long timestamp = System.currentTimeMillis() / 1000;
+
+            GdQueryCardOrderReq req = GdQueryCardOrderReq.builder()
+                    .queryBeginTime(startTime)
+                    .queryEndTime(endTime)
+                    .brhNo(rsaProperties.getGd().getBrhNo())
+                    .pageNo(String.valueOf(pageNo))
+                    .pageSize(String.valueOf(pageSize))
+                    .timestamp(String.valueOf(timestamp)).build();
+            String sign = GdRsaUtils.rsa256Sign(BeanUtil.beanToMap(req), rsaProperties.getGd().getPrivateKey());
+            req.setSign(sign);
+            String body = JSONUtil.toJsonStr(req);
+            String response = HttpRequest.post(url)
+                    .header(Header.CONTENT_TYPE, "application/json")
+                    .body(body)
+                    .timeout(50000)//超时,毫秒
+                    .execute().body();
+            Optional.ofNullable(response).orElseThrow(() -> new GlobalCustomerException("调用接口失败"));
+            GdCommRes<GdQueryOrderRes> commRes = JSONUtil.toBean(response, new TypeReference<GdCommRes<GdQueryOrderRes>>() {}, true);
+            if(commRes.getResultCode() == 1){
+                return commRes.getData().getRecords();
+            }else{
+                throw new GlobalCustomerException(commRes.getErrorDesc());
+            }
+
+        } catch (Exception e) {
+            log.error("请求广电接口报错:{}", e.getLocalizedMessage());
+            throw new GlobalCustomerException(e.getLocalizedMessage());
+        }
+    }
+
+}

+ 0 - 1
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/service/impl/KxsMachineServiceImpl.java

@@ -52,7 +52,6 @@ import java.util.stream.Collectors;
 @Service("kxsMachineService")
 @RequiredArgsConstructor
 @Slf4j
-@EnableAsync
 public class KxsMachineServiceImpl extends ServiceImpl<KxsMachineMapper, KxsMachine> implements KxsMachineService {
 
     private final KxsBrandMapper kxsBrandMapper;

+ 284 - 0
kxs-product/kxs-product-biz/src/main/java/com/kxs/product/biz/util/GdRsaUtils.java

@@ -0,0 +1,284 @@
+package com.kxs.product.biz.util;
+
+import cn.hutool.core.util.StrUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.*;
+import java.util.stream.Collectors;
+
+
+/**
+ * rsa验签工具。
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-23
+ */
+public class GdRsaUtils {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(GdRsaUtils.class);
+
+    public static final String KEY_ALGORITHM = "RSA";
+    public static final String DEFAULT_CHARSET = "UTF-8";
+    // TODO: 配置私钥 (用于加密)
+    public static final String DEFAULT_PRIVATE_KEY = "";
+    // TODO: 配置公钥 (用于解密)
+    public static final String DEFAULT_PUBLIC_KEY = "";
+
+    /**
+     * 获取公钥
+     *
+     * @param publicKeyStr
+     * @return
+     * @throws Exception
+     */
+    public static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
+        try {
+            byte[] buffer = Base64.getDecoder().decode(publicKeyStr);
+            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
+            RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
+            return restorePublicKey(publicKey.getEncoded());
+
+        } catch (NoSuchAlgorithmException e) {
+            throw new Exception("无此算法");
+        } catch (InvalidKeySpecException e) {
+            throw new Exception("公钥非法");
+        } catch (IOException e) {
+            throw new Exception("公钥数据内容读取错误");
+        } catch (NullPointerException e) {
+            throw new Exception("公钥数据为空");
+        }
+    }
+
+    /**
+     * 还原公钥
+     *
+     * @param keyBytes
+     * @return
+     * @throws Exception
+     */
+    private static PublicKey restorePublicKey(byte[] keyBytes) throws Exception {
+        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
+        try {
+            KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
+            return factory.generatePublic(x509EncodedKeySpec);
+        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+            throw new Exception(e);
+        }
+    }
+
+    /**
+     * 通过私钥KEY获取解密私钥
+     *
+     * @param privateKeyStr
+     * @return
+     * @throws Exception
+     */
+    public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception {
+        try {
+            byte[] buffer = Base64.getDecoder().decode(privateKeyStr);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
+            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
+            return restorePrivateKey(privateKey.getEncoded());
+        } catch (NoSuchAlgorithmException e) {
+            throw new Exception("无此算法");
+        } catch (InvalidKeySpecException e) {
+            throw new Exception("公钥非法");
+        } catch (IOException e) {
+            throw new Exception("公钥数据内容读取错误");
+        } catch (NullPointerException e) {
+            throw new Exception("公钥数据为空");
+        }
+    }
+
+
+    /**
+     * 还原私钥
+     *
+     * @param keyBytes
+     * @return
+     * @throws Exception
+     */
+    private static PrivateKey restorePrivateKey(byte[] keyBytes) throws Exception {
+        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
+        try {
+            KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
+            return factory.generatePrivate(pkcs8EncodedKeySpec);
+        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+            throw new Exception(e);
+        }
+    }
+
+    /**
+     * 根据请求参数生成待签名的字符串
+     *
+     * @param params
+     * @return
+     */
+    public static String getSignContent(Map<String, String> params) {
+        params.remove("sign");
+        Map<String, String> sortedParams = new TreeMap<>(params);
+
+        StringBuilder content = new StringBuilder();
+        List<String> keys = new ArrayList<>(sortedParams.keySet());
+        Collections.sort(keys);
+        int index = 0;
+        for (String key : keys) {
+            String value = sortedParams.get(key);
+            if (!StrUtil.isAllBlank(key, value)) {
+                content.append(index == 0 ? "" : "&").append(key).append("=").append(value);
+                index++;
+            }
+        }
+        return content.toString();
+    }
+
+    /**
+     * sha256WithRsa 验签
+     *
+     * @param content
+     * @param sign
+     * @param publicKey
+     * @param charset
+     * @return
+     */
+    public static boolean rsa256CheckContent(String content, String sign, String publicKey, String charset) throws Exception {
+        try {
+            PublicKey pubKey = loadPublicKey(publicKey);
+            Signature signature = Signature.getInstance("SHA256WithRSA");
+            signature.initVerify(pubKey);
+            if (StrUtil.isEmpty(charset)) {
+                signature.update(content.getBytes());
+            } else {
+                signature.update(content.getBytes(charset));
+            }
+            return signature.verify(Base64.getDecoder().decode(sign.getBytes()));
+        } catch (Exception e) {
+            throw new Exception("签名失败,RSAcontent=" + content + ";charset=" + charset + ";sign=" + sign, e);
+        }
+    }
+
+    /**
+     * sha256WithRsa 签名
+     *
+     * @param content
+     * @param privateKey
+     * @param charset
+     * @return
+     */
+    public static String rsa256Sign(String content, String privateKey, String charset) throws Exception {
+        try {
+            PrivateKey priKey = loadPrivateKey(privateKey);
+            Signature signature = Signature.getInstance("SHA256WithRSA");
+            signature.initSign(priKey);
+            if (StrUtil.isEmpty(charset)) {
+                signature.update(content.getBytes());
+            } else {
+                signature.update(content.getBytes(charset));
+            }
+            byte[] signed = signature.sign();
+            return new String(Base64.getEncoder().encode(signed));
+        } catch (Exception e) {
+            throw new Exception("签名失败,RSAcontent=" + content + ";charset=" + charset, e);
+        }
+    }
+
+    /**
+     * 生成接口签名
+     *
+     * @param reqParams
+     * @return
+     * @throws Exception
+     */
+    public static String rsa256Sign(Map<String, Object> reqParams, String privateKey) throws Exception {
+        Map<String, String> params = reqParams.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, v -> String.valueOf(v.getValue())));
+        String checkContent = GdRsaUtils.getSignContent(params);
+        String sign = null;
+        try {
+            sign = GdRsaUtils.rsa256Sign(checkContent, privateKey, DEFAULT_CHARSET);
+        } catch (Exception e) {
+            throw new Exception(e);
+        }
+        return sign;
+    }
+
+    /**
+     * 校验接口请求签名
+     *
+     * @param reqParams
+     * @return
+     * @throws Exception
+     */
+    public static boolean checkSign(Map<String, Object> reqParams, String publicKey) throws Exception {
+        Map<String, String> params = reqParams.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, v -> String.valueOf(v.getValue())));
+        String checkContent = GdRsaUtils.getSignContent(params);
+        String sign = (String) reqParams.get("sign");
+        boolean isSuccess;
+        try {
+            isSuccess = GdRsaUtils.rsa256CheckContent(checkContent, sign, publicKey, DEFAULT_CHARSET);
+        } catch (Exception e) {
+            throw new Exception(e);
+        }
+        return isSuccess;
+    }
+
+    /**
+     * 生成RSA密钥对
+     */
+    public static void generateKeyPair() {
+        try {
+            // 指定生成密钥的算法和密钥长度(密钥长度,常用值:1024、2048、4096)
+            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+            kpg.initialize(1024);
+
+            // 获取密钥对
+            KeyPair keyPair = kpg.genKeyPair();
+            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
+            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
+
+            // 获取公钥字符串
+            String publicKeyString = new String(Base64.getDecoder().decode(publicKey.getEncoded()));
+            // 得到私钥字符串
+            String privateKeyString = new String(Base64.getDecoder().decode((privateKey.getEncoded())));
+
+            System.out.println("公钥:" + publicKeyString);
+            System.out.println("私钥:" + privateKeyString);
+        } catch (Exception e) {
+            LOGGER.info("生成公钥私钥异常:" + e.getMessage());
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        // 生成签名
+        Map<String, Object> reqParams = new HashMap<>(8);
+        reqParams.put("pageNo", 1);
+        reqParams.put("pageSize", 10);
+        reqParams.put("brhNo", "test");
+        reqParams.put("queryBeginTime", "2024-01-16");
+        reqParams.put("queryEndTime", "2024-01-16");
+        reqParams.put("timestamp", System.currentTimeMillis() / 1000);
+        String sign = GdRsaUtils.rsa256Sign(reqParams, DEFAULT_PRIVATE_KEY);
+        System.out.println("生成签名:" + sign);
+
+        // 验签
+        reqParams.put("sign", sign);
+        final boolean result = GdRsaUtils.checkSign(reqParams, DEFAULT_PUBLIC_KEY);
+        assert result;
+    }
+
+}

+ 38 - 0
kxs-product/kxs-product-biz/src/main/resources/mapper/KxsGdReportMapper.xml

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.kxs.product.biz.mapper.KxsGdReportMapper">
+
+    <resultMap type="com.kxs.product.api.model.KxsGdReport" id="KxsGdReportMap">
+        <result column="id" property="id" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+        <result column="del_flag" property="delFlag" />
+        <result column="version" property="version" />
+        <result column="user_id" property="userId" />
+        <result column="username" property="username" />
+        <result column="user_code" property="userCode" />
+        <result column="province" property="province" />
+        <result column="city" property="city" />
+        <result column="put_name" property="putName" />
+        <result column="put_mobile" property="putMobile" />
+        <result column="remark" property="remark" />
+        <result column="status" property="status" />
+        <result column="gd_sn" property="gdSn" />
+        <result column="gd_mobile" property="gdMobile" />
+        <result column="is_check" property="isCheck" />
+
+    </resultMap>
+    <select id="getByPage" resultType="com.kxs.product.api.vo.kxsapp.gd.GdReportListVO">
+        select id, create_time, put_name, put_mobile, gd_sn, gd_mobile, status
+        from kxs_gd_report
+        <where>
+            and del_flag = 0
+            and user_id = #{userId}
+            and status = #{status}
+            <if test="keyword != null and keyword != ''">
+                and (put_name = #{keyword} or put_mobile = #{keyword})
+            </if>
+        </where>
+    </select>
+
+</mapper>

+ 8 - 0
kxs-user/kxs-user-api/src/main/java/com/kxs/user/api/feign/RemoteKxsUserService.java

@@ -25,6 +25,14 @@ import java.util.List;
 public interface RemoteKxsUserService {
 
 
+	/**
+	 * 通过手机号码校验验证码
+	 * @param phone 电话信息
+	 * @param code 验证码
+	 * @param from 调用标志
+	 */
+	@GetExchange("/app/checkMobileCode")
+	R<Boolean> checkMobileCode(@RequestParam("phone") String phone, @RequestParam("code") String code, @RequestHeader(SecurityConstants.FROM) String from);
 
 	/**
 	 * 通过手机号码查询用户信息

+ 0 - 5
kxs-user/kxs-user-biz/pom.xml

@@ -79,11 +79,6 @@
             <groupId>com.kxs</groupId>
             <artifactId>kxs-product-api</artifactId>
         </dependency>
-        <!-- 实现对 RocketMQ 的自动化配置 -->
-        <dependency>
-            <groupId>com.kxs</groupId>
-            <artifactId>kxs-common-mq</artifactId>
-        </dependency>
 
     </dependencies>
 

+ 13 - 0
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/controller/kxsapp/KxsAppController.java

@@ -57,6 +57,19 @@ public class KxsAppController {
         return R.ok(kxsUserService.sendCode(phone));
     }
 
+    /**
+     * 验证验证码
+     *
+     * @param phone 手机号
+     */
+    @Inner
+    @GetMapping("/checkMobileCode")
+    public R checkMobileCode(@RequestParam("phone") String phone, @RequestParam("code") String code) {
+
+        kxsUserService.checkValidateCode(phone, code);
+        return R.ok(Boolean.TRUE);
+    }
+
 
     /**
      * 是否设置支付密码

+ 5 - 2
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/service/impl/KxsUserServiceImpl.java

@@ -3,6 +3,7 @@ package com.kxs.user.biz.service.impl;
 import cn.hutool.core.text.CharSequenceUtil;
 import cn.hutool.core.util.IdcardUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.crypto.SecureUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -38,6 +39,7 @@ import com.kxs.user.biz.constant.enums.UserErrorTypeEnum;
 import com.kxs.user.biz.constant.enums.UserRealStatusEnum;
 import com.kxs.user.biz.mapper.*;
 import com.kxs.user.biz.service.KxsUserService;
+import com.kxs.user.biz.util.SmsUtils;
 import io.seata.spring.annotation.GlobalTransactional;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.BeanUtils;
@@ -186,9 +188,10 @@ public class KxsUserServiceImpl extends ServiceImpl<KxsUserMapper, KxsUser> impl
             throw new ValidateCodeException(UserErrorTypeEnum.CODE_NOT_EX.getDescription());
         }
 
-        String code = "111111"; //RandomUtil.randomNumbers(Integer.parseInt(UserConstants.CODE_SIZE));
+        String code = RandomUtil.randomNumbers(Integer.parseInt(UserConstants.CODE_SIZE));
         redisTemplate.opsForValue().set(key, code, UserConstants.CODE_TIME, TimeUnit.SECONDS);
-
+        //发送短信
+        SmsUtils.sendCode(mobile, code);
         return Boolean.TRUE;
     }
 

+ 75 - 0
kxs-user/kxs-user-biz/src/main/java/com/kxs/user/biz/util/SmsUtils.java

@@ -0,0 +1,75 @@
+package com.kxs.user.biz.util;
+
+import cn.hutool.http.Header;
+import cn.hutool.http.HttpRequest;
+import io.micrometer.common.util.StringUtils;
+
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 短信程序
+ *
+ * @author 没秃顶的码农
+ * @date 2024-04-24
+ */
+public class SmsUtils {
+
+    public static void sendCode(String mobile, String code){
+
+        Map<String, String> queries = new HashMap<>();
+        queries.put("mobile", mobile);
+        queries.put("param", "**code**:" +code+",**minute**:5");
+
+        //smsSignId(短信前缀)和templateId(短信模板),可登录国阳云控制台自助申请。参考文档:http://help.guoyangyun.com/Problem/Qm.html
+
+        queries.put("smsSignId", "0f6eccbf0ff343029a7bffc144591fd8");
+        queries.put("templateId", "908e94ccf08b4476ba6c876d13f084ad");
+
+
+
+        String path = "https://gyytz.market.alicloudapi.com/sms/smsSend";
+        String url = SmsUtils.buildUrl(path, queries);
+
+        HttpRequest.post(url)
+                .header(Header.AUTHORIZATION, "APPCODE 8e5704921ca3422f80f0deb935a7ddc6")
+                .execute().body();
+
+    }
+    /**
+     * 构建url
+     *
+     * @param url    url
+     * @param queries 查询
+     * @return {@link String}
+     */
+    public static String buildUrl(String url, Map<String, String> queries) {
+        StringBuilder sbUrl = new StringBuilder();
+        sbUrl.append(url);
+        if (null != queries) {
+            StringBuilder sbQuery = new StringBuilder();
+            for (Map.Entry<String, String> query : queries.entrySet()) {
+                if (!sbQuery.isEmpty()) {
+                    sbQuery.append("&");
+                }
+                if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
+                    sbQuery.append(query.getValue());
+                }
+                if (!StringUtils.isBlank(query.getKey())) {
+                    sbQuery.append(query.getKey());
+                    if (!StringUtils.isBlank(query.getValue())) {
+                        sbQuery.append("=");
+                        sbQuery.append(URLEncoder.encode(query.getValue(), StandardCharsets.UTF_8));
+                    }
+                }
+            }
+            if (!sbQuery.isEmpty()) {
+                sbUrl.append("?").append(sbQuery);
+            }
+        }
+
+        return sbUrl.toString();
+    }
+}