Commit aa4d9869dfcee6af8eaf4a0e337f2d0ff84372a8
1 parent
7d925fdd
feat mall user info
Showing
28 changed files
with
936 additions
and
24 deletions
cashier-mall/src/main/java/com/diligrp/cashier/mall/MallConstants.java
| 1 | 1 | package com.diligrp.cashier.mall; |
| 2 | 2 | |
| 3 | 3 | |
| 4 | +/** | |
| 5 | + * 商城常量 | |
| 6 | + */ | |
| 4 | 7 | public interface MallConstants { |
| 5 | 8 | String RESULT_SUCCESS = "success"; |
| 6 | 9 | String RESULT_FAILURE = "fail"; |
| 7 | 10 | |
| 8 | 11 | Integer RT_MALL_SOURCE = 1; |
| 12 | + | |
| 13 | + String MALL_TOKEN = "mall_token:"; | |
| 14 | + String MALL_USER_INFO = "mall_user_info:"; | |
| 9 | 15 | } | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/api/MallAuthApi.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.api; | |
| 2 | + | |
| 3 | +import com.diligrp.cashier.mall.MallConstants; | |
| 4 | +import com.diligrp.cashier.mall.context.MallInitializeContext; | |
| 5 | +import com.diligrp.cashier.mall.domain.rtmall.RtMarkMessage; | |
| 6 | +import com.diligrp.cashier.mall.domain.rtmall.co.AuthLoginCO; | |
| 7 | +import com.diligrp.cashier.mall.domain.rtmall.co.UserInfoCO; | |
| 8 | +import com.diligrp.cashier.mall.domain.rtmall.vo.UserInfoVO; | |
| 9 | +import com.diligrp.cashier.mall.sign.RtMallSign; | |
| 10 | +import com.diligrp.cashier.shared.annotation.ParamLogPrint; | |
| 11 | +import com.diligrp.cashier.shared.annotation.Sign; | |
| 12 | +import com.diligrp.cashier.shared.domain.Message; | |
| 13 | +import com.diligrp.cashier.shared.util.JsonUtils; | |
| 14 | +import jakarta.annotation.Resource; | |
| 15 | +import jakarta.validation.Valid; | |
| 16 | +import org.slf4j.Logger; | |
| 17 | +import org.slf4j.LoggerFactory; | |
| 18 | +import org.springframework.data.redis.core.RedisTemplate; | |
| 19 | +import org.springframework.validation.annotation.Validated; | |
| 20 | +import org.springframework.web.bind.annotation.PostMapping; | |
| 21 | +import org.springframework.web.bind.annotation.RequestBody; | |
| 22 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 23 | +import org.springframework.web.bind.annotation.RestController; | |
| 24 | + | |
| 25 | +import java.util.Objects; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * @ClassName MallAuthApi.java | |
| 29 | + * @author dengwei | |
| 30 | + * @version 1.0.0 | |
| 31 | + * @Description MallAuthApi | |
| 32 | + */ | |
| 33 | +@RestController | |
| 34 | +@RequestMapping("/mall") | |
| 35 | +@Validated | |
| 36 | +public class MallAuthApi { | |
| 37 | + private static final Logger log = LoggerFactory.getLogger(MallAuthApi.class); | |
| 38 | + @Resource | |
| 39 | + private RedisTemplate<String, Object> redisTemplate; | |
| 40 | + | |
| 41 | + /** | |
| 42 | + * 获取授权连接 | |
| 43 | + */ | |
| 44 | + @PostMapping("/auth") | |
| 45 | + @ParamLogPrint(outPrint = true) | |
| 46 | + public Message<String> authLogin(@RequestBody @Valid AuthLoginCO authLogin) { | |
| 47 | + return Message.success(MallInitializeContext.getByChannel(authLogin.getChannel()).authLogin(authLogin)); | |
| 48 | + } | |
| 49 | + | |
| 50 | + /** | |
| 51 | + * 获取用户信息 | |
| 52 | + */ | |
| 53 | + @PostMapping("/user/info") | |
| 54 | + @ParamLogPrint(outPrint = true) | |
| 55 | + @Sign(sign = RtMallSign.class) | |
| 56 | + public RtMarkMessage<UserInfoVO> userInfo(@RequestBody @Valid Object req) { | |
| 57 | + UserInfoCO userInfo = JsonUtils.convertValue(req, UserInfoCO.class); | |
| 58 | + AuthLoginCO authLogin = JsonUtils.fromJsonString(Objects.requireNonNull(redisTemplate.opsForValue().get(MallConstants.MALL_TOKEN + userInfo.getToken())).toString(), AuthLoginCO.class); | |
| 59 | + UserInfoVO userInfoVO = MallInitializeContext.getByChannel(authLogin.getChannel()).userInfo(authLogin); | |
| 60 | + return RtMarkMessage.success(userInfoVO); | |
| 61 | + } | |
| 62 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/context/MallInitializeContext.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.context; | |
| 2 | + | |
| 3 | +import com.diligrp.cashier.mall.exception.MallException; | |
| 4 | +import com.diligrp.cashier.mall.service.paychannel.AbstractPayChannel; | |
| 5 | +import com.diligrp.cashier.mall.service.sourcechannel.AbstractChannel; | |
| 6 | +import com.diligrp.cashier.shared.util.SpringContextUtils; | |
| 7 | +import com.google.common.collect.Maps; | |
| 8 | +import org.slf4j.Logger; | |
| 9 | +import org.slf4j.LoggerFactory; | |
| 10 | +import org.springframework.beans.factory.DisposableBean; | |
| 11 | +import org.springframework.beans.factory.InitializingBean; | |
| 12 | +import org.springframework.stereotype.Component; | |
| 13 | + | |
| 14 | +import java.util.Map; | |
| 15 | +import java.util.Optional; | |
| 16 | + | |
| 17 | +/** | |
| 18 | + * @author dengwei | |
| 19 | + * @version 1.0.0 | |
| 20 | + * @ClassName MallInitializeContext.java | |
| 21 | + * @Description MallInitializeContext | |
| 22 | + */ | |
| 23 | +@Component | |
| 24 | +public class MallInitializeContext implements InitializingBean, DisposableBean { | |
| 25 | + private static final Logger log = LoggerFactory.getLogger(MallInitializeContext.class); | |
| 26 | + public static Map<String, AbstractChannel> SOURCE_CHANNEL_MAP = Maps.newConcurrentMap(); | |
| 27 | + public static Map<Integer, AbstractPayChannel> PAY_CHANNEL_MAP = Maps.newConcurrentMap(); | |
| 28 | + | |
| 29 | + /** | |
| 30 | + * 容器启动完成加载 | |
| 31 | + */ | |
| 32 | + @Override | |
| 33 | + public void afterPropertiesSet() throws Exception { | |
| 34 | + SpringContextUtils.getBeanOfTpe(AbstractChannel.class).forEach((key, value) -> { | |
| 35 | + SOURCE_CHANNEL_MAP.put(value.channel(), value); | |
| 36 | + }); | |
| 37 | + | |
| 38 | + SpringContextUtils.getBeanOfTpe(AbstractPayChannel.class).forEach((key, value) -> { | |
| 39 | + PAY_CHANNEL_MAP.put(value.getPayChannel(), value); | |
| 40 | + }); | |
| 41 | + } | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 容器销毁加载 | |
| 45 | + */ | |
| 46 | + @Override | |
| 47 | + public void destroy() throws Exception { | |
| 48 | + log.info("spring container destroy"); | |
| 49 | + } | |
| 50 | + | |
| 51 | + /** | |
| 52 | + * getByType | |
| 53 | + */ | |
| 54 | + public static AbstractChannel getByChannel(String channel) { | |
| 55 | + return Optional.ofNullable(SOURCE_CHANNEL_MAP.get(channel)).orElseThrow(() -> new MallException("不支持该渠道!")); | |
| 56 | + } | |
| 57 | + | |
| 58 | + /** | |
| 59 | + * getByPayChannel | |
| 60 | + */ | |
| 61 | + public static AbstractPayChannel getByPayChannel(Integer payChannel) { | |
| 62 | + return Optional.ofNullable(PAY_CHANNEL_MAP.get(payChannel)).orElseThrow(() -> new MallException("不支持该渠道!")); | |
| 63 | + } | |
| 64 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/domain/rtmall/RtMarkBaseCO.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.domain.rtmall; | |
| 2 | + | |
| 3 | +import com.fasterxml.jackson.databind.PropertyNamingStrategies; | |
| 4 | +import com.fasterxml.jackson.databind.annotation.JsonNaming; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * @ClassName RtMarkBaseCO.java | |
| 8 | + * @author dengwei | |
| 9 | + * @version 1.0.0 | |
| 10 | + * @Description RtMarkBaseCO | |
| 11 | + * @date 2025-12-25 16:26 | |
| 12 | + */ | |
| 13 | +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) | |
| 14 | +public class RtMarkBaseCO { | |
| 15 | + private String appKey; | |
| 16 | + private String version; | |
| 17 | + private String timestamp; | |
| 18 | + private String nonceStr; | |
| 19 | + private String sign; | |
| 20 | + | |
| 21 | + public String getAppKey() { | |
| 22 | + return appKey; | |
| 23 | + } | |
| 24 | + | |
| 25 | + public void setAppKey(String appKey) { | |
| 26 | + this.appKey = appKey; | |
| 27 | + } | |
| 28 | + | |
| 29 | + public String getVersion() { | |
| 30 | + return version; | |
| 31 | + } | |
| 32 | + | |
| 33 | + public void setVersion(String version) { | |
| 34 | + this.version = version; | |
| 35 | + } | |
| 36 | + | |
| 37 | + public String getTimestamp() { | |
| 38 | + return timestamp; | |
| 39 | + } | |
| 40 | + | |
| 41 | + public void setTimestamp(String timestamp) { | |
| 42 | + this.timestamp = timestamp; | |
| 43 | + } | |
| 44 | + | |
| 45 | + public String getNonceStr() { | |
| 46 | + return nonceStr; | |
| 47 | + } | |
| 48 | + | |
| 49 | + public void setNonceStr(String nonceStr) { | |
| 50 | + this.nonceStr = nonceStr; | |
| 51 | + } | |
| 52 | + | |
| 53 | + public String getSign() { | |
| 54 | + return sign; | |
| 55 | + } | |
| 56 | + | |
| 57 | + public void setSign(String sign) { | |
| 58 | + this.sign = sign; | |
| 59 | + } | |
| 60 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/domain/RtMarkMessage.java renamed to cashier-mall/src/main/java/com/diligrp/cashier/mall/domain/rtmall/RtMarkMessage.java
cashier-mall/src/main/java/com/diligrp/cashier/mall/domain/rtmall/co/AuthLoginCO.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.domain.rtmall.co; | |
| 2 | + | |
| 3 | +import jakarta.validation.constraints.NotBlank; | |
| 4 | +import jakarta.validation.constraints.NotNull; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * @ClassName AuthLoginCO.java | |
| 8 | + * @author dengwei | |
| 9 | + * @version 1.0.0 | |
| 10 | + * @Description AuthLoginCO | |
| 11 | + * @date 2025-12-25 10:55 | |
| 12 | + */ | |
| 13 | +public class AuthLoginCO { | |
| 14 | + /** | |
| 15 | + * 用户编号 | |
| 16 | + */ | |
| 17 | + @NotBlank(message = "用户编号不能为空!") | |
| 18 | + private String userCode; | |
| 19 | + | |
| 20 | + /** | |
| 21 | + * 用户名 | |
| 22 | + */ | |
| 23 | + @NotBlank(message = "用户名称不能为空!") | |
| 24 | + private String username; | |
| 25 | + | |
| 26 | + /** | |
| 27 | + * 渠道-中瑞 地利 | |
| 28 | + * @see com.diligrp.cashier.mall.type.OrderChannel | |
| 29 | + */ | |
| 30 | + @NotBlank(message = "渠道不能为空!") | |
| 31 | + private String channel; | |
| 32 | + | |
| 33 | + /** | |
| 34 | + * 商户编号 | |
| 35 | + */ | |
| 36 | + @NotBlank(message = "商户编号不能为空!") | |
| 37 | + private String mchId; | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 订单来源(1大润发 2山姆) | |
| 41 | + * @see com.diligrp.cashier.mall.type.OrderSource | |
| 42 | + */ | |
| 43 | + @NotNull(message = "订单来源不能为空!") | |
| 44 | + private Integer source; | |
| 45 | + | |
| 46 | + /** | |
| 47 | + * 订单类型-1线下扫码购,2 接口扫码购,3小程序 | |
| 48 | + * @see com.diligrp.cashier.mall.type.OrderType | |
| 49 | + */ | |
| 50 | + @NotNull(message = "订单类型不能为空!") | |
| 51 | + private Integer orderType; | |
| 52 | + | |
| 53 | + /** | |
| 54 | + * 联系电话 | |
| 55 | + */ | |
| 56 | + private String mobile; | |
| 57 | + | |
| 58 | + /** | |
| 59 | + * 经度 | |
| 60 | + */ | |
| 61 | + private String longitude; | |
| 62 | + | |
| 63 | + /** | |
| 64 | + * 纬度 | |
| 65 | + */ | |
| 66 | + private String latitude; | |
| 67 | + | |
| 68 | + public String getLatitude() { | |
| 69 | + return latitude; | |
| 70 | + } | |
| 71 | + | |
| 72 | + public void setLatitude(String latitude) { | |
| 73 | + this.latitude = latitude; | |
| 74 | + } | |
| 75 | + | |
| 76 | + public String getLongitude() { | |
| 77 | + return longitude; | |
| 78 | + } | |
| 79 | + | |
| 80 | + public void setLongitude(String longitude) { | |
| 81 | + this.longitude = longitude; | |
| 82 | + } | |
| 83 | + | |
| 84 | + public Integer getOrderType() { | |
| 85 | + return orderType; | |
| 86 | + } | |
| 87 | + | |
| 88 | + public void setOrderType(Integer orderType) { | |
| 89 | + this.orderType = orderType; | |
| 90 | + } | |
| 91 | + | |
| 92 | + public String getMobile() { | |
| 93 | + return mobile; | |
| 94 | + } | |
| 95 | + | |
| 96 | + public void setMobile(String mobile) { | |
| 97 | + this.mobile = mobile; | |
| 98 | + } | |
| 99 | + | |
| 100 | + public Integer getSource() { | |
| 101 | + return source; | |
| 102 | + } | |
| 103 | + | |
| 104 | + public void setSource(Integer source) { | |
| 105 | + this.source = source; | |
| 106 | + } | |
| 107 | + | |
| 108 | + public String getMchId() { | |
| 109 | + return mchId; | |
| 110 | + } | |
| 111 | + | |
| 112 | + public void setMchId(String mchId) { | |
| 113 | + this.mchId = mchId; | |
| 114 | + } | |
| 115 | + | |
| 116 | + public String getChannel() { | |
| 117 | + return channel; | |
| 118 | + } | |
| 119 | + | |
| 120 | + public void setChannel(String channel) { | |
| 121 | + this.channel = channel; | |
| 122 | + } | |
| 123 | + | |
| 124 | + public String getUserCode() { | |
| 125 | + return userCode; | |
| 126 | + } | |
| 127 | + | |
| 128 | + public void setUserCode(String userCode) { | |
| 129 | + this.userCode = userCode; | |
| 130 | + } | |
| 131 | + | |
| 132 | + public String getUsername() { | |
| 133 | + return username; | |
| 134 | + } | |
| 135 | + | |
| 136 | + public void setUsername(String username) { | |
| 137 | + this.username = username; | |
| 138 | + } | |
| 139 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/domain/rtmall/co/UserInfoCO.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.domain.rtmall.co; | |
| 2 | + | |
| 3 | +import com.diligrp.cashier.mall.domain.rtmall.RtMarkBaseCO; | |
| 4 | +import com.diligrp.cashier.shared.jackson.deserializer.SecondToDateDeserializer; | |
| 5 | +import com.diligrp.cashier.shared.jackson.serialization.DateToSecondSerializer; | |
| 6 | +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; | |
| 7 | +import com.fasterxml.jackson.databind.annotation.JsonSerialize; | |
| 8 | +import jakarta.validation.constraints.NotBlank; | |
| 9 | + | |
| 10 | +import java.time.LocalDateTime; | |
| 11 | + | |
| 12 | +/** | |
| 13 | + * @ClassName UserInfoCO.java | |
| 14 | + * @author dengwei | |
| 15 | + * @version 1.0.0 | |
| 16 | + * @Description UserInfoCO | |
| 17 | + * @date 2025-12-25 16:28 | |
| 18 | + */ | |
| 19 | +public class UserInfoCO extends RtMarkBaseCO { | |
| 20 | + @NotBlank(message = "token不能为空!") | |
| 21 | + private String token; | |
| 22 | + | |
| 23 | + @JsonSerialize(using = DateToSecondSerializer.class) | |
| 24 | + @JsonDeserialize(using = SecondToDateDeserializer.class) | |
| 25 | + private LocalDateTime createTime; | |
| 26 | + | |
| 27 | + public String getToken() { | |
| 28 | + return token; | |
| 29 | + } | |
| 30 | + | |
| 31 | + public void setToken(String token) { | |
| 32 | + this.token = token; | |
| 33 | + } | |
| 34 | + | |
| 35 | + public LocalDateTime getCreateTime() { | |
| 36 | + return createTime; | |
| 37 | + } | |
| 38 | + | |
| 39 | + public void setCreateTime(LocalDateTime createTime) { | |
| 40 | + this.createTime = createTime; | |
| 41 | + } | |
| 42 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/domain/rtmall/vo/UserInfoVO.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.domain.rtmall.vo; | |
| 2 | + | |
| 3 | +import com.fasterxml.jackson.databind.PropertyNamingStrategies; | |
| 4 | +import com.fasterxml.jackson.databind.annotation.JsonNaming; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * @ClassName UserInfoVO.java | |
| 8 | + * @author dengwei | |
| 9 | + * @version 1.0.0 | |
| 10 | + * @Description UserInfoVO | |
| 11 | + * @date 2025-12-25 16:31 | |
| 12 | + */ | |
| 13 | +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) | |
| 14 | +public class UserInfoVO { | |
| 15 | + private String userCode; | |
| 16 | + private String mobile; | |
| 17 | + private String userName; | |
| 18 | + private String companyCode; | |
| 19 | + | |
| 20 | + public String getUserCode() { | |
| 21 | + return userCode; | |
| 22 | + } | |
| 23 | + | |
| 24 | + public void setUserCode(String userCode) { | |
| 25 | + this.userCode = userCode; | |
| 26 | + } | |
| 27 | + | |
| 28 | + public String getMobile() { | |
| 29 | + return mobile; | |
| 30 | + } | |
| 31 | + | |
| 32 | + public void setMobile(String mobile) { | |
| 33 | + this.mobile = mobile; | |
| 34 | + } | |
| 35 | + | |
| 36 | + public String getUserName() { | |
| 37 | + return userName; | |
| 38 | + } | |
| 39 | + | |
| 40 | + public void setUserName(String userName) { | |
| 41 | + this.userName = userName; | |
| 42 | + } | |
| 43 | + | |
| 44 | + public String getCompanyCode() { | |
| 45 | + return companyCode; | |
| 46 | + } | |
| 47 | + | |
| 48 | + public void setCompanyCode(String companyCode) { | |
| 49 | + this.companyCode = companyCode; | |
| 50 | + } | |
| 51 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/exception/MallExceptionHandler.java
cashier-mall/src/main/java/com/diligrp/cashier/mall/property/MallDynamicProperty.java renamed to cashier-mall/src/main/java/com/diligrp/cashier/mall/property/RtMallDynamicProperty.java
| ... | ... | @@ -17,8 +17,8 @@ import java.util.Optional; |
| 17 | 17 | */ |
| 18 | 18 | @Configuration |
| 19 | 19 | @RefreshScope |
| 20 | -@ConfigurationProperties(prefix = "sign") | |
| 21 | -public class MallDynamicProperty { | |
| 20 | +@ConfigurationProperties(prefix = "rtmall.sign") | |
| 21 | +public class RtMallDynamicProperty { | |
| 22 | 22 | |
| 23 | 23 | private List<AppSecretDynamicProperty> appSecrets; |
| 24 | 24 | |
| ... | ... | @@ -26,12 +26,18 @@ public class MallDynamicProperty { |
| 26 | 26 | @Value("${source:1}") |
| 27 | 27 | private Integer source; |
| 28 | 28 | |
| 29 | + @Value("${orderType:3}") | |
| 30 | + private Integer orderType; | |
| 31 | + | |
| 29 | 32 | @Value("${appKey:}") |
| 30 | 33 | private String appKey; |
| 31 | 34 | |
| 32 | 35 | @Value("${appSecret:}") |
| 33 | 36 | private String appSecret; |
| 34 | 37 | |
| 38 | + @Value("${companyCode:}") | |
| 39 | + private String companyCode; | |
| 40 | + | |
| 35 | 41 | @Value("${authUrl:https://hourh5-em-shop.feiniugo.com}") |
| 36 | 42 | private String authUrl; |
| 37 | 43 | |
| ... | ... | @@ -66,6 +72,22 @@ public class MallDynamicProperty { |
| 66 | 72 | public void setAuthUrl(String authUrl) { |
| 67 | 73 | this.authUrl = authUrl; |
| 68 | 74 | } |
| 75 | + | |
| 76 | + public Integer getOrderType() { | |
| 77 | + return orderType; | |
| 78 | + } | |
| 79 | + | |
| 80 | + public void setOrderType(Integer orderType) { | |
| 81 | + this.orderType = orderType; | |
| 82 | + } | |
| 83 | + | |
| 84 | + public String getCompanyCode() { | |
| 85 | + return companyCode; | |
| 86 | + } | |
| 87 | + | |
| 88 | + public void setCompanyCode(String companyCode) { | |
| 89 | + this.companyCode = companyCode; | |
| 90 | + } | |
| 69 | 91 | } |
| 70 | 92 | |
| 71 | 93 | public List<AppSecretDynamicProperty> getAppSecrets() { |
| ... | ... | @@ -88,4 +110,30 @@ public class MallDynamicProperty { |
| 88 | 110 | .findFirst() |
| 89 | 111 | .orElse(null); |
| 90 | 112 | } |
| 113 | + | |
| 114 | + /** | |
| 115 | + * getBySource | |
| 116 | + * | |
| 117 | + */ | |
| 118 | + public AppSecretDynamicProperty getBySourceAndType(Integer source, Integer orderType) { | |
| 119 | + return Optional.ofNullable(appSecrets) | |
| 120 | + .orElse(Collections.emptyList()) | |
| 121 | + .stream() | |
| 122 | + .filter(item -> item.getSource().equals(source) && item.getOrderType().equals(orderType)) | |
| 123 | + .findFirst() | |
| 124 | + .orElse(null); | |
| 125 | + } | |
| 126 | + | |
| 127 | + /** | |
| 128 | + * getBySource | |
| 129 | + * | |
| 130 | + */ | |
| 131 | + public AppSecretDynamicProperty getByAppKey(String appKey) { | |
| 132 | + return Optional.ofNullable(appSecrets) | |
| 133 | + .orElse(Collections.emptyList()) | |
| 134 | + .stream() | |
| 135 | + .filter(item -> item.getAppKey().equals(appKey)) | |
| 136 | + .findFirst() | |
| 137 | + .orElse(null); | |
| 138 | + } | |
| 91 | 139 | } | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/paychannel/AbstractPayChannel.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.service.paychannel; | |
| 2 | + | |
| 3 | +import org.slf4j.Logger; | |
| 4 | +import org.slf4j.LoggerFactory; | |
| 5 | + | |
| 6 | +/** | |
| 7 | + * @ClassName AbstractPayChannel.java | |
| 8 | + * @author dengwei | |
| 9 | + * @version 1.0.0 | |
| 10 | + * @Description AbstractPayChannel | |
| 11 | + * @date 2025-12-25 17:07 | |
| 12 | + */ | |
| 13 | +public abstract class AbstractPayChannel { | |
| 14 | + protected final Logger log = LoggerFactory.getLogger(getClass()); | |
| 15 | + | |
| 16 | + public abstract Integer getPayChannel(); | |
| 17 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/paychannel/CardPayChannel.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.service.paychannel; | |
| 2 | + | |
| 3 | +import org.springframework.stereotype.Component; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @ClassName CardPayChannel.java | |
| 7 | + * @author dengwei | |
| 8 | + * @version 1.0.0 | |
| 9 | + * @Description CardPayChannel | |
| 10 | + * @date 2025-12-25 17:08 | |
| 11 | + */ | |
| 12 | +@Component | |
| 13 | +public class CardPayChannel extends AbstractPayChannel { | |
| 14 | + @Override | |
| 15 | + public Integer getPayChannel() { | |
| 16 | + return 0; | |
| 17 | + } | |
| 18 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/paychannel/WeChatPayChannel.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.service.paychannel; | |
| 2 | + | |
| 3 | +import org.springframework.stereotype.Component; | |
| 4 | + | |
| 5 | +/** | |
| 6 | + * @ClassName WeChatPayChannel.java | |
| 7 | + * @author dengwei | |
| 8 | + * @version 1.0.0 | |
| 9 | + * @Description WeChatPayChannel | |
| 10 | + * @date 2025-12-25 17:08 | |
| 11 | + */ | |
| 12 | +@Component | |
| 13 | +public class WeChatPayChannel extends AbstractPayChannel { | |
| 14 | + @Override | |
| 15 | + public Integer getPayChannel() { | |
| 16 | + return 1; | |
| 17 | + } | |
| 18 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/sourcechannel/AbstractChannel.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.service.sourcechannel; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.IdUtil; | |
| 4 | +import com.diligrp.cashier.mall.MallConstants; | |
| 5 | +import com.diligrp.cashier.mall.domain.rtmall.co.AuthLoginCO; | |
| 6 | +import com.diligrp.cashier.mall.domain.rtmall.vo.UserInfoVO; | |
| 7 | +import com.diligrp.cashier.mall.property.RtMallDynamicProperty; | |
| 8 | +import com.diligrp.cashier.shared.util.DateUtils; | |
| 9 | +import com.diligrp.cashier.shared.util.JsonUtils; | |
| 10 | +import jakarta.annotation.Resource; | |
| 11 | +import org.slf4j.Logger; | |
| 12 | +import org.slf4j.LoggerFactory; | |
| 13 | +import org.springframework.data.redis.core.RedisTemplate; | |
| 14 | + | |
| 15 | +import java.util.concurrent.TimeUnit; | |
| 16 | + | |
| 17 | +/** | |
| 18 | + * @ClassName AbstractChannel.java | |
| 19 | + * @author dengwei | |
| 20 | + * @version 1.0.0 | |
| 21 | + * @Description AbstractChannel | |
| 22 | + * @date 2025-12-25 11:19 | |
| 23 | + */ | |
| 24 | +public abstract class AbstractChannel { | |
| 25 | + private static final Logger log = LoggerFactory.getLogger(AbstractChannel.class); | |
| 26 | + | |
| 27 | + @Resource | |
| 28 | + protected RtMallDynamicProperty rtMallDynamicProperty; | |
| 29 | + @Resource | |
| 30 | + protected RedisTemplate<String, Object> redisTemplate; | |
| 31 | + | |
| 32 | + /** | |
| 33 | + * authLogin | |
| 34 | + */ | |
| 35 | + public String authLogin(AuthLoginCO authLogin) { | |
| 36 | + String token = IdUtil.fastSimpleUUID(); | |
| 37 | + long timestamp = DateUtils.timestampInSeconds(); | |
| 38 | + | |
| 39 | + String authUrl = authUrl(authLogin, token, timestamp); | |
| 40 | + | |
| 41 | + // token 缓存 | |
| 42 | + String tokenKey = MallConstants.MALL_TOKEN + token; | |
| 43 | + redisTemplate.opsForValue().set(tokenKey, JsonUtils.toJsonString(authLogin), 1, TimeUnit.DAYS); | |
| 44 | + | |
| 45 | + // 用户信息缓存 中瑞、dili是独立系统部署 可能存在相同用户id 所以需要加上渠道 | |
| 46 | + String userKey = MallConstants.MALL_USER_INFO + authLogin.getUserCode() + "_" + authLogin.getChannel(); | |
| 47 | + redisTemplate.opsForValue().set(userKey, JsonUtils.toJsonString(authLogin), 1, TimeUnit.DAYS); | |
| 48 | + return authUrl; | |
| 49 | + } | |
| 50 | + | |
| 51 | + /** | |
| 52 | + * userInfo | |
| 53 | + * | |
| 54 | + */ | |
| 55 | + public UserInfoVO userInfo(AuthLoginCO authLogin) { | |
| 56 | + RtMallDynamicProperty.AppSecretDynamicProperty property = rtMallDynamicProperty.getBySourceAndType(authLogin.getSource(), authLogin.getOrderType()); | |
| 57 | + log.info("authUrl property: {}", JsonUtils.toJsonString(property)); | |
| 58 | + | |
| 59 | + UserInfoVO userInfoVO = JsonUtils.convertValue(authLogin, UserInfoVO.class); | |
| 60 | + userInfoVO.setUserCode(authLogin.getUserCode() + "_" + authLogin.getChannel()); | |
| 61 | + userInfoVO.setUserName(authLogin.getUsername()); | |
| 62 | + | |
| 63 | + userInfoChannel(userInfoVO, property); | |
| 64 | + return userInfoVO; | |
| 65 | + } | |
| 66 | + | |
| 67 | + /** | |
| 68 | + * 渠道 | |
| 69 | + */ | |
| 70 | + public abstract String channel(); | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * authLoginUrl | |
| 74 | + */ | |
| 75 | + public abstract String authUrl(AuthLoginCO authLogin, String token, long timestamp); | |
| 76 | + | |
| 77 | + public abstract void userInfoChannel(UserInfoVO authLogin, RtMallDynamicProperty.AppSecretDynamicProperty userInfoVO); | |
| 78 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/service/sourcechannel/RtMallChannel.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.service.sourcechannel; | |
| 2 | + | |
| 3 | +import com.diligrp.cashier.mall.domain.rtmall.co.AuthLoginCO; | |
| 4 | +import com.diligrp.cashier.mall.domain.rtmall.vo.UserInfoVO; | |
| 5 | +import com.diligrp.cashier.mall.property.RtMallDynamicProperty; | |
| 6 | +import com.diligrp.cashier.mall.type.OrderChannel; | |
| 7 | +import com.diligrp.cashier.mall.util.RtMallSignMd5Utils; | |
| 8 | +import com.diligrp.cashier.shared.util.JsonUtils; | |
| 9 | +import com.diligrp.cashier.shared.util.UrlParamParserUtils; | |
| 10 | +import org.slf4j.Logger; | |
| 11 | +import org.slf4j.LoggerFactory; | |
| 12 | +import org.springframework.stereotype.Component; | |
| 13 | + | |
| 14 | +import java.util.Map; | |
| 15 | + | |
| 16 | +/** | |
| 17 | + * @ClassName RtMallChannel.java | |
| 18 | + * @author dengwei | |
| 19 | + * @version 1.0.0 | |
| 20 | + * @Description RtMallChannel | |
| 21 | + * @date 2025-12-25 11:20 | |
| 22 | + */ | |
| 23 | +@Component | |
| 24 | +public class RtMallChannel extends AbstractChannel { | |
| 25 | + private static final Logger log = LoggerFactory.getLogger(RtMallChannel.class); | |
| 26 | + | |
| 27 | + @Override | |
| 28 | + public String authUrl(AuthLoginCO authLogin, String token, long timestamp) { | |
| 29 | + RtMallDynamicProperty.AppSecretDynamicProperty property = rtMallDynamicProperty.getBySourceAndType(authLogin.getSource(), authLogin.getOrderType()); | |
| 30 | + log.info("authUrl property: {}", JsonUtils.toJsonString(property)); | |
| 31 | + | |
| 32 | + // 替换参数 | |
| 33 | + String authUrl = property.getAuthUrl(); | |
| 34 | + authUrl = String.format(authUrl, token, timestamp, authLogin.getLongitude(), authLogin.getLatitude()); | |
| 35 | + log.info("authUrl format1: {}", authUrl); | |
| 36 | + | |
| 37 | + // 获取参数 | |
| 38 | + Map<String, String> queryParams = UrlParamParserUtils.parseQueryParams(authUrl); | |
| 39 | + log.info("authUrl queryParams: {}", JsonUtils.toJsonString(queryParams)); | |
| 40 | + | |
| 41 | + // 生成签名 | |
| 42 | + String sign = RtMallSignMd5Utils.generateSign(queryParams, property.getAppSecret()); | |
| 43 | + log.info("authUrl sign: {}", sign); | |
| 44 | + authUrl = authUrl.concat("&sign=").concat(sign); | |
| 45 | + return authUrl; | |
| 46 | + } | |
| 47 | + | |
| 48 | + /** | |
| 49 | + * userInfo | |
| 50 | + */ | |
| 51 | + @Override | |
| 52 | + public void userInfoChannel(final UserInfoVO authLogin, | |
| 53 | + final RtMallDynamicProperty.AppSecretDynamicProperty property) { | |
| 54 | + authLogin.setCompanyCode(property.getCompanyCode()); | |
| 55 | + } | |
| 56 | + | |
| 57 | + @Override | |
| 58 | + public String channel() { | |
| 59 | + return OrderChannel.RT_MART.getCode(); | |
| 60 | + } | |
| 61 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/sign/RtMallSign.java
| 1 | 1 | package com.diligrp.cashier.mall.sign; |
| 2 | 2 | |
| 3 | -import com.diligrp.cashier.mall.MallConstants; | |
| 4 | 3 | import com.diligrp.cashier.mall.exception.RtMartMallException; |
| 5 | -import com.diligrp.cashier.mall.property.MallDynamicProperty; | |
| 4 | +import com.diligrp.cashier.mall.property.RtMallDynamicProperty; | |
| 6 | 5 | import com.diligrp.cashier.mall.type.RtMarkErrorCode; |
| 7 | 6 | import com.diligrp.cashier.mall.util.RtMallSignMd5Utils; |
| 8 | 7 | import com.diligrp.cashier.shared.handler.sign.SecuritySign; |
| ... | ... | @@ -31,7 +30,7 @@ public class RtMallSign implements SecuritySign { |
| 31 | 30 | private static final Logger log = LoggerFactory.getLogger(RtMallSign.class); |
| 32 | 31 | |
| 33 | 32 | @Resource |
| 34 | - private MallDynamicProperty mallDynamicProperty; | |
| 33 | + private RtMallDynamicProperty mallDynamicProperty; | |
| 35 | 34 | |
| 36 | 35 | @Override |
| 37 | 36 | public void sign(HttpServletRequest request, HttpServletResponse response, Object data) { |
| ... | ... | @@ -45,15 +44,21 @@ public class RtMallSign implements SecuritySign { |
| 45 | 44 | throw new RtMartMallException(RtMarkErrorCode.E4003.getCode(), RtMarkErrorCode.E4003.getMessage()); |
| 46 | 45 | } |
| 47 | 46 | |
| 48 | - MallDynamicProperty.AppSecretDynamicProperty property = mallDynamicProperty.getBySource(MallConstants.RT_MALL_SOURCE); | |
| 47 | + Object sign = paramMap.get("sign"); | |
| 48 | + if (Objects.isNull(sign)) { | |
| 49 | + throw new RtMartMallException(RtMarkErrorCode.E4004.getCode(), RtMarkErrorCode.E4004.getMessage()); | |
| 50 | + } | |
| 51 | + paramMap.remove("sign"); | |
| 52 | + | |
| 53 | + RtMallDynamicProperty.AppSecretDynamicProperty property = mallDynamicProperty.getByAppKey(appKey.toString()); | |
| 49 | 54 | if (Objects.isNull(property)) { |
| 50 | - throw new RtMartMallException(RtMarkErrorCode.E4001.getCode(), RtMarkErrorCode.E4001.getMessage()); | |
| 55 | + throw new RtMartMallException(RtMarkErrorCode.E4003.getCode(), RtMarkErrorCode.E4003.getMessage()); | |
| 51 | 56 | } |
| 52 | 57 | |
| 53 | 58 | try { |
| 54 | 59 | log.info("appKey:{}, secretKey:{}", property.getAppKey(), property.getAppSecret()); |
| 55 | 60 | String signKey = RtMallSignMd5Utils.generateSign(paramMap, property.getAppSecret()); |
| 56 | - Assert.isTrue(Objects.equals(signKey, paramMap.get("sign").toString()), "验签失败!"); | |
| 61 | + Assert.isTrue(Objects.equals(signKey, sign.toString()), "验签失败!"); | |
| 57 | 62 | } catch (Exception e) { |
| 58 | 63 | throw new RtMartMallException(RtMarkErrorCode.E4004.getCode(), RtMarkErrorCode.E4004.getMessage()); |
| 59 | 64 | } | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/type/OrderChannel.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.type; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * @ClassName OrderChannel.java | |
| 5 | + * @author dengwei | |
| 6 | + * @version 1.0.0 | |
| 7 | + * @Description OrderChannel | |
| 8 | + * @date 2025-12-25 11:18 | |
| 9 | + */ | |
| 10 | +public enum OrderChannel { | |
| 11 | + RT_MART("1", "大润发"), | |
| 12 | + SAM("2", "山姆"); | |
| 13 | + | |
| 14 | + public final String code; | |
| 15 | + public final String description; | |
| 16 | + | |
| 17 | + OrderChannel(String code, String description) { | |
| 18 | + this.code = code; | |
| 19 | + this.description = description; | |
| 20 | + } | |
| 21 | + | |
| 22 | + public String getCode() { | |
| 23 | + return code; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public String getDescription() { | |
| 27 | + return description; | |
| 28 | + } | |
| 29 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/type/OrderSource.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.type; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * @ClassName OrderSrouce.java | |
| 5 | + * @author dengwei | |
| 6 | + * @version 1.0.0 | |
| 7 | + * @Description OrderSource | |
| 8 | + * @date 2025-12-25 15:11 | |
| 9 | + */ | |
| 10 | +public enum OrderSource { | |
| 11 | + RT_MART(1, "大润发"), | |
| 12 | + SAM_CLUB(2, "山姆"); | |
| 13 | + | |
| 14 | + public final int code; | |
| 15 | + public final String name; | |
| 16 | + | |
| 17 | + OrderSource(int code, String name) { | |
| 18 | + this.code = code; | |
| 19 | + this.name = name; | |
| 20 | + } | |
| 21 | + | |
| 22 | + public int getCode() { | |
| 23 | + return code; | |
| 24 | + } | |
| 25 | + | |
| 26 | + public String getName() { | |
| 27 | + return name; | |
| 28 | + } | |
| 29 | +} | ... | ... |
cashier-mall/src/main/java/com/diligrp/cashier/mall/type/OrderType.java
0 → 100644
| 1 | +package com.diligrp.cashier.mall.type; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * @ClassName OrderType.java | |
| 5 | + * @author dengwei | |
| 6 | + * @version 1.0.0 | |
| 7 | + * @Description OrderType | |
| 8 | + * @date 2025-12-25 11:17 | |
| 9 | + */ | |
| 10 | +public enum OrderType { | |
| 11 | + OFFLINE_SCAN(1, "线下扫码购"), | |
| 12 | + API_SCAN(2, "接口扫码购"), | |
| 13 | + MINI_PROGRAM(3, "小程序"); | |
| 14 | + | |
| 15 | + private final int code; | |
| 16 | + private final String description; | |
| 17 | + | |
| 18 | + OrderType(int code, String description) { | |
| 19 | + this.code = code; | |
| 20 | + this.description = description; | |
| 21 | + } | |
| 22 | + | |
| 23 | + public int getCode() { | |
| 24 | + return code; | |
| 25 | + } | |
| 26 | + | |
| 27 | + public String getDescription() { | |
| 28 | + return description; | |
| 29 | + } | |
| 30 | +} | ... | ... |
cashier-shared/build.gradle
| ... | ... | @@ -7,8 +7,10 @@ dependencies { |
| 7 | 7 | api 'org.springframework.cloud:spring-cloud-starter-loadbalancer' |
| 8 | 8 | api 'org.springframework.cloud:spring-cloud-starter-openfeign' |
| 9 | 9 | api 'org.springframework.boot:spring-boot-starter-aop' |
| 10 | + api 'org.springframework.boot:spring-boot-starter-validation' | |
| 10 | 11 | api libs.cache.caffeine |
| 11 | 12 | api libs.common.collections4 |
| 13 | + api libs.google.guava | |
| 12 | 14 | |
| 13 | 15 | runtimeOnly libs.mysql.driver |
| 14 | 16 | } | ... | ... |
cashier-shared/src/main/java/com/diligrp/cashier/shared/ErrorCode.java
| ... | ... | @@ -16,6 +16,8 @@ public class ErrorCode { |
| 16 | 16 | public static final String OBJECT_NOT_FOUND = "300004"; |
| 17 | 17 | // 对象已存在 |
| 18 | 18 | public static final String OBJECT_ALREADY_EXISTS = "300005"; |
| 19 | + // 请求方式 | |
| 20 | + public static final String METHOD_NOT_SUPPORTED_ERROR = "300006"; | |
| 19 | 21 | // 数据并发修改 |
| 20 | 22 | public static final String SYSTEM_BUSY_ERROR = "301000"; |
| 21 | 23 | // 无效对象状态 | ... | ... |
cashier-shared/src/main/java/com/diligrp/cashier/shared/exception/DefaultExceptionHandler.java
| ... | ... | @@ -2,11 +2,24 @@ package com.diligrp.cashier.shared.exception; |
| 2 | 2 | |
| 3 | 3 | import com.diligrp.cashier.shared.ErrorCode; |
| 4 | 4 | import com.diligrp.cashier.shared.domain.Message; |
| 5 | +import jakarta.validation.ConstraintViolation; | |
| 6 | +import jakarta.validation.ConstraintViolationException; | |
| 5 | 7 | import org.slf4j.Logger; |
| 6 | 8 | import org.slf4j.LoggerFactory; |
| 9 | +import org.springframework.context.support.DefaultMessageSourceResolvable; | |
| 10 | +import org.springframework.validation.BindException; | |
| 11 | +import org.springframework.validation.BindingResult; | |
| 12 | +import org.springframework.validation.ObjectError; | |
| 13 | +import org.springframework.web.HttpRequestMethodNotSupportedException; | |
| 14 | +import org.springframework.web.bind.MethodArgumentNotValidException; | |
| 15 | +import org.springframework.web.bind.MissingServletRequestParameterException; | |
| 7 | 16 | import org.springframework.web.bind.annotation.ExceptionHandler; |
| 8 | 17 | import org.springframework.web.bind.annotation.RestControllerAdvice; |
| 9 | 18 | |
| 19 | +import java.util.List; | |
| 20 | +import java.util.Set; | |
| 21 | +import java.util.stream.Collectors; | |
| 22 | + | |
| 10 | 23 | @RestControllerAdvice |
| 11 | 24 | public class DefaultExceptionHandler { |
| 12 | 25 | private final Logger LOG = LoggerFactory.getLogger(this.getClass()); |
| ... | ... | @@ -23,6 +36,40 @@ public class DefaultExceptionHandler { |
| 23 | 36 | return Message.failure(ErrorCode.ILLEGAL_ARGUMENT_ERROR, ex.getMessage()); |
| 24 | 37 | } |
| 25 | 38 | |
| 39 | + @ExceptionHandler(value = ConstraintViolationException.class) | |
| 40 | + public Message<?> constraintViolationException(ConstraintViolationException exs) { | |
| 41 | + Set<ConstraintViolation<?>> violations = exs.getConstraintViolations(); | |
| 42 | + String msg = violations.stream().map(ConstraintViolation::getMessage) | |
| 43 | + .collect(Collectors.joining(",")); | |
| 44 | + return Message.failure(ErrorCode.ILLEGAL_ARGUMENT_ERROR, msg); | |
| 45 | + } | |
| 46 | + | |
| 47 | + @ExceptionHandler(value = {MethodArgumentNotValidException.class, BindException.class}) | |
| 48 | + public Message<?> methodArgumentNotValidException(Exception e) { | |
| 49 | + BindingResult bindingResult; | |
| 50 | + if (e instanceof MethodArgumentNotValidException) { | |
| 51 | + bindingResult = ((MethodArgumentNotValidException) e).getBindingResult(); | |
| 52 | + } else { | |
| 53 | + bindingResult = ((BindException) e).getBindingResult(); | |
| 54 | + } | |
| 55 | + List<ObjectError> allErrors = bindingResult.getAllErrors(); | |
| 56 | + String msg = allErrors.stream().map(DefaultMessageSourceResolvable::getDefaultMessage) | |
| 57 | + .collect(Collectors.joining("、")); | |
| 58 | + | |
| 59 | + return Message.failure(ErrorCode.ILLEGAL_ARGUMENT_ERROR, msg); | |
| 60 | + } | |
| 61 | + | |
| 62 | + @ExceptionHandler(MissingServletRequestParameterException.class) | |
| 63 | + public Message<?> missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException ex) { | |
| 64 | + return Message.failure(ErrorCode.ILLEGAL_ARGUMENT_ERROR, String.format("缺少参数:%s", ex.getParameterName())); | |
| 65 | + } | |
| 66 | + | |
| 67 | + @ExceptionHandler({HttpRequestMethodNotSupportedException.class}) | |
| 68 | + public Message<?> handleRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex) { | |
| 69 | + return Message.failure(ErrorCode.METHOD_NOT_SUPPORTED_ERROR, "请求方式错误!"); | |
| 70 | + } | |
| 71 | + | |
| 72 | + | |
| 26 | 73 | @ExceptionHandler(Exception.class) |
| 27 | 74 | public Message<?> defaultExceptionHandler(Exception ex) { |
| 28 | 75 | LOG.warn("assistant platform service exception", ex); | ... | ... |
cashier-shared/src/main/java/com/diligrp/cashier/shared/exception/PlatformServiceException.java
| ... | ... | @@ -30,10 +30,10 @@ public class PlatformServiceException extends RuntimeException { |
| 30 | 30 | super(message, ex); |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | - @Override | |
| 34 | - public Throwable fillInStackTrace() { | |
| 35 | - return stackTrace ? super.fillInStackTrace() : this; | |
| 36 | - } | |
| 33 | +// @Override | |
| 34 | +// public Throwable fillInStackTrace() { | |
| 35 | +// return stackTrace ? super.fillInStackTrace() : this; | |
| 36 | +// } | |
| 37 | 37 | |
| 38 | 38 | public String getCode() { |
| 39 | 39 | return code; | ... | ... |
cashier-shared/src/main/java/com/diligrp/cashier/shared/jackson/deserializer/SecondToDateDeserializer.java
0 → 100644
| 1 | +package com.diligrp.cashier.shared.jackson.deserializer; | |
| 2 | + | |
| 3 | +import com.fasterxml.jackson.core.JacksonException; | |
| 4 | +import com.fasterxml.jackson.core.JsonParser; | |
| 5 | +import com.fasterxml.jackson.databind.DeserializationContext; | |
| 6 | +import com.fasterxml.jackson.databind.JsonDeserializer; | |
| 7 | + | |
| 8 | +import java.io.IOException; | |
| 9 | +import java.time.Instant; | |
| 10 | +import java.time.LocalDateTime; | |
| 11 | +import java.time.ZoneOffset; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * @ClassName SecondToDateDeserializer.java | |
| 15 | + * @author dengwei | |
| 16 | + * @version 1.0.0 | |
| 17 | + * @Description SecondToDateDeserializer | |
| 18 | + * @date 2025-12-25 17:54 | |
| 19 | + */ | |
| 20 | +public class SecondToDateDeserializer extends JsonDeserializer<LocalDateTime> { | |
| 21 | + @Override | |
| 22 | + public LocalDateTime deserialize(JsonParser parser, DeserializationContext deserializationContext) throws IOException, JacksonException { | |
| 23 | + long timestamp = parser.getValueAsLong(); | |
| 24 | + return LocalDateTime.ofInstant( | |
| 25 | + Instant.ofEpochSecond(timestamp), | |
| 26 | + ZoneOffset.UTC | |
| 27 | + ); | |
| 28 | + } | |
| 29 | +} | ... | ... |
cashier-shared/src/main/java/com/diligrp/cashier/shared/jackson/serialization/DateToSecondSerializer.java
0 → 100644
| 1 | +package com.diligrp.cashier.shared.jackson.serialization; | |
| 2 | + | |
| 3 | +import com.fasterxml.jackson.core.JsonGenerator; | |
| 4 | +import com.fasterxml.jackson.databind.JsonSerializer; | |
| 5 | +import com.fasterxml.jackson.databind.SerializerProvider; | |
| 6 | + | |
| 7 | +import java.io.IOException; | |
| 8 | +import java.time.LocalDateTime; | |
| 9 | +import java.time.ZoneOffset; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @ClassName DateToSecondSerializer.java | |
| 13 | + * @author dengwei | |
| 14 | + * @version 1.0.0 | |
| 15 | + * @Description DateToSecondSerializer | |
| 16 | + * @date 2025-12-25 17:57 | |
| 17 | + */ | |
| 18 | +public class DateToSecondSerializer extends JsonSerializer<LocalDateTime> { | |
| 19 | + @Override | |
| 20 | + public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException { | |
| 21 | + gen.writeNumber(value.toInstant(ZoneOffset.UTC).getEpochSecond()); | |
| 22 | + } | |
| 23 | +} | ... | ... |
cashier-shared/src/main/java/com/diligrp/cashier/shared/util/DateUtils.java
| ... | ... | @@ -3,6 +3,7 @@ package com.diligrp.cashier.shared.util; |
| 3 | 3 | import com.diligrp.cashier.shared.Constants; |
| 4 | 4 | |
| 5 | 5 | import java.text.SimpleDateFormat; |
| 6 | +import java.time.Instant; | |
| 6 | 7 | import java.time.LocalDate; |
| 7 | 8 | import java.time.LocalDateTime; |
| 8 | 9 | import java.time.ZoneOffset; |
| ... | ... | @@ -51,11 +52,11 @@ public class DateUtils { |
| 51 | 52 | public static String format(Date date) { |
| 52 | 53 | return format(date, Constants.DATE_TIME_FORMAT); |
| 53 | 54 | } |
| 54 | - | |
| 55 | + | |
| 55 | 56 | public static LocalDateTime addDays(long amount) { |
| 56 | - LocalDateTime localDateTime = LocalDateTime.now(); | |
| 57 | - localDateTime.plusDays(amount); | |
| 58 | - return localDateTime; | |
| 57 | + LocalDateTime localDateTime = LocalDateTime.now(); | |
| 58 | + localDateTime.plusDays(amount); | |
| 59 | + return localDateTime; | |
| 59 | 60 | } |
| 60 | 61 | |
| 61 | 62 | public static String format(Date date, String format) { |
| ... | ... | @@ -112,17 +113,25 @@ public class DateUtils { |
| 112 | 113 | } |
| 113 | 114 | |
| 114 | 115 | /** |
| 115 | - * 获取时间戳 | |
| 116 | - */ | |
| 117 | - public static long parseMilliSecond(LocalDateTime localDateTime){ | |
| 118 | - return parseMilliSecond(localDateTime,null); | |
| 116 | + * 获取时间戳 | |
| 117 | + */ | |
| 118 | + public static long parseMilliSecond(LocalDateTime localDateTime) { | |
| 119 | + return parseMilliSecond(localDateTime, null); | |
| 119 | 120 | } |
| 120 | 121 | |
| 121 | - public static long parseMilliSecond(LocalDateTime localDateTime, String zoneNumStr){ | |
| 122 | + public static long parseMilliSecond(LocalDateTime localDateTime, String zoneNumStr) { | |
| 122 | 123 | //默认东八区 |
| 123 | - if (ObjectUtils.isEmpty(zoneNumStr)){ | |
| 124 | + if (ObjectUtils.isEmpty(zoneNumStr)) { | |
| 124 | 125 | zoneNumStr = "+8"; |
| 125 | 126 | } |
| 126 | 127 | return localDateTime.toInstant(ZoneOffset.of(zoneNumStr)).toEpochMilli(); |
| 127 | 128 | } |
| 129 | + | |
| 130 | + /** | |
| 131 | + * 时间戳-秒 | |
| 132 | + * | |
| 133 | + */ | |
| 134 | + public static long timestampInSeconds() { | |
| 135 | + return Instant.now().getEpochSecond(); | |
| 136 | + } | |
| 128 | 137 | } | ... | ... |
cashier-shared/src/main/java/com/diligrp/cashier/shared/util/UrlParamParserUtils.java
0 → 100644
| 1 | +package com.diligrp.cashier.shared.util; | |
| 2 | + | |
| 3 | +import com.diligrp.cashier.shared.exception.PlatformServiceException; | |
| 4 | + | |
| 5 | +import java.net.URI; | |
| 6 | +import java.net.URLDecoder; | |
| 7 | +import java.nio.charset.StandardCharsets; | |
| 8 | +import java.util.HashMap; | |
| 9 | +import java.util.Map; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * @ClassName UrlParamParserUtils.java | |
| 13 | + * @author dengwei | |
| 14 | + * @version 1.0.0 | |
| 15 | + * @Description UrlParamParserUtils | |
| 16 | + * @date 2025-12-25 15:34 | |
| 17 | + */ | |
| 18 | +public class UrlParamParserUtils { | |
| 19 | + public static Map<String, String> parseQueryParams(String url) { | |
| 20 | + try { | |
| 21 | + URI uri = new URI(url); | |
| 22 | + String query = uri.getQuery(); | |
| 23 | + if (query == null || query.isEmpty()) { | |
| 24 | + return new HashMap<>(); | |
| 25 | + } | |
| 26 | + | |
| 27 | + Map<String, String> params = new HashMap<>(); | |
| 28 | + String[] pairs = query.split("&"); | |
| 29 | + for (String pair : pairs) { | |
| 30 | + String[] keyValue = pair.split("=", 2); | |
| 31 | + String key = URLDecoder.decode(keyValue[0], StandardCharsets.UTF_8); | |
| 32 | + String value = keyValue.length > 1 ? URLDecoder.decode(keyValue[1], StandardCharsets.UTF_8) : ""; | |
| 33 | + params.put(key, value); | |
| 34 | + } | |
| 35 | + return params; | |
| 36 | + } catch (Exception e) { | |
| 37 | + throw new PlatformServiceException("Invalid URL"); | |
| 38 | + } | |
| 39 | + } | |
| 40 | +} | ... | ... |
gradle/libs.versions.toml
| ... | ... | @@ -9,6 +9,8 @@ mysqlDriverVersion = "8.0.33" |
| 9 | 9 | redissonVersion = "3.52.0" |
| 10 | 10 | caffeineVersion = "3.2.3" |
| 11 | 11 | collections4Version= "4.5.0" |
| 12 | +guavaVersion = "33.5.0-jre" | |
| 13 | + | |
| 12 | 14 | |
| 13 | 15 | [libraries] |
| 14 | 16 | #spring-boot-starter = {module = 'org.springframework.boot:spring-boot-starter', version.ref = 'springBootVersion'} |
| ... | ... | @@ -20,6 +22,7 @@ mysql-driver = {module = 'mysql:mysql-connector-java', version.ref = 'mysqlDrive |
| 20 | 22 | redisson-starter = {module = 'org.redisson:redisson-spring-boot-starter', version.ref = 'redissonVersion'} |
| 21 | 23 | cache-caffeine = {module = 'com.github.ben-manes.caffeine:caffeine', version.ref = 'caffeineVersion'} |
| 22 | 24 | common-collections4 = {module = 'org.apache.commons:commons-collections4', version.ref = 'collections4Version'} |
| 25 | +google-guava = {module = 'com.google.guava:guava', version.ref = 'guavaVersion'} | |
| 23 | 26 | |
| 24 | 27 | [plugins] |
| 25 | 28 | spring-boot = {id = 'org.springframework.boot', version.ref = 'springBootVersion'} | ... | ... |