From b9522d131e168a92c88f23e2c0a3a2df079926b4 Mon Sep 17 00:00:00 2001 From: zhibing.pu <393733352@qq.com> Date: 星期一, 19 八月 2024 17:43:43 +0800 Subject: [PATCH] 新增加小程序接口 --- ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SwaggerHandler.java | 68 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java | 30 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TInvoiceTypeController.java | 26 ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/ValidateCodeHandler.java | 34 ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderInvoice.java | 22 ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/CaptchaConfig.java | 135 +- ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TShoppingOrderServiceImpl.java | 188 +++ ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/KaptchaTextCreator.java | 116 - ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TInvoiceInformationMapper.xml | 4 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyShoppingOrderList.java | 30 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetNoInvoicedOrder.java | 17 ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/ValidateCodeService.java | 22 ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TInvoiceInformationController.java | 79 + ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderInvoiceController.java | 45 ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SentinelFallbackHandler.java | 44 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TExchangeOrderController.java | 18 ruoyi-gateway/src/main/java/com/ruoyi/gateway/RuoYiGatewayApplication.java | 34 ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/SwaggerProvider.java | 113 +- ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java | 168 +- ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml | 14 ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java | 192 +- ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyShoppingOrderInfo.java | 56 + ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/HMACSHA1.java | 14 ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/SignFilter.java | 288 ++-- ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/XssProperties.java | 60 ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/RouterFunctionConfiguration.java | 99 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TShoppingOrderController.java | 70 + ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java | 213 +++ ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/OrderInvoiceList.java | 26 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java | 16 ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TOrderInvoiceMapper.xml | 6 ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/CacheRequestFilter.java | 122 +- ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetOrderInvoiceList.java | 17 ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/RequestParamGlobalFilter.java | 102 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TOrderInvoiceService.java | 32 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TShoppingOrderService.java | 41 ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java | 94 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java | 12 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TShoppingOrderMapper.java | 12 ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java | 32 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetMyShoppingOrderList.java | 17 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java | 13 ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/GatewayConfig.java | 16 ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TInvoiceInformation.java | 6 ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/BlackListUrlFilter.java | 91 ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports | 3 ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java | 172 +- ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/CaptchaProperties.java | 59 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyOrderInvoiceInfo.java | 38 ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TShoppingOrderMapper.xml | 15 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddOrderInvoice.java | 18 ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TInvoiceType.java | 7 ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java | 60 ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/InvoiceTypeFallbackFactory.java | 34 ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/InvoiceTypeClient.java | 26 55 files changed, 2,136 insertions(+), 1,150 deletions(-) diff --git a/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TInvoiceInformation.java b/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TInvoiceInformation.java index c3d62b5..439ced7 100644 --- a/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TInvoiceInformation.java +++ b/ruoyi-api/ruoyi-api-account/src/main/java/com/ruoyi/account/api/model/TInvoiceInformation.java @@ -68,9 +68,9 @@ @TableField("bank_account") private String bankAccount; -// @ApiModelProperty(value = "设置默认(0=否,1=是)") -// @TableField("default") -// private Integer default; + @ApiModelProperty(value = "设置默认(0=否,1=是)") + @TableField("is_default") + private Integer isDefault; diff --git a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderInvoice.java b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderInvoice.java index f7f675c..280b1b0 100644 --- a/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderInvoice.java +++ b/ruoyi-api/ruoyi-api-order/src/main/java/com/ruoyi/order/api/model/TOrderInvoice.java @@ -11,6 +11,7 @@ import java.io.Serializable; import java.math.BigDecimal; +import java.time.LocalDateTime; /** * <p> @@ -47,10 +48,14 @@ @ApiModelProperty(value = "开票公司") @TableField("invoicing_company") private String invoicingCompany; + + @ApiModelProperty(value = "发票类型id") + @TableField("invoice_type_id") + private Integer invoiceTypeId; - @ApiModelProperty(value = "发票类型(1=增值税普通发票,2=增值税专用发票)") + @ApiModelProperty(value = "发票类型") @TableField("invoice_type") - private Integer invoiceType; + private String invoiceType; @ApiModelProperty(value = "发票材质(1=纸质发票,2=电子发票)") @TableField("invoice_material") @@ -103,6 +108,17 @@ @ApiModelProperty(value = "状态(1=待开票,2=开票中,3=已开票)") @TableField("status") private Integer status; - + + @ApiModelProperty(value = "添加时间") + @TableField("create_time") + private LocalDateTime createTime; + + @ApiModelProperty(value = "开票时间") + @TableField("billing_time") + private LocalDateTime billingTime; + + @ApiModelProperty(value = "开票人id") + @TableField("billing_user_id") + private Integer billingUserId; } diff --git a/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TInvoiceType.java b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TInvoiceType.java index 0fb7f18..e0be5a0 100644 --- a/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TInvoiceType.java +++ b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TInvoiceType.java @@ -8,6 +8,7 @@ import lombok.EqualsAndHashCode; import java.io.Serializable; +import java.math.BigDecimal; import java.time.LocalDateTime; /** @@ -44,15 +45,15 @@ @ApiModelProperty(value = "电费税率") @TableField("electricity_tariff") - private Double electricityTariff; + private BigDecimal electricityTariff; @ApiModelProperty(value = "服务费税率") @TableField("service_tariff") - private Double serviceTariff; + private BigDecimal serviceTariff; @ApiModelProperty(value = "增值服务费税率") @TableField("added_service_tariff") - private Double addedServiceTariff; + private BigDecimal addedServiceTariff; diff --git a/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/InvoiceTypeFallbackFactory.java b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/InvoiceTypeFallbackFactory.java new file mode 100644 index 0000000..d1a16c0 --- /dev/null +++ b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/factory/InvoiceTypeFallbackFactory.java @@ -0,0 +1,34 @@ +package com.ruoyi.other.api.factory; + +import com.ruoyi.common.core.domain.R; +import com.ruoyi.other.api.domain.TInvoiceType; +import com.ruoyi.other.api.feignClient.InvoiceTypeClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cloud.openfeign.FallbackFactory; +import org.springframework.stereotype.Component; + + +/** + * 商品服务降级处理 + * + * @author ruoyi + */ +@Component +public class InvoiceTypeFallbackFactory implements FallbackFactory<InvoiceTypeClient> +{ + private static final Logger log = LoggerFactory.getLogger(InvoiceTypeFallbackFactory.class); + + @Override + public InvoiceTypeClient create(Throwable throwable) { + log.error("开票类型失败:{}", throwable.getMessage()); + return new InvoiceTypeClient() { + + + @Override + public R<TInvoiceType> getInvoiceType(Integer id) { + throw new RuntimeException(throwable.getMessage()); + } + }; + } +} diff --git a/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/InvoiceTypeClient.java b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/InvoiceTypeClient.java new file mode 100644 index 0000000..896f3db --- /dev/null +++ b/ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/feignClient/InvoiceTypeClient.java @@ -0,0 +1,26 @@ +package com.ruoyi.other.api.feignClient; + +import com.ruoyi.common.core.constant.ServiceNameConstants; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.other.api.domain.TInvoiceType; +import com.ruoyi.other.api.factory.InvoiceTypeFallbackFactory; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; + +/** + * @author zhibing.pu + * @Date 2024/8/19 15:57 + */ +@FeignClient(contextId = "IntegralRuleClient", value = ServiceNameConstants.OTHER_SERVICE, fallbackFactory = InvoiceTypeFallbackFactory.class) +public interface InvoiceTypeClient { + + + /** + * 根据id获取发票类型 + * @param id + * @return + */ + @PostMapping("/t-invoice-type/getInvoiceType/{id}") + R<TInvoiceType> getInvoiceType(@PathVariable("id") Integer id); +} diff --git a/ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 8ca6c74..9033994 100644 --- a/ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/ruoyi-api/ruoyi-api-other/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -5,4 +5,5 @@ com.ruoyi.other.api.factory.VipFallbackFactory com.ruoyi.other.api.factory.IntegralRuleFallbackFactory com.ruoyi.other.api.factory.GoodsFallbackFactory -com.ruoyi.other.api.factory.CouponFallbackFactory \ No newline at end of file +com.ruoyi.other.api.factory.CouponFallbackFactory +com.ruoyi.other.api.factory.InvoiceTypeFallbackFactory \ No newline at end of file diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/RuoYiGatewayApplication.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/RuoYiGatewayApplication.java index 3c54b77..b67f5ef 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/RuoYiGatewayApplication.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/RuoYiGatewayApplication.java @@ -6,24 +6,22 @@ /** * 网关启动程序 - * + * * @author ruoyi */ -@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) -public class RuoYiGatewayApplication -{ - public static void main(String[] args) - { - SpringApplication.run(RuoYiGatewayApplication.class, args); - System.out.println("(♥◠‿◠)ノ゙ 若依网关启动成功 ლ(´ڡ`ლ)゙ \n" + - " .-------. ____ __ \n" + - " | _ _ \\ \\ \\ / / \n" + - " | ( ' ) | \\ _. / ' \n" + - " |(_ o _) / _( )_ .' \n" + - " | (_,_).' __ ___(_ o _)' \n" + - " | |\\ \\ | || |(_,_)' \n" + - " | | \\ `' /| `-' / \n" + - " | | \\ / \\ / \n" + - " ''-' `'-' `-..-' "); - } +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) +public class RuoYiGatewayApplication { + public static void main(String[] args) { + SpringApplication.run(RuoYiGatewayApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 若依网关启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/CaptchaConfig.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/CaptchaConfig.java index e6c6d9d..bc27c00 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/CaptchaConfig.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/CaptchaConfig.java @@ -1,83 +1,82 @@ package com.ruoyi.gateway.config; import java.util.Properties; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; + import static com.google.code.kaptcha.Constants.*; /** * 验证码配置 - * + * * @author ruoyi */ @Configuration -public class CaptchaConfig -{ - @Bean(name = "captchaProducer") - public DefaultKaptcha getKaptchaBean() - { - DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); - Properties properties = new Properties(); - // 是否有边框 默认为true 我们可以自己设置yes,no - properties.setProperty(KAPTCHA_BORDER, "yes"); - // 验证码文本字符颜色 默认为Color.BLACK - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); - // 验证码图片宽度 默认为200 - properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); - // 验证码图片高度 默认为50 - properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); - // 验证码文本字符大小 默认为40 - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); - // KAPTCHA_SESSION_KEY - properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); - // 验证码文本字符长度 默认为5 - properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); - // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); - // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy - properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); - Config config = new Config(properties); - defaultKaptcha.setConfig(config); - return defaultKaptcha; - } - - @Bean(name = "captchaProducerMath") - public DefaultKaptcha getKaptchaBeanMath() - { - DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); - Properties properties = new Properties(); - // 是否有边框 默认为true 我们可以自己设置yes,no - properties.setProperty(KAPTCHA_BORDER, "yes"); - // 边框颜色 默认为Color.BLACK - properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); - // 验证码文本字符颜色 默认为Color.BLACK - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); - // 验证码图片宽度 默认为200 - properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); - // 验证码图片高度 默认为50 - properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); - // 验证码文本字符大小 默认为40 - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); - // KAPTCHA_SESSION_KEY - properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); - // 验证码文本生成器 - properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.gateway.config.KaptchaTextCreator"); - // 验证码文本字符间距 默认为2 - properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); - // 验证码文本字符长度 默认为5 - properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); - // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) - properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); - // 验证码噪点颜色 默认为Color.BLACK - properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); - // 干扰实现类 - properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); - // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy - properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); - Config config = new Config(properties); - defaultKaptcha.setConfig(config); - return defaultKaptcha; - } +public class CaptchaConfig { + @Bean(name = "captchaProducer") + public DefaultKaptcha getKaptchaBean() { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 是否有边框 默认为true 我们可以自己设置yes,no + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 验证码文本字符颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); + // 验证码图片宽度 默认为200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 验证码图片高度 默认为50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 验证码文本字符大小 默认为40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); + // 验证码文本字符长度 默认为5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); + // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } + + @Bean(name = "captchaProducerMath") + public DefaultKaptcha getKaptchaBeanMath() { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 是否有边框 默认为true 我们可以自己设置yes,no + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 边框颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); + // 验证码文本字符颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); + // 验证码图片宽度 默认为200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 验证码图片高度 默认为50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 验证码文本字符大小 默认为40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); + // 验证码文本生成器 + properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.gateway.config.KaptchaTextCreator"); + // 验证码文本字符间距 默认为2 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); + // 验证码文本字符长度 默认为5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); + // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 验证码噪点颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); + // 干扰实现类 + properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); + // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } } \ No newline at end of file diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/GatewayConfig.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/GatewayConfig.java index 3bb6d8e..7fc604d 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/GatewayConfig.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/GatewayConfig.java @@ -8,16 +8,14 @@ /** * 网关限流配置 - * + * * @author ruoyi */ @Configuration -public class GatewayConfig -{ - @Bean - @Order(Ordered.HIGHEST_PRECEDENCE) - public SentinelFallbackHandler sentinelGatewayExceptionHandler() - { - return new SentinelFallbackHandler(); - } +public class GatewayConfig { + @Bean + @Order(Ordered.HIGHEST_PRECEDENCE) + public SentinelFallbackHandler sentinelGatewayExceptionHandler() { + return new SentinelFallbackHandler(); + } } \ No newline at end of file diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/KaptchaTextCreator.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/KaptchaTextCreator.java index f68e0fa..8485afa 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/KaptchaTextCreator.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/KaptchaTextCreator.java @@ -1,75 +1,61 @@ package com.ruoyi.gateway.config; import java.util.Random; + import com.google.code.kaptcha.text.impl.DefaultTextCreator; /** * 验证码文本生成器 - * + * * @author ruoyi */ -public class KaptchaTextCreator extends DefaultTextCreator -{ - private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); - - @Override - public String getText() - { - Integer result = 0; - Random random = new Random(); - int x = random.nextInt(10); - int y = random.nextInt(10); - StringBuilder suChinese = new StringBuilder(); - int randomoperands = random.nextInt(3); - if (randomoperands == 0) - { - result = x * y; - suChinese.append(CNUMBERS[x]); - suChinese.append("*"); - suChinese.append(CNUMBERS[y]); - } - else if (randomoperands == 1) - { - if ((x != 0) && y % x == 0) - { - result = y / x; - suChinese.append(CNUMBERS[y]); - suChinese.append("/"); - suChinese.append(CNUMBERS[x]); - } - else - { - result = x + y; - suChinese.append(CNUMBERS[x]); - suChinese.append("+"); - suChinese.append(CNUMBERS[y]); - } - } - else if (randomoperands == 2) - { - if (x >= y) - { - result = x - y; - suChinese.append(CNUMBERS[x]); - suChinese.append("-"); - suChinese.append(CNUMBERS[y]); - } - else - { - result = y - x; - suChinese.append(CNUMBERS[y]); - suChinese.append("-"); - suChinese.append(CNUMBERS[x]); - } - } - else - { - result = x + y; - suChinese.append(CNUMBERS[x]); - suChinese.append("+"); - suChinese.append(CNUMBERS[y]); - } - suChinese.append("=?@" + result); - return suChinese.toString(); - } +public class KaptchaTextCreator extends DefaultTextCreator { + private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); + + @Override + public String getText() { + Integer result = 0; + Random random = new Random(); + int x = random.nextInt(10); + int y = random.nextInt(10); + StringBuilder suChinese = new StringBuilder(); + int randomoperands = random.nextInt(3); + if (randomoperands == 0) { + result = x * y; + suChinese.append(CNUMBERS[x]); + suChinese.append("*"); + suChinese.append(CNUMBERS[y]); + } else if (randomoperands == 1) { + if ((x != 0) && y % x == 0) { + result = y / x; + suChinese.append(CNUMBERS[y]); + suChinese.append("/"); + suChinese.append(CNUMBERS[x]); + } else { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + } else if (randomoperands == 2) { + if (x >= y) { + result = x - y; + suChinese.append(CNUMBERS[x]); + suChinese.append("-"); + suChinese.append(CNUMBERS[y]); + } else { + result = y - x; + suChinese.append(CNUMBERS[y]); + suChinese.append("-"); + suChinese.append(CNUMBERS[x]); + } + } else { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + suChinese.append("=?@" + result); + return suChinese.toString(); + } } \ No newline at end of file diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/RouterFunctionConfiguration.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/RouterFunctionConfiguration.java index 6c20c07..387516a 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/RouterFunctionConfiguration.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/RouterFunctionConfiguration.java @@ -21,59 +21,54 @@ /** * 路由配置信息 - * + * * @author ruoyi */ @Configuration -public class RouterFunctionConfiguration -{ - - /** - * 这里为支持的请求头,如果有自定义的header字段请自己添加 - */ - private static final String ALLOWED_HEADERS = "X-Requested-With, Content-Type, Authorization, credential, X-XSRF-TOKEN, token, username, client, request-origion, sign, nonce_str"; - private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD"; - private static final String ALLOWED_ORIGIN = "*"; - private static final String ALLOWED_EXPOSE = "*"; - private static final String MAX_AGE = "18000L"; - - @Autowired - private ValidateCodeHandler validateCodeHandler; - - @SuppressWarnings("rawtypes") - @Bean - public RouterFunction routerFunction() - { - return RouterFunctions.route( - RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), - validateCodeHandler); - } - - /** - * 跨域配置 - */ - @Bean - public WebFilter corsFilter() - { - return (ServerWebExchange ctx, WebFilterChain chain) -> { - ServerHttpRequest request = ctx.getRequest(); - if (CorsUtils.isCorsRequest(request)) - { - ServerHttpResponse response = ctx.getResponse(); - HttpHeaders headers = response.getHeaders(); - headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS); - headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS); - headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN); - headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE); - headers.add("Access-Control-Max-Age", MAX_AGE); - headers.add("Access-Control-Allow-Credentials", "true"); - if (request.getMethod() == HttpMethod.OPTIONS) - { - response.setStatusCode(HttpStatus.OK); - return Mono.empty(); - } - } - return chain.filter(ctx); - }; - } +public class RouterFunctionConfiguration { + + /** + * 这里为支持的请求头,如果有自定义的header字段请自己添加 + */ + private static final String ALLOWED_HEADERS = "X-Requested-With, Content-Type, Authorization, credential, X-XSRF-TOKEN, token, username, client, request-origion, sign, nonce_str, timestamp"; + private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD"; + private static final String ALLOWED_ORIGIN = "*"; + private static final String ALLOWED_EXPOSE = "*"; + private static final String MAX_AGE = "18000L"; + + @Autowired + private ValidateCodeHandler validateCodeHandler; + + @SuppressWarnings("rawtypes") + @Bean + public RouterFunction routerFunction() { + return RouterFunctions.route( + RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), + validateCodeHandler); + } + + /** + * 跨域配置 + */ + @Bean + public WebFilter corsFilter() { + return (ServerWebExchange ctx, WebFilterChain chain) -> { + ServerHttpRequest request = ctx.getRequest(); + if (CorsUtils.isCorsRequest(request)) { + ServerHttpResponse response = ctx.getResponse(); + HttpHeaders headers = response.getHeaders(); + headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS); + headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS); + headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN); + headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE); + headers.add("Access-Control-Max-Age", MAX_AGE); + headers.add("Access-Control-Allow-Credentials", "true"); + if (request.getMethod() == HttpMethod.OPTIONS) { + response.setStatusCode(HttpStatus.OK); + return Mono.empty(); + } + } + return chain.filter(ctx); + }; + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/SwaggerProvider.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/SwaggerProvider.java index 7c58673..495dd46 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/SwaggerProvider.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/SwaggerProvider.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.config.GatewayProperties; import org.springframework.cloud.gateway.route.RouteLocator; @@ -15,65 +16,61 @@ /** * 聚合系统接口 - * + * * @author ruoyi */ @Component -public class SwaggerProvider implements SwaggerResourcesProvider, WebFluxConfigurer -{ - /** - * Swagger2默认的url后缀 - */ - public static final String SWAGGER2URL = "/v2/api-docs"; - - /** - * 网关路由 - */ - @Lazy - @Autowired - private RouteLocator routeLocator; - - @Autowired - private GatewayProperties gatewayProperties; - - /** - * 聚合其他服务接口 - * - * @return - */ - @Override - public List<SwaggerResource> get() - { - List<SwaggerResource> resourceList = new ArrayList<>(); - List<String> routes = new ArrayList<>(); - // 获取网关中配置的route - routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); - gatewayProperties.getRoutes().stream() - .filter(routeDefinition -> routes - .contains(routeDefinition.getId())) - .forEach(routeDefinition -> routeDefinition.getPredicates().stream() - .filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName())) - .filter(predicateDefinition -> !"ruoyi-auth".equalsIgnoreCase(routeDefinition.getId())) - .forEach(predicateDefinition -> resourceList - .add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs() - .get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", SWAGGER2URL))))); - return resourceList; - } - - private SwaggerResource swaggerResource(String name, String location) - { - SwaggerResource swaggerResource = new SwaggerResource(); - swaggerResource.setName(name); - swaggerResource.setLocation(location); - swaggerResource.setSwaggerVersion("2.0"); - return swaggerResource; - } - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) - { - /** swagger-ui 地址 */ - registry.addResourceHandler("/swagger-ui/**","*/doc.html") - .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); - } +public class SwaggerProvider implements SwaggerResourcesProvider, WebFluxConfigurer { + /** + * Swagger2默认的url后缀 + */ + public static final String SWAGGER2URL = "/v2/api-docs"; + + /** + * 网关路由 + */ + @Lazy + @Autowired + private RouteLocator routeLocator; + + @Autowired + private GatewayProperties gatewayProperties; + + /** + * 聚合其他服务接口 + * + * @return + */ + @Override + public List<SwaggerResource> get() { + List<SwaggerResource> resourceList = new ArrayList<>(); + List<String> routes = new ArrayList<>(); + // 获取网关中配置的route + routeLocator.getRoutes().subscribe(route -> routes.add(route.getId())); + gatewayProperties.getRoutes().stream() + .filter(routeDefinition -> routes + .contains(routeDefinition.getId())) + .forEach(routeDefinition -> routeDefinition.getPredicates().stream() + .filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName())) + .filter(predicateDefinition -> !"ruoyi-auth".equalsIgnoreCase(routeDefinition.getId())) + .forEach(predicateDefinition -> resourceList + .add(swaggerResource(routeDefinition.getId(), predicateDefinition.getArgs() + .get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", SWAGGER2URL))))); + return resourceList; + } + + private SwaggerResource swaggerResource(String name, String location) { + SwaggerResource swaggerResource = new SwaggerResource(); + swaggerResource.setName(name); + swaggerResource.setLocation(location); + swaggerResource.setSwaggerVersion("2.0"); + return swaggerResource; + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + /** swagger-ui 地址 */ + registry.addResourceHandler("/swagger-ui/**", "*/doc.html") + .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/CaptchaProperties.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/CaptchaProperties.java index f6bb000..fb086bc 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/CaptchaProperties.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/CaptchaProperties.java @@ -6,41 +6,36 @@ /** * 验证码配置 - * + * * @author ruoyi */ @Configuration @RefreshScope @ConfigurationProperties(prefix = "security.captcha") -public class CaptchaProperties -{ - /** - * 验证码开关 - */ - private Boolean enabled; - - /** - * 验证码类型(math 数组计算 char 字符) - */ - private String type; - - public Boolean getEnabled() - { - return enabled; - } - - public void setEnabled(Boolean enabled) - { - this.enabled = enabled; - } - - public String getType() - { - return type; - } - - public void setType(String type) - { - this.type = type; - } +public class CaptchaProperties { + /** + * 验证码开关 + */ + private Boolean enabled; + + /** + * 验证码类型(math 数组计算 char 字符) + */ + private String type; + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java index 1d2c56a..5797322 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java @@ -2,32 +2,30 @@ import java.util.ArrayList; import java.util.List; + import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Configuration; /** * 放行白名单配置 - * + * * @author ruoyi */ @Configuration @RefreshScope @ConfigurationProperties(prefix = "security.ignore") -public class IgnoreWhiteProperties -{ - /** - * 放行白名单配置,网关不校验此处的白名单 - */ - private List<String> whites = new ArrayList<>(); - - public List<String> getWhites() - { - return whites; - } - - public void setWhites(List<String> whites) - { - this.whites = whites; - } +public class IgnoreWhiteProperties { + /** + * 放行白名单配置,网关不校验此处的白名单 + */ + private List<String> whites = new ArrayList<>(); + + public List<String> getWhites() { + return whites; + } + + public void setWhites(List<String> whites) { + this.whites = whites; + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/XssProperties.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/XssProperties.java index 891679e..39441b8 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/XssProperties.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/XssProperties.java @@ -2,47 +2,43 @@ import java.util.ArrayList; import java.util.List; + import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Configuration; /** * XSS跨站脚本配置 - * + * * @author ruoyi */ @Configuration @RefreshScope @ConfigurationProperties(prefix = "security.xss") -public class XssProperties -{ - /** - * Xss开关 - */ - private Boolean enabled; - - /** - * 排除路径 - */ - private List<String> excludeUrls = new ArrayList<>(); - - public Boolean getEnabled() - { - return enabled; - } - - public void setEnabled(Boolean enabled) - { - this.enabled = enabled; - } - - public List<String> getExcludeUrls() - { - return excludeUrls; - } - - public void setExcludeUrls(List<String> excludeUrls) - { - this.excludeUrls = excludeUrls; - } +public class XssProperties { + /** + * Xss开关 + */ + private Boolean enabled; + + /** + * 排除路径 + */ + private List<String> excludeUrls = new ArrayList<>(); + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public List<String> getExcludeUrls() { + return excludeUrls; + } + + public void setExcludeUrls(List<String> excludeUrls) { + this.excludeUrls = excludeUrls; + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java index e829417..1b0eb25 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java @@ -36,102 +36,106 @@ /** * 网关鉴权 - * + * * @author ruoyi */ @Component public class AuthFilter implements GlobalFilter, Ordered { - private static final Logger log = LoggerFactory.getLogger(AuthFilter.class); - - // 排除过滤的 uri 地址,nacos自行添加 - @Autowired - private IgnoreWhiteProperties ignoreWhite; - - @Autowired - private RedisService redisService; - - - @Override - public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { - ServerHttpRequest request = exchange.getRequest(); - ServerHttpRequest.Builder mutate = request.mutate(); - - String url = request.getURI().getPath(); - // 跳过不需要验证的路径 - if (StringUtils.matches(url, ignoreWhite.getWhites())) { - return chain.filter(exchange); - } - String token = getToken(request); - if (StringUtils.isEmpty(token)) { - return unauthorizedResponse(exchange, "令牌不能为空"); - } - Claims claims = JwtUtils.parseToken(token); - if (claims == null) { - return unauthorizedResponse(exchange, "令牌已过期或验证不正确!"); - } - String userkey = JwtUtils.getUserKey(claims); - boolean islogin = redisService.hasKey(getTokenKey(userkey)); - if (!islogin) { - return unauthorizedResponse(exchange, "登录状态已过期"); - } - String userid = JwtUtils.getUserId(claims); - String username = JwtUtils.getUserName(claims); - if (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username)) { - return unauthorizedResponse(exchange, "令牌验证失败"); - } - - // 设置用户信息到请求 - addHeader(mutate, SecurityConstants.USER_KEY, userkey); - addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid); - addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username); - // 内部请求来源参数清除 - removeHeader(mutate, SecurityConstants.FROM_SOURCE); - return chain.filter(exchange.mutate().request(mutate.build()).build()); - } - - private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value) { - if (value == null) { - return; - } - String valueStr = value.toString(); - String valueEncode = ServletUtils.urlEncode(valueStr); - mutate.header(name, valueEncode); - } - - private void removeHeader(ServerHttpRequest.Builder mutate, String name) { - mutate.headers(httpHeaders -> httpHeaders.remove(name)).build(); - } - - private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) { - log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath()); - return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED); - } - - /** - * 获取缓存key - */ - private String getTokenKey(String token) - { - return CacheConstants.LOGIN_TOKEN_KEY + token; - } - - /** - * 获取请求token - */ - private String getToken(ServerHttpRequest request) { - String token = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION); - // 如果前端设置了令牌前缀,则裁剪掉前缀 - if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX)) - { - token = token.replaceFirst(TokenConstants.PREFIX, StringUtils.EMPTY); - } - return token; - } - - - @Override - public int getOrder() - { - return -300; - } + private static final Logger log = LoggerFactory.getLogger(AuthFilter.class); + + // 排除过滤的 uri 地址,nacos自行添加 + @Autowired + private IgnoreWhiteProperties ignoreWhite; + + @Autowired + private RedisService redisService; + + + @Override + public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + ServerHttpRequest.Builder mutate = request.mutate(); + + String url = request.getURI().getPath(); + // 跳过不需要验证的路径 + if (StringUtils.matches(url, ignoreWhite.getWhites())) { + return chain.filter(exchange); + } + String token = getToken(request); + if (StringUtils.isEmpty(token)) { + return unauthorizedResponse(exchange, "令牌不能为空"); + } + Claims claims = JwtUtils.parseToken(token); + if (claims == null) { + return unauthorizedResponse(exchange, "令牌已过期或验证不正确!"); + } + String userkey = JwtUtils.getUserKey(claims); + boolean islogin = redisService.hasKey(getTokenKey(userkey)); + if (!islogin) { + return unauthorizedResponse(exchange, "登录状态已过期"); + } + String userid = JwtUtils.getUserId(claims); + String username = JwtUtils.getUserName(claims); + if (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username)) { + return unauthorizedResponse(exchange, "令牌验证失败"); + } + + // 设置用户信息到请求 + addHeader(mutate, SecurityConstants.USER_KEY, userkey); + addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid); + addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username); + // 内部请求来源参数清除 + removeHeader(mutate, SecurityConstants.FROM_SOURCE); + return chain.filter(exchange.mutate().request(mutate.build()).build()); + } + + private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value) { + if (value == null) { + return; + } + String valueStr = value.toString(); + String valueEncode = ServletUtils.urlEncode(valueStr); + mutate.header(name, valueEncode); + } + + private void removeHeader(ServerHttpRequest.Builder mutate, String name) { + mutate.headers(httpHeaders -> httpHeaders.remove(name)).build(); + } + + private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) { + log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath()); + return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED); + } + + /** + * 获取缓存key + */ + private String getTokenKey(String token) { + return CacheConstants.LOGIN_TOKEN_KEY + token; + } + + /** + * 获取请求token + */ + private String getToken(ServerHttpRequest request) { + String token = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION); + // 如果前端设置了令牌前缀,则裁剪掉前缀 + if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX)) { + token = token.replaceFirst(TokenConstants.PREFIX, StringUtils.EMPTY); + } + return token; + } + + + /** + * 防抖处理 + */ + + + + + @Override + public int getOrder() { + return -300; + } } \ No newline at end of file diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/BlackListUrlFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/BlackListUrlFilter.java index 343bd01..8a56dcf 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/BlackListUrlFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/BlackListUrlFilter.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; + import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.stereotype.Component; @@ -10,56 +11,48 @@ /** * 黑名单过滤器 - * + * * @author ruoyi */ @Component -public class BlackListUrlFilter extends AbstractGatewayFilterFactory<BlackListUrlFilter.Config> -{ - @Override - public GatewayFilter apply(Config config) - { - return (exchange, chain) -> { - - String url = exchange.getRequest().getURI().getPath(); - if (config.matchBlacklist(url)) - { - return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求地址不允许访问"); - } - - return chain.filter(exchange); - }; - } - - public BlackListUrlFilter() - { - super(Config.class); - } - - public static class Config - { - private List<String> blacklistUrl; - - private List<Pattern> blacklistUrlPattern = new ArrayList<>(); - - public boolean matchBlacklist(String url) - { - return !blacklistUrlPattern.isEmpty() && blacklistUrlPattern.stream().anyMatch(p -> p.matcher(url).find()); - } - - public List<String> getBlacklistUrl() - { - return blacklistUrl; - } - - public void setBlacklistUrl(List<String> blacklistUrl) - { - this.blacklistUrl = blacklistUrl; - this.blacklistUrlPattern.clear(); - this.blacklistUrl.forEach(url -> { - this.blacklistUrlPattern.add(Pattern.compile(url.replaceAll("\\*\\*", "(.*?)"), Pattern.CASE_INSENSITIVE)); - }); - } - } - +public class BlackListUrlFilter extends AbstractGatewayFilterFactory<BlackListUrlFilter.Config> { + public BlackListUrlFilter() { + super(Config.class); + } + + @Override + public GatewayFilter apply(Config config) { + return (exchange, chain) -> { + + String url = exchange.getRequest().getURI().getPath(); + if (config.matchBlacklist(url)) { + return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求地址不允许访问"); + } + + return chain.filter(exchange); + }; + } + + public static class Config { + private List<String> blacklistUrl; + + private List<Pattern> blacklistUrlPattern = new ArrayList<>(); + + public boolean matchBlacklist(String url) { + return !blacklistUrlPattern.isEmpty() && blacklistUrlPattern.stream().anyMatch(p -> p.matcher(url).find()); + } + + public List<String> getBlacklistUrl() { + return blacklistUrl; + } + + public void setBlacklistUrl(List<String> blacklistUrl) { + this.blacklistUrl = blacklistUrl; + this.blacklistUrlPattern.clear(); + this.blacklistUrl.forEach(url -> { + this.blacklistUrlPattern.add(Pattern.compile(url.replaceAll("\\*\\*", "(.*?)"), Pattern.CASE_INSENSITIVE)); + }); + } + } + } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/CacheRequestFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/CacheRequestFilter.java index 94c6cb5..2228c96 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/CacheRequestFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/CacheRequestFilter.java @@ -2,6 +2,7 @@ import java.util.Collections; import java.util.List; + import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.OrderedGatewayFilter; @@ -14,74 +15,61 @@ /** * 获取body请求数据(解决流不能重复读取问题) - * + * * @author ruoyi */ @Component -public class CacheRequestFilter extends AbstractGatewayFilterFactory<CacheRequestFilter.Config> -{ - public CacheRequestFilter() - { - super(Config.class); - } - - @Override - public String name() - { - return "CacheRequestFilter"; - } - - @Override - public GatewayFilter apply(Config config) - { - CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter(); - Integer order = config.getOrder(); - if (order == null) - { - return cacheRequestGatewayFilter; - } - return new OrderedGatewayFilter(cacheRequestGatewayFilter, order); - } - - public static class CacheRequestGatewayFilter implements GatewayFilter - { - @Override - public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) - { - // GET DELETE 不过滤 - HttpMethod method = exchange.getRequest().getMethod(); - if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) - { - return chain.filter(exchange); - } - return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> { - if (serverHttpRequest == exchange.getRequest()) - { - return chain.filter(exchange); - } - return chain.filter(exchange.mutate().request(serverHttpRequest).build()); - }); - } - } - - @Override - public List<String> shortcutFieldOrder() - { - return Collections.singletonList("order"); - } - - static class Config - { - private Integer order; - - public Integer getOrder() - { - return order; - } - - public void setOrder(Integer order) - { - this.order = order; - } - } +public class CacheRequestFilter extends AbstractGatewayFilterFactory<CacheRequestFilter.Config> { + public CacheRequestFilter() { + super(Config.class); + } + + @Override + public String name() { + return "CacheRequestFilter"; + } + + @Override + public GatewayFilter apply(Config config) { + CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter(); + Integer order = config.getOrder(); + if (order == null) { + return cacheRequestGatewayFilter; + } + return new OrderedGatewayFilter(cacheRequestGatewayFilter, order); + } + + @Override + public List<String> shortcutFieldOrder() { + return Collections.singletonList("order"); + } + + public static class CacheRequestGatewayFilter implements GatewayFilter { + @Override + public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { + // GET DELETE 不过滤 + HttpMethod method = exchange.getRequest().getMethod(); + if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) { + return chain.filter(exchange); + } + return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> { + if (serverHttpRequest == exchange.getRequest()) { + return chain.filter(exchange); + } + return chain.filter(exchange.mutate().request(serverHttpRequest).build()); + }); + } + } + + static class Config { + private Integer order; + + public Integer getOrder() { + return order; + } + + public void setOrder(Integer order) { + this.order = order; + } + } } \ No newline at end of file diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/HMACSHA1.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/HMACSHA1.java index 976f086..5b7782d 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/HMACSHA1.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/HMACSHA1.java @@ -6,17 +6,15 @@ import javax.crypto.spec.SecretKeySpec; public class HMACSHA1 { - + private static final String MAC_NAME = "HmacSHA1"; private static final String ENCODING = "UTF-8"; - + /** * 使用 HMAC-SHA1 签名方法对对encryptText进行签名 - * - * @param encryptText - * 被签名的字符串 - * @param encryptKey - * 密钥 + * + * @param encryptText 被签名的字符串 + * @param encryptKey 密钥 * @return * @throws Exception */ @@ -28,7 +26,7 @@ // 生成一个指定 Mac 算法 的 Mac 对象 // 用给定密钥初始化 Mac 对象 mac.init(secretKey); - + byte[] text = encryptText.getBytes(ENCODING); // 完成 Mac 操作 return mac.doFinal(text); diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/RequestParamGlobalFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/RequestParamGlobalFilter.java index c13f096..dd622ed 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/RequestParamGlobalFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/RequestParamGlobalFilter.java @@ -42,57 +42,53 @@ */ @Component public class RequestParamGlobalFilter implements GlobalFilter, Ordered { - - - - @Override - public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { - ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange); - return chain.filter(exchange.mutate().request(httpRequestDecorator).build()); - } - - - - - private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange) { - ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) { - @Override - public Flux<DataBuffer> getBody() { - Flux<DataBuffer> body = super.getBody(); - return body.buffer().map(dataBuffers -> { - DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); - DataBuffer join = dataBufferFactory.join(dataBuffers); - byte[] content = new byte[join.readableByteCount()]; - join.read(content); - DataBufferUtils.release(join); - String bodyStr = new String(content, StandardCharsets.UTF_8); - // 转成字节 - byte[] bytes = bodyStr.getBytes(); - NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); - DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); - buffer.write(bytes); - return buffer; - }); - } - - @Override - public HttpHeaders getHeaders() { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.putAll(super.getHeaders()); - // 由于修改了请求体的body,导致content-length长度不确定,因此需要删除原先的content-length - httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); - httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); - return httpHeaders; - } - - }; - return serverHttpRequestDecorator; - } - - - @Override - public int getOrder() - { - return HIGHEST_PRECEDENCE; - } + + + @Override + public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange); + return chain.filter(exchange.mutate().request(httpRequestDecorator).build()); + } + + + private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange) { + ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) { + @Override + public Flux<DataBuffer> getBody() { + Flux<DataBuffer> body = super.getBody(); + return body.buffer().map(dataBuffers -> { + DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); + DataBuffer join = dataBufferFactory.join(dataBuffers); + byte[] content = new byte[join.readableByteCount()]; + join.read(content); + DataBufferUtils.release(join); + String bodyStr = new String(content, StandardCharsets.UTF_8); + // 转成字节 + byte[] bytes = bodyStr.getBytes(); + NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); + DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); + buffer.write(bytes); + return buffer; + }); + } + + @Override + public HttpHeaders getHeaders() { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.putAll(super.getHeaders()); + // 由于修改了请求体的body,导致content-length长度不确定,因此需要删除原先的content-length + httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); + httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); + return httpHeaders; + } + + }; + return serverHttpRequestDecorator; + } + + + @Override + public int getOrder() { + return HIGHEST_PRECEDENCE; + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/SignFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/SignFilter.java index 7ea17ff..8dac047 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/SignFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/SignFilter.java @@ -40,155 +40,149 @@ /** * 网关鉴权 - * + * * @author ruoyi */ @Component public class SignFilter implements GlobalFilter, Ordered { - private static final Logger log = LoggerFactory.getLogger(SignFilter.class); - - // 排除过滤的 uri 地址,nacos自行添加 - @Autowired - private IgnoreWhiteProperties ignoreWhite; - - @Autowired - private RedisService redisService; - - @Value("${security.sign}") - private boolean parameter_signature; - - - @Override - public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { - ServerHttpRequest request = exchange.getRequest(); - ServerHttpRequest.Builder mutate = request.mutate(); - - HttpMethod method = request.getMethod(); - if(method != HttpMethod.POST){ - return chain.filter(exchange.mutate().request(mutate.build()).build()); - } - String sign = request.getHeaders().getFirst(TokenConstants.SIGN); - String nonce_str = request.getHeaders().getFirst(TokenConstants.NONCE_STR); - if (parameter_signature && StringUtils.isEmpty(sign)) { - return unauthorizedResponse(exchange, "签名不能为空!"); - } - if (parameter_signature && StringUtils.isEmpty(nonce_str)) { - return unauthorizedResponse(exchange, "签名不能为空!"); - } - if(parameter_signature){ - return authSign(exchange, chain, sign, nonce_str); - } - return chain.filter(exchange.mutate().request(mutate.build()).build()); - } - - - - private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) { - log.error("[签名异常处理]请求路径:{}", exchange.getRequest().getPath()); - return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.BAD_REQUEST); - } - - - /** - * 校验签名 - * @return - */ - private Mono<Void> authSign(ServerWebExchange exchange, GatewayFilterChain chain, String sign, String nonce_str){ - return DataBufferUtils.join(exchange.getRequest().getBody()) - .flatMap(dataBuffer -> { - byte[] bytes = new byte[dataBuffer.readableByteCount()]; - dataBuffer.read(bytes); - String bodyString = new String(bytes, StandardCharsets.UTF_8); - log.info("请求参数:{}", bodyString); - if(!authSign(JSON.parseObject(bodyString), sign, nonce_str)){ - return unauthorizedResponse(exchange, "签名验证失败!"); - } - DataBufferUtils.release(dataBuffer); - Flux<DataBuffer> cachedFlux = Flux.defer(() -> { - DataBuffer buffer = exchange.getResponse().bufferFactory() - .wrap(bytes); - return Mono.just(buffer); - }); - ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) { - @Override - public Flux<DataBuffer> getBody() { - return cachedFlux; - } - }; - return chain.filter(exchange.mutate().request(mutatedRequest) - .build()); - }); - } - - - - /** - * 签名校验 - * @return - */ - private boolean authSign(JSONObject jsonStr, String sign, String nonce_str) { - System.err.println("请求签名:" + sign); - String signUrlEncode = localSignUrl(jsonStr, nonce_str); - signUrlEncode = signUrlEncode.replaceAll("& #40;", "\\(") - .replaceAll("& #41;", "\\)"); - if(sign.equals(signUrlEncode)){ - return true; - } - System.err.println("签名值:" + signUrlEncode); - return false; - } - - - /** - * 组装签名路径 - * @param params - * @return - */ - public static String localSignUrl(JSONObject params, String key) { - List<String> keySet = new ArrayList<>(params.keySet()); - // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) - Collections.sort(keySet, new Comparator<String>() { - @Override - public int compare(String o1, String o2) { - return o1.compareTo(o2); - } - }); - // 构造签名键值对的格式 - StringBuilder sb = new StringBuilder(); - for (String k : keySet) { - String v = params.getString(k); - if(StringUtils.isNotEmpty(v)){ - sb.append(k + "=" + v + "&"); - } - } - String signUrl = sb.substring(0, sb.length() - 1); - System.err.println("签名串:" + signUrl); - return signUrlEncode(signUrl, key); - } - - - /** - * 签名字符串加密 - * @param signUrl - * @param encryptKey - * @return - */ - public static String signUrlEncode(String signUrl, String encryptKey) { - byte[] signByte = new byte[0]; - try { - signByte = HMACSHA1.HmacSHA1Encrypt(signUrl, encryptKey); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - String localSign = Base64.encodeBase64String(signByte); - return localSign; - } - - - @Override - public int getOrder() - { - return -200; - } + private static final Logger log = LoggerFactory.getLogger(SignFilter.class); + + // 排除过滤的 uri 地址,nacos自行添加 + @Autowired + private IgnoreWhiteProperties ignoreWhite; + + @Autowired + private RedisService redisService; + + @Value("${security.sign}") + private boolean parameter_signature; + + /** + * 组装签名路径 + * + * @param params + * @return + */ + public static String localSignUrl(JSONObject params, String key) { + List<String> keySet = new ArrayList<>(params.keySet()); + // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) + Collections.sort(keySet, new Comparator<String>() { + @Override + public int compare(String o1, String o2) { + return o1.compareTo(o2); + } + }); + // 构造签名键值对的格式 + StringBuilder sb = new StringBuilder(); + for (String k : keySet) { + String v = params.getString(k); + if (StringUtils.isNotEmpty(v)) { + sb.append(k + "=" + v + "&"); + } + } + String signUrl = sb.substring(0, sb.length() - 1); + System.err.println("签名串:" + signUrl); + return signUrlEncode(signUrl, key); + } + + /** + * 签名字符串加密 + * + * @param signUrl + * @param encryptKey + * @return + */ + public static String signUrlEncode(String signUrl, String encryptKey) { + byte[] signByte = new byte[0]; + try { + signByte = HMACSHA1.HmacSHA1Encrypt(signUrl, encryptKey); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + String localSign = Base64.encodeBase64String(signByte); + return localSign; + } + + @Override + public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + ServerHttpRequest.Builder mutate = request.mutate(); + + HttpMethod method = request.getMethod(); + if (method != HttpMethod.POST) { + return chain.filter(exchange.mutate().request(mutate.build()).build()); + } + String sign = request.getHeaders().getFirst(TokenConstants.SIGN); + String nonce_str = request.getHeaders().getFirst(TokenConstants.NONCE_STR); + if (parameter_signature && StringUtils.isEmpty(sign)) { + return unauthorizedResponse(exchange, "签名不能为空!"); + } + if (parameter_signature && StringUtils.isEmpty(nonce_str)) { + return unauthorizedResponse(exchange, "签名不能为空!"); + } + if (parameter_signature) { + return authSign(exchange, chain, sign, nonce_str); + } + return chain.filter(exchange.mutate().request(mutate.build()).build()); + } + + private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) { + log.error("[签名异常处理]请求路径:{}", exchange.getRequest().getPath()); + return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.BAD_REQUEST); + } + + /** + * 校验签名 + * + * @return + */ + private Mono<Void> authSign(ServerWebExchange exchange, GatewayFilterChain chain, String sign, String nonce_str) { + return DataBufferUtils.join(exchange.getRequest().getBody()) + .flatMap(dataBuffer -> { + byte[] bytes = new byte[dataBuffer.readableByteCount()]; + dataBuffer.read(bytes); + String bodyString = new String(bytes, StandardCharsets.UTF_8); + log.info("请求参数:{}", bodyString); + if (!authSign(JSON.parseObject(bodyString), sign, nonce_str)) { + return unauthorizedResponse(exchange, "签名验证失败!"); + } + DataBufferUtils.release(dataBuffer); + Flux<DataBuffer> cachedFlux = Flux.defer(() -> { + DataBuffer buffer = exchange.getResponse().bufferFactory() + .wrap(bytes); + return Mono.just(buffer); + }); + ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) { + @Override + public Flux<DataBuffer> getBody() { + return cachedFlux; + } + }; + return chain.filter(exchange.mutate().request(mutatedRequest) + .build()); + }); + } + + /** + * 签名校验 + * + * @return + */ + private boolean authSign(JSONObject jsonStr, String sign, String nonce_str) { + System.err.println("请求签名:" + sign); + String signUrlEncode = localSignUrl(jsonStr, nonce_str); + signUrlEncode = signUrlEncode.replaceAll("& #40;", "\\(") + .replaceAll("& #41;", "\\)"); + if (sign.equals(signUrlEncode)) { + return true; + } + System.err.println("签名值:" + signUrlEncode); + return false; + } + + @Override + public int getOrder() { + return -200; + } } \ No newline at end of file diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java index d5b75fd..02d7bb4 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java @@ -3,6 +3,7 @@ import java.nio.CharBuffer; import java.nio.charset.StandardCharsets; import java.util.concurrent.atomic.AtomicReference; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; @@ -24,56 +25,45 @@ * @author ruoyi */ @Component -public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object> -{ - private final static String[] VALIDATE_URL = new String[] { "/auth/login", "/auth/register" }; - - @Autowired - private ValidateCodeService validateCodeService; - - @Autowired - private CaptchaProperties captchaProperties; - - private static final String CODE = "code"; - - private static final String UUID = "uuid"; - - @Override - public GatewayFilter apply(Object config) - { - return (exchange, chain) -> { - ServerHttpRequest request = exchange.getRequest(); - - // 非登录/注册请求或验证码关闭,不处理 - if (!StringUtils.containsAnyIgnoreCase(request.getURI().getPath(), VALIDATE_URL) || !captchaProperties.getEnabled()) - { - return chain.filter(exchange); - } - - try - { - String rspStr = resolveBodyFromRequest(request); - JSONObject obj = JSON.parseObject(rspStr); - validateCodeService.checkCaptcha(obj.getString(CODE), obj.getString(UUID)); - } - catch (Exception e) - { - return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage()); - } - return chain.filter(exchange); - }; - } - - private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) - { - // 获取请求体 - Flux<DataBuffer> body = serverHttpRequest.getBody(); - AtomicReference<String> bodyRef = new AtomicReference<>(); - body.subscribe(buffer -> { - CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); - DataBufferUtils.release(buffer); - bodyRef.set(charBuffer.toString()); - }); - return bodyRef.get(); - } +public class ValidateCodeFilter extends AbstractGatewayFilterFactory<Object> { + private final static String[] VALIDATE_URL = new String[]{"/auth/login", "/auth/register"}; + private static final String CODE = "code"; + private static final String UUID = "uuid"; + @Autowired + private ValidateCodeService validateCodeService; + @Autowired + private CaptchaProperties captchaProperties; + + @Override + public GatewayFilter apply(Object config) { + return (exchange, chain) -> { + ServerHttpRequest request = exchange.getRequest(); + + // 非登录/注册请求或验证码关闭,不处理 + if (!StringUtils.containsAnyIgnoreCase(request.getURI().getPath(), VALIDATE_URL) || !captchaProperties.getEnabled()) { + return chain.filter(exchange); + } + + try { + String rspStr = resolveBodyFromRequest(request); + JSONObject obj = JSON.parseObject(rspStr); + validateCodeService.checkCaptcha(obj.getString(CODE), obj.getString(UUID)); + } catch (Exception e) { + return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage()); + } + return chain.filter(exchange); + }; + } + + private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) { + // 获取请求体 + Flux<DataBuffer> body = serverHttpRequest.getBody(); + AtomicReference<String> bodyRef = new AtomicReference<>(); + body.subscribe(buffer -> { + CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); + DataBufferUtils.release(buffer); + bodyRef.set(charBuffer.toString()); + }); + return bodyRef.get(); + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java index 6d3e498..72a2e08 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java @@ -44,93 +44,87 @@ */ @Component @ConditionalOnProperty(value = "security.xss.enabled", havingValue = "true") -public class XssFilter implements GlobalFilter, Ordered -{ - private static final Logger log = LoggerFactory.getLogger(XssFilter.class); - // 跨站脚本的 xss 配置,nacos自行添加 - @Autowired - private XssProperties xss; - - @Override - public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { - ServerHttpRequest request = exchange.getRequest(); - // xss开关未开启 或 通过nacos关闭,不过滤 - if (!xss.getEnabled()) { - return chain.filter(exchange); - } - // GET DELETE 不过滤 - HttpMethod method = request.getMethod(); - if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) { - return chain.filter(exchange); - } - // 非json类型,不过滤 - if (!isJsonRequest(exchange)) { - return chain.filter(exchange); - } - // excludeUrls 不过滤 - String url = request.getURI().getPath(); - if (StringUtils.matches(url, xss.getExcludeUrls())) { - return chain.filter(exchange); - } - ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange); - return chain.filter(exchange.mutate().request(httpRequestDecorator).build()); - } - - - - - - - private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange) { - ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) { - @Override - public Flux<DataBuffer> getBody() { - Flux<DataBuffer> body = super.getBody(); - return body.buffer().map(dataBuffers -> { - DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); - DataBuffer join = dataBufferFactory.join(dataBuffers); - byte[] content = new byte[join.readableByteCount()]; - join.read(content); - DataBufferUtils.release(join); - String bodyStr = new String(content, StandardCharsets.UTF_8); - // 防xss攻击过滤 - bodyStr = EscapeUtil.clean(bodyStr); - // 转成字节 - byte[] bytes = bodyStr.getBytes(); - NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); - DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); - buffer.write(bytes); - return buffer; - }); - } - - @Override - public HttpHeaders getHeaders() { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.putAll(super.getHeaders()); - // 由于修改了请求体的body,导致content-length长度不确定,因此需要删除原先的content-length - httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); - httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); - return httpHeaders; - } - - }; - return serverHttpRequestDecorator; - } - - /** - * 是否是Json请求 - * - * @param exchange HTTP请求 - */ - public boolean isJsonRequest(ServerWebExchange exchange) { - String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); - return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); - } - - @Override - public int getOrder() - { - return -100; - } +public class XssFilter implements GlobalFilter, Ordered { + private static final Logger log = LoggerFactory.getLogger(XssFilter.class); + // 跨站脚本的 xss 配置,nacos自行添加 + @Autowired + private XssProperties xss; + + @Override + public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { + ServerHttpRequest request = exchange.getRequest(); + // xss开关未开启 或 通过nacos关闭,不过滤 + if (!xss.getEnabled()) { + return chain.filter(exchange); + } + // GET DELETE 不过滤 + HttpMethod method = request.getMethod(); + if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) { + return chain.filter(exchange); + } + // 非json类型,不过滤 + if (!isJsonRequest(exchange)) { + return chain.filter(exchange); + } + // excludeUrls 不过滤 + String url = request.getURI().getPath(); + if (StringUtils.matches(url, xss.getExcludeUrls())) { + return chain.filter(exchange); + } + ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange); + return chain.filter(exchange.mutate().request(httpRequestDecorator).build()); + } + + + private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange) { + ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) { + @Override + public Flux<DataBuffer> getBody() { + Flux<DataBuffer> body = super.getBody(); + return body.buffer().map(dataBuffers -> { + DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); + DataBuffer join = dataBufferFactory.join(dataBuffers); + byte[] content = new byte[join.readableByteCount()]; + join.read(content); + DataBufferUtils.release(join); + String bodyStr = new String(content, StandardCharsets.UTF_8); + // 防xss攻击过滤 + bodyStr = EscapeUtil.clean(bodyStr); + // 转成字节 + byte[] bytes = bodyStr.getBytes(); + NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); + DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); + buffer.write(bytes); + return buffer; + }); + } + + @Override + public HttpHeaders getHeaders() { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.putAll(super.getHeaders()); + // 由于修改了请求体的body,导致content-length长度不确定,因此需要删除原先的content-length + httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); + httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked"); + return httpHeaders; + } + + }; + return serverHttpRequestDecorator; + } + + /** + * 是否是Json请求 + * + * @param exchange HTTP请求 + */ + public boolean isJsonRequest(ServerWebExchange exchange) { + String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); + return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); + } + + @Override + public int getOrder() { + return -100; + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java index 29ea5e3..cb88f5f 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java @@ -19,38 +19,30 @@ */ @Order(-1) @Configuration -public class GatewayExceptionHandler implements ErrorWebExceptionHandler -{ - private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class); - - @Override - public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) - { - ServerHttpResponse response = exchange.getResponse(); - - if (exchange.getResponse().isCommitted()) - { - return Mono.error(ex); - } - - String msg; - - if (ex instanceof NotFoundException) - { - msg = "服务未找到"; - } - else if (ex instanceof ResponseStatusException) - { - ResponseStatusException responseStatusException = (ResponseStatusException) ex; - msg = responseStatusException.getMessage(); - } - else - { - msg = "内部服务器错误"; - } - - log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage()); - - return ServletUtils.webFluxResponseWriter(response, msg); - } +public class GatewayExceptionHandler implements ErrorWebExceptionHandler { + private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class); + + @Override + public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) { + ServerHttpResponse response = exchange.getResponse(); + + if (exchange.getResponse().isCommitted()) { + return Mono.error(ex); + } + + String msg; + + if (ex instanceof NotFoundException) { + msg = "服务未找到"; + } else if (ex instanceof ResponseStatusException) { + ResponseStatusException responseStatusException = (ResponseStatusException) ex; + msg = responseStatusException.getMessage(); + } else { + msg = "内部服务器错误"; + } + + log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage()); + + return ServletUtils.webFluxResponseWriter(response, msg); + } } \ No newline at end of file diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SentinelFallbackHandler.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SentinelFallbackHandler.java index 86abf88..0974811 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SentinelFallbackHandler.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SentinelFallbackHandler.java @@ -13,29 +13,23 @@ * * @author ruoyi */ -public class SentinelFallbackHandler implements WebExceptionHandler -{ - private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) - { - return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求超过最大数,请稍候再试"); - } - - @Override - public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) - { - if (exchange.getResponse().isCommitted()) - { - return Mono.error(ex); - } - if (!BlockException.isBlockException(ex)) - { - return Mono.error(ex); - } - return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange)); - } - - private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) - { - return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable); - } +public class SentinelFallbackHandler implements WebExceptionHandler { + private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) { + return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求超过最大数,请稍候再试"); + } + + @Override + public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) { + if (exchange.getResponse().isCommitted()) { + return Mono.error(ex); + } + if (!BlockException.isBlockException(ex)) { + return Mono.error(ex); + } + return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange)); + } + + private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable) { + return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable); + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SwaggerHandler.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SwaggerHandler.java index daa21af..eeb58a1 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SwaggerHandler.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SwaggerHandler.java @@ -1,6 +1,7 @@ package com.ruoyi.gateway.handler; import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -16,41 +17,34 @@ @RestController @RequestMapping("/swagger-resources") -public class SwaggerHandler -{ - @Autowired(required = false) - private SecurityConfiguration securityConfiguration; - - @Autowired(required = false) - private UiConfiguration uiConfiguration; - - private final SwaggerResourcesProvider swaggerResources; - - @Autowired - public SwaggerHandler(SwaggerResourcesProvider swaggerResources) - { - this.swaggerResources = swaggerResources; - } - - @GetMapping("/configuration/security") - public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() - { - return Mono.just(new ResponseEntity<>( - Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), - HttpStatus.OK)); - } - - @GetMapping("/configuration/ui") - public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() - { - return Mono.just(new ResponseEntity<>( - Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); - } - - @SuppressWarnings("rawtypes") - @GetMapping("") - public Mono<ResponseEntity> swaggerResources() - { - return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); - } +public class SwaggerHandler { + private final SwaggerResourcesProvider swaggerResources; + @Autowired(required = false) + private SecurityConfiguration securityConfiguration; + @Autowired(required = false) + private UiConfiguration uiConfiguration; + + @Autowired + public SwaggerHandler(SwaggerResourcesProvider swaggerResources) { + this.swaggerResources = swaggerResources; + } + + @GetMapping("/configuration/security") + public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() { + return Mono.just(new ResponseEntity<>( + Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), + HttpStatus.OK)); + } + + @GetMapping("/configuration/ui") + public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() { + return Mono.just(new ResponseEntity<>( + Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK)); + } + + @SuppressWarnings("rawtypes") + @GetMapping("") + public Mono<ResponseEntity> swaggerResources() { + return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK))); + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/ValidateCodeHandler.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/ValidateCodeHandler.java index 45e7b15..3dc68d6 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/ValidateCodeHandler.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/ValidateCodeHandler.java @@ -1,6 +1,7 @@ package com.ruoyi.gateway.handler; import java.io.IOException; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; @@ -19,23 +20,18 @@ * @author ruoyi */ @Component -public class ValidateCodeHandler implements HandlerFunction<ServerResponse> -{ - @Autowired - private ValidateCodeService validateCodeService; - - @Override - public Mono<ServerResponse> handle(ServerRequest serverRequest) - { - AjaxResult ajax; - try - { - ajax = validateCodeService.createCaptcha(); - } - catch (CaptchaException | IOException e) - { - return Mono.error(e); - } - return ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(ajax)); - } +public class ValidateCodeHandler implements HandlerFunction<ServerResponse> { + @Autowired + private ValidateCodeService validateCodeService; + + @Override + public Mono<ServerResponse> handle(ServerRequest serverRequest) { + AjaxResult ajax; + try { + ajax = validateCodeService.createCaptcha(); + } catch (CaptchaException | IOException e) { + return Mono.error(e); + } + return ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(ajax)); + } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/ValidateCodeService.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/ValidateCodeService.java index 8a74aeb..8747e48 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/ValidateCodeService.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/ValidateCodeService.java @@ -1,6 +1,7 @@ package com.ruoyi.gateway.service; import java.io.IOException; + import com.ruoyi.common.core.exception.CaptchaException; import com.ruoyi.common.core.web.domain.AjaxResult; @@ -9,15 +10,14 @@ * * @author ruoyi */ -public interface ValidateCodeService -{ - /** - * 生成验证码 - */ - public AjaxResult createCaptcha() throws IOException, CaptchaException; - - /** - * 校验验证码 - */ - public void checkCaptcha(String key, String value) throws CaptchaException; +public interface ValidateCodeService { + /** + * 生成验证码 + */ + public AjaxResult createCaptcha() throws IOException, CaptchaException; + + /** + * 校验验证码 + */ + public void checkCaptcha(String key, String value) throws CaptchaException; } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java index 2ae87bd..365cad6 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java @@ -5,6 +5,7 @@ import java.util.concurrent.TimeUnit; import javax.annotation.Resource; import javax.imageio.ImageIO; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.FastByteArrayOutputStream; @@ -26,94 +27,81 @@ * @author ruoyi */ @Service -public class ValidateCodeServiceImpl implements ValidateCodeService -{ - @Resource(name = "captchaProducer") - private Producer captchaProducer; - - @Resource(name = "captchaProducerMath") - private Producer captchaProducerMath; - - @Autowired - private RedisService redisService; - - @Autowired - private CaptchaProperties captchaProperties; - - /** - * 生成验证码 - */ - @Override - public AjaxResult createCaptcha() throws IOException, CaptchaException - { - AjaxResult ajax = AjaxResult.success(); - boolean captchaEnabled = captchaProperties.getEnabled(); - ajax.put("captchaEnabled", captchaEnabled); - if (!captchaEnabled) - { - return ajax; - } - - // 保存验证码信息 - String uuid = IdUtils.simpleUUID(); - String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; - - String capStr = null, code = null; - BufferedImage image = null; - - String captchaType = captchaProperties.getType(); - // 生成验证码 - if ("math".equals(captchaType)) - { - String capText = captchaProducerMath.createText(); - capStr = capText.substring(0, capText.lastIndexOf("@")); - code = capText.substring(capText.lastIndexOf("@") + 1); - image = captchaProducerMath.createImage(capStr); - } - else if ("char".equals(captchaType)) - { - capStr = code = captchaProducer.createText(); - image = captchaProducer.createImage(capStr); - } - - redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); - // 转换流信息写出 - FastByteArrayOutputStream os = new FastByteArrayOutputStream(); - try - { - ImageIO.write(image, "jpg", os); - } - catch (IOException e) - { - return AjaxResult.error(e.getMessage()); - } - - ajax.put("uuid", uuid); - ajax.put("img", Base64.encode(os.toByteArray())); - return ajax; - } - - /** - * 校验验证码 - */ - @Override - public void checkCaptcha(String code, String uuid) throws CaptchaException - { - if (StringUtils.isEmpty(code)) - { - throw new CaptchaException("验证码不能为空"); - } - if (StringUtils.isEmpty(uuid)) - { - throw new CaptchaException("验证码已失效"); - } - String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; - String captcha = redisService.getCacheObject(verifyKey); - redisService.deleteObject(verifyKey); - - if (!code.equalsIgnoreCase(captcha)) - { - throw new CaptchaException("验证码错误"); - } - } +public class ValidateCodeServiceImpl implements ValidateCodeService { + @Resource(name = "captchaProducer") + private Producer captchaProducer; + + @Resource(name = "captchaProducerMath") + private Producer captchaProducerMath; + + @Autowired + private RedisService redisService; + + @Autowired + private CaptchaProperties captchaProperties; + + /** + * 生成验证码 + */ + @Override + public AjaxResult createCaptcha() throws IOException, CaptchaException { + AjaxResult ajax = AjaxResult.success(); + boolean captchaEnabled = captchaProperties.getEnabled(); + ajax.put("captchaEnabled", captchaEnabled); + if (!captchaEnabled) { + return ajax; + } + + // 保存验证码信息 + String uuid = IdUtils.simpleUUID(); + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; + + String capStr = null, code = null; + BufferedImage image = null; + + String captchaType = captchaProperties.getType(); + // 生成验证码 + if ("math".equals(captchaType)) { + String capText = captchaProducerMath.createText(); + capStr = capText.substring(0, capText.lastIndexOf("@")); + code = capText.substring(capText.lastIndexOf("@") + 1); + image = captchaProducerMath.createImage(capStr); + } else if ("char".equals(captchaType)) { + capStr = code = captchaProducer.createText(); + image = captchaProducer.createImage(capStr); + } + + redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); + // 转换流信息写出 + FastByteArrayOutputStream os = new FastByteArrayOutputStream(); + try { + ImageIO.write(image, "jpg", os); + } catch (IOException e) { + return AjaxResult.error(e.getMessage()); + } + + ajax.put("uuid", uuid); + ajax.put("img", Base64.encode(os.toByteArray())); + return ajax; + } + + /** + * 校验验证码 + */ + @Override + public void checkCaptcha(String code, String uuid) throws CaptchaException { + if (StringUtils.isEmpty(code)) { + throw new CaptchaException("验证码不能为空"); + } + if (StringUtils.isEmpty(uuid)) { + throw new CaptchaException("验证码已失效"); + } + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; + String captcha = redisService.getCacheObject(verifyKey); + redisService.deleteObject(verifyKey); + + if (!code.equalsIgnoreCase(captcha)) { + throw new CaptchaException("验证码错误"); + } + } } diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TInvoiceInformationController.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TInvoiceInformationController.java index 4a6346b..29a90fb 100644 --- a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TInvoiceInformationController.java +++ b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TInvoiceInformationController.java @@ -1,8 +1,16 @@ package com.ruoyi.account.controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.account.api.model.TInvoiceInformation; +import com.ruoyi.account.service.TInvoiceInformationService; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.security.service.TokenService; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; /** * <p> @@ -16,5 +24,72 @@ @RequestMapping("/t-invoice-information") public class TInvoiceInformationController { + @Resource + private TInvoiceInformationService invoiceInformationService; + + @Resource + private TokenService tokenService; + + + @ResponseBody + @GetMapping(value = "/getInvoiceInformationList") + @ApiOperation(value = "获取开票抬头数据列表", tags = {"小程序-充电发票"}) + public AjaxResult<List<TInvoiceInformation>> getInvoiceInformationList(){ + Long userId = tokenService.getLoginUserApplet().getUserId(); + List<TInvoiceInformation> list = invoiceInformationService.list(new LambdaQueryWrapper<TInvoiceInformation>().eq(TInvoiceInformation::getAppUserId, userId).eq(TInvoiceInformation::getDelFlag, 0)); + return AjaxResult.success(list); + } + + + + @ResponseBody + @PostMapping(value = "/addInvoiceInformation") + @ApiOperation(value = "添加开票抬头数据", tags = {"小程序-充电发票"}) + public AjaxResult addInvoiceInformation(@RequestBody TInvoiceInformation invoiceInformation){ + Long userId = tokenService.getLoginUserApplet().getUserId(); + //如果当前是默认抬头,则需要去除其他的默认配置 + if(1 == invoiceInformation.getIsDefault()){ + TInvoiceInformation one = invoiceInformationService.getOne(new LambdaQueryWrapper<TInvoiceInformation>().eq(TInvoiceInformation::getDelFlag, 0) + .eq(TInvoiceInformation::getIsDefault, 1).eq(TInvoiceInformation::getAppUserId, userId)); + if(null != one){ + one.setIsDefault(0); + invoiceInformationService.updateById(one); + } + } + + invoiceInformation.setAppUserId(userId); + invoiceInformationService.save(invoiceInformation); + return AjaxResult.success(); + } + + + @ResponseBody + @GetMapping(value = "/getInvoiceInformationInfo/{id}") + @ApiOperation(value = "获取开票抬头详情数据", tags = {"小程序-充电发票"}) + public AjaxResult<TInvoiceInformation> getInvoiceInformationInfo(@PathVariable String id){ + TInvoiceInformation information = invoiceInformationService.getById(id); + return AjaxResult.success(information); + } + + + + @ResponseBody + @PostMapping(value = "/editInvoiceInformation") + @ApiOperation(value = "编辑开票抬头数据", tags = {"小程序-充电发票"}) + public AjaxResult editInvoiceInformation(@RequestBody TInvoiceInformation invoiceInformation){ + Long userId = tokenService.getLoginUserApplet().getUserId(); + //如果当前是默认抬头,则需要去除其他的默认配置 + if(1 == invoiceInformation.getIsDefault()){ + TInvoiceInformation one = invoiceInformationService.getOne(new LambdaQueryWrapper<TInvoiceInformation>().eq(TInvoiceInformation::getDelFlag, 0) + .eq(TInvoiceInformation::getIsDefault, 1).eq(TInvoiceInformation::getAppUserId, userId)); + if(null != one && !one.getId().equals(invoiceInformation.getId())){ + one.setIsDefault(0); + invoiceInformationService.updateById(one); + } + } + invoiceInformationService.updateById(invoiceInformation); + return AjaxResult.success(); + } + } diff --git a/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TInvoiceInformationMapper.xml b/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TInvoiceInformationMapper.xml index 113c0f6..262bb81 100644 --- a/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TInvoiceInformationMapper.xml +++ b/ruoyi-service/ruoyi-account/src/main/resources/mapper/account/TInvoiceInformationMapper.xml @@ -14,14 +14,14 @@ <result column="company_phone" property="companyPhone" /> <result column="deposit_bank" property="depositBank" /> <result column="bank_account" property="bankAccount" /> - <result column="default" property="default" /> + <result column="is_default" property="isDefault" /> <result column="create_time" property="createTime" /> <result column="del_flag" property="delFlag" /> </resultMap> <!-- 通用查询结果列 --> <sql id="Base_Column_List"> - id, app_user_id, invoice_type, invoicing_object_type, name, tax_identification_number, company_address, company_phone, deposit_bank, bank_account, default, create_time, del_flag + id, app_user_id, invoice_type, invoicing_object_type, name, tax_identification_number, company_address, company_phone, deposit_bank, bank_account, is_default, create_time, del_flag </sql> </mapper> diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java index af5cec4..459df14 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TChargingOrderController.java @@ -10,7 +10,9 @@ import com.ruoyi.order.api.model.TChargingOrder; import com.ruoyi.order.api.query.TChargingCountQuery; import com.ruoyi.order.dto.GetMyChargingOrderList; +import com.ruoyi.order.dto.GetNoInvoicedOrder; import com.ruoyi.order.dto.MyChargingOrderInfo; +import com.ruoyi.order.dto.MyChargingOrderList; import com.ruoyi.order.service.TChargingOrderService; import io.swagger.annotations.Api; import org.springframework.beans.factory.annotation.Autowired; @@ -115,5 +117,16 @@ MyChargingOrderInfo myChargingOrderInfo = chargingOrderService.getMyChargingOrderInfo(id); return AjaxResult.success(myChargingOrderInfo); } + + + + @ResponseBody + @GetMapping(value = "/getNoInvoicedOrder") + @ApiOperation(value = "获取未开票的订单数据", tags = {"小程序-充电发票"}) + public AjaxResult<List<MyChargingOrderList>> getNoInvoicedOrder(@RequestBody GetNoInvoicedOrder query){ + List<MyChargingOrderList> list = chargingOrderService.getNoInvoicedOrder(query); + return AjaxResult.success(list); + } + } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TExchangeOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TExchangeOrderController.java index d5dc5e8..5f4fb2a 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TExchangeOrderController.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TExchangeOrderController.java @@ -166,5 +166,23 @@ return AjaxResult.success(goodsExchangeOrder); } + + @PutMapping("/confirmReceipt/{id}") + @ApiOperation(value = "确认收货操作", tags = {"小程序-兑换记录"}) + public AjaxResult confirmReceipt(@PathVariable String id){ + TExchangeOrder tExchangeOrder = exchangeOrderService.getById(id); + if(tExchangeOrder.getStatus() == 3){ + return AjaxResult.error("不能重复确认收货"); + } + if(tExchangeOrder.getStatus() == 1){ + return AjaxResult.error("订单还未发货呢"); + } + if(tExchangeOrder.getStatus() == 4){ + return AjaxResult.error("订单已取消,不允许操作。"); + } + tExchangeOrder.setStatus(3); + exchangeOrderService.updateById(tExchangeOrder); + return AjaxResult.success(); + } } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderInvoiceController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderInvoiceController.java index 664a0dc..8e2cd80 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderInvoiceController.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TOrderInvoiceController.java @@ -1,9 +1,18 @@ package com.ruoyi.order.controller; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.order.dto.AddOrderInvoice; +import com.ruoyi.order.dto.GetOrderInvoiceList; +import com.ruoyi.order.dto.MyOrderInvoiceInfo; +import com.ruoyi.order.dto.OrderInvoiceList; +import com.ruoyi.order.service.TOrderInvoiceService; import io.swagger.annotations.Api; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; /** * <p> @@ -18,5 +27,37 @@ @RequestMapping("/t-order-invoice") public class TOrderInvoiceController { + @Resource + private TOrderInvoiceService orderInvoiceService; + + + + + @ResponseBody + @PostMapping("/addOrderInvoice") + @ApiOperation(value = "添加开票申请", tags = {"小程序-充电发票"}) + public AjaxResult addOrderInvoice(@RequestBody AddOrderInvoice addOrderInvoice){ + return orderInvoiceService.addOrderInvoice(addOrderInvoice); + } + + + + @ResponseBody + @GetMapping("/getMyOrderInvoiceList") + @ApiOperation(value = "获取开票记录列表", tags = {"小程序-充电发票"}) + public AjaxResult<List<OrderInvoiceList>> getMyOrderInvoiceList(GetOrderInvoiceList query){ + List<OrderInvoiceList> myOrderInvoiceList = orderInvoiceService.getMyOrderInvoiceList(query); + return AjaxResult.success(myOrderInvoiceList); + } + + + + @ResponseBody + @GetMapping("/getMyOrderInvoiceInfo/{id}") + @ApiOperation(value = "获取开票记录详情", tags = {"小程序-充电发票"}) + public AjaxResult<MyOrderInvoiceInfo> getMyOrderInvoiceInfo(@PathVariable String id){ + MyOrderInvoiceInfo myOrderInvoiceInfo = orderInvoiceService.getMyOrderInvoiceInfo(id); + return AjaxResult.success(myOrderInvoiceInfo); + } } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TShoppingOrderController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TShoppingOrderController.java index 186eaed..e853464 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TShoppingOrderController.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/TShoppingOrderController.java @@ -1,9 +1,17 @@ package com.ruoyi.order.controller; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.order.api.model.TExchangeOrder; +import com.ruoyi.order.api.model.TShoppingOrder; +import com.ruoyi.order.dto.*; +import com.ruoyi.order.service.TShoppingOrderService; import io.swagger.annotations.Api; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import io.swagger.annotations.ApiOperation; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.List; /** * <p> @@ -17,6 +25,62 @@ @RestController @RequestMapping("/t-shopping-order") public class TShoppingOrderController { - + + @Resource + private TShoppingOrderService shoppingOrderService; + + + @GetMapping("/getMyShoppingOrderList") + @ApiOperation(value = "获取购买订单列表", tags = {"小程序-商城购买订单"}) + public AjaxResult<List<MyShoppingOrderList>> getMyShoppingOrderList(GetMyShoppingOrderList query){ + List<MyShoppingOrderList> list = shoppingOrderService.getMyShoppingOrderList(query); + return AjaxResult.success(list); + } + + + + @GetMapping("/getMyShoppingOrderInfo/{id}") + @ApiOperation(value = "获取购买订单详情", tags = {"小程序-商城购买订单"}) + public AjaxResult<MyShoppingOrderInfo> getMyShoppingOrderInfo(@PathVariable String id){ + MyShoppingOrderInfo info = shoppingOrderService.getMyShoppingOrderInfo(id); + return AjaxResult.success(info); + } + + + + @PutMapping("/confirmReceipt/{id}") + @ApiOperation(value = "确认收货操作", tags = {"小程序-商城购买订单"}) + public AjaxResult confirmReceipt(@PathVariable String id){ + TShoppingOrder shoppingOrder = shoppingOrderService.getById(id); + if(shoppingOrder.getStatus() == 3){ + return AjaxResult.error("不能重复确认收货"); + } + if(shoppingOrder.getStatus() == 1){ + return AjaxResult.error("订单还未发货呢"); + } + if(shoppingOrder.getStatus() == 4){ + return AjaxResult.error("订单已取消,不允许操作。"); + } + shoppingOrder.setStatus(3); + shoppingOrderService.updateById(shoppingOrder); + return AjaxResult.success(); + } + + + @PutMapping("/cancelOrder/{id}") + @ApiOperation(value = "取消订单操作", tags = {"小程序-商城购买订单"}) + public AjaxResult cancelOrder(@PathVariable String id){ + return shoppingOrderService.cancelOrder(id); + } + + + + @ResponseBody + @GetMapping(value = "/getNoInvoicedOrder") + @ApiOperation(value = "获取未开票的订单数据", tags = {"小程序-充电发票"}) + public AjaxResult<List<MyShoppingOrderList>> getNoInvoicedOrder(GetNoInvoicedOrder query){ + List<MyShoppingOrderList> list = shoppingOrderService.getNoInvoicedOrder(query); + return AjaxResult.success(list); + } } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddOrderInvoice.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddOrderInvoice.java new file mode 100644 index 0000000..988ec28 --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/AddOrderInvoice.java @@ -0,0 +1,18 @@ +package com.ruoyi.order.dto; + +import com.ruoyi.order.api.model.TOrderInvoice; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + + +/** + * @author zhibing.pu + * @Date 2024/8/19 15:29 + */ +@Data +@ApiModel +public class AddOrderInvoice extends TOrderInvoice { + @ApiModelProperty("订单数据数组[{\"id\":111,\"amount\":30}]") + private String orders; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetMyShoppingOrderList.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetMyShoppingOrderList.java new file mode 100644 index 0000000..d724d96 --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetMyShoppingOrderList.java @@ -0,0 +1,17 @@ +package com.ruoyi.order.dto; + +import com.ruoyi.common.core.web.page.BasePage; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author zhibing.pu + * @Date 2024/8/19 13:43 + */ +@Data +@ApiModel +public class GetMyShoppingOrderList extends BasePage { + @ApiModelProperty(value = "状态(0=全部,1=待发货,2=待收货,3=已完成)") + private Integer status; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetNoInvoicedOrder.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetNoInvoicedOrder.java new file mode 100644 index 0000000..5884a8f --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetNoInvoicedOrder.java @@ -0,0 +1,17 @@ +package com.ruoyi.order.dto; + +import com.ruoyi.common.core.web.page.BasePage; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author zhibing.pu + * @Date 2024/8/19 14:33 + */ +@Data +@ApiModel +public class GetNoInvoicedOrder extends BasePage { + @ApiModelProperty("日期") + private String month; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetOrderInvoiceList.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetOrderInvoiceList.java new file mode 100644 index 0000000..0e8c0ca --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/GetOrderInvoiceList.java @@ -0,0 +1,17 @@ +package com.ruoyi.order.dto; + +import com.ruoyi.common.core.web.page.BasePage; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @author zhibing.pu + * @Date 2024/8/19 16:17 + */ +@Data +@ApiModel +public class GetOrderInvoiceList extends BasePage { + @ApiModelProperty("状态(1=已申请,2=开票中,3=开票成功)") + private Integer status; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyOrderInvoiceInfo.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyOrderInvoiceInfo.java new file mode 100644 index 0000000..620e5e1 --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyOrderInvoiceInfo.java @@ -0,0 +1,38 @@ +package com.ruoyi.order.dto; + +import com.baomidou.mybatisplus.annotation.TableField; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +/** + * @author zhibing.pu + * @Date 2024/8/19 16:58 + */ +@Data +@ApiModel +public class MyOrderInvoiceInfo { + @ApiModelProperty("订单id") + private String id; + @ApiModelProperty("订单号") + private String code; + @ApiModelProperty("发票类型") + private String invoiceType; + @ApiModelProperty("开票订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单)") + private Integer orderType; + @ApiModelProperty("抬头类型(1=个人,2=企业)") + private Integer invoicingObjectType; + @ApiModelProperty("发票金额") + private BigDecimal totalAmount; + @ApiModelProperty("电子发票地址") + private String invoiceUrl; + @ApiModelProperty(value = "状态(1=待开票,2=开票中,3=已开票)") + private Integer status; + @ApiModelProperty("关联订单(商城订单)") + private List<MyShoppingOrderList> shoppingOrder; + @ApiModelProperty("关联订单(充电订单)") + private List<MyChargingOrderList> chargingOrder; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyShoppingOrderInfo.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyShoppingOrderInfo.java new file mode 100644 index 0000000..307d58f --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyShoppingOrderInfo.java @@ -0,0 +1,56 @@ +package com.ruoyi.order.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author zhibing.pu + * @Date 2024/8/19 14:04 + */ +@Data +@ApiModel +public class MyShoppingOrderInfo { + @ApiModelProperty("订单id") + private String id; + @ApiModelProperty("状态(1=待发货,2=待收货,3=已完成,4=已取消)") + private Integer status; + @ApiModelProperty("收货人姓名") + private String consignee; + @ApiModelProperty("电话") + private String phone; + @ApiModelProperty("地址") + private String address; + @ApiModelProperty("快递公司") + private String expressCompany; + @ApiModelProperty("快递单号") + private String expressNumber; + @ApiModelProperty("商品名称") + private String name; + @ApiModelProperty("商品图片") + private String imgUrl; + @ApiModelProperty("数量") + private Integer number; + @ApiModelProperty("单价") + private BigDecimal unitPrice; + @ApiModelProperty("订单编号") + private String code; + @ApiModelProperty("下单时间") + private String createTime; + @ApiModelProperty("支付金额") + private BigDecimal paymentAmount; + @ApiModelProperty("备注") + private String remark; + @ApiModelProperty("发货时间") + private String deliveryTime; + @ApiModelProperty("完成时间") + private String finishTime; + @ApiModelProperty("优惠券类型(1=充电优惠券,2=购物优惠券)") + private Integer couponType; + @ApiModelProperty("优惠券有效天数") + private Integer days; + @ApiModelProperty("有效期截止时间") + private String endTime; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyShoppingOrderList.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyShoppingOrderList.java new file mode 100644 index 0000000..6cc1346 --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/MyShoppingOrderList.java @@ -0,0 +1,30 @@ +package com.ruoyi.order.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author zhibing.pu + * @Date 2024/8/19 13:45 + */ +@Data +@ApiModel +public class MyShoppingOrderList { + @ApiModelProperty(value = "订单id") + private String id; + @ApiModelProperty("封面图") + private String imgUrl; + @ApiModelProperty("商品名称") + private String name; + @ApiModelProperty("状态(1=待发货,2=待收货,3=已完成,4=已取消)") + private Integer status; + @ApiModelProperty("单价") + private BigDecimal unitPrice; + @ApiModelProperty("数量") + private Integer number; + @ApiModelProperty("支付金额") + private BigDecimal paymentAmount; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/OrderInvoiceList.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/OrderInvoiceList.java new file mode 100644 index 0000000..928876f --- /dev/null +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/dto/OrderInvoiceList.java @@ -0,0 +1,26 @@ +package com.ruoyi.order.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * @author zhibing.pu + * @Date 2024/8/19 16:18 + */ +@Data +@ApiModel +public class OrderInvoiceList { + @ApiModelProperty("数据id") + private String id; + @ApiModelProperty("订单类型(1=充电订单,2=购物订单,3=兑换订单,4=会员订单)") + private Integer orderType; + @ApiModelProperty("开票金额") + private BigDecimal totalAmount; + @ApiModelProperty("抬头名称") + private String name; + @ApiModelProperty("申请时间") + private String createTime; +} diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java index 1b186da..2cb8469 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingOrderMapper.java @@ -2,7 +2,9 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.order.api.model.TChargingOrder; +import com.ruoyi.order.dto.GetNoInvoicedOrder; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; @@ -27,5 +29,17 @@ * @param pageSize * @return */ - List<TChargingOrder> getMyChargingOrderList(Long appUserId, Integer type, Integer pageCurr, Integer pageSize); + List<TChargingOrder> getMyChargingOrderList(@Param("appUserId") Long appUserId, @Param("type") Integer type, + @Param("pageCurr") Integer pageCurr, @Param("pageSize") Integer pageSize); + + + /** + * 获取待开票订单列表 + * @param month 筛选时间2024-01-01 + * @param pageCurr + * @param pageSize + * @return + */ + List<TChargingOrder> getNoInvoicedOrder(@Param("appUserId") Long appUserId, @Param("month") String month, + @Param("pageCurr") Integer pageCurr, @Param("pageSize") Integer pageSize); } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TShoppingOrderMapper.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TShoppingOrderMapper.java index da4a11c..5cb1c33 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TShoppingOrderMapper.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TShoppingOrderMapper.java @@ -22,4 +22,16 @@ public interface TShoppingOrderMapper extends BaseMapper<TShoppingOrder> { List<TActivityStatisticslVO> activityStatistics(@Param("pageInfo") PageInfo<TActivityStatisticslVO> pageInfo, @Param("req")TActivityStatisticsQuery dto); + + + /** + * 获取未开票的订单数据 + * @param appUserId + * @param month + * @param pageCurr + * @param pageSize + * @return + */ + List<TShoppingOrder> getNoInvoicedOrder(@Param("appUserId") Long appUserId, @Param("month") String month, + @Param("pageCurr") Integer pageCurr, @Param("pageSize") Integer pageSize); } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java index d5e9755..d4b0897 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingOrderService.java @@ -4,8 +4,12 @@ import com.ruoyi.common.core.web.page.BasePage; import com.ruoyi.order.api.model.TChargingOrder; import com.ruoyi.order.dto.GetMyChargingOrderList; +import com.ruoyi.order.dto.GetNoInvoicedOrder; import com.ruoyi.order.dto.MyChargingOrderInfo; +import com.ruoyi.order.dto.MyChargingOrderList; +import org.springframework.web.bind.annotation.RequestBody; +import java.util.List; import java.util.Map; /** @@ -33,4 +37,12 @@ * @return */ MyChargingOrderInfo getMyChargingOrderInfo(String id); + + + /** + * 获取待开票订单列表 + * @param query + * @return + */ + List<MyChargingOrderList> getNoInvoicedOrder(GetNoInvoicedOrder query); } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TOrderInvoiceService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TOrderInvoiceService.java index ee4cbb5..d44196e 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TOrderInvoiceService.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TOrderInvoiceService.java @@ -1,7 +1,14 @@ package com.ruoyi.order.service; import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.order.api.model.TOrderInvoice; +import com.ruoyi.order.dto.AddOrderInvoice; +import com.ruoyi.order.dto.GetOrderInvoiceList; +import com.ruoyi.order.dto.MyOrderInvoiceInfo; +import com.ruoyi.order.dto.OrderInvoiceList; + +import java.util.List; /** * <p> @@ -12,5 +19,28 @@ * @since 2024-08-07 */ public interface TOrderInvoiceService extends IService<TOrderInvoice> { - + + + /** + * 添加开票申请 + * @param addOrderInvoice + * @return + */ + AjaxResult addOrderInvoice(AddOrderInvoice addOrderInvoice); + + + /** + * 获取小程序用户开票记录 + * @param query + * @return + */ + List<OrderInvoiceList> getMyOrderInvoiceList(GetOrderInvoiceList query); + + + /** + * 获取开票申请详情 + * @param id + * @return + */ + MyOrderInvoiceInfo getMyOrderInvoiceInfo(String id); } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TShoppingOrderService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TShoppingOrderService.java index da59889..c503367 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TShoppingOrderService.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TShoppingOrderService.java @@ -1,11 +1,20 @@ package com.ruoyi.order.service; import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.PageInfo; import com.ruoyi.order.api.model.TShoppingOrder; import com.ruoyi.order.api.query.TActivityStatisticsQuery; import com.ruoyi.order.api.vo.TActivityStatisticslVO; import com.ruoyi.order.api.vo.TActivityVO; +import com.ruoyi.order.dto.GetMyShoppingOrderList; +import com.ruoyi.order.dto.GetNoInvoicedOrder; +import com.ruoyi.order.dto.MyShoppingOrderInfo; +import com.ruoyi.order.dto.MyShoppingOrderList; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.List; /** * <p> @@ -18,4 +27,36 @@ public interface TShoppingOrderService extends IService<TShoppingOrder> { TActivityVO activityStatistics(TActivityStatisticsQuery dto); + + + /** + * 获取小程序商城购买订单列表 + * @param query + * @return + */ + List<MyShoppingOrderList> getMyShoppingOrderList(GetMyShoppingOrderList query); + + + /** + * 获取购买订单详情 + * @param id + * @return + */ + MyShoppingOrderInfo getMyShoppingOrderInfo(String id); + + + /** + * 取消订单 + * @param id + * @return + */ + AjaxResult cancelOrder(String id); + + + /** + * 获取未开票的订单列表 + * @param query + * @return + */ + List<MyShoppingOrderList> getNoInvoicedOrder(GetNoInvoicedOrder query); } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java index ae4d583..d22e59a 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java @@ -15,6 +15,7 @@ import com.ruoyi.order.api.model.TChargingOrder; import com.ruoyi.order.api.model.TChargingOrderAccountingStrategy; import com.ruoyi.order.dto.GetMyChargingOrderList; +import com.ruoyi.order.dto.GetNoInvoicedOrder; import com.ruoyi.order.dto.MyChargingOrderInfo; import com.ruoyi.order.dto.MyChargingOrderList; import com.ruoyi.order.mapper.TChargingOrderMapper; @@ -137,4 +138,33 @@ myChargingOrderInfo.setActionable(myChargingOrderInfo.getEndTime() + 604800000L > System.currentTimeMillis() ? 0 : 1); return myChargingOrderInfo; } + + + /** + * 获取待开票订单列表 + * @param query + * @return + */ + @Override + public List<MyChargingOrderList> getNoInvoicedOrder(GetNoInvoicedOrder query) { + Long appUserId = tokenService.getLoginUserApplet().getUserId(); + List<TChargingOrder> orderList = this.baseMapper.getNoInvoicedOrder(appUserId, query.getMonth(), query.getPageCurr(), query.getPageSize()); + List<MyChargingOrderList> list = new ArrayList<>(); + for (TChargingOrder tChargingOrder : orderList) { + MyChargingOrderList myChargingOrderList = new MyChargingOrderList(); + myChargingOrderList.setId(tChargingOrder.getId().toString()); + myChargingOrderList.setStatus(tChargingOrder.getStatus()); + Site site = siteClient.getSiteByIds(Arrays.asList(tChargingOrder.getSiteId())).getData().get(0); + myChargingOrderList.setTitle(site.getName()); + myChargingOrderList.setChargingDegree(tChargingOrder.getChargingCapacity()); + String name = chargingGunClient.getAllName(tChargingOrder.getChargingGunId()).getData(); + myChargingOrderList.setName(name); + myChargingOrderList.setEndMode(tChargingOrder.getEndMode()); + BigDecimal payMoney = tChargingOrder.getStatus() < 4 ? tChargingOrder.getRechargeAmount() : tChargingOrder.getPaymentAmount(); + myChargingOrderList.setPayMoney(payMoney); + myChargingOrderList.setCreateTime(tChargingOrder.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + list.add(myChargingOrderList); + } + return list; + } } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java index 2440069..ac22a39 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TOrderInvoiceServiceImpl.java @@ -1,10 +1,42 @@ package com.ruoyi.order.service.impl; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient; +import com.ruoyi.chargingPile.api.feignClient.SiteClient; +import com.ruoyi.chargingPile.api.model.Site; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.core.web.domain.AjaxResult; +import com.ruoyi.common.security.service.TokenService; +import com.ruoyi.order.api.model.TChargingOrder; import com.ruoyi.order.api.model.TOrderInvoice; +import com.ruoyi.order.api.model.TOrderInvoiceDetail; +import com.ruoyi.order.api.model.TShoppingOrder; +import com.ruoyi.order.dto.*; import com.ruoyi.order.mapper.TOrderInvoiceMapper; +import com.ruoyi.order.service.TChargingOrderService; +import com.ruoyi.order.service.TOrderInvoiceDetailService; import com.ruoyi.order.service.TOrderInvoiceService; +import com.ruoyi.order.service.TShoppingOrderService; +import com.ruoyi.other.api.domain.TCoupon; +import com.ruoyi.other.api.domain.TGoods; +import com.ruoyi.other.api.domain.TInvoiceType; +import com.ruoyi.other.api.feignClient.CouponClient; +import com.ruoyi.other.api.feignClient.GoodsClient; +import com.ruoyi.other.api.feignClient.InvoiceTypeClient; +import io.seata.spring.annotation.GlobalTransactional; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; /** * <p> @@ -16,5 +48,184 @@ */ @Service public class TOrderInvoiceServiceImpl extends ServiceImpl<TOrderInvoiceMapper, TOrderInvoice> implements TOrderInvoiceService { - + + @Resource + private TokenService tokenService; + + @Resource + private TOrderInvoiceDetailService orderInvoiceDetailService; + + @Resource + private InvoiceTypeClient invoiceTypeClient; + + @Resource + private TChargingOrderService chargingOrderService; + + @Resource + private TShoppingOrderService shoppingOrderService; + + @Resource + private ChargingGunClient chargingGunClient; + + @Resource + private SiteClient siteClient; + + @Resource + private GoodsClient goodsClient; + + @Resource + private CouponClient couponClient; + + + + + + /** + * 添加开票申请 + * @param addOrderInvoice + * @return + */ + @Override + @GlobalTransactional(rollbackFor = Exception.class) + public AjaxResult addOrderInvoice(AddOrderInvoice addOrderInvoice) { + Long userId = tokenService.getLoginUserApplet().getUserId(); + String orders = addOrderInvoice.getOrders(); + if(StringUtils.isNotEmpty(orders)){ + return AjaxResult.error("请选择有效的订单"); + } + JSONArray parse = JSONArray.parse(orders); + List<Long> orderIds = new ArrayList<>(); + Map<Long, BigDecimal> map = new HashMap<>(); + for (int i = 0; i < parse.size(); i++) { + JSONObject jsonObject = parse.getJSONObject(i); + Long id = jsonObject.getLong("id"); + BigDecimal amount = jsonObject.getBigDecimal("amount"); + orderIds.add(id); + map.put(id, amount); + } + long count = orderInvoiceDetailService.count(new LambdaQueryWrapper<TOrderInvoiceDetail>().eq(TOrderInvoiceDetail::getOrderType, addOrderInvoice.getOrderType()) + .in(TOrderInvoiceDetail::getOrderId, orderIds)); + if(count > 0){ + return AjaxResult.error("不能重复申请开票,请刷新数据后重试"); + } + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); + String code = Math.random() * 1000 + sdf.format(new Date()); + addOrderInvoice.setAppUserId(userId); + addOrderInvoice.setCode(code); + addOrderInvoice.setStatus(1); + this.save(addOrderInvoice); + //获取开票类型 + TInvoiceType invoiceType = invoiceTypeClient.getInvoiceType(addOrderInvoice.getInvoiceTypeId()).getData(); + for (Long orderId : orderIds) { + TOrderInvoiceDetail orderInvoiceDetail = new TOrderInvoiceDetail(); + orderInvoiceDetail.setOrderInvoiceId(addOrderInvoice.getId()); + orderInvoiceDetail.setInvoiceAmount(map.get(orderId)); + orderInvoiceDetail.setOrderType(addOrderInvoice.getOrderType()); + orderInvoiceDetail.setOrderId(orderId); + orderInvoiceDetail.setElectricityTariff(invoiceType.getElectricityTariff()); + orderInvoiceDetail.setServiceTariff(invoiceType.getServiceTariff()); + orderInvoiceDetail.setAddedServiceTariff(invoiceType.getAddedServiceTariff()); + orderInvoiceDetailService.save(orderInvoiceDetail); + } + return AjaxResult.success(); + } + + + /** + * 获取开票记录列表 + * @param query + * @return + */ + @Override + public List<OrderInvoiceList> getMyOrderInvoiceList(GetOrderInvoiceList query) { + Long userId = tokenService.getLoginUserApplet().getUserId(); + List<TOrderInvoice> list = this.list(new LambdaQueryWrapper<TOrderInvoice>().eq(TOrderInvoice::getAppUserId, userId) + .eq(TOrderInvoice::getStatus, query.getStatus()).orderByDesc(TOrderInvoice::getCreateTime) + .last(" limit " + query.getPageCurr() + ", " + query.getPageSize())); + List<OrderInvoiceList> pageList = new ArrayList<>(); + for (TOrderInvoice tOrderInvoice : list) { + OrderInvoiceList orderInvoiceList = new OrderInvoiceList(); + orderInvoiceList.setId(tOrderInvoice.getId().toString()); + orderInvoiceList.setOrderType(tOrderInvoice.getOrderType()); + orderInvoiceList.setTotalAmount(tOrderInvoice.getTotalAmount()); + orderInvoiceList.setName(tOrderInvoice.getName()); + orderInvoiceList.setCreateTime(tOrderInvoice.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + pageList.add(orderInvoiceList); + } + return pageList; + } + + + /** + * 获取开票申请详情 + * @param id + * @return + */ + @Override + public MyOrderInvoiceInfo getMyOrderInvoiceInfo(String id) { + TOrderInvoice orderInvoice = this.getById(id); + MyOrderInvoiceInfo myOrderInvoiceInfo = new MyOrderInvoiceInfo(); + myOrderInvoiceInfo.setId(id); + myOrderInvoiceInfo.setCode(orderInvoice.getCode()); + myOrderInvoiceInfo.setInvoiceType(orderInvoice.getInvoiceType()); + myOrderInvoiceInfo.setOrderType(orderInvoice.getOrderType()); + myOrderInvoiceInfo.setInvoicingObjectType(orderInvoice.getInvoicingObjectType()); + myOrderInvoiceInfo.setTotalAmount(orderInvoice.getTotalAmount()); + myOrderInvoiceInfo.setInvoiceUrl(orderInvoice.getInvoiceUrl()); + myOrderInvoiceInfo.setStatus(orderInvoice.getStatus()); + Integer orderType = orderInvoice.getOrderType(); + List<TOrderInvoiceDetail> list = orderInvoiceDetailService.list(new LambdaQueryWrapper<TOrderInvoiceDetail>().eq(TOrderInvoiceDetail::getOrderInvoiceId, id)); + List<Long> orderIds = list.stream().map(TOrderInvoiceDetail::getOrderId).collect(Collectors.toList()); + //充电订单 + if(orderType == 1){ + List<TChargingOrder> orderList = chargingOrderService.listByIds(orderIds); + List<MyChargingOrderList> chargingOrder = new ArrayList<>(); + for (TChargingOrder tChargingOrder : orderList) { + MyChargingOrderList myChargingOrderList = new MyChargingOrderList(); + myChargingOrderList.setId(tChargingOrder.getId().toString()); + myChargingOrderList.setStatus(tChargingOrder.getStatus()); + Site site = siteClient.getSiteByIds(Arrays.asList(tChargingOrder.getSiteId())).getData().get(0); + myChargingOrderList.setTitle(site.getName()); + myChargingOrderList.setChargingDegree(tChargingOrder.getChargingCapacity()); + String name = chargingGunClient.getAllName(tChargingOrder.getChargingGunId()).getData(); + myChargingOrderList.setName(name); + myChargingOrderList.setEndMode(tChargingOrder.getEndMode()); + BigDecimal payMoney = tChargingOrder.getStatus() < 4 ? tChargingOrder.getRechargeAmount() : tChargingOrder.getPaymentAmount(); + myChargingOrderList.setPayMoney(payMoney); + myChargingOrderList.setCreateTime(tChargingOrder.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + chargingOrder.add(myChargingOrderList); + } + myOrderInvoiceInfo.setChargingOrder(chargingOrder); + } + //购物订单 + if(orderType == 2){ + List<TShoppingOrder> orderList = shoppingOrderService.listByIds(orderIds); + List<MyShoppingOrderList> shoppingOrder = new ArrayList<>(); + for (TShoppingOrder tShoppingOrder : orderList) { + MyShoppingOrderList myShoppingOrderList = new MyShoppingOrderList(); + myShoppingOrderList.setId(tShoppingOrder.getId().toString()); + String name = ""; + String imgUrl = ""; + if(tShoppingOrder.getOrderType() == 1){ + TGoods goods = goodsClient.getGoodsById(tShoppingOrder.getGoodsId()).getData(); + name = goods.getName(); + imgUrl = goods.getCoverPicture(); + }else{ + TCoupon coupon = couponClient.getCouponById1(tShoppingOrder.getGoodsId()).getData(); + name = coupon.getName(); + imgUrl = coupon.getCoverPicture(); + } + myShoppingOrderList.setName(name); + myShoppingOrderList.setImgUrl(imgUrl); + myShoppingOrderList.setStatus(tShoppingOrder.getStatus()); + BigDecimal unitPrice = tShoppingOrder.getPaymentAmount().divide(new BigDecimal(tShoppingOrder.getPurchaseQuantity())).setScale(2, BigDecimal.ROUND_HALF_EVEN); + myShoppingOrderList.setUnitPrice(unitPrice); + myShoppingOrderList.setNumber(tShoppingOrder.getPurchaseQuantity()); + myShoppingOrderList.setPaymentAmount(tShoppingOrder.getPaymentAmount()); + shoppingOrder.add(myShoppingOrderList); + } + myOrderInvoiceInfo.setShoppingOrder(shoppingOrder); + } + return myOrderInvoiceInfo; + } } diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TShoppingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TShoppingOrderServiceImpl.java index ab1b1d6..b809d8f 100644 --- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TShoppingOrderServiceImpl.java +++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TShoppingOrderServiceImpl.java @@ -1,17 +1,31 @@ package com.ruoyi.order.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.ruoyi.account.api.feignClient.AppUserAddressClient; +import com.ruoyi.account.api.model.TAppUserAddress; +import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.PageInfo; +import com.ruoyi.common.security.service.TokenService; +import com.ruoyi.order.api.model.TExchangeOrder; import com.ruoyi.order.api.model.TShoppingOrder; import com.ruoyi.order.api.query.TActivityStatisticsQuery; import com.ruoyi.order.api.vo.TActivityStatisticslVO; import com.ruoyi.order.api.vo.TActivityVO; +import com.ruoyi.order.dto.*; import com.ruoyi.order.mapper.TShoppingOrderMapper; import com.ruoyi.order.service.TShoppingOrderService; +import com.ruoyi.other.api.domain.TCoupon; +import com.ruoyi.other.api.domain.TGoods; +import com.ruoyi.other.api.feignClient.CouponClient; +import com.ruoyi.other.api.feignClient.GoodsClient; import org.springframework.stereotype.Service; +import javax.annotation.Resource; import java.math.BigDecimal; import java.text.SimpleDateFormat; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.List; /** @@ -24,6 +38,21 @@ */ @Service public class TShoppingOrderServiceImpl extends ServiceImpl<TShoppingOrderMapper, TShoppingOrder> implements TShoppingOrderService { + + @Resource + private TokenService tokenService; + + @Resource + private GoodsClient goodsClient; + + @Resource + private CouponClient couponClient; + + @Resource + private AppUserAddressClient appUserAddressClient; + + + @Override public TActivityVO activityStatistics(TActivityStatisticsQuery dto) { @@ -121,4 +150,163 @@ res.setGrantVip(grantVip); return res; } + + + /** + * 获取小程序商城购买订单列表 + * @param query + * @return + */ + @Override + public List<MyShoppingOrderList> getMyShoppingOrderList(GetMyShoppingOrderList query) { + Long userId = tokenService.getLoginUserApplet().getUserId(); + LambdaQueryWrapper<TShoppingOrder> wrapper = new LambdaQueryWrapper<TShoppingOrder>().eq(TShoppingOrder::getDelFlag, 0) + .eq(TShoppingOrder::getAppUserId, userId); + if(query.getStatus() != 0){ + wrapper.eq(TShoppingOrder::getStatus, query.getStatus()); + } + List<TShoppingOrder> list = this.list(wrapper.orderByDesc(TShoppingOrder::getCreateTime).last(" limit " + query.getPageCurr() + ", " + query.getPageSize())); + List<MyShoppingOrderList> pageList = new ArrayList<>(); + for (TShoppingOrder tShoppingOrder : list) { + MyShoppingOrderList myShoppingOrderList = new MyShoppingOrderList(); + myShoppingOrderList.setId(tShoppingOrder.getId().toString()); + String name = ""; + String imgUrl = ""; + if(tShoppingOrder.getOrderType() == 1){ + TGoods goods = goodsClient.getGoodsById(tShoppingOrder.getGoodsId()).getData(); + name = goods.getName(); + imgUrl = goods.getCoverPicture(); + }else{ + TCoupon coupon = couponClient.getCouponById1(tShoppingOrder.getGoodsId()).getData(); + name = coupon.getName(); + imgUrl = coupon.getCoverPicture(); + } + myShoppingOrderList.setName(name); + myShoppingOrderList.setImgUrl(imgUrl); + myShoppingOrderList.setStatus(tShoppingOrder.getStatus()); + BigDecimal unitPrice = tShoppingOrder.getPaymentAmount().divide(new BigDecimal(tShoppingOrder.getPurchaseQuantity())).setScale(2, BigDecimal.ROUND_HALF_EVEN); + myShoppingOrderList.setUnitPrice(unitPrice); + myShoppingOrderList.setNumber(tShoppingOrder.getPurchaseQuantity()); + myShoppingOrderList.setPaymentAmount(tShoppingOrder.getPaymentAmount()); + pageList.add(myShoppingOrderList); + } + return pageList; + } + + + /** + * 获取购买订单详情 + * @param id + * @return + */ + @Override + public MyShoppingOrderInfo getMyShoppingOrderInfo(String id) { + TShoppingOrder shoppingOrder = this.getById(id); + MyShoppingOrderInfo info = new MyShoppingOrderInfo(); + info.setId(id); + info.setStatus(shoppingOrder.getStatus()); + TAppUserAddress userAddress = appUserAddressClient.getAppUserAddressById(shoppingOrder.getAppUserAddressId()).getData(); + info.setConsignee(userAddress.getName()); + info.setPhone(userAddress.getPhone()); + info.setAddress(userAddress.getAddress()); + info.setExpressCompany(shoppingOrder.getExpressCompany()); + info.setExpressNumber(shoppingOrder.getExpressNumber()); + String name = ""; + String imgUrl = ""; + if(shoppingOrder.getOrderType() == 1){ + TGoods goods = goodsClient.getGoodsById(shoppingOrder.getGoodsId()).getData(); + name = goods.getName(); + imgUrl = goods.getCoverPicture(); + }else{ + TCoupon coupon = couponClient.getCouponById1(shoppingOrder.getGoodsId()).getData(); + info.setCouponType(coupon.getType()); + info.setDays(coupon.getDays()); + info.setEndTime(coupon.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + name = coupon.getName(); + imgUrl = coupon.getCoverPicture(); + } + info.setName(name); + info.setImgUrl(imgUrl); + info.setNumber(shoppingOrder.getPurchaseQuantity()); + BigDecimal unitPrice = shoppingOrder.getPaymentAmount().divide(new BigDecimal(shoppingOrder.getPurchaseQuantity())).setScale(2, BigDecimal.ROUND_HALF_EVEN); + info.setUnitPrice(unitPrice); + info.setCode(shoppingOrder.getCode()); + info.setCreateTime(shoppingOrder.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + info.setPaymentAmount(shoppingOrder.getPaymentAmount()); + info.setRemark(shoppingOrder.getRemark()); + info.setDeliveryTime(shoppingOrder.getConsignerTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + info.setFinishTime(shoppingOrder.getReceivingTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + return info; + } + + + /** + * 取消订单 + * @param id + * @return + */ + @Override + public AjaxResult cancelOrder(String id) { + TShoppingOrder shoppingOrder = this.getById(id); + if(shoppingOrder.getStatus() == 2){ + return AjaxResult.error("订单已发货,不能取消"); + } + if(shoppingOrder.getStatus() == 3){ + return AjaxResult.error("订单已完成,不能取消"); + } + if(shoppingOrder.getStatus() == 4){ + return AjaxResult.error("订单已取消,不能重复操作"); + } + //先查询第三方订单状态订单是否退款 + //支付方式(1=微信,2=支付宝) todo 待完善 + Integer paymentType = shoppingOrder.getPaymentType(); + if(1 == paymentType){ + + } + if(2 == paymentType){ + + } + //退款成功后需要判断商品库存类型后决定是否需要回退库存 + //加redis锁处理高并发 + + + return AjaxResult.success(); + } + + + /** + * 获取未开票的订单列表 + * @param query + * @return + */ + @Override + public List<MyShoppingOrderList> getNoInvoicedOrder(GetNoInvoicedOrder query) { + Long userId = tokenService.getLoginUserApplet().getUserId(); + List<TShoppingOrder> list = this.baseMapper.getNoInvoicedOrder(userId, query.getMonth(), query.getPageCurr(), query.getPageSize()); + List<MyShoppingOrderList> pageList = new ArrayList<>(); + for (TShoppingOrder tShoppingOrder : list) { + MyShoppingOrderList myShoppingOrderList = new MyShoppingOrderList(); + myShoppingOrderList.setId(tShoppingOrder.getId().toString()); + String name = ""; + String imgUrl = ""; + if(tShoppingOrder.getOrderType() == 1){ + TGoods goods = goodsClient.getGoodsById(tShoppingOrder.getGoodsId()).getData(); + name = goods.getName(); + imgUrl = goods.getCoverPicture(); + }else{ + TCoupon coupon = couponClient.getCouponById1(tShoppingOrder.getGoodsId()).getData(); + name = coupon.getName(); + imgUrl = coupon.getCoverPicture(); + } + myShoppingOrderList.setName(name); + myShoppingOrderList.setImgUrl(imgUrl); + myShoppingOrderList.setStatus(tShoppingOrder.getStatus()); + BigDecimal unitPrice = tShoppingOrder.getPaymentAmount().divide(new BigDecimal(tShoppingOrder.getPurchaseQuantity())).setScale(2, BigDecimal.ROUND_HALF_EVEN); + myShoppingOrderList.setUnitPrice(unitPrice); + myShoppingOrderList.setNumber(tShoppingOrder.getPurchaseQuantity()); + myShoppingOrderList.setPaymentAmount(tShoppingOrder.getPaymentAmount()); + pageList.add(myShoppingOrderList); + } + return pageList; + } } diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml index 418f126..20c1eb3 100644 --- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml +++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingOrderMapper.xml @@ -55,4 +55,18 @@ limit #{pageCurr}, #{pageSize} </if> </select> + + + + <select id="getNoInvoicedOrder" resultMap="BaseResultMap"> + select * from t_charging_order where del_flag = 0 and app_user_id = #{appUserId} + <if test="null != month and '' != month"> + and DATE_FORMAT(end_time, '%Y-%m') = #{month} + </if> + and id not in (select order_id from t_order_invoice_detail where order_type = 1) + order by create_time desc + <if test="null != pageCurr and null != pageSize"> + limit #{pageCurr}, #{pageSize} + </if> + </select> </mapper> diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TOrderInvoiceMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TOrderInvoiceMapper.xml index b5c6c33..d7fddbe 100644 --- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TOrderInvoiceMapper.xml +++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TOrderInvoiceMapper.xml @@ -9,6 +9,7 @@ <result column="app_user_id" property="appUserId" /> <result column="order_type" property="orderType" /> <result column="invoicing_company" property="invoicingCompany" /> + <result column="invoice_type_id" property="invoiceTypeId"/> <result column="invoice_type" property="invoiceType" /> <result column="invoice_material" property="invoiceMaterial" /> <result column="invoicing_method" property="invoicingMethod" /> @@ -23,11 +24,14 @@ <result column="invoice_url" property="invoiceUrl" /> <result column="mailbox" property="mailbox" /> <result column="status" property="status" /> + <result column="create_time" property="createTime" /> + <result column="billing_time" property="billingTime" /> + <result column="billing_user_id" property="billingUserId" /> </resultMap> <!-- 通用查询结果列 --> <sql id="Base_Column_List"> - id, code, app_user_id, order_type, invoicing_company, invoice_type, invoice_material, invoicing_method, invoicing_object_type, name, tax_identification_number, company_address, company_phone, deposit_bank, bank_account, total_amount, invoice_url, mailbox, status + id, code, app_user_id, order_type, invoicing_company, invoice_type_id, invoice_type, invoice_material, invoicing_method, invoicing_object_type, name, tax_identification_number, company_address, company_phone, deposit_bank, bank_account, total_amount, invoice_url, mailbox, status, create_time, billing_time, billing_user_id </sql> </mapper> diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TShoppingOrderMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TShoppingOrderMapper.xml index f5636c2..b7b0d0b 100644 --- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TShoppingOrderMapper.xml +++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TShoppingOrderMapper.xml @@ -204,5 +204,18 @@ </if> </if> </select> - + + + + <select id="getNoInvoicedOrder" resultMap="BaseResultMap"> + select * from t_shopping_order where del_flag = 0 and app_user_id = #{appUserId} + <if test="null != month and '' != month"> + and DATE_FORMAT(create_time, '%Y-%m') = #{month} + </if> + and id not in (select order_id from t_order_invoice_detail where order_type = 2) + order by create_time desc + <if test="null != pageCurr and null != pageSize"> + limit #{pageCurr}, #{pageSize} + </if> + </select> </mapper> diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TInvoiceTypeController.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TInvoiceTypeController.java index 9eacc23..3d7c91f 100644 --- a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TInvoiceTypeController.java +++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TInvoiceTypeController.java @@ -1,6 +1,8 @@ package com.ruoyi.other.controller; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.PageInfo; import com.ruoyi.other.api.domain.TInvoiceType; @@ -74,5 +76,29 @@ } return AjaxResult.success(); } + + + + @ResponseBody + @DeleteMapping("/getInvoiceTypeList") + @ApiOperation(value = "获取开票类型", tags = {"小程序-充电发票"}) + public AjaxResult<List<TInvoiceType>> getInvoiceTypeList(){ + List<TInvoiceType> list = invoiceTypeService.list(new LambdaQueryWrapper<TInvoiceType>() + .eq(TInvoiceType::getDelFlag, 0).orderByAsc(TInvoiceType::getCreateTime)); + return AjaxResult.success(list); + } + + + /** + * 根据id获取发票类型 + * @param id + * @return + */ + @ResponseBody + @PostMapping("/getInvoiceType/{id}") + public R<TInvoiceType> getInvoiceType(@PathVariable Integer id){ + TInvoiceType invoiceType = invoiceTypeService.getById(id); + return R.ok(invoiceType); + } } -- Gitblit v1.7.1