Merge remote-tracking branch 'origin/master'
New file |
| | |
| | | package com.ruoyi.account.api.dto; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | @ApiModel(value = "UpdatePhoneDTO对象",description = "更换手机号DTO") |
| | | public class UpdatePhoneDTO implements Serializable { |
| | | |
| | | @ApiModelProperty(value = "手机号") |
| | | @NotBlank(message = "手机号不能为空") |
| | | private String phone; |
| | | |
| | | @ApiModelProperty(value = "验证码") |
| | | @NotBlank(message = "验证码不能为空") |
| | | private String code; |
| | | |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public R<TAppUser> selectByPhone(String phone) { |
| | | return R.fail("通过手机号查询用户失败:"+throwable.getMessage()); |
| | | } |
| | | |
| | | @Override |
| | | public R<List<TAppUser>> getUserByIds(List<Long> appUserIds) { |
| | | return R.fail("根据用户id查询用户信息失败:"+throwable.getMessage()); |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | @PostMapping("/t-app-user//user/updateAppUser") |
| | | @PostMapping("/t-app-user/user/updateAppUser") |
| | | R updateAppUser(@RequestBody TAppUser appUser); |
| | | |
| | | /** |
| | | * 通过手机号查询用户 |
| | | * @param phone |
| | | * @return |
| | | */ |
| | | @GetMapping("/t-app-user/user/selectByPhone") |
| | | R<TAppUser> selectByPhone(@RequestParam("phone") String phone); |
| | | } |
| | |
| | | @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; |
| | | |
| | | |
| | | |
| | |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableLogic; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.ruoyi.common.core.web.domain.BasePojo; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_charging_pile_notification") |
| | | @ApiModel(value="TChargingPileNotification对象", description="") |
| | | public class TChargingPileNotification implements Serializable { |
| | | public class TChargingPileNotification extends BasePojo { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | |
| | | @ApiModelProperty(value = "通知内容") |
| | | @TableField("content") |
| | | private String content; |
| | | |
| | | @ApiModelProperty(value = "发送时间") |
| | | @TableField("create_time") |
| | | private LocalDateTime createTime; |
| | | |
| | | @ApiModelProperty(value = "删除状态(0=否,1=是)") |
| | | @TableField("del_flag") |
| | | @TableLogic |
| | | private Integer delFlag; |
| | | |
| | | |
| | | } |
| | |
| | | private BigDecimal electrovalence; |
| | | @ApiModelProperty(value = "会员电价") |
| | | private BigDecimal vipElectrovalence; |
| | | @ApiModelProperty(value = "开通会员预计可省") |
| | | private BigDecimal money; |
| | | @ApiModelProperty(value = "额外赠送优惠券X张") |
| | | private Integer couponCount; |
| | | @ApiModelProperty(value = "超时占位费说明") |
| | | private String spaceChargeExplain; |
| | | |
| | |
| | | @ApiModelProperty(value = "计费策略明细集合") |
| | | private List<TAccountingStrategyDetail> accountingStrategyDetailList; |
| | | |
| | | @ApiModelProperty(value = "一級审核人员") |
| | | private String firstUserName; |
| | | |
| | | @ApiModelProperty(value = "二級审核人员") |
| | | private String twoUserName; |
| | | |
| | | |
| | | } |
| | |
| | | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | |
| | | @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") |
| | |
| | | @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; |
| | | |
| | | } |
| | |
| | | package com.ruoyi.other.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.core.web.domain.BasePojo; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | |
| | | |
| | | @ApiModelProperty(value = "开始时间") |
| | | @TableField("start_time") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime startTime; |
| | | |
| | | @ApiModelProperty(value = "结束时间") |
| | | @TableField("end_time") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime endTime; |
| | | |
| | | @ApiModelProperty(value = "跳转类型(1=小程序内页面,2=小程序地址,3=网页地址)") |
| | |
| | | package com.ruoyi.other.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.core.web.domain.BasePojo; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | |
| | | |
| | | @ApiModelProperty(value = "开始时间") |
| | | @TableField("start_time") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime startTime; |
| | | |
| | | @ApiModelProperty(value = "结束时间") |
| | | @TableField("end_time") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime endTime; |
| | | |
| | | @ApiModelProperty(value = "显示位置(1=banner广告,2=弹出广告)") |
| | |
| | | package com.ruoyi.other.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.core.web.domain.BasePojo; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | |
| | | |
| | | @ApiModelProperty(value = "使用截止时间") |
| | | @TableField("end_time") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime endTime; |
| | | |
| | | @ApiModelProperty(value = "获取后有效天数") |
| | |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | |
| | | |
| | | @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; |
| | | |
| | | |
| | | |
| | |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableLogic; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.core.web.domain.BasePojo; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | |
| | | |
| | | @ApiModelProperty(value = "开始时间") |
| | | @TableField("start_time") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime startTime; |
| | | |
| | | @ApiModelProperty(value = "结束时间") |
| | | @TableField("end_time") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime endTime; |
| | | |
| | | |
| | |
| | | package com.ruoyi.other.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.*; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.core.web.domain.BasePojo; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | |
| | | |
| | | @ApiModelProperty(value = "月卡折扣开始时间") |
| | | @TableField("monthly_card_discount_start") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime monthlyCardDiscountStart; |
| | | |
| | | @ApiModelProperty(value = "月卡折扣结束时间") |
| | | @TableField("monthly_card_discount_end") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime monthlyCardDiscountEnd; |
| | | |
| | | @ApiModelProperty(value = "月卡折扣显示(0=否,1=是)") |
| | |
| | | |
| | | @ApiModelProperty(value = "季卡折扣开始时间") |
| | | @TableField("season_card_discount_start") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime seasonCardDiscountStart; |
| | | |
| | | @ApiModelProperty(value = "季卡折扣结束时间") |
| | | @TableField("season_card_discount_end") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime seasonCardDiscountEnd; |
| | | |
| | | @ApiModelProperty(value = "季卡折扣显示(0=否,1=是)") |
| | |
| | | |
| | | @ApiModelProperty(value = "年卡折扣开始时间") |
| | | @TableField("annual_card_discount_start") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime annualCardDiscountStart; |
| | | |
| | | @ApiModelProperty(value = "年卡折扣结束时间") |
| | | @TableField("annual_card_discount_end") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private LocalDateTime annualCardDiscountEnd; |
| | | |
| | | @ApiModelProperty(value = "年卡折扣显示(0=否,1=是)") |
New file |
| | |
| | | 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()); |
| | | } |
| | | }; |
| | | } |
| | | } |
New file |
| | |
| | | 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); |
| | | } |
| | |
| | | com.ruoyi.other.api.factory.VipFallbackFactory |
| | | com.ruoyi.other.api.factory.IntegralRuleFallbackFactory |
| | | com.ruoyi.other.api.factory.GoodsFallbackFactory |
| | | com.ruoyi.other.api.factory.CouponFallbackFactory |
| | | com.ruoyi.other.api.factory.CouponFallbackFactory |
| | | com.ruoyi.other.api.factory.InvoiceTypeFallbackFactory |
| | |
| | | <version>${hutool.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.ruoyi</groupId> |
| | | <artifactId>ruoyi-api-account</artifactId> |
| | | <version>3.6.2</version> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | <build> |
| | |
| | | |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.ruoyi.account.api.feignClient.AppUserClient; |
| | | import com.ruoyi.account.api.model.TAppUser; |
| | | import com.ruoyi.common.core.constant.Constants; |
| | | import com.ruoyi.common.core.constant.MsgConstants; |
| | | import com.ruoyi.common.core.utils.HttpUtils; |
| | | import com.ruoyi.common.core.utils.MsgUtil; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | import com.ruoyi.common.redis.service.RedisService; |
| | | import com.ruoyi.system.api.domain.SysRole; |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | |
| | | import com.ruoyi.system.api.model.LoginUser; |
| | | |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * token 控制 |
| | |
| | | private SysLoginService sysLoginService; |
| | | @Resource |
| | | private SysUserClient userClient; |
| | | |
| | | |
| | | |
| | | |
| | | |
| | |
| | | sysLoginService.register(registerBody.getUsername(), registerBody.getPassword(), request); |
| | | return R.ok(); |
| | | } |
| | | |
| | | } |
| | |
| | | */ |
| | | public static final String DATE_FORMATTER_TIME = "yyyy-MM-dd HH:mm:ss"; |
| | | public static final String DATE_FORMATTER_DATE = "yyyy-MM-dd"; |
| | | |
| | | /** |
| | | * 后缀 |
| | | */ |
| | | public static final String APPLET = "_applet"; |
| | | /** |
| | | * 定时任务违规的字符 |
| | | */ |
New file |
| | |
| | | package com.ruoyi.common.core.constant; |
| | | |
| | | /** |
| | | * 短信常量 |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class MsgConstants |
| | | { |
| | | /** 短信发送地址 */ |
| | | public static final String SEND_URL = "http://112.35.1.155:1992/sms/tmpsubmit"; |
| | | /** 更换手机号短信验证码 TEMPLATE_ID */ |
| | | public static final String CODE_TEMPLATE_ID = "5bf3949463e54c03a25c6fce3ad48139"; |
| | | |
| | | /** 停车占位提醒 TEMPLATE_ID */ |
| | | public static final String STOP_TEMPLATE_ID = "4940ce98a3f94f67aa9f5cd2d4e05cbd"; |
| | | |
| | | /** 充电结束 TEMPLATE_ID */ |
| | | public static final String CHARGE_TEMPLATE_ID = "47b2eb376cfa436faae041a6f2f22688"; |
| | | |
| | | /** 桩故障(自动/手动) TEMPLATE_ID */ |
| | | public static final String FAULT_TEMPLATE_ID = "37956469a14a47e484a747a1e7e462de"; |
| | | /** 更换手机号短信验证码 AP_ID */ |
| | | public static final String CODE_AP_ID = "GH123"; |
| | | |
| | | /** 停车占位提醒 AP_ID */ |
| | | public static final String STOP_AP_ID = "TC123"; |
| | | |
| | | /** 充电结束 AP_ID */ |
| | | public static final String CHARGE_AP_ID = "CD123"; |
| | | |
| | | /** 桩故障(自动/手动) AP_ID */ |
| | | public static final String FAULT_AP_ID = "GZ123"; |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.common.core.utils; |
| | | |
| | | import com.ruoyi.common.core.constant.Constants; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import javax.net.ssl.*; |
| | | import java.io.*; |
| | | import java.net.*; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.security.cert.X509Certificate; |
| | | |
| | | /** |
| | | * 通用http发送方法 |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class HttpUtils |
| | | { |
| | | private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); |
| | | |
| | | /** |
| | | * 向指定 URL 发送GET方法的请求 |
| | | * |
| | | * @param url 发送请求的 URL |
| | | * @return 所代表远程资源的响应结果 |
| | | */ |
| | | public static String sendGet(String url) |
| | | { |
| | | return sendGet(url, StringUtils.EMPTY); |
| | | } |
| | | |
| | | /** |
| | | * 向指定 URL 发送GET方法的请求 |
| | | * |
| | | * @param url 发送请求的 URL |
| | | * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 |
| | | * @return 所代表远程资源的响应结果 |
| | | */ |
| | | public static String sendGet(String url, String param) |
| | | { |
| | | return sendGet(url, param, Constants.UTF8); |
| | | } |
| | | |
| | | /** |
| | | * 向指定 URL 发送GET方法的请求 |
| | | * |
| | | * @param url 发送请求的 URL |
| | | * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 |
| | | * @param contentType 编码类型 |
| | | * @return 所代表远程资源的响应结果 |
| | | */ |
| | | public static String sendGet(String url, String param, String contentType) |
| | | { |
| | | StringBuilder result = new StringBuilder(); |
| | | BufferedReader in = null; |
| | | try |
| | | { |
| | | String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url; |
| | | log.info("sendGet - {}", urlNameString); |
| | | URL realUrl = new URL(urlNameString); |
| | | URLConnection connection = realUrl.openConnection(); |
| | | connection.setRequestProperty("accept", "*/*"); |
| | | connection.setRequestProperty("connection", "Keep-Alive"); |
| | | connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); |
| | | connection.connect(); |
| | | in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); |
| | | String line; |
| | | while ((line = in.readLine()) != null) |
| | | { |
| | | result.append(line); |
| | | } |
| | | log.info("recv - {}", result); |
| | | } |
| | | catch (ConnectException e) |
| | | { |
| | | log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); |
| | | } |
| | | catch (SocketTimeoutException e) |
| | | { |
| | | log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); |
| | | } |
| | | catch (IOException e) |
| | | { |
| | | log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); |
| | | } |
| | | finally |
| | | { |
| | | try |
| | | { |
| | | if (in != null) |
| | | { |
| | | in.close(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); |
| | | } |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 向指定 URL 发送POST方法的请求 |
| | | * |
| | | * @param url 发送请求的 URL |
| | | * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 |
| | | * @return 所代表远程资源的响应结果 |
| | | */ |
| | | public static String sendPost(String url, String param) |
| | | { |
| | | PrintWriter out = null; |
| | | BufferedReader in = null; |
| | | StringBuilder result = new StringBuilder(); |
| | | try |
| | | { |
| | | log.info("sendPost - {}", url); |
| | | URL realUrl = new URL(url); |
| | | URLConnection conn = realUrl.openConnection(); |
| | | conn.setRequestProperty("accept", "*/*"); |
| | | conn.setRequestProperty("connection", "Keep-Alive"); |
| | | conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); |
| | | conn.setRequestProperty("Accept-Charset", "utf-8"); |
| | | conn.setRequestProperty("contentType", "utf-8"); |
| | | conn.setDoOutput(true); |
| | | conn.setDoInput(true); |
| | | out = new PrintWriter(conn.getOutputStream()); |
| | | out.print(param); |
| | | out.flush(); |
| | | in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); |
| | | String line; |
| | | while ((line = in.readLine()) != null) |
| | | { |
| | | result.append(line); |
| | | } |
| | | log.info("recv - {}", result); |
| | | } |
| | | catch (ConnectException e) |
| | | { |
| | | log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); |
| | | } |
| | | catch (SocketTimeoutException e) |
| | | { |
| | | log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); |
| | | } |
| | | catch (IOException e) |
| | | { |
| | | log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); |
| | | } |
| | | finally |
| | | { |
| | | try |
| | | { |
| | | if (out != null) |
| | | { |
| | | out.close(); |
| | | } |
| | | if (in != null) |
| | | { |
| | | in.close(); |
| | | } |
| | | } |
| | | catch (IOException ex) |
| | | { |
| | | log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); |
| | | } |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | public static String sendSSLPost(String url, String param) |
| | | { |
| | | StringBuilder result = new StringBuilder(); |
| | | String urlNameString = url + "?" + param; |
| | | try |
| | | { |
| | | log.info("sendSSLPost - {}", urlNameString); |
| | | SSLContext sc = SSLContext.getInstance("SSL"); |
| | | sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); |
| | | URL console = new URL(urlNameString); |
| | | HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); |
| | | conn.setRequestProperty("accept", "*/*"); |
| | | conn.setRequestProperty("connection", "Keep-Alive"); |
| | | conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); |
| | | conn.setRequestProperty("Accept-Charset", "utf-8"); |
| | | conn.setRequestProperty("contentType", "utf-8"); |
| | | conn.setDoOutput(true); |
| | | conn.setDoInput(true); |
| | | |
| | | conn.setSSLSocketFactory(sc.getSocketFactory()); |
| | | conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); |
| | | conn.connect(); |
| | | InputStream is = conn.getInputStream(); |
| | | BufferedReader br = new BufferedReader(new InputStreamReader(is)); |
| | | String ret = ""; |
| | | while ((ret = br.readLine()) != null) |
| | | { |
| | | if (ret != null && !"".equals(ret.trim())) |
| | | { |
| | | result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)); |
| | | } |
| | | } |
| | | log.info("recv - {}", result); |
| | | conn.disconnect(); |
| | | br.close(); |
| | | } |
| | | catch (ConnectException e) |
| | | { |
| | | log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); |
| | | } |
| | | catch (SocketTimeoutException e) |
| | | { |
| | | log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); |
| | | } |
| | | catch (IOException e) |
| | | { |
| | | log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); |
| | | } |
| | | return result.toString(); |
| | | } |
| | | |
| | | public static String post(String strURL, String params) { |
| | | String result = ""; |
| | | BufferedReader reader = null; |
| | | try { |
| | | URL url = new URL(strURL);// 创建连接 |
| | | HttpURLConnection connection = (HttpURLConnection) url |
| | | .openConnection(); |
| | | connection.setDoOutput(true); |
| | | connection.setDoInput(true); |
| | | connection.setUseCaches(false); |
| | | connection.setInstanceFollowRedirects(true); |
| | | connection.setRequestMethod("POST"); // 设置请求方式 |
| | | connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式 |
| | | connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式 |
| | | connection.connect(); |
| | | if (params != null && !StringUtils.isEmpty(params)) { |
| | | byte[] writebytes = params.getBytes(); |
| | | // 设置文件长度 |
| | | // connection.setRequestProperty("Content-Length", String.valueOf(writebytes.length)); |
| | | OutputStream outwritestream = connection.getOutputStream(); |
| | | outwritestream.write(params.getBytes()); |
| | | outwritestream.flush(); |
| | | outwritestream.close(); |
| | | // Log.d("hlhupload", "doJsonPost: conn"+connection.getResponseCode()); |
| | | } |
| | | if (connection.getResponseCode() == 200) { |
| | | log.info("<<<<<<<<<<<<<请求响应:{}", connection.getResponseMessage()); |
| | | reader = new BufferedReader( |
| | | new InputStreamReader(connection.getInputStream())); |
| | | result = reader.readLine(); |
| | | log.info("<<<<<<<<<<<<<请求响应:{}", result); |
| | | } else { |
| | | throw new ServiceException(connection.getResponseMessage()); |
| | | } |
| | | } catch (Exception e) { |
| | | throw new ServiceException("http的post请求异常!" + e.getMessage()); |
| | | } finally { |
| | | if (reader != null) { |
| | | try { |
| | | reader.close(); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | private static class TrustAnyTrustManager implements X509TrustManager |
| | | { |
| | | @Override |
| | | public void checkClientTrusted(X509Certificate[] chain, String authType) |
| | | { |
| | | } |
| | | |
| | | @Override |
| | | public void checkServerTrusted(X509Certificate[] chain, String authType) |
| | | { |
| | | } |
| | | |
| | | @Override |
| | | public X509Certificate[] getAcceptedIssuers() |
| | | { |
| | | return new X509Certificate[] {}; |
| | | } |
| | | } |
| | | |
| | | private static class TrustAnyHostnameVerifier implements HostnameVerifier |
| | | { |
| | | @Override |
| | | public boolean verify(String hostname, SSLSession session) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package com.ruoyi.common.core.utils; |
| | | |
| | | import java.security.MessageDigest; |
| | | import java.security.NoSuchAlgorithmException; |
| | | |
| | | public class MD5Util { |
| | | |
| | | /** |
| | | * 给指定字符串按照md5算法去加密 |
| | | * |
| | | * @param psd 需要加密的密码 加盐处理 |
| | | * |
| | | * @return md5后的字符串 |
| | | */ |
| | | public static String encoder(String psd) { |
| | | try { |
| | | //加盐处理 |
| | | psd = psd + "mobilesafe"; |
| | | //1,指定加密算法类型 |
| | | MessageDigest digest = MessageDigest.getInstance("MD5"); |
| | | //2,将需要加密的字符串中转换成byte类型的数组,然后进行随机哈希过程 |
| | | byte[] bs = digest.digest(psd.getBytes()); |
| | | // System.out.println(bs.length); |
| | | //3,循环遍历bs,然后让其生成32位字符串,固定写法 |
| | | //4,拼接字符串过程 |
| | | StringBuffer stringBuffer = new StringBuffer(); |
| | | for (byte b : bs) { |
| | | int i = b & 0xff; |
| | | //int类型的i需要转换成16机制字符 |
| | | String hexString = Integer.toHexString(i); |
| | | // System.out.println(hexString); |
| | | if (hexString.length() < 2) { |
| | | hexString = "0" + hexString; |
| | | } |
| | | stringBuffer.append(hexString); |
| | | } |
| | | //5,打印测试 |
| | | System.out.println(stringBuffer.toString()); |
| | | return stringBuffer.toString(); |
| | | } catch (NoSuchAlgorithmException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * MD5加密字符串 |
| | | * |
| | | * @param str |
| | | * @return |
| | | */ |
| | | public static String getMD5(String str) { |
| | | if (StringUtils.isNotEmpty(str)) { |
| | | try { |
| | | MessageDigest md = MessageDigest.getInstance("MD5"); |
| | | md.update(str.getBytes()); |
| | | byte b[] = md.digest(); |
| | | int i; |
| | | StringBuffer buf = new StringBuffer(""); |
| | | for (int offset = 0; offset < b.length; offset++) { |
| | | i = b[offset]; |
| | | if (i < 0) |
| | | i += 256; |
| | | if (i < 16) |
| | | buf.append("0"); |
| | | buf.append(Integer.toHexString(i)); |
| | | } |
| | | //32位加密(小写) |
| | | return buf.toString(); |
| | | //32位加密(大写) |
| | | //return buf.toString().toUpperCase(); |
| | | // 16位的加密(小写) |
| | | //return buf.toString().substring(8, 24); |
| | | // 16位的加密(大写) |
| | | //return buf.toString().substring(8, 24).toUpperCase(); |
| | | } catch (NoSuchAlgorithmException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * 获取32位大写 |
| | | * |
| | | * @param str |
| | | * @return |
| | | */ |
| | | public static String getMD5_32_upper(String str) { |
| | | if (StringUtils.isNotEmpty(str)) |
| | | return getMD5(str).toUpperCase(); |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * 获取32位小写 |
| | | * |
| | | * @param str |
| | | * @return |
| | | */ |
| | | public static String getMD5_32_lower(String str) { |
| | | if (StringUtils.isNotEmpty(str)) |
| | | return getMD5(str).toLowerCase(); |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * 获取16位大写 |
| | | * |
| | | * @param str |
| | | * @return |
| | | */ |
| | | public static String getMD5_16_upper(String str) { |
| | | if (StringUtils.isNotEmpty(str)) |
| | | return getMD5(str).substring(8, 24).toUpperCase(); |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * 获取16位小写 |
| | | * |
| | | * @param str |
| | | * @return |
| | | */ |
| | | public static String getMD5_16_lower(String str) { |
| | | if (StringUtils.isNotEmpty(str)) |
| | | return getMD5(str).substring(8, 24).toLowerCase(); |
| | | return ""; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.common.core.utils; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.ruoyi.common.core.constant.MsgConstants; |
| | | import com.ruoyi.common.core.utils.req.SubmitTempletReq; |
| | | import org.apache.commons.codec.binary.Base64; |
| | | |
| | | import java.util.concurrent.ThreadLocalRandom; |
| | | |
| | | public class MsgUtil { |
| | | |
| | | public final static String ecName= "四川明星新能源科技有限公司"; |
| | | public final static String secretKey= "MX_xny2023?9"; |
| | | public final static String sign= "1PUAVuY2b"; |
| | | |
| | | |
| | | |
| | | /** |
| | | * 更换手机号:【签名】验证码:XXX,用于更换手机号。请勿转发。 |
| | | * @param phone 手机号 |
| | | * @param code 验证码 |
| | | * @return |
| | | */ |
| | | public static String codeMsg(String phone,String code){ |
| | | SubmitTempletReq submitReq = new SubmitTempletReq(); |
| | | String[] paramss = {code}; |
| | | submitReq.setApId(MsgConstants.CODE_AP_ID); |
| | | submitReq.setEcName(ecName); |
| | | submitReq.setSecretKey(secretKey); |
| | | submitReq.setParams(JSON.toJSONString(paramss)); |
| | | submitReq.setMobiles(phone); |
| | | submitReq.setAddSerial(""); |
| | | submitReq.setSign(sign); |
| | | submitReq.setTemplateId(MsgConstants.CODE_TEMPLATE_ID); |
| | | StringBuffer stringBuffer = new StringBuffer(); |
| | | stringBuffer.append(submitReq.getEcName()); |
| | | stringBuffer.append(submitReq.getApId()); |
| | | stringBuffer.append(submitReq.getSecretKey()); |
| | | stringBuffer.append(submitReq.getTemplateId()); |
| | | stringBuffer.append(submitReq.getMobiles()); |
| | | stringBuffer.append(submitReq.getParams()); |
| | | stringBuffer.append(submitReq.getSign()); |
| | | stringBuffer.append(submitReq.getAddSerial()); |
| | | submitReq.setMac(MD5Util.getMD5(stringBuffer.toString())); |
| | | String reqText = JSON.toJSONString(submitReq); |
| | | //加密 |
| | | String encode = Base64.encodeBase64String(reqText.getBytes()); |
| | | System.err.println(encode); |
| | | return encode; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 停车占位提醒:车辆已在3小时前完成充电,请及时取车,避免长时间占用充电资源。 |
| | | * @param phone 手机号 |
| | | * @return |
| | | */ |
| | | public static String stopMsg(String phone){ |
| | | SubmitTempletReq submitReq = new SubmitTempletReq(); |
| | | submitReq.setTemplateId(MsgConstants.STOP_TEMPLATE_ID); |
| | | submitReq.setApId(MsgConstants.STOP_AP_ID); |
| | | submitReq.setEcName(ecName); |
| | | submitReq.setSecretKey(secretKey); |
| | | submitReq.setMobiles(phone); |
| | | submitReq.setAddSerial(""); |
| | | submitReq.setSign(sign); |
| | | StringBuffer stringBuffer = new StringBuffer(); |
| | | stringBuffer.append(submitReq.getEcName()); |
| | | stringBuffer.append(submitReq.getApId()); |
| | | stringBuffer.append(submitReq.getSecretKey()); |
| | | stringBuffer.append(submitReq.getTemplateId()); |
| | | stringBuffer.append(submitReq.getMobiles()); |
| | | stringBuffer.append(submitReq.getParams()); |
| | | stringBuffer.append(submitReq.getSign()); |
| | | stringBuffer.append(submitReq.getAddSerial()); |
| | | submitReq.setMac(MD5Util.getMD5(stringBuffer.toString())); |
| | | String reqText = JSON.toJSONString(submitReq); |
| | | //加密 |
| | | String encode = Base64.encodeBase64String(reqText.getBytes()); |
| | | System.err.println(encode); |
| | | return encode; |
| | | } |
| | | |
| | | /** |
| | | * 充电结束:车辆充电结束,请及时取车。 |
| | | * @param phone 手机号 |
| | | * @return |
| | | */ |
| | | public static String chargeStopMsg(String phone){ |
| | | SubmitTempletReq submitReq = new SubmitTempletReq(); |
| | | submitReq.setTemplateId(MsgConstants.CHARGE_TEMPLATE_ID); |
| | | submitReq.setApId(MsgConstants.CHARGE_AP_ID); |
| | | submitReq.setEcName(ecName); |
| | | submitReq.setSecretKey(secretKey); |
| | | submitReq.setMobiles(phone); |
| | | submitReq.setAddSerial(""); |
| | | submitReq.setSign(sign); |
| | | StringBuffer stringBuffer = new StringBuffer(); |
| | | stringBuffer.append(submitReq.getEcName()); |
| | | stringBuffer.append(submitReq.getApId()); |
| | | stringBuffer.append(submitReq.getSecretKey()); |
| | | stringBuffer.append(submitReq.getTemplateId()); |
| | | stringBuffer.append(submitReq.getMobiles()); |
| | | stringBuffer.append(submitReq.getParams()); |
| | | stringBuffer.append(submitReq.getSign()); |
| | | stringBuffer.append(submitReq.getAddSerial()); |
| | | submitReq.setMac(MD5Util.getMD5(stringBuffer.toString())); |
| | | String reqText = JSON.toJSONString(submitReq); |
| | | //加密 |
| | | String encode = Base64.encodeBase64String(reqText.getBytes()); |
| | | System.err.println(encode); |
| | | return encode; |
| | | } |
| | | |
| | | /** phone 单词可拼接5000个号码 |
| | | * 桩故障(自动/手动):检测到【电站1】【编号】号桩设备离线,请及时查看处理! |
| | | * @param phone 手机号 |
| | | * @param site 站点名称 |
| | | * @param chargeGun 桩编号 |
| | | * @return |
| | | */ |
| | | public static String faultMsg(String phone,String site,String chargeGun){ |
| | | SubmitTempletReq submitReq = new SubmitTempletReq(); |
| | | if(site.length()<=10){ |
| | | String[] paramss = {site,chargeGun}; |
| | | submitReq.setParams(JSON.toJSONString(paramss)); |
| | | }else{ |
| | | String work1 = site.substring(0,10); |
| | | String[] paramss = {work1,chargeGun}; |
| | | submitReq.setParams(JSON.toJSONString(paramss)); |
| | | } |
| | | submitReq.setTemplateId(MsgConstants.FAULT_TEMPLATE_ID); |
| | | submitReq.setApId(MsgConstants.FAULT_AP_ID); |
| | | submitReq.setEcName(ecName); |
| | | submitReq.setSecretKey(secretKey); |
| | | submitReq.setMobiles(phone); |
| | | submitReq.setAddSerial(""); |
| | | submitReq.setSign(sign); |
| | | StringBuffer stringBuffer = new StringBuffer(); |
| | | stringBuffer.append(submitReq.getEcName()); |
| | | stringBuffer.append(submitReq.getApId()); |
| | | stringBuffer.append(submitReq.getSecretKey()); |
| | | stringBuffer.append(submitReq.getTemplateId()); |
| | | stringBuffer.append(submitReq.getMobiles()); |
| | | stringBuffer.append(submitReq.getParams()); |
| | | stringBuffer.append(submitReq.getSign()); |
| | | stringBuffer.append(submitReq.getAddSerial()); |
| | | submitReq.setMac(MD5Util.getMD5(stringBuffer.toString())); |
| | | String reqText = JSON.toJSONString(submitReq); |
| | | //加密 |
| | | String encode = Base64.encodeBase64String(reqText.getBytes()); |
| | | System.err.println(encode); |
| | | return encode; |
| | | } |
| | | /** |
| | | * 生成验证码 |
| | | * @return |
| | | */ |
| | | public static String createCode(){ |
| | | return String.valueOf(ThreadLocalRandom.current().nextInt(100000, 999999)); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.common.core.utils.req; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | @Data |
| | | public class SubmitTempletReq implements Serializable { |
| | | |
| | | /** |
| | | * 企业名称 |
| | | */ |
| | | private String ecName; |
| | | /** |
| | | * 接口账号用户名 |
| | | */ |
| | | private String apId; |
| | | /** |
| | | * 密码 |
| | | */ |
| | | private String secretKey; |
| | | /** |
| | | * 模板ID。在云MAS平台创建模板,路径:『短信』→『模板短信』→『模板管理』,创建后提交审核,审核通过将获得模板ID。 |
| | | */ |
| | | private String templateId; |
| | | /** |
| | | * 收信手机号码。英文逗号分隔,每批次限5000个号码,例:“13800138000,13800138001,13800138002”。 |
| | | */ |
| | | private String mobiles; |
| | | /** |
| | | * 模板变量。格式:[“param1”,“param2”],无变量模板填[""] |
| | | */ |
| | | private String params; |
| | | /** |
| | | * 签名 |
| | | */ |
| | | private String sign; |
| | | /** |
| | | * 扩展码。依据开户时申请的服务代码匹配类型而定,如为精确匹配,此项填写空字符串("");如为模糊匹配,此项可填写空字符串或自定义的扩展码,注:服务代码加扩展码总长度不能超过20位。 |
| | | */ |
| | | private String addSerial; |
| | | /** |
| | | * 参数校验序列,生成方法:将ecName、apId、secretKey、templateId、mobiles、params、sign、addSerial按序拼接(无间隔符),通过MD5(32位小写)计算出的值。 |
| | | */ |
| | | private String mac; |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.common.core.web.domain; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | public class BaseDelete { |
| | | |
| | | @ApiModelProperty(value = "id集合") |
| | | private List<Integer> ids; |
| | | |
| | | } |
| | |
| | | |
| | | /** |
| | | * 网关启动程序 |
| | | * |
| | | * |
| | | * @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" + |
| | | " ''-' `'-' `-..-' "); |
| | | } |
| | | } |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | |
| | | /** |
| | | * 网关限流配置 |
| | | * |
| | | * |
| | | * @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(); |
| | | } |
| | | } |
| | |
| | | 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(); |
| | | } |
| | | } |
| | |
| | | |
| | | /** |
| | | * 路由配置信息 |
| | | * |
| | | * |
| | | * @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); |
| | | }; |
| | | } |
| | | } |
| | |
| | | |
| | | 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; |
| | |
| | | |
| | | /** |
| | | * 聚合系统接口 |
| | | * |
| | | * |
| | | * @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/"); |
| | | } |
| | | } |
| | |
| | | |
| | | /** |
| | | * 验证码配置 |
| | | * |
| | | * |
| | | * @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; |
| | | } |
| | | } |
| | |
| | | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | |
| | | /** |
| | | * 网关鉴权 |
| | | * |
| | | * |
| | | * @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; |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | |
| | | /** |
| | | * 黑名单过滤器 |
| | | * |
| | | * |
| | | * @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)); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | 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; |
| | |
| | | |
| | | /** |
| | | * 获取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; |
| | | } |
| | | } |
| | | } |
| | |
| | | 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 |
| | | */ |
| | |
| | | // 生成一个指定 Mac 算法 的 Mac 对象 |
| | | // 用给定密钥初始化 Mac 对象 |
| | | mac.init(secretKey); |
| | | |
| | | |
| | | byte[] text = encryptText.getBytes(ENCODING); |
| | | // 完成 Mac 操作 |
| | | return mac.doFinal(text); |
| | |
| | | */ |
| | | @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; |
| | | } |
| | | } |
| | |
| | | |
| | | /** |
| | | * 网关鉴权 |
| | | * |
| | | * |
| | | * @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; |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | * @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(); |
| | | } |
| | | } |
| | |
| | | */ |
| | | @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; |
| | | } |
| | | } |
| | |
| | | */ |
| | | @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); |
| | | } |
| | | } |
| | |
| | | * |
| | | * @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); |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | |
| | | @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))); |
| | | } |
| | | } |
| | |
| | | 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; |
| | |
| | | * @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)); |
| | | } |
| | | } |
| | |
| | | package com.ruoyi.gateway.service; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | import com.ruoyi.common.core.exception.CaptchaException; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | |
| | |
| | | * |
| | | * @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; |
| | | } |
| | |
| | | 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; |
| | |
| | | * @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("验证码错误"); |
| | | } |
| | | } |
| | | } |
| | |
| | | @Autowired |
| | | private ChargingOrderClient chargingOrderClient; |
| | | /** |
| | | * 小程序扫一扫 添加车辆 |
| | | * @param dto |
| | | * @return |
| | | */ |
| | | @ApiOperation(value = "添加车辆", tags = {"小程序-扫一扫"}) |
| | | @PostMapping(value = "/scan/addCar") |
| | | public AjaxResult addCar(@RequestBody TAppUserCar dto) { |
| | | dto.setAppUserId(tokenService.getLoginUserApplet().getUserId()); |
| | | appUserCarService.save(dto); |
| | | return AjaxResult.success(); |
| | | } |
| | | /** |
| | | * 查询用户可用优惠券数量 |
| | | * @return |
| | | */ |
| | |
| | | import com.ruoyi.account.wx.model.WeixinProperties; |
| | | import com.ruoyi.account.wx.tools.WxAppletTools; |
| | | import com.ruoyi.account.util.GiveVipUtil; |
| | | import com.ruoyi.common.core.constant.Constants; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.utils.StringUtils; |
| | | import com.ruoyi.common.core.utils.bean.BeanUtils; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | import com.ruoyi.common.core.web.domain.BasePojo; |
| | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.aspectj.weaver.loadtime.Aj; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | |
| | | private TokenService tokenService; |
| | | @Autowired |
| | | private RedisService redisService; |
| | | @Autowired |
| | | private WeixinProperties wxConfig; |
| | | @Autowired |
| | | private RestTemplate wxRestTemplate; |
| | | |
| | | @Resource |
| | | private TAppUserSignService signService; |
| | |
| | | return R.ok(); |
| | | } |
| | | |
| | | @ApiOperation(value = "更换手机号", tags = {"小程序-用户管理-更换手机号"}) |
| | | @PostMapping(value = "/user/updatePhone") |
| | | public AjaxResult<String> updatePhone(@Validated @RequestBody UpdatePhoneDTO dto) { |
| | | String code = redisService.getCacheObject(dto.getPhone() + Constants.APPLET); |
| | | if(StringUtils.isEmpty(code)){ |
| | | return AjaxResult.error("验证码已过期,请重新获取验证码!"); |
| | | } |
| | | if(!code.equals(dto.getCode())){ |
| | | return AjaxResult.error("验证码错误!"); |
| | | } |
| | | // 获取当前用户信息 |
| | | Long userId = tokenService.getLoginUserApplet().getUserId(); |
| | | TAppUser appUser = appUserService.getById(userId); |
| | | appUser.setPhone(dto.getPhone()); |
| | | appUserService.updateById(appUser); |
| | | return AjaxResult.success(); |
| | | } |
| | | |
| | | /** |
| | | * 根据用户id查询用户信息 |
| | | * @param appUserIds 用户id |
| | |
| | | return R.ok(); |
| | | } |
| | | |
| | | /** |
| | | * 通过手机号查询用户 |
| | | * @param phone |
| | | * @return |
| | | */ |
| | | @GetMapping("/user/selectByPhone") |
| | | public R<TAppUser> selectByPhone(@RequestParam("phone") String phone){ |
| | | return R.ok(appUserService.getOne(Wrappers.lambdaQuery(TAppUser.class) |
| | | .eq(TAppUser::getPhone,phone) |
| | | .last("LIMIT 1"))); |
| | | } |
| | | |
| | | // @ApiOperation(value = "签到", tags = {"小程序-个人中心-签到"}) |
| | | // @PostMapping(value = "/user/sign") |
| | |
| | | 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> |
| | |
| | | @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(); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | * @return |
| | | */ |
| | | Map<String, Object> getUserInfo(TAppUser appUser); |
| | | |
| | | /** |
| | | * 账号判断 |
| | | * @param status |
| | | */ |
| | | public void throwInfo(Integer status); |
| | | } |
| | |
| | | import com.ruoyi.account.service.TAppUserService; |
| | | import com.ruoyi.account.wx.model.WeixinProperties; |
| | | import com.ruoyi.account.wx.pojo.AppletUserDecodeData; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.common.security.service.TokenService; |
| | | import com.ruoyi.system.api.model.LoginUserApplet; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | appUser.setPhone(appletUserDecodeData.getPhoneNumber()); |
| | | } |
| | | } |
| | | if(Objects.nonNull(appUser.getStatus())){ |
| | | throwInfo(appUser.getStatus()); |
| | | } |
| | | appUser.setAvatar(appletUserDecodeData.getAvatarUrl()); |
| | | appUser.setCity(appletUserDecodeData.getCity()); |
| | | appUser.setName(appletUserDecodeData.getNickName()); |
| | |
| | | appUser.setPhone(userInfo.getMobile()); |
| | | } |
| | | } |
| | | if(Objects.nonNull(appUser.getStatus())){ |
| | | throwInfo(appUser.getStatus()); |
| | | } |
| | | appUser.setAvatar(userInfo.getAvatar()); |
| | | appUser.setCity(userInfo.getCity()); |
| | | appUser.setName(userInfo.getNickName()); |
| | |
| | | tokenInfos.put("info",loginUserApplet); |
| | | return tokenInfos; |
| | | } |
| | | |
| | | @Override |
| | | public void throwInfo(Integer status){ |
| | | switch (status){ |
| | | case 2: |
| | | throw new ServiceException("账号被冻结,请联系管理员"); |
| | | case 3: |
| | | throw new ServiceException("账号已注销,请重新注册使用"); |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | } |
| | |
| | | <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> |
New file |
| | |
| | | package com.ruoyi.chargingPile.controller; |
| | | |
| | | import com.ruoyi.account.api.feignClient.AppUserClient; |
| | | import com.ruoyi.account.api.model.TAppUser; |
| | | import com.ruoyi.chargingPile.api.model.TChargingPile; |
| | | import com.ruoyi.chargingPile.service.TChargingPileNotificationService; |
| | | import com.ruoyi.common.core.constant.Constants; |
| | | import com.ruoyi.common.core.constant.MsgConstants; |
| | | import com.ruoyi.common.core.utils.HttpUtils; |
| | | import com.ruoyi.common.core.utils.MsgUtil; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | import com.ruoyi.common.redis.service.RedisService; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | |
| | | import java.util.Objects; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | public class CodeController { |
| | | |
| | | @Autowired |
| | | private RedisService redisService; |
| | | @Autowired |
| | | private AppUserClient appUserClient; |
| | | @Autowired |
| | | private TChargingPileNotificationService chargingPileNotificationService; |
| | | |
| | | /** |
| | | * 获取验证码 |
| | | * |
| | | * @param phone 手机号 |
| | | * @return 结果 |
| | | */ |
| | | @ApiOperation(value = "获取验证码",notes = "获取验证码",tags = {"更换手机号获取验证码"}) |
| | | @GetMapping("getCode") |
| | | public AjaxResult getCode(@RequestParam("phone") String phone) |
| | | { |
| | | TAppUser appUser = appUserClient.selectByPhone(phone).getData(); |
| | | if (Objects.nonNull(appUser)){ |
| | | return AjaxResult.error("该手机号已绑定账号"); |
| | | } |
| | | String code = MsgUtil.createCode(); |
| | | redisService.setCacheObject(phone+ Constants.APPLET,code,5L, TimeUnit.MINUTES); |
| | | String reqStr = MsgUtil.codeMsg(phone, code); |
| | | String result = HttpUtils.post(MsgConstants.SEND_URL, reqStr); |
| | | // 记录短信发送 |
| | | chargingPileNotificationService.saveData(1,null,null,phone,"验证码:"+code+",用于更换手机号。请勿转发。"); |
| | | return AjaxResult.success(result); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | |
| | | @ResponseBody |
| | | @PostMapping("/getSiteList") |
| | | @PostMapping("/addSite") |
| | | @ApiOperation(value = "添加站点", tags = {"管理后台-站点管理"}) |
| | | public AjaxResult addSite(@RequestBody Site site){ |
| | | return siteService.addSite(site); |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.account.api.feignClient.AppUserClient; |
| | | import com.ruoyi.chargingPile.api.dto.TAccountingStrategyDTO; |
| | | import com.ruoyi.chargingPile.api.model.*; |
| | | import com.ruoyi.chargingPile.api.query.TAccountingStrategyQuery; |
| | |
| | | import com.ruoyi.chargingPile.service.TChargingPileService; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | import com.ruoyi.common.core.web.domain.BaseDelete; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.common.security.service.TokenService; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.log.enums.OperatorType; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | |
| | | import java.math.BigInteger; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalTime; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | private TChargingPileService chargingPileService; |
| | | @Autowired |
| | | private ISiteService siteService; |
| | | |
| | | @Autowired |
| | | private SysUserClient sysUserClient; |
| | | @Resource |
| | | private TokenService tokenService; |
| | | |
| | |
| | | */ |
| | | @ApiOperation(tags = {"后台-计费策略", "管理后台-站点管理"},value = "查看计费策略详情") |
| | | @GetMapping(value = "/getDetailById") |
| | | public AjaxResult<TAccountingStrategy> getDetailById(@RequestParam("id") Integer id) { |
| | | return AjaxResult.ok(accountingStrategyService.getById(id)); |
| | | public AjaxResult<TAccountingStrategyVO> getDetailById(@RequestParam("id") Integer id) { |
| | | TAccountingStrategy accountingStrategy = accountingStrategyService.getById(id); |
| | | TAccountingStrategyVO accountingStrategyVO = new TAccountingStrategyVO(); |
| | | BeanUtils.copyProperties(accountingStrategy,accountingStrategyVO); |
| | | // 查询用户信息 |
| | | String firstUserName = sysUserClient.getSysUser(accountingStrategy.getFirstUserId()).getData().getNickName(); |
| | | String twoUserName = sysUserClient.getSysUser(accountingStrategy.getTwoUserId()).getData().getNickName(); |
| | | accountingStrategyVO.setFirstUserName(firstUserName); |
| | | accountingStrategyVO.setTwoUserName(twoUserName); |
| | | return AjaxResult.ok(accountingStrategyVO); |
| | | } |
| | | |
| | | /** |
| | |
| | | @Log(title = "批量删除计费策略", businessType = BusinessType.DELETE,operatorType = OperatorType.MANAGE) |
| | | @ApiOperation(tags = {"后台-计费策略"},value = "批量删除计费策略") |
| | | @DeleteMapping(value = "/deleteByIds") |
| | | public AjaxResult<Boolean> deleteByIds(@RequestBody List<Integer> ids) { |
| | | public AjaxResult<Boolean> deleteByIds(@RequestParam String ids) { |
| | | String[] split = ids.split(","); |
| | | // 刪除计费策略明细信息 |
| | | accountingStrategyDetailService.remove(Wrappers.lambdaQuery(TAccountingStrategyDetail.class) |
| | | .in(TAccountingStrategyDetail::getAccountingStrategyId, ids)); |
| | | return AjaxResult.ok(accountingStrategyService.removeByIds(ids)); |
| | | .in(TAccountingStrategyDetail::getAccountingStrategyId, Arrays.asList(split))); |
| | | return AjaxResult.success(accountingStrategyService.removeByIds(Arrays.asList(split))); |
| | | } |
| | | |
| | | |
| | |
| | | import com.ruoyi.chargingPile.service.TCarportService; |
| | | import com.ruoyi.chargingPile.service.TVehicleRampService; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | import com.ruoyi.common.core.web.domain.BaseDelete; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.log.enums.OperatorType; |
| | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @Log(title = "批量删除车库", businessType = BusinessType.DELETE,operatorType = OperatorType.MANAGE) |
| | | @ApiOperation(tags = {"后台-车库"},value = "批量删除车库") |
| | | @DeleteMapping(value = "/deleteByIds") |
| | | public AjaxResult<Boolean> deleteByIds(@RequestBody List<Integer> ids) { |
| | | public AjaxResult<Boolean> deleteByIds(@RequestParam String ids) { |
| | | String[] split = ids.split(","); |
| | | // 刪除车道信息 |
| | | vehicleRampService.remove(Wrappers.lambdaQuery(TVehicleRamp.class) |
| | | .in(TVehicleRamp::getCarportId, ids)); |
| | | return AjaxResult.ok(carportService.removeByIds(ids)); |
| | | .in(TVehicleRamp::getCarportId, Arrays.asList(split))); |
| | | return AjaxResult.ok(carportService.removeByIds(Arrays.asList(split))); |
| | | } |
| | | |
| | | } |
| | |
| | | import com.ruoyi.chargingPile.service.TChargingPileService; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | import com.ruoyi.common.core.web.domain.BaseDelete; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @Log(title = "批量删除充电枪", businessType = BusinessType.DELETE,operatorType = OperatorType.MANAGE) |
| | | @ApiOperation(tags = {"后台-充电枪"},value = "批量删除充电枪") |
| | | @DeleteMapping(value = "/deleteByIds") |
| | | public AjaxResult<Boolean> deleteByIds(@RequestBody List<Integer> ids) { |
| | | return AjaxResult.ok(chargingGunService.removeByIds(ids)); |
| | | public AjaxResult<Boolean> deleteByIds(@RequestParam String ids) { |
| | | String[] split = ids.split(","); |
| | | return AjaxResult.ok(chargingGunService.removeByIds(Arrays.asList(split))); |
| | | } |
| | | |
| | | /** |
| | |
| | | @Log(title = "添加故障报修管理", businessType = BusinessType.INSERT,operatorType = OperatorType.MOBILE) |
| | | @ApiOperation(tags = {"小程序-故障报修"},value = "添加故障报修管理") |
| | | @PostMapping(value = "/add") |
| | | public AjaxResult<Boolean> add(@Validated @RequestBody TFaultMessage dto) { |
| | | return AjaxResult.ok(faultMessageService.save(dto)); |
| | | public AjaxResult<String> add(@Validated @RequestBody TFaultMessage dto) { |
| | | faultMessageService.add(dto); |
| | | return AjaxResult.success(); |
| | | } |
| | | |
| | | |
| | |
| | | import com.ruoyi.chargingPile.api.vo.TMonitoringEquipmentVO; |
| | | import com.ruoyi.chargingPile.service.TMonitoringEquipmentService; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | import com.ruoyi.common.core.web.domain.BaseDelete; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @Log(title = "批量删除监控", businessType = BusinessType.DELETE,operatorType = OperatorType.MANAGE) |
| | | @ApiOperation(tags = {"后台-监控"},value = "批量删除监控") |
| | | @DeleteMapping(value = "/deleteByIds") |
| | | public AjaxResult<Boolean> deleteByIds(@RequestBody List<Integer> ids) { |
| | | return AjaxResult.ok(monitoringEquipmentService.removeByIds(ids)); |
| | | public AjaxResult<Boolean> deleteByIds(@RequestParam String ids) { |
| | | String[] split = ids.split(","); |
| | | return AjaxResult.ok(monitoringEquipmentService.removeByIds(Arrays.asList(split))); |
| | | } |
| | | |
| | | } |
| | |
| | | import com.ruoyi.chargingPile.service.TVehicleRampService; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | import com.ruoyi.common.core.web.domain.BaseDelete; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @Log(title = "批量删除停车场", businessType = BusinessType.DELETE,operatorType = OperatorType.MANAGE) |
| | | @ApiOperation(tags = {"后台-停车场"},value = "批量删除停车场") |
| | | @DeleteMapping(value = "/deleteByIds") |
| | | public AjaxResult<Boolean> deleteByIds(@RequestBody List<Integer> ids) { |
| | | public AjaxResult<Boolean> deleteByIds(@RequestParam String ids) { |
| | | String[] split = ids.split(","); |
| | | // 刪除车道信息 |
| | | vehicleRampService.remove(Wrappers.lambdaQuery(TVehicleRamp.class) |
| | | .in(TVehicleRamp::getParkingLotId, ids)); |
| | | .in(TVehicleRamp::getParkingLotId, Arrays.asList(split))); |
| | | // 删除车库信息 |
| | | carportService.remove(Wrappers.lambdaQuery(TCarport.class) |
| | | .in(TCarport::getParkingLotId, ids)); |
| | | return AjaxResult.ok(parkingLotService.removeByIds(ids)); |
| | | .in(TCarport::getParkingLotId, Arrays.asList(split))); |
| | | return AjaxResult.ok(parkingLotService.removeByIds(Arrays.asList(split))); |
| | | } |
| | | |
| | | /** |
| | |
| | | import com.ruoyi.chargingPile.api.model.TVehicleRamp; |
| | | import com.ruoyi.chargingPile.service.TVehicleRampService; |
| | | import com.ruoyi.common.core.web.domain.AjaxResult; |
| | | import com.ruoyi.common.core.web.domain.BaseDelete; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.log.enums.OperatorType; |
| | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @Log(title = "批量删除车道", businessType = BusinessType.DELETE,operatorType = OperatorType.MANAGE) |
| | | @ApiOperation(tags = {"后台-车道"},value = "批量删除车道") |
| | | @DeleteMapping(value = "/deleteByIds") |
| | | public AjaxResult<Boolean> deleteByIds(@RequestBody List<Integer> ids) { |
| | | return AjaxResult.ok(vehicleRampService.removeByIds(ids)); |
| | | public AjaxResult<Boolean> deleteByIds(@RequestParam String ids) { |
| | | String[] split = ids.split(","); |
| | | return AjaxResult.ok(vehicleRampService.removeByIds(Arrays.asList(split))); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return |
| | | */ |
| | | PageInfo<TChargingPileNotification> chargingPileNotificationPageList(Integer siteId, BasePage basePage); |
| | | |
| | | /** |
| | | * |
| | | * @param type 1=验证码 2=停车占位 3=充电结束 4=桩故障 |
| | | * @param phone 手机号 |
| | | * @param data 内容 |
| | | */ |
| | | void saveData(Integer type,Integer siteId,Integer chargingPileId, String phone, String data); |
| | | |
| | | } |
| | |
| | | */ |
| | | public interface TFaultMessageService extends IService<TFaultMessage> { |
| | | |
| | | /** |
| | | * 添加故障报修管理 |
| | | * @param dto |
| | | * @return |
| | | */ |
| | | void add(TFaultMessage dto); |
| | | } |
| | |
| | | pageInfo.setRecords(list); |
| | | return pageInfo; |
| | | } |
| | | |
| | | @Override |
| | | public void saveData(Integer type,Integer siteId,Integer chargingPileId, String phone, String data) { |
| | | TChargingPileNotification notification = new TChargingPileNotification(); |
| | | switch (type){ |
| | | case 1: |
| | | // 验证码 |
| | | notification.setPhone(phone); |
| | | notification.setContent(data); |
| | | break; |
| | | default: |
| | | // 停车占位 |
| | | notification.setSiteId(siteId); |
| | | notification.setChargingPileId(chargingPileId); |
| | | notification.setPhone(phone); |
| | | notification.setContent(data); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | package com.ruoyi.chargingPile.service.impl; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.chargingPile.api.model.Site; |
| | | import com.ruoyi.chargingPile.api.model.TChargingPile; |
| | | import com.ruoyi.chargingPile.api.model.TFaultMessage; |
| | | import com.ruoyi.chargingPile.mapper.TFaultMessageMapper; |
| | | import com.ruoyi.chargingPile.service.ISiteService; |
| | | import com.ruoyi.chargingPile.service.TChargingPileNotificationService; |
| | | import com.ruoyi.chargingPile.service.TChargingPileService; |
| | | import com.ruoyi.chargingPile.service.TFaultMessageService; |
| | | import com.ruoyi.common.core.utils.MsgUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | |
| | | * @author xiaochen |
| | | * @since 2024-08-08 |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | public class TFaultMessageServiceImpl extends ServiceImpl<TFaultMessageMapper, TFaultMessage> implements TFaultMessageService { |
| | | |
| | | @Autowired |
| | | private ISiteService siteService; |
| | | @Autowired |
| | | private TChargingPileService chargingPileService; |
| | | @Autowired |
| | | private TChargingPileNotificationService chargingPileNotificationService; |
| | | |
| | | @Override |
| | | public void add(TFaultMessage dto) { |
| | | // 故障短信提醒 |
| | | Site site = siteService.getById(dto.getSiteId()); |
| | | TChargingPile chargingPile = chargingPileService.getById(dto.getChargingPileId()); |
| | | String siteName = site.getName(); |
| | | String result = MsgUtil.faultMsg(site.getPhone(), site.getName(), chargingPile.getNumber() + ""); |
| | | log.info("故障短信提醒:{}",result); |
| | | if(siteName.length()>10){ |
| | | siteName = siteName.substring(0,10); |
| | | } |
| | | chargingPileNotificationService.saveData(4,dto.getSiteId(),dto.getChargingPileId(),site.getPhone(),"检测到"+siteName+"..."+chargingPile.getNumber()+"号桩设备离线,请及时查看处理!"); |
| | | this.save(dto); |
| | | } |
| | | } |
| | |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.HashSet; |
| | |
| | | Integer objectId = sysUser.getObjectId(); |
| | | // 查询管理站点下的停车场 |
| | | List<TParkingLotVO> parkingLotVOS = parkingLotService.getList(null); |
| | | if(CollectionUtils.isEmpty(parkingLotVOS)){ |
| | | return new PageInfo<>(); |
| | | } |
| | | List<Integer> parkingLotIds = parkingLotVOS.stream().map(TParkingLotVO::getId).collect(Collectors.toList()); |
| | | |
| | | PageInfo<TMonitoringEquipmentVO> pageInfo = new PageInfo<>(query.getPageCurr(),query.getPageSize()); |
| | | List<TMonitoringEquipmentVO> list = this.baseMapper.pageList(query,pageInfo,parkingLotIds); |
| | | for (TMonitoringEquipmentVO monitoringEquipmentVO : list) { |
| | | TParkingLotVO tParkingLotVO = parkingLotVOS.stream().filter(park -> park.getId().equals(monitoringEquipmentVO.getParkingLotId())).findFirst().get(); |
| | | TParkingLotVO tParkingLotVO = parkingLotVOS.stream().filter(park -> monitoringEquipmentVO.getParkingLotId().equals(park.getId())).findFirst().get(); |
| | | if(null != tParkingLotVO){ |
| | | Integer siteId = tParkingLotVO.getSiteId(); |
| | | monitoringEquipmentVO.setAuthQueryInfo(roleType == 1 ? true : partnerService.authMenu(objectId, siteId, SiteMenu.PARKING_LOT_MONITOR)); |
| | |
| | | import com.ruoyi.common.core.web.page.BasePage; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.order.api.model.TChargingOrder; |
| | | import com.ruoyi.order.api.model.TOrderEvaluate; |
| | | 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.dto.OrderEvaluateVo; |
| | | import com.ruoyi.order.service.TChargingOrderService; |
| | | import com.ruoyi.order.service.TOrderEvaluateService; |
| | | import com.ruoyi.order.service.TOrderEvaluateTagService; |
| | | import io.swagger.annotations.Api; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import io.swagger.annotations.ApiOperation; |
| | |
| | | private TChargingOrderService chargingOrderService; |
| | | @Autowired |
| | | private TokenService tokenService; |
| | | @Autowired |
| | | private TOrderEvaluateService orderEvaluateService; |
| | | @Autowired |
| | | private TOrderEvaluateTagService orderEvaluateTagService; |
| | | |
| | | @ResponseBody |
| | | @PostMapping(value = "/addEvaluate") |
| | | @ApiOperation(value = "添加评价", tags = {"小程序-扫一扫"}) |
| | | public AjaxResult getMyChargingOrderList(@RequestBody OrderEvaluateVo dto){ |
| | | dto.setAppUserId(tokenService.getLoginUserApplet().getUserId()); |
| | | orderEvaluateService.addOrderEvaluate(dto); |
| | | return AjaxResult.success(); |
| | | } |
| | | /** |
| | | * 查询用户最近一次充电记录使用的车辆 |
| | | * @param |
| | |
| | | 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); |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | 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(); |
| | | } |
| | | } |
| | | |
| | |
| | | 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> |
| | |
| | | @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); |
| | | } |
| | | } |
| | | |
| | |
| | | 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> |
| | |
| | | @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); |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | 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; |
| | | } |
New file |
| | |
| | | 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; |
| | | } |
New file |
| | |
| | | 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; |
| | | } |
New file |
| | |
| | | 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; |
| | | } |
New file |
| | |
| | | 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; |
| | | } |
New file |
| | |
| | | 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; |
| | | } |
New file |
| | |
| | | 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; |
| | | } |
New file |
| | |
| | | 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; |
| | | } |
| | |
| | | |
| | | 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; |
| | |
| | | * @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); |
| | | } |
| | |
| | | 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); |
| | | } |
| | |
| | | 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; |
| | | |
| | | /** |
| | |
| | | * @return |
| | | */ |
| | | MyChargingOrderInfo getMyChargingOrderInfo(String id); |
| | | |
| | | |
| | | /** |
| | | * 获取待开票订单列表 |
| | | * @param query |
| | | * @return |
| | | */ |
| | | List<MyChargingOrderList> getNoInvoicedOrder(GetNoInvoicedOrder query); |
| | | } |
| | |
| | | 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> |
| | |
| | | * @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); |
| | | } |
| | |
| | | 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> |
| | |
| | | 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); |
| | | } |
| | |
| | | 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; |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | 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> |
| | |
| | | */ |
| | | @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; |
| | | } |
| | | } |
| | |
| | | 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; |
| | | |
| | | /** |
| | |
| | | */ |
| | | @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) { |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | 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> |
| | |
| | | <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" /> |
| | |
| | | <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> |
| | |
| | | </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> |
| | |
| | | } |
| | | |
| | | @ApiOperation(tags = {"小程序-广告管理"},value = "广告列表查询") |
| | | @PostMapping(value = "/list") |
| | | @GetMapping(value = "/list") |
| | | public AjaxResult<List<TAdvertising>> list() { |
| | | return AjaxResult.ok(advertisingService.list(Wrappers.lambdaQuery(TAdvertising.class) |
| | | .eq(TAdvertising::getStatus, AdvertisingStatusEnum.YES.getCode()))); |
| | |
| | | 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; |
| | |
| | | } |
| | | 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); |
| | | } |
| | | } |
| | | |