diff --git a/pom.xml b/pom.xml index c2498f5..e2b107c 100644 --- a/pom.xml +++ b/pom.xml @@ -58,6 +58,11 @@ true + + org.springframework.boot + spring-boot-starter-validation + + org.projectlombok diff --git a/src/main/java/com/gxwebsoft/apps/task/OrderTask.java b/src/main/java/com/gxwebsoft/apps/task/OrderTask.java index 68735f9..abf3690 100644 --- a/src/main/java/com/gxwebsoft/apps/task/OrderTask.java +++ b/src/main/java/com/gxwebsoft/apps/task/OrderTask.java @@ -1,6 +1,7 @@ package com.gxwebsoft.apps.task; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUnit; @@ -12,9 +13,11 @@ import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.request.AlipayTradeOrderinfoSyncRequest; import com.alipay.api.response.AlipayTradeOrderinfoSyncResponse; +import com.aliyuncs.exceptions.ClientException; import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import com.baomidou.mybatisplus.annotation.SqlParser; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.BeanUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; @@ -26,8 +29,12 @@ import com.gxwebsoft.apps.service.EquipmentGoodsService; import com.gxwebsoft.apps.service.EquipmentOrderGoodsService; import com.gxwebsoft.apps.service.EquipmentService; import com.gxwebsoft.common.core.config.MybatisPlusConfig; +import com.gxwebsoft.common.core.enums.ESmsType; import com.gxwebsoft.common.core.utils.AlipayConfigUtil; +import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.common.system.param.SmsCaptchaParam; +import com.gxwebsoft.common.system.service.AliSmsService; import com.gxwebsoft.common.system.service.UserService; import com.gxwebsoft.love.entity.UserPlanLog; import com.gxwebsoft.love.param.UserPlanLogParam; @@ -44,6 +51,7 @@ import org.springframework.util.NumberUtils; import javax.annotation.Resource; import java.math.BigDecimal; import java.text.SimpleDateFormat; +import java.time.LocalDate; import java.util.*; import java.util.stream.Collectors; @@ -85,6 +93,9 @@ public class OrderTask { private FreezeOrderService freezeOrderService; @Resource private OrderPayService orderPayService; + @Resource + private AliSmsService aliSmsService; + /** * 计算逾期 @@ -420,4 +431,52 @@ public class OrderTask { orderPayService.update(updateWrapper); } + + /** + * 逾期预警 + */ + @Scheduled(cron = "0 30 9 * * ? ") + public void exceedAlert() { + List alertList = orderService.findAlertList(); + if(CollectionUtil.isNotEmpty(alertList)){ + log.info("开始发送订单到期预警通知!"); + int succ = 0; + for(Order order : alertList){ + SmsCaptchaParam aram = SmsCaptchaParam.builder() + .phone(order.getPhone()) + .type(ESmsType.ALERT.name()) + .templateParam("{\"code\":" + Math.abs(order.getExpirationDay()) + "}") + .build(); + try{ + ApiResult ret = aliSmsService.sendSms(aram); + if(ret.isOk()) + succ++; + } catch (ClientException e){ + log.error(e.getMessage(), e); + } + } + log.info("发送订单到期预警通知结束!总数{}条,成功{}条!", alertList.size(), succ); + } + + List overdueList = orderService.findAlertList(); + if(CollectionUtil.isNotEmpty(overdueList)) { + log.info("开始发送订单超期提醒通知!"); + int succ = 0; + for(Order order : alertList){ + SmsCaptchaParam aram = SmsCaptchaParam.builder() + .phone(order.getPhone()) + .type(ESmsType.OVERDUE.name()) + .templateParam("{\"code\":" + order.getExpirationDay() + "}") + .build(); + try{ + ApiResult ret = aliSmsService.sendSms(aram); + if(ret.isOk()) + succ++; + } catch (ClientException e){ + log.error(e.getMessage(), e); + } + } + log.info("发送逾期提醒通知结束!总数{}条,成功{}条!", alertList.size(), succ); + } + } } diff --git a/src/main/java/com/gxwebsoft/common/core/config/ConfigProperties.java b/src/main/java/com/gxwebsoft/common/core/config/ConfigProperties.java index dfee5d3..9b4c68d 100644 --- a/src/main/java/com/gxwebsoft/common/core/config/ConfigProperties.java +++ b/src/main/java/com/gxwebsoft/common/core/config/ConfigProperties.java @@ -1,5 +1,6 @@ package com.gxwebsoft.common.core.config; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -102,4 +103,6 @@ public class ConfigProperties { private String bucketName; private String bucketDomain; + @ApiModelProperty("项目默认租户") + private Integer tenantId; } diff --git a/src/main/java/com/gxwebsoft/common/core/constants/OrderConstants.java b/src/main/java/com/gxwebsoft/common/core/constants/OrderConstants.java index 9ddac40..7f149f8 100644 --- a/src/main/java/com/gxwebsoft/common/core/constants/OrderConstants.java +++ b/src/main/java/com/gxwebsoft/common/core/constants/OrderConstants.java @@ -8,8 +8,8 @@ public class OrderConstants { public static final String PAY_METHOD_OTHER = "40"; // 其他支付 // 付款状态 - public static final Integer PAY_STATUS_NO_PAY = 10; // 未付款 - public static final Integer PAY_STATUS_SUCCESS = 20; // 已付款 + public static final int PAY_STATUS_NO_PAY = 10; // 未付款 + public static final int PAY_STATUS_SUCCESS = 20; // 已付款 // 发货状态 public static final Integer DELIVERY_STATUS_NO = 10; // 未发货 diff --git a/src/main/java/com/gxwebsoft/common/core/enums/ESmsType.java b/src/main/java/com/gxwebsoft/common/core/enums/ESmsType.java new file mode 100644 index 0000000..a5fb09e --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/core/enums/ESmsType.java @@ -0,0 +1,18 @@ +package com.gxwebsoft.common.core.enums; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum ESmsType { + LOGIN("SMS_290002047"), + RECEIPT("SMS_290002047"), + ALERT("SMS_464505085"), + OVERDUE("SMS_464525076"); + + @ApiModelProperty("短信模版编号") + private String templateId; + +} diff --git a/src/main/java/com/gxwebsoft/common/core/exception/GlobalExceptionHandler.java b/src/main/java/com/gxwebsoft/common/core/exception/GlobalExceptionHandler.java index 6649a2d..1031957 100644 --- a/src/main/java/com/gxwebsoft/common/core/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/gxwebsoft/common/core/exception/GlobalExceptionHandler.java @@ -3,15 +3,23 @@ package com.gxwebsoft.common.core.exception; import com.gxwebsoft.common.core.Constants; import com.gxwebsoft.common.core.utils.CommonUtil; import com.gxwebsoft.common.core.web.ApiResult; +import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.access.AccessDeniedException; +import org.springframework.validation.ObjectError; import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; /** * 全局异常处理器 @@ -19,11 +27,10 @@ import javax.servlet.http.HttpServletResponse; * @author WebSoft * @since 2018-02-22 11:29:30 */ -@ControllerAdvice +@RestControllerAdvice +@Slf4j public class GlobalExceptionHandler { - private final Logger logger = LoggerFactory.getLogger(getClass()); - @ResponseBody @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public ApiResult methodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException e, HttpServletResponse response) { @@ -31,26 +38,33 @@ public class GlobalExceptionHandler { return new ApiResult<>(Constants.RESULT_ERROR_CODE, "请求方式不正确").setError(e.toString()); } - @ResponseBody @ExceptionHandler(AccessDeniedException.class) public ApiResult accessDeniedExceptionHandler(AccessDeniedException e, HttpServletResponse response) { CommonUtil.addCrossHeaders(response); return new ApiResult<>(Constants.UNAUTHORIZED_CODE, Constants.UNAUTHORIZED_MSG).setError(e.toString()); } - @ResponseBody @ExceptionHandler(BusinessException.class) public ApiResult businessExceptionHandler(BusinessException e, HttpServletResponse response) { CommonUtil.addCrossHeaders(response); return new ApiResult<>(e.getCode(), e.getMessage()); } - @ResponseBody @ExceptionHandler(Throwable.class) public ApiResult exceptionHandler(Throwable e, HttpServletResponse response) { - logger.error(e.getMessage(), e); + log.error(e.getMessage(), e); CommonUtil.addCrossHeaders(response); return new ApiResult<>(Constants.RESULT_ERROR_CODE, Constants.RESULT_ERROR_MSG).setError(e.toString()); } + @ExceptionHandler(value = MethodArgumentNotValidException.class) + @ResponseBody + public ApiResult MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) + { + //获取实体类定义的校验注解字段上的message作为异常信息,@NotBlank(message = "用户密码不能为空!")异常信息即为"用户密码不能为空!" + List allErrors = e.getBindingResult().getAllErrors(); + String message = allErrors.stream().map(s -> s.getDefaultMessage()).collect(Collectors.joining(";")); + List msgList = Arrays.asList(message.split(";")); + return new ApiResult<>(Constants.RESULT_ERROR_CODE, msgList.get(0)); + } } diff --git a/src/main/java/com/gxwebsoft/common/core/utils/AlipayConfigUtil.java b/src/main/java/com/gxwebsoft/common/core/utils/AlipayConfigUtil.java index 9b92078..cbb44ed 100644 --- a/src/main/java/com/gxwebsoft/common/core/utils/AlipayConfigUtil.java +++ b/src/main/java/com/gxwebsoft/common/core/utils/AlipayConfigUtil.java @@ -10,6 +10,7 @@ import com.gxwebsoft.common.core.config.ConfigProperties; import com.gxwebsoft.common.core.exception.BusinessException; import com.gxwebsoft.common.system.entity.Setting; import com.gxwebsoft.common.system.service.SettingService; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; @@ -20,6 +21,7 @@ import javax.annotation.Resource; * @author leng * */ +@Slf4j @Component public class AlipayConfigUtil { private final StringRedisTemplate stringRedisTemplate; @@ -34,6 +36,7 @@ public class AlipayConfigUtil { @Resource private ConfigProperties pathConfig; + @Resource private SettingService settingService; public AlipayConfigUtil(StringRedisTemplate stringRedisTemplate){ @@ -69,9 +72,8 @@ public class AlipayConfigUtil { * 获取支付宝秘钥 */ public JSONObject payment(Integer tenantId) { - System.out.println("tenantId = " + tenantId); String key = "setting:payment:" + tenantId; - System.out.println("key = " + key); + log.info("tenantId:{}, redis key:{}",tenantId, key); String cache = stringRedisTemplate.opsForValue().get(key); if (cache == null) { Setting payment = settingService.getData("payment"); diff --git a/src/main/java/com/gxwebsoft/common/core/web/ApiResult.java b/src/main/java/com/gxwebsoft/common/core/web/ApiResult.java index eab091a..52f96ad 100644 --- a/src/main/java/com/gxwebsoft/common/core/web/ApiResult.java +++ b/src/main/java/com/gxwebsoft/common/core/web/ApiResult.java @@ -1,6 +1,7 @@ package com.gxwebsoft.common.core.web; import com.fasterxml.jackson.annotation.JsonInclude; +import com.gxwebsoft.common.core.Constants; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; @@ -37,6 +38,10 @@ public class ApiResult implements Serializable { this(code, message, null); } + public ApiResult(String message) { + this(Constants.RESULT_OK_CODE, message, null); + } + public ApiResult(Integer code, String message, T data) { this(code, message, data, null); } @@ -84,4 +89,7 @@ public class ApiResult implements Serializable { return this; } + public boolean isOk(){ + return this.code == Constants.RESULT_OK_CODE; + } } diff --git a/src/main/java/com/gxwebsoft/common/system/controller/AccessKeyController.java b/src/main/java/com/gxwebsoft/common/system/controller/AccessKeyController.java index d80c9b9..bf6df69 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/AccessKeyController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/AccessKeyController.java @@ -2,6 +2,7 @@ package com.gxwebsoft.common.system.controller; import cn.hutool.core.util.StrUtil; import com.gxwebsoft.common.core.annotation.OperationLog; +import com.gxwebsoft.common.core.enums.ESmsType; import com.gxwebsoft.common.core.utils.CacheClient; import com.gxwebsoft.common.core.utils.CommonUtil; import com.gxwebsoft.common.core.web.*; @@ -40,7 +41,7 @@ public class AccessKeyController extends BaseController { final PageResult accessKeyPageResult = accessKeyService.pageRel(param); if (param.getCode() != null) { // 短信验证码校验 - String code = cacheClient.get(param.getPhone(), String.class); + String code = cacheClient.get(ESmsType.LOGIN.name() + ":" + param.getPhone(), String.class); if (StrUtil.equals(code,param.getCode())) { return success(accessKeyPageResult); } diff --git a/src/main/java/com/gxwebsoft/common/system/controller/MainController.java b/src/main/java/com/gxwebsoft/common/system/controller/MainController.java index 851dd1f..55e2872 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/MainController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/MainController.java @@ -7,13 +7,13 @@ import com.aliyuncs.CommonResponse; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.exceptions.ClientException; -import com.aliyuncs.exceptions.ServerException; import com.aliyuncs.http.MethodType; import com.aliyuncs.profile.DefaultProfile; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.google.gson.Gson; import com.gxwebsoft.common.core.annotation.OperationLog; import com.gxwebsoft.common.core.config.ConfigProperties; +import com.gxwebsoft.common.core.enums.ESmsType; import com.gxwebsoft.common.core.security.JwtSubject; import com.gxwebsoft.common.core.security.JwtUtil; import com.gxwebsoft.common.core.utils.CacheClient; @@ -31,18 +31,23 @@ import com.gxwebsoft.common.system.param.UpdatePasswordParam; import com.gxwebsoft.common.system.result.CaptchaResult; import com.gxwebsoft.common.system.result.LoginResult; import com.gxwebsoft.common.system.service.AccessKeyService; +import com.gxwebsoft.common.system.service.AliSmsService; import com.gxwebsoft.common.system.service.LoginRecordService; import com.gxwebsoft.common.system.service.RoleMenuService; import com.gxwebsoft.common.system.service.UserService; import com.wf.captcha.SpecCaptcha; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomStringUtils; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.HashMap; @@ -59,6 +64,7 @@ import java.util.concurrent.TimeUnit; @Api(tags = "登录认证") @RestController @RequestMapping("/api") +@Slf4j public class MainController extends BaseController { @Resource private ConfigProperties configProperties; @@ -71,9 +77,9 @@ public class MainController extends BaseController { @Resource private CacheClient cacheClient; @Resource - private StringRedisTemplate stringRedisTemplate; - @Resource private AccessKeyService accessKeyService; + @Resource + private AliSmsService aliSmsService; @ApiOperation("用户登录") @PostMapping("/login") @@ -205,41 +211,36 @@ public class MainController extends BaseController { @ApiOperation("短信验证码") @PostMapping("/sendSmsCaptcha") - public ApiResult sendSmsCaptcha(@RequestBody SmsCaptchaParam param) { - DefaultProfile profile = DefaultProfile.getProfile("regionld", "LTAI5tBWM9dSmEAoQFhNqxqJ", "Dr0BqiKl7eaL1NNKoCd12qKsbgjnum"); - IAcsClient client = new DefaultAcsClient(profile); - CommonRequest request = new CommonRequest(); - request.setSysMethod(MethodType.POST); - request.setSysDomain("dysmsapi.aliyuncs.com"); - request.setSysVersion("2017-05-25"); - request.setSysAction("SendSms"); - request.putQueryParameter("RegionId", "cn-hangzhou"); - request.putQueryParameter("PhoneNumbers", param.getPhone()); - request.putQueryParameter("SignName", "南宁网宿科技"); - request.putQueryParameter("TemplateCode", "SMS_257840118"); - // 生成短信验证码 - Random randObj = new Random(); - String code = Integer.toString(100000 + randObj.nextInt(900000)); - request.putQueryParameter("TemplateParam", "{\"code\":" + code + "}"); - try { - CommonResponse response = client.getCommonResponse(request); - String json = response.getData(); - Gson g = new Gson(); - HashMap result = g.fromJson(json, HashMap.class); - if("OK".equals(result.get("Message"))) { - cacheClient.set(param.getPhone(),code,5L,TimeUnit.MINUTES); - return success("发送成功",result.get("Message")); - }else{ - return fail("发送失败"); + public ApiResult sendSmsCaptcha(@RequestBody @Valid SmsCaptchaParam param) { + try { +// User user = getLoginUser(); +// param.setTenantId(user.getTenantId()); + + String code = RandomStringUtils.randomNumeric(6); + param.setTemplateParam("{\"code\":" + code + "}"); + ApiResult ret = aliSmsService.sendSms(param); + if(ret.isOk()){ + ESmsType type = ESmsType.valueOf(param.getType()); + cacheClient.set(type.name() + ":" + param.getPhone(), code,5L,TimeUnit.MINUTES); + } + return success(ret); + } catch (ClientException e) { + log.error(e.getMessage(), e); + return fail("发送出错!"); } - } catch (ServerException e) { - e.printStackTrace(); - } catch (ClientException e) { - e.printStackTrace(); - } - return fail("发送失败"); } +// @ApiOperation("预警短信") +// @PostMapping("/sendSmsAlert") +// public ApiResult sendSmsAlert(@RequestBody SmsCaptchaParam param) { +// try { +// return aliSmsService.sendSms(param); +// } catch (ClientException e) { +// log.error(e.getMessage(), e); +// return fail("发送出错!"); +// } +// } + @OperationLog @ApiOperation("重置密码") @PutMapping("/password") @@ -251,7 +252,7 @@ public class MainController extends BaseController { return fail("验证码不能为空"); } // 短信验证码校验 - String code = cacheClient.get(user.getPhone(), String.class); + String code = cacheClient.get(ESmsType.LOGIN.name() + ":" + user.getPhone(), String.class); if (!StrUtil.equals(code,user.getCode())) { return fail("验证码不正确"); } diff --git a/src/main/java/com/gxwebsoft/common/system/param/SmsCaptchaParam.java b/src/main/java/com/gxwebsoft/common/system/param/SmsCaptchaParam.java index 765b9eb..eaae8ad 100644 --- a/src/main/java/com/gxwebsoft/common/system/param/SmsCaptchaParam.java +++ b/src/main/java/com/gxwebsoft/common/system/param/SmsCaptchaParam.java @@ -1,10 +1,17 @@ package com.gxwebsoft.common.system.param; import com.fasterxml.jackson.annotation.JsonInclude; +import com.gxwebsoft.common.core.enums.ESmsType; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.validation.annotation.Validated; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; import java.io.Serializable; /** @@ -14,18 +21,29 @@ import java.io.Serializable; * @since 2021-08-30 17:35:16 */ @Data -@JsonInclude(JsonInclude.Include.NON_NULL) +//@JsonInclude(JsonInclude.Include.NON_NULL) @ApiModel(description = "发送短信验证码参数") +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Validated public class SmsCaptchaParam implements Serializable { private static final long serialVersionUID = 1L; - @ApiModelProperty("短信签名") - private String signName; +// @ApiModelProperty("短信签名") +// private String signName; - @ApiModelProperty("手机号码") + @ApiModelProperty(value = "手机号码", required = true) + @NotBlank(message = "手机号码不能为空!") + @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误") private String phone; - @ApiModelProperty("短信模板") - private String TemplateParam; + @ApiModelProperty("短信模板参数") + private String templateParam; + @ApiModelProperty("验证码类型") + private String type = ESmsType.LOGIN.name(); + + @ApiModelProperty(value = "租户id", hidden = true) + private Integer tenantId; } diff --git a/src/main/java/com/gxwebsoft/common/system/service/AliSmsService.java b/src/main/java/com/gxwebsoft/common/system/service/AliSmsService.java new file mode 100644 index 0000000..5b842b1 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/service/AliSmsService.java @@ -0,0 +1,23 @@ +package com.gxwebsoft.common.system.service; + + +import com.aliyuncs.exceptions.ClientException; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.system.param.SmsCaptchaParam; + +/** + * 阿里短信服务层 + * + * @author WebSoft + * @since 2018-12-24 16:10:41 + */ +public interface AliSmsService { + + /** + * 发送阿里短信 + * @param param + * @return + */ + ApiResult sendSms(SmsCaptchaParam param) throws ClientException; + +} diff --git a/src/main/java/com/gxwebsoft/common/system/service/SettingService.java b/src/main/java/com/gxwebsoft/common/system/service/SettingService.java index 9432620..ff8a590 100644 --- a/src/main/java/com/gxwebsoft/common/system/service/SettingService.java +++ b/src/main/java/com/gxwebsoft/common/system/service/SettingService.java @@ -50,6 +50,8 @@ public interface SettingService extends IService { Setting getData(String settingKey); + String getContent(String settingKey, Integer tenantId); + JSONObject getCache(String key); void initConfig(Setting setting); diff --git a/src/main/java/com/gxwebsoft/common/system/service/impl/AliSmsServiceImpl.java b/src/main/java/com/gxwebsoft/common/system/service/impl/AliSmsServiceImpl.java new file mode 100644 index 0000000..ce30152 --- /dev/null +++ b/src/main/java/com/gxwebsoft/common/system/service/impl/AliSmsServiceImpl.java @@ -0,0 +1,72 @@ +package com.gxwebsoft.common.system.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.aliyuncs.CommonRequest; +import com.aliyuncs.CommonResponse; +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.http.MethodType; +import com.aliyuncs.profile.DefaultProfile; +import com.google.gson.Gson; +import com.gxwebsoft.common.core.Constants; +import com.gxwebsoft.common.core.config.ConfigProperties; +import com.gxwebsoft.common.core.enums.ESmsType; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.system.param.SmsCaptchaParam; +import com.gxwebsoft.common.system.service.AliSmsService; +import com.gxwebsoft.common.system.service.SettingService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.HashMap; + +@Service +@Slf4j +@RequiredArgsConstructor +public class AliSmsServiceImpl implements AliSmsService { + private final SettingService settingService; + private final ConfigProperties configProperties; + @Override + public ApiResult sendSms(SmsCaptchaParam param) throws ClientException { + Integer tenantId = param.getTenantId(); + if(null == tenantId){ + tenantId = configProperties.getTenantId(); + } + String smsConfig = settingService.getContent("sms", tenantId); + if(StrUtil.isBlank(smsConfig)){ + return new ApiResult(Constants.RESULT_ERROR_CODE, "短信参数未配置!"); + } + JSONObject smsConfigJson = JSON.parseObject(smsConfig); + + DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", smsConfigJson.getString("accessKeyId"), smsConfigJson.getString("accessKeySecret")); + IAcsClient client = new DefaultAcsClient(profile); + String signName = smsConfigJson.getString("sign"); + + ESmsType type = ESmsType.valueOf(param.getType()); + CommonRequest request = new CommonRequest(); + request.setSysMethod(MethodType.POST); + request.setSysDomain("dysmsapi.aliyuncs.com"); + request.setSysVersion("2017-05-25"); + request.setSysAction("SendSms"); + request.putQueryParameter("RegionId", "cn-hangzhou"); + String phone = param.getPhone(); + request.putQueryParameter("PhoneNumbers", phone); + request.putQueryParameter("SignName", signName); + request.putQueryParameter("TemplateCode", type.getTemplateId()); + request.putQueryParameter("TemplateParam", param.getTemplateParam()); + + CommonResponse response = client.getCommonResponse(request); + String json = response.getData(); + Gson g = new Gson(); + HashMap result = g.fromJson(json, HashMap.class); + if("OK".equals(result.get("Message"))) { + return new ApiResult("发送成功"); + } + log.warn("阿里云短信发送失败!{}", json); + return new ApiResult(Constants.RESULT_ERROR_CODE, "发送失败"); + } +} diff --git a/src/main/java/com/gxwebsoft/common/system/service/impl/SettingServiceImpl.java b/src/main/java/com/gxwebsoft/common/system/service/impl/SettingServiceImpl.java index 702c265..464d83f 100644 --- a/src/main/java/com/gxwebsoft/common/system/service/impl/SettingServiceImpl.java +++ b/src/main/java/com/gxwebsoft/common/system/service/impl/SettingServiceImpl.java @@ -1,5 +1,6 @@ package com.gxwebsoft.common.system.service.impl; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -99,6 +100,32 @@ public class SettingServiceImpl extends ServiceImpl impl return query().eq("setting_key", settingKey).one(); } + @Override + public String getContent(String settingKey, Integer tenantId) { + String redisKey = settingKey + ":"; + if(null != tenantId){ + redisKey += tenantId; + } else { + redisKey += -1; + } + if(stringRedisTemplate.hasKey(redisKey)){ + return stringRedisTemplate.opsForValue().get(redisKey); + } + + Setting setting = query().eq("setting_key", settingKey) + .eq(null != tenantId, "tenant_id", tenantId) + .eq("deleted", 0) + .orderByDesc("setting_id") + .last("limit 1") + .one(); + if(null == setting){ + return ""; + } + String ret = setting.getContent(); + stringRedisTemplate.opsForValue().set(redisKey, ret); + return ret; + } + @Override public JSONObject getCache(String key) { final String cache = stringRedisTemplate.opsForValue().get(key); diff --git a/src/main/java/com/gxwebsoft/open/controller/OpenEquipmentController.java b/src/main/java/com/gxwebsoft/open/controller/OpenEquipmentController.java index cd263de..c3ea0e9 100644 --- a/src/main/java/com/gxwebsoft/open/controller/OpenEquipmentController.java +++ b/src/main/java/com/gxwebsoft/open/controller/OpenEquipmentController.java @@ -1,6 +1,9 @@ package com.gxwebsoft.open.controller; +import cn.hutool.core.bean.copier.BeanCopier; +import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; import com.alipay.api.DefaultAlipayClient; @@ -14,7 +17,9 @@ import com.gxwebsoft.apps.param.EquipmentParam; import com.gxwebsoft.apps.service.EquipmentRecordService; import com.gxwebsoft.apps.service.EquipmentService; import com.gxwebsoft.common.core.annotation.OperationLog; +import com.gxwebsoft.common.core.enums.ESmsType; import com.gxwebsoft.common.core.utils.AlipayConfigUtil; +import com.gxwebsoft.common.core.utils.CacheClient; import com.gxwebsoft.common.core.utils.ImageUtil; import com.gxwebsoft.common.core.web.*; import com.gxwebsoft.common.system.entity.User; @@ -24,6 +29,7 @@ import com.gxwebsoft.shop.entity.Order; import com.gxwebsoft.shop.entity.OrderPay; import com.gxwebsoft.shop.entity.OrderRefund; import com.gxwebsoft.shop.param.OrderParam; +import com.gxwebsoft.shop.param.OrderReceiptParam; import com.gxwebsoft.shop.service.OrderPayService; import com.gxwebsoft.shop.service.OrderRefundService; import com.gxwebsoft.shop.service.OrderService; @@ -34,6 +40,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; @@ -76,6 +83,9 @@ public class OpenEquipmentController extends BaseController { @Resource private RestTemplate restTemplate; + @Resource + private CacheClient cacheClient; + @PreAuthorize("hasAuthority('apps:equipment:list')") @OperationLog @ApiOperation("分页查询设备管理") @@ -373,10 +383,53 @@ public class OpenEquipmentController extends BaseController { return fail("换电失败"); } - @ApiOperation("重置") + @ApiOperation("确认收货") + @PostMapping("/receipt") + public ApiResult receipt(@RequestBody @Validated OrderReceiptParam receiptParam) { + // 验证签名 + isCheckSign(); + + Order order = orderService.getById(receiptParam.getOrderId()); + Integer receiptStatus = order.getReceiptStatus(); + if(receiptStatus == 20){ + return fail("订单已确认收货,不能重复确认!"); + } + // 验证身份证真实性 + if(StringUtils.hasText(receiptParam.getOrderSourceData())) { + String orderSourceDataString = receiptParam.getOrderSourceData(); + List images = JSONObject.parseArray(orderSourceDataString, String.class); + String front = ImageUtil.ImageBase64(images.get(0) + "?x-oss-process=image/resize,w_750/quality,Q_80"); + + String back = ImageUtil.ImageBase64(images.get(1) + "?x-oss-process=image/resize,w_750/quality,Q_80"); + + IdcardRespVO verify = idcardService.verify(front, back); + if(!"FP00000".equals(verify.getCode())) { + return fail("请上传身份证正面照片"); + } + if(verify.getIssueDate() == null || verify.getIssueOrg() == null || verify.getExpireDate() == null) { + return fail("请上传身份证反面照片"); + } + } + + // 短信验证码校验 + String receiptPhone = receiptParam.getCaptcha(); + String captcha = receiptParam.getCaptcha(); + String code = cacheClient.get(ESmsType.RECEIPT.name() + ":" + receiptPhone, String.class); + if (!StrUtil.equals(code, captcha)) { + return fail("验证码不正确"); + } + + BeanCopier.create(receiptParam, order, CopyOptions.create().ignoreNullValue()).copy(); + order.setReceiptStatus(20); + orderService.updateById(order); + return success("确认收货成功"); + } + + /*@ApiOperation("确认收货") @PostMapping("/receipt") public ApiResult receipt(@RequestBody Order order) { - + // 验证签名 + isCheckSign(); // 验证身份证真实性 if(StringUtils.hasText(order.getOrderSourceData())) { String orderSourceDataString = order.getOrderSourceData(); @@ -392,16 +445,11 @@ public class OpenEquipmentController extends BaseController { if(verify.getIssueDate() == null || verify.getIssueOrg() == null || verify.getExpireDate() == null) { return fail("请上传身份证反面照片"); } - } - - - // 验证签名 - isCheckSign(); orderService.updateById(order); - return success("重置成功"); - } + return success("确认收货成功"); + }*/ @ApiModelProperty("退租") @PostMapping("/rentingOut") diff --git a/src/main/java/com/gxwebsoft/open/controller/OpenMainController.java b/src/main/java/com/gxwebsoft/open/controller/OpenMainController.java index cfae984..deb112f 100644 --- a/src/main/java/com/gxwebsoft/open/controller/OpenMainController.java +++ b/src/main/java/com/gxwebsoft/open/controller/OpenMainController.java @@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.google.gson.Gson; import com.gxwebsoft.common.core.annotation.OperationLog; import com.gxwebsoft.common.core.config.ConfigProperties; +import com.gxwebsoft.common.core.enums.ESmsType; import com.gxwebsoft.common.core.exception.BusinessException; import com.gxwebsoft.common.core.security.JwtSubject; import com.gxwebsoft.common.core.security.JwtUtil; @@ -146,7 +147,7 @@ public class OpenMainController extends BaseController { String email = user.getEmail(); // 邮箱 // 短信验证 - if (!StrUtil.equals(code,cacheClient.get(phone,String.class)) && !StrUtil.equals(code,"170083")) { + if (!StrUtil.equals(code,cacheClient.get(ESmsType.LOGIN.name() + ":" + phone,String.class)) && !StrUtil.equals(code,"170083")) { throw new BusinessException("验证码不正确"); } user.setUsername(username); diff --git a/src/main/java/com/gxwebsoft/shop/controller/PaymentController.java b/src/main/java/com/gxwebsoft/shop/controller/PaymentController.java index 2cac759..bc85305 100644 --- a/src/main/java/com/gxwebsoft/shop/controller/PaymentController.java +++ b/src/main/java/com/gxwebsoft/shop/controller/PaymentController.java @@ -3,6 +3,9 @@ package com.gxwebsoft.shop.controller; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayConstants; @@ -15,7 +18,6 @@ import com.alipay.api.response.AlipayTradeCreateResponse; import com.alipay.api.response.AlipayTradeQueryResponse; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.gxwebsoft.apps.entity.BcTemporary; -import com.gxwebsoft.apps.entity.EquipmentGoods; import com.gxwebsoft.apps.param.BcTemporaryParam; import com.gxwebsoft.apps.service.BcTemporaryService; import com.gxwebsoft.apps.service.EquipmentGoodsService; @@ -33,6 +35,7 @@ import com.gxwebsoft.shop.service.*; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; import org.springframework.core.env.Environment; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.transaction.annotation.Transactional; @@ -42,6 +45,7 @@ import javax.annotation.Resource; import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Map; @@ -55,6 +59,7 @@ import static com.gxwebsoft.common.core.constants.OrderConstants.*; * @author 科技小王子 * @since 2022-12-15 19:11:07 */ +@Slf4j @Api(tags = "商城支付方式记录表管理") @RestController @RequestMapping("/api/shop/payment") @@ -256,7 +261,6 @@ public class PaymentController extends BaseController { // 订单数据 OrderPay order = orderPayService.getById(id); - Merchant merchant = merchantService.getMerchantByCode(order.getMerchantCode()); // final EquipmentGoods eg = equipmentGoodsService.getById(order.getGoodsId()); @@ -265,13 +269,13 @@ public class PaymentController extends BaseController { try { AlipayTradeCreateRequest request = new AlipayTradeCreateRequest(); // 配置公共请求参数 - request.setNotifyUrl(pathConfig.getServerUrl() + "/shop/payment/mp-alipay/notify"); + request.setNotifyUrl(pathConfig.getServerUrl() + "/shop/payment/mp-alipay/notify"); // request.setNotifyUrl("http://1.14.132.108:10090/api/shop/payment/mp-alipay/notify"); request.setReturnUrl(null); // 配置业务参数 JSONObject bizContent = new JSONObject(); - System.out.println("bizContent = " + order); - bizContent.put("out_trade_no", order.getOrderNo()); + String orderNo = order.getOrderNo(); + bizContent.put("out_trade_no", orderNo); bizContent.put("total_amount", order.getPayPrice()); bizContent.put("subject", merchant.getMerchantName()); // 拿不到手机号码?? @@ -279,11 +283,32 @@ public class PaymentController extends BaseController { request.setBizContent(bizContent.toString()); //SDK 已经封装掉了公共参数,这里只需要传入业务参数。 AlipayTradeCreateResponse response = alipayClient.certificateExecute(request); - System.out.println("response = " + response); +// log.info("支付宝支付返回信息:{}", response); + if(!response.isSuccess()){ + String subCode = response.getSubCode(); + if("ACQ.TRADE_HAS_CLOSE".equals(subCode)){ + String orderNoNew = IdUtil.getSnowflakeNextIdStr(); + log.warn("原支付宝支付订单{}已关闭!重新生成支付订单号{}!", orderNo, orderNoNew); + order.setOrderNo(orderNoNew); + orderPayService.updateById(order); + + bizContent.put("out_trade_no", orderNoNew); + request.setBizContent(bizContent.toString()); + response = alipayClient.certificateExecute(request); + if(response.isSuccess()){ + String trade_no = response.getTradeNo();// 获取返回的tradeNO。 + return success("支付成功", trade_no); + } + } + + log.error("发起支付宝支付失败!{}", JSON.toJSONString(response)); + return fail("发起支付宝支付失败!"); + } + String trade_no = response.getTradeNo();// 获取返回的tradeNO。 return success("支付成功", trade_no); } catch (AlipayApiException e) { - e.printStackTrace(); + log.error(e.getErrMsg(), e); throw new RuntimeException(); } } @@ -292,20 +317,24 @@ public class PaymentController extends BaseController { @OperationLog @PostMapping("/mp-alipay/notify") public String alipayNotify(@RequestParam Map params) throws AlipayApiException, ParseException { - System.out.println("异步处理>>>>"); - System.out.println("params = " + params); + log.info("异步处理支付宝通知消息>>>>param:{}", params); String outTradeNo = params.get("out_trade_no"); +// OrderPay order = orderPayService.selectByOutTransNo(outTradeNo); OrderPay order = orderPayService.lambdaQuery().eq(OrderPay::getOrderNo, outTradeNo).one(); if (order == null) { - throw new BusinessException("订单不存在"); + throw new BusinessException("订单不存在,第三方返回单号:" + outTradeNo); + } + + Integer payStatus = order.getPayStatus(); + if(payStatus >= PAY_STATUS_SUCCESS){ + throw new BusinessException("订单已支付成功"); } final JSONObject config = alipayConfig.payment(order.getTenantId()); // 生成环境证书路径 String alipayCertPublicKey = pathConfig.getUploadPath() + "file" + config.getString("alipayCertPublicKey"); // TODO 验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,校验成功后在response中返回success并继续商户自身业务处理,校验失败返回failure boolean flag = AlipaySignature.rsaCertCheckV1(params, alipayCertPublicKey, AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2); - System.out.println("flag>>>>>>>>>>>>>>>>>>>>>>>"); - System.out.println(flag); + log.info("flag>>>>>>>>>>>>>>>>>>>>>>>{}", flag); // 处理订单业务 if (flag) { final String tradeStatus = params.get("trade_status"); @@ -337,6 +366,7 @@ public class PaymentController extends BaseController { order.setPayTime(DateUtil.date()); order.setTradeId(trade_no); order.setSubject(subject); + order.setOrderNo(outTradeNo); Order parentOrder = orderService.getById(order.getRentOrderId()); parentOrder.setCurrPeriods(parentOrder.getCurrPeriods() + 1); @@ -380,6 +410,7 @@ public class PaymentController extends BaseController { isCheckSign(); // 订单数据 OrderPay order = orderPayService.getByIdRel(id); + // 当前登录用户id User user = new User(); // 代付款情况 @@ -530,6 +561,10 @@ public class PaymentController extends BaseController { isCheckSign(); // 订单数据 Order order = orderService.getByIdRel(id); + if(null == order){ + return fail("订单不存在"); + } + // 实例化客户端 DefaultAlipayClient alipayClient = alipayConfig.alipayClient(order.getTenantId()); AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); @@ -538,12 +573,9 @@ public class PaymentController extends BaseController { request.setBizContent(bizContent.toString()); AlipayTradeQueryResponse response = alipayClient.certificateExecute(request); if (response.isSuccess()) { - System.out.println("调用成功"); - orderService.paySuccess(response); - } else { - System.out.println("调用失败"); + return orderService.paySuccess(response); } - return success("调用成功", response); + return fail("支付宝返回失败!", response); } @ApiModelProperty("测试") @@ -585,4 +617,11 @@ public class PaymentController extends BaseController { // orderService.paySuccess(params); return "success"; } + +// @ApiModelProperty("测试JSON字段匹配") +// @GetMapping("/mp-alipay/testJson") +// public ApiResult testJson(String outTransNo) { +// OrderPay orderPay = orderPayService.selectByOutTransNo(outTransNo); +// return success(orderPay); +// } } diff --git a/src/main/java/com/gxwebsoft/shop/entity/Order.java b/src/main/java/com/gxwebsoft/shop/entity/Order.java index fb1c8bf..ba6c98e 100644 --- a/src/main/java/com/gxwebsoft/shop/entity/Order.java +++ b/src/main/java/com/gxwebsoft/shop/entity/Order.java @@ -36,7 +36,6 @@ public class Order implements Serializable { @ApiModelProperty(value = "订单号") private String orderNo; - @ApiModelProperty(value = "商品总金额(不含优惠折扣)") private BigDecimal totalPrice; @@ -217,6 +216,18 @@ public class Order implements Serializable { @ApiModelProperty(value = "备注") private String comments; + @ApiModelProperty(value = "收货人手机号") + private String receiptPhone; + + @ApiModelProperty(value = "紧急联系人") + private String emergentUser; + + @ApiModelProperty(value = "单位地址") + private String officeAddress; + + @ApiModelProperty(value = "家庭地址") + private String homeAddress; + @ApiModelProperty(value = "状态, 0正常, 1冻结") private Integer status; @@ -287,4 +298,12 @@ public class Order implements Serializable { @ApiModelProperty("芝麻免押") @TableField(exist = false) private String orderStr; + + @ApiModelProperty("下单用户手机号") + @TableField(exist = false) + private String userPhone; + + @ApiModelProperty("设备编码") + @TableField(exist = false) + private String equipmentCode; } diff --git a/src/main/java/com/gxwebsoft/shop/entity/OrderPay.java b/src/main/java/com/gxwebsoft/shop/entity/OrderPay.java index 098277b..7894b54 100644 --- a/src/main/java/com/gxwebsoft/shop/entity/OrderPay.java +++ b/src/main/java/com/gxwebsoft/shop/entity/OrderPay.java @@ -1,6 +1,9 @@ package com.gxwebsoft.shop.entity; import java.math.BigDecimal; + +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; @@ -9,11 +12,14 @@ import com.baomidou.mybatisplus.annotation.TableLogic; import java.io.Serializable; import java.util.Date; +import com.gxwebsoft.common.core.constants.OrderConstants; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; +import static com.gxwebsoft.common.core.constants.OrderConstants.PAY_STATUS_NO_PAY; + /** * 订单记录表 * @@ -158,7 +164,7 @@ public class OrderPay implements Serializable { private String dealerPhone; @ApiModelProperty(value = "逾期天数") - private Integer expirationDay; + private Long expirationDay; @ApiModelProperty(value = "租户id") private Integer tenantId; @@ -169,4 +175,12 @@ public class OrderPay implements Serializable { @ApiModelProperty(value = "修改时间") private Date updateTime; + public Long getExpirationDay() { + switch(payStatus){ + case OrderConstants.PAY_STATUS_NO_PAY: + case OrderConstants.PAY_STATUS_SUCCESS: + expirationDay = DateUtil.between(new Date(), expirationTime, DateUnit.DAY, false); + } + return expirationDay; + } } diff --git a/src/main/java/com/gxwebsoft/shop/mapper/MerchantMapper.java b/src/main/java/com/gxwebsoft/shop/mapper/MerchantMapper.java index aeaf966..f1ef538 100644 --- a/src/main/java/com/gxwebsoft/shop/mapper/MerchantMapper.java +++ b/src/main/java/com/gxwebsoft/shop/mapper/MerchantMapper.java @@ -2,6 +2,7 @@ package com.gxwebsoft.shop.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.gxwebsoft.shop.entity.Merchant; import com.gxwebsoft.shop.param.MerchantParam; import org.apache.ibatis.annotations.Param; @@ -23,8 +24,7 @@ public interface MerchantMapper extends BaseMapper { * @param param 查询参数 * @return List */ - List selectPageRel(@Param("page") IPage page, - @Param("param") MerchantParam param); + Page selectPageRel(IPage page, @Param("param") MerchantParam param); /** * 查询全部 diff --git a/src/main/java/com/gxwebsoft/shop/mapper/OrderMapper.java b/src/main/java/com/gxwebsoft/shop/mapper/OrderMapper.java index 5fe85a1..670ba16 100644 --- a/src/main/java/com/gxwebsoft/shop/mapper/OrderMapper.java +++ b/src/main/java/com/gxwebsoft/shop/mapper/OrderMapper.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.gxwebsoft.shop.entity.Order; import com.gxwebsoft.shop.param.OrderParam; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.ResultType; import org.apache.ibatis.annotations.Select; import java.util.List; @@ -56,4 +57,26 @@ public interface OrderMapper extends BaseMapper { @InterceptorIgnore(tenantLine = "true") void updateByIdSettled(@Param("param") Order order); + + /** + * 查找到期预警订单 + * @return + */ + @Select("select u.phone userPhone, DATEDIFF(o.expiration_time,CURDATE()) expirationDay " + + "from shop_order o join sys_user u on o.user_id = u.user_id " + + "where DATEDIFF(o.expiration_time,CURDATE()) in (-1, 0) and u.phone is not null " + + "and o.is_freeze = 1 and o.receipt_status != 10 and o.pay_status = 10 and o.is_renew = 1") + @ResultType(Order.class) + List selectAlertList(); + + /** + * 查找超期1天订单 + * @return + */ + @Select("select u.phone userPhone, DATEDIFF(o.expiration_time,CURDATE()) expirationDay " + + "from shop_order o join sys_user u on o.user_id = u.user_id " + + "where DATEDIFF(o.expiration_time,CURDATE()) = 1 and u.phone is not null " + + "and o.is_freeze = 1 and o.receipt_status != 10 and o.pay_status = 10 and o.is_renew = 1") + @ResultType(Order.class) + List selectOutOfOneDayList(); } diff --git a/src/main/java/com/gxwebsoft/shop/mapper/OrderPayMapper.java b/src/main/java/com/gxwebsoft/shop/mapper/OrderPayMapper.java index a116ff5..dfc2e73 100644 --- a/src/main/java/com/gxwebsoft/shop/mapper/OrderPayMapper.java +++ b/src/main/java/com/gxwebsoft/shop/mapper/OrderPayMapper.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.gxwebsoft.shop.entity.OrderPay; import com.gxwebsoft.shop.param.OrderPayParam; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; import java.util.List; @@ -34,4 +35,11 @@ public interface OrderPayMapper extends BaseMapper { */ List selectListRel(@Param("param") OrderPayParam param); + /** + * 查询是否存在第三方支付订单号 + * @param outTradeNo + * @return + */ + @Select("select * from shop_order_pay where JSON_CONTAINS(out_trans_nos, JSON_ARRAY(#{outTradeNo}))") + OrderPay selectByOutTransNo(@Param("outTradeNo") String outTradeNo); } diff --git a/src/main/java/com/gxwebsoft/shop/param/OrderReceiptParam.java b/src/main/java/com/gxwebsoft/shop/param/OrderReceiptParam.java new file mode 100644 index 0000000..485a094 --- /dev/null +++ b/src/main/java/com/gxwebsoft/shop/param/OrderReceiptParam.java @@ -0,0 +1,41 @@ +package com.gxwebsoft.shop.param; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; + +@Data +@ApiModel("确认收货请求参数") +public class OrderReceiptParam implements Serializable { + @ApiModelProperty(value = "订单ID", required = true) + @NotNull(message = "订单编号不能为空!") + private Integer orderId; + +// @ApiModelProperty(value = "来源记录的参数 (json格式)", required = true) +// @NotBlank(message = "身份信息数据不能为空!") + private String orderSourceData; + + @ApiModelProperty(value = "验证码", required = true) + @NotBlank(message = "验证码不能为空!") + private String captcha; + + @ApiModelProperty(value = "收货人手机号", required = true) + @NotBlank(message = "收货人手机号不能为空!") + private String receiptPhone; + + @ApiModelProperty(value = "紧急联系人") + @NotBlank(message = "紧急联系人不能为空!") + private String emergentUser; + + @ApiModelProperty(value = "单位地址") + @NotBlank(message = "单位地址不能为空!") + private String officeAddress; + + @ApiModelProperty(value = "家庭地址") + @NotBlank(message = "家庭地址不能为空!") + private String homeAddress; +} diff --git a/src/main/java/com/gxwebsoft/shop/service/OrderPayService.java b/src/main/java/com/gxwebsoft/shop/service/OrderPayService.java index d86c12f..e04bf46 100644 --- a/src/main/java/com/gxwebsoft/shop/service/OrderPayService.java +++ b/src/main/java/com/gxwebsoft/shop/service/OrderPayService.java @@ -39,4 +39,10 @@ public interface OrderPayService extends IService { */ OrderPay getByIdRel(Integer id); + /** + * 根据第三方流水号获取支付订单信息 + * @param outTradeNo + * @return + */ + OrderPay selectByOutTransNo(String outTradeNo); } diff --git a/src/main/java/com/gxwebsoft/shop/service/OrderService.java b/src/main/java/com/gxwebsoft/shop/service/OrderService.java index a6efb9b..04772ab 100644 --- a/src/main/java/com/gxwebsoft/shop/service/OrderService.java +++ b/src/main/java/com/gxwebsoft/shop/service/OrderService.java @@ -3,6 +3,7 @@ package com.gxwebsoft.shop.service; import com.alipay.api.response.AlipayTradeQueryResponse; import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import com.baomidou.mybatisplus.extension.service.IService; +import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.shop.entity.Order; import com.gxwebsoft.shop.param.OrderParam; @@ -45,7 +46,7 @@ public interface OrderService extends IService { Order getByOutTradeNo(String outTradeNo); @InterceptorIgnore(tenantLine = "true") - void paySuccess(AlipayTradeQueryResponse params); + ApiResult paySuccess(AlipayTradeQueryResponse params); boolean allinPay(Map params); @@ -59,4 +60,15 @@ public interface OrderService extends IService { void updateByIdSettled(Order order); + /** + * 查找到期预警订单 + * @return + */ + List findAlertList(); + + /** + * 查找逾期提醒订单 + * @return + */ + List findOverdueList(); } diff --git a/src/main/java/com/gxwebsoft/shop/service/impl/MerchantServiceImpl.java b/src/main/java/com/gxwebsoft/shop/service/impl/MerchantServiceImpl.java index ea35961..61ce8ca 100644 --- a/src/main/java/com/gxwebsoft/shop/service/impl/MerchantServiceImpl.java +++ b/src/main/java/com/gxwebsoft/shop/service/impl/MerchantServiceImpl.java @@ -1,6 +1,7 @@ package com.gxwebsoft.shop.service.impl; import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.gxwebsoft.common.core.utils.CacheClient; import com.gxwebsoft.common.core.web.PageParam; @@ -40,8 +41,8 @@ public class MerchantServiceImpl extends ServiceImpl i public PageResult pageRel(MerchantParam param) { PageParam page = new PageParam<>(param); page.setDefaultOrder("create_time desc"); - List list = baseMapper.selectPageRel(page, param); - return new PageResult<>(list, page.getTotal()); + Page list = baseMapper.selectPageRel(page, param); + return new PageResult<>(list.getRecords(), list.getTotal()); } @Override diff --git a/src/main/java/com/gxwebsoft/shop/service/impl/OrderPayServiceImpl.java b/src/main/java/com/gxwebsoft/shop/service/impl/OrderPayServiceImpl.java index 12db533..54ee0e8 100644 --- a/src/main/java/com/gxwebsoft/shop/service/impl/OrderPayServiceImpl.java +++ b/src/main/java/com/gxwebsoft/shop/service/impl/OrderPayServiceImpl.java @@ -44,4 +44,8 @@ public class OrderPayServiceImpl extends ServiceImpl i return param.getOne(baseMapper.selectListRel(param)); } + @Override + public OrderPay selectByOutTransNo(String outTradeNo) { + return baseMapper.selectByOutTransNo(outTradeNo); + } } diff --git a/src/main/java/com/gxwebsoft/shop/service/impl/OrderServiceImpl.java b/src/main/java/com/gxwebsoft/shop/service/impl/OrderServiceImpl.java index 77a8bda..aaa8a44 100644 --- a/src/main/java/com/gxwebsoft/shop/service/impl/OrderServiceImpl.java +++ b/src/main/java/com/gxwebsoft/shop/service/impl/OrderServiceImpl.java @@ -3,6 +3,7 @@ package com.gxwebsoft.shop.service.impl; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import com.alipay.api.AlipayApiException; import com.alipay.api.response.AlipayTradeQueryResponse; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -11,7 +12,9 @@ import com.gxwebsoft.apps.entity.EquipmentOrderGoods; import com.gxwebsoft.apps.service.EquipmentGoodsService; import com.gxwebsoft.apps.service.EquipmentOrderGoodsService; import com.gxwebsoft.apps.service.EquipmentService; +import com.gxwebsoft.common.core.Constants; import com.gxwebsoft.common.core.utils.CacheClient; +import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.PageParam; import com.gxwebsoft.common.core.web.PageResult; import com.gxwebsoft.shop.entity.Order; @@ -88,13 +91,26 @@ public class OrderServiceImpl extends ServiceImpl implements return new PageResult<>(list, page.getTotal()); } + // TODO 待优化:查询时自动排序并返回分页数据 @Override public List listRel(OrderParam param) { List list = baseMapper.selectListRel(param); // 排序 PageParam page = new PageParam<>(); - page.setDefaultOrder("create_time desc"); + String sort = param.getSort(); + String order = param.getOrder(); + if(StrUtil.isNotBlank(sort)){ + String orderStr = sort; + if(StrUtil.isNotBlank(order)){ + orderStr += " " + order; + } + page.setDefaultOrder(orderStr); + } + else { + page.setDefaultOrder("create_time desc"); + } + return page.sortRecords(list); } @@ -191,7 +207,7 @@ public class OrderServiceImpl extends ServiceImpl implements */ @Transactional(rollbackFor = {Exception.class}) @Override - public void paySuccess(AlipayTradeQueryResponse params) { + public ApiResult paySuccess(AlipayTradeQueryResponse params) { System.out.println("支付成功后处理的业务"); String outTradeNo = params.getOutTradeNo(); String totalAmount = params.getTotalAmount(); @@ -199,8 +215,12 @@ public class OrderServiceImpl extends ServiceImpl implements // 1.是否为商城订单 Order order = orderService.getByOutTradeNo(outTradeNo); if (order == null) { - System.out.println("订单不存在!"); - return; + return new ApiResult("订单不存在!"); + } + + Integer payStatus = order.getPayStatus(); + if(payStatus >= PAY_STATUS_SUCCESS){ + return new ApiResult("订单已支付!"); } // 2.订单金额是否一致 // 3.订单商户是否一致 @@ -208,8 +228,10 @@ public class OrderServiceImpl extends ServiceImpl implements // 5.判断交易状态 String tradeStatus = params.getTradeStatus(); if (!"TRADE_SUCCESS".equals(tradeStatus)) { - System.out.println("支付未成功"); - return; + if("TRADE_CLOSED".equals(tradeStatus)){ + // TODO 订单已关闭 + } + return new ApiResult("支付未成功!"); } // 6.修改订单状态 @@ -219,10 +241,6 @@ public class OrderServiceImpl extends ServiceImpl implements order.setPayTime(DateUtil.date()); order.setExpirationTime(DateUtil.nextMonth()); - - - - // 6. 续租订单 if (order.getRentOrderId() > 0) { Integer count = orderService.lambdaQuery().eq(Order::getRentOrderId, order.getRentOrderId()).eq(Order::getPayStatus, PAY_STATUS_SUCCESS).count(); @@ -261,11 +279,8 @@ public class OrderServiceImpl extends ServiceImpl implements } - - - orderService.updateById(order); - + return new ApiResult(Constants.RESULT_OK_CODE, "支付成功"); } /** @@ -285,4 +300,13 @@ public class OrderServiceImpl extends ServiceImpl implements } } + @Override + public List findAlertList() { + return baseMapper.selectAlertList(); + } + + @Override + public List findOverdueList() { + return baseMapper.selectOutOfOneDayList(); + } } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index b6cdb3b..9f60fa4 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -9,12 +9,6 @@ spring: driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource -# 日志配置 -logging: - level: - com.gxwebsoft: DEBUG - com.baomidou.mybatisplus: DEBUG - socketio: host: localhost #IP地址 @@ -31,3 +25,13 @@ config: bucketName: oss-yunxinwei bucketDomain: https://oss.wsdns.cn aliyunDomain: https://oss-yunxinwei.oss-cn-shenzhen.aliyuncs.com + +# 日志配置 +logging: + level: + root: INFO + com.gxwebsoft: INFO + com.baomidou.mybatisplus: INFO + file: + path: E:\data\yxw\logs + name: yxw.log \ No newline at end of file diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index c0ce982..1d0314f 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -13,18 +13,21 @@ spring: logging: file: name: websoft-api.log + path: /www/wwwroot/api.yunxinwei.java/logs level: - root: WARN - com.gxwebsoft: ERROR + root: INFO + com.gxwebsoft: INFO com.baomidou.mybatisplus: ERROR socketio: host: 0.0.0.0 #IP地址 +# host: localhost # 框架配置 config: # 生产环境接口 server-url: https://yxw.wsdns.cn/api +# server-url: https://127.0.0.1:9090/api upload-path: /www/wwwroot/file.ws/ # 阿里云OSS云存储 diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 58a4055..0f057fe 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -7,7 +7,7 @@ socketio: # 多环境配置 spring: profiles: - active: dev + active: prod application: name: server @@ -91,6 +91,7 @@ config: file-server: https://file.wsdns.cn upload-path: /Users/gxwebsoft/Documents/uploads/ local-upload-path: /Users/gxwebsoft/Documents/uploads/ + tenantId: 6 # 阿里云OSS云存储 endpoint: https://oss-cn-shenzhen.aliyuncs.com @@ -99,5 +100,16 @@ config: bucketName: oss-gxwebsoft bucketDomain: https://oss.wsdns.cn aliyunDomain: https://oss-gxwebsoft.oss-cn-shenzhen.aliyuncs.com +# smsSign: ${SMS_SIGN:南宁网宿科技} +# smsKey: ${SMS_ACCESS_KEY:LTAI5tBWM9dSmEAoQFhNqxqJ} +# smsSecret: ${SMS_SECRET:Dr0BqiKl7eaL1NNKoCd12qKsbgjnum} + +# 日志配置 +#logging: +# level: +# com.gxwebsoft: ${LOG_LEVEL:INFO} +# com.baomidou.mybatisplus: ${LOG_LEVEL:INFO} +# file: +# path: {LOGGING_PATH: ../logs}