Commit c5e6a6fb by wuwenlong

注册登陆

parent 5a98afa6
......@@ -17,7 +17,7 @@ import share.common.core.controller.BaseController;
import share.common.core.domain.AjaxResult;
import share.common.enums.BusinessType;
import share.system.domain.SConsumer;
import share.system.service.ISConsumerService;
import share.system.service.SConsumerService;
import share.common.utils.poi.ExcelUtil;
import share.common.core.page.TableDataInfo;
......@@ -32,7 +32,7 @@ import share.common.core.page.TableDataInfo;
public class SConsumerController extends BaseController
{
@Autowired
private ISConsumerService sConsumerService;
private SConsumerService sConsumerService;
/**
* 查询会员用户列表
......
......@@ -55,9 +55,9 @@ spring:
druid:
# 主库数据源
master:
url: jdbc:mysql://10.106.30.135:3306/xzdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
url: jdbc:mysql://127.0.0.1:3306/xzdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
username: root
password: root
password: 1234
# 从库数据源
slave:
# 从数据源开关/默认关闭
......
......@@ -131,7 +131,51 @@
<version>3.3.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.59</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.16</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.7</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.64</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package share.common.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target(METHOD)
public @interface AccessLimit {
int seconds();
int maxCount();
boolean needLogin() default true;
}
package share.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/**
* RestTemplate配置组件
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
restTemplate.getMessageConverters().add(new WxMappingJackson2HttpMessageConverter());
return restTemplate;
}
@Bean
public ClientHttpRequestFactory httpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(10000);//ms
factory.setConnectTimeout(15000);//ms
return factory;
}
//解决微信返回json Content-Type 值却是 text/plain 的问题
public class WxMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
public WxMappingJackson2HttpMessageConverter(){
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.TEXT_PLAIN);
mediaTypes.add(MediaType.TEXT_HTML);
setSupportedMediaTypes(mediaTypes);
}
}
}
package share.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 读取项目相关配置
*
* @author ruoyi
*/
@Data
@Component
@ConfigurationProperties(prefix = "wechat")
public class WeChatConfig
{
private String appId;
private String appSecret;
private String publicAppId;
private String publicAppSecret;
private Integer wechatJsApiDebug;
}
......@@ -9,6 +9,86 @@ import io.jsonwebtoken.Claims;
*/
public class Constants
{
//测试环境,经测试需要,手机验证码测试环境可以不需要就能登录,value为1,则不验证验证码
public static final String PHONE_TEST_KEY = "phone_test_key";
//通过uuid缓存的key 查找对应的 token数据 WX_TOKEN_USER:TOKEN
public static final String WX_TOKEN_BY_USERID = "WX_TOKEN_BY_USERID:";
public static final long TOKEN_EXPRESS_MINUTES = (60 * 24); //24小时
//用户登token redis存储前缀
public static final String USER_TOKEN_REDIS_KEY_PREFIX = "TOKEN_USER:";
//小程序用户登token redis存储前缀
public static final String WX_USER_TOKEN_REDIS_KEY_PREFIX = "WX_TOKEN_USER:";
//支付方式
public static final String PAY_TYPE_WE_CHAT = "weixin"; //微信支付
public static final String PAY_TYPE_YUE = "yue"; //余额支付
public static final String PAY_TYPE_OFFLINE = "offline"; //线下支付
public static final String PAY_TYPE_ALI_PAY = "alipay"; //支付宝
public static final String ORDER_NO_PREFIX_WE_CHAT = "wx"; //微信平台下单订单号前缀
public static final String ORDER_NO_PREFIX_H5 = "h5"; //微信平台下单订单号前缀
//第三方登录token类型
public static final int THIRD_LOGIN_TOKEN_TYPE_PUBLIC = 1; //公众号
public static final int THIRD_LOGIN_TOKEN_TYPE_PROGRAM = 2; //小程序
public static final int THIRD_LOGIN_TOKEN_TYPE_UNION_ID = 3; //unionid
public static final int THIRD_ADMIN_LOGIN_TOKEN_TYPE_PUBLIC = 4; //后台登录公众号
public static final int THIRD_LOGIN_TOKEN_TYPE_IOS_WX = 5; //ios 微信
public static final int THIRD_LOGIN_TOKEN_TYPE_ANDROID_WX = 6; //android微信
public static final int THIRD_LOGIN_TOKEN_TYPE_IOS = 7; //ios
public static final int NUM_ZERO = 0;
public static final int NUM_ONE = 1;
public static final int NUM_TWO = 2;
public static final int NUM_THREE = 3;
public static final int NUM_FOUR = 4;
public static final int NUM_FIVE = 5;
public static final int NUM_SEVEN = 7;
public static final int NUM_TEN = 10;
public static final int NUM_ONE_HUNDRED = 100;
//验证码过期时间
public static final String CONFIG_KEY_SMS_CODE_EXPIRE = "1";
//头部 token令牌key
public static final String HEADER_AUTHORIZATION_KEY = "Authori-zation";
public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DATE_FORMAT_UTC = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
public static final String DATE_FORMAT_DATE = "yyyy-MM-dd";
public static final String DATE_FORMAT_YEAR = "yyyy";
public static final String DATE_FORMAT_MONTH_DATE = "MM-dd";
public static final String DATE_FORMAT_MONTH = "yyyy-MM";
public static final String DATE_TIME_FORMAT_NUM = "yyyyMMddHHmmss";
public static final String DATE_FORMAT_NUM = "yyyyMMdd";
public static final String DATE_FORMAT_START = "yyyy-MM-dd 00:00:00";
public static final String DATE_FORMAT_END = "yyyy-MM-dd 23:59:59";
public static final String DATE_FORMAT_MONTH_START = "yyyy-MM-01 00:00:00";
public static final String DATE_FORMAT_YEAR_START = "yyyy-01-01 00:00:00";
public static final String DATE_FORMAT_YEAR_END = "yyyy-12-31 23:59:59";
public static final String DATE_FORMAT_HH_MM_SS = "HH:mm:ss";
public static final String DATE_FORMAT_START_PEREND = "00:00:00";
public static final String DATE_FORMAT_END_PEREND = "23:59:59";
public static final String DATE_FORMAT_HHMM = "yyyy-MM-dd HH:mm";
//会员搜索日期类型
public static final String SEARCH_DATE_DAY = "today"; //今天
public static final String SEARCH_DATE_YESTERDAY = "yesterday"; //昨天
public static final String SEARCH_DATE_LATELY_7 = "lately7"; //最近7天
public static final String SEARCH_DATE_LATELY_30 = "lately30"; //最近30天
public static final String SEARCH_DATE_WEEK = "week"; //本周
public static final String SEARCH_DATE_PRE_WEEK = "preWeek"; //上周
public static final String SEARCH_DATE_MONTH = "month"; //本月
public static final String SEARCH_DATE_PRE_MONTH = "preMonth"; //上月
public static final String SEARCH_DATE_YEAR = "year"; //年
public static final String SEARCH_DATE_PRE_YEAR = "preYear"; //上一年
// 时间类型开始时间
public static String DATE_TIME_TYPE_BEGIN = "begin";
// 时间类型结束时间
public static String DATE_TIME_TYPE_END = "end";
/**
* UTF-8 字符集
*/
......
package share.common.constant;
/**
* 支付相关常量类
*/
public class PayConstants {
//支付方式
public static final String PAY_TYPE_WE_CHAT = "weixin"; //微信支付
public static final String PAY_TYPE_YUE = "yue"; //余额支付
public static final String PAY_TYPE_OFFLINE = "offline"; //线下支付
public static final String PAY_TYPE_ALI_PAY = "alipay"; //支付宝
public static final String PAY_TYPE_ZERO_PAY = "zeroPay"; // 零元付
//支付渠道
public static final String PAY_CHANNEL_WE_CHAT_H5 = "weixinh5"; //H5唤起微信支付
public static final String PAY_CHANNEL_WE_CHAT_PUBLIC = "public"; //公众号
public static final String PAY_CHANNEL_WE_CHAT_PROGRAM = "routine"; //小程序
public static final String PAY_CHANNEL_WE_CHAT_APP_IOS = "weixinAppIos"; //微信App支付ios
public static final String PAY_CHANNEL_WE_CHAT_APP_ANDROID = "weixinAppAndroid"; //微信App支付android
public static final String PAY_CHANNEL_ALI_PAY = "alipay"; //支付宝支付
public static final String PAY_CHANNEL_ALI_APP_PAY = "appAliPay"; //支付宝App支付
public static final String WX_PAY_TRADE_TYPE_JS = "JSAPI";
public static final String WX_PAY_TRADE_TYPE_H5 = "MWEB";
//微信支付接口请求地址
public static final String WX_PAY_API_URL = "https://api.mch.weixin.qq.com/";
// 微信统一预下单
public static final String WX_PAY_API_URI = "pay/unifiedorder";
// 微信查询订单
public static final String WX_PAY_ORDER_QUERY_API_URI = "pay/orderquery";
// 微信支付回调地址
public static final String WX_PAY_NOTIFY_API_URI = "/api/admin/payment/callback/wechat";
// 微信退款回调地址
public static final String WX_PAY_REFUND_NOTIFY_API_URI = "/api/admin/payment/callback/wechat/refund";
public static final String WX_PAY_SIGN_TYPE_MD5 = "MD5";
public static final String WX_PAY_SIGN_TYPE_SHA256 = "HMAC-SHA256";
public static final String PAY_BODY = "支付中心-订单支付";
public static final String FIELD_SIGN = "sign";
// 公共号退款
public static final String WX_PAY_REFUND_API_URI= "secapi/pay/refund";
}
package share.common.constant;
/**
* 正则表达式类
*/
public class RegularConstants {
//数字
public static final String NUMBER = "^-?[0-9]+";
//邮箱
public static final String EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$";
//手机
public static final String PHONE = "^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$";
//只校验手机为11位
public static final String PHONE_TWO = "^1\\d{10}$";
//整数或者小数:
public static final String INTEGER_OR_FLOAT = "^[0-9]+=\\.{0,1}[0-9]{0,2}$";
//n位的数字
public static final String NUMBER_LEN = "^\\d{n}$";
//n位的数字
public static final String NUMBER_MIN_LEN = "^\\d{n,}$";
//m~n位的数字
public static final String NUMBER_LEN_RANGE = "^\\d{m,n}$";
//零和非零开头的数字
public static final String NUMBER_LEN_UNSIGNED_CONTAINS_ZERO = "^(0|[1-9][0-9]*)$";
//有两位小数的正实数
public static final String FLOAT_TWO_LEN = "^[0-9]+(.[0-9]{2})?$";
//有两位小数的正实数
public static final String FLOAT_LEN_RANGE = "^[0-9]+(.[0-9]{1,3})?$";
//非零的正整数
public static final String NUMBER_UNSIGNED = "^\\+?[1-9][0-9]*$";
//非0的负数
public static final String NUMBER_NOT_UNSIGNED = "^\\-[1-9][]0-9\"*$";
//3位字符串
public static final String STRING_THREE_LEN = "^.{3}$";
//所有英文字母
public static final String STRING_ALL_EN_CHARS = "^[A-Za-z]+$";
//由26个大写英文字母组成的字符串
public static final String STRING_UPPER_EN_CHARS = "^[A-Z]+$";
//由26个小写英文字母组成的字符串
public static final String STRING_LOWER_EN_CHARS = "^[a-z]+$";
//由数字和26个英文字母组成的字符串
public static final String STRING_ALL_EN_CHARS_AND_NUMBER = "^[A-Za-z0-9]+$";
//由数字和26个英文字母组成的字符串
public static final String STRING_ALL_EN_CHARS_AND_UNDER_LINE = "^\\w+";
//验证用户密码, 正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。
public static final String PASSWORD = "^[a-zA-Z]\\w{5,17}$";
//验证码, 正确格式为:4位数字验证码。
public static final String SMS_VALIDATE_CODE_NUM = "^\\d{6}$";
//验证码, 正确格式为:6位数字验证码。
public static final String VALIDATE_CODE_NUM_SIX = "^\\d{6}$";
//汉字
public static final String CHINESE = "^[\\u4e00-\\u9fa5]{0,}$";
//url http开头
public static final String URL = "^http://([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?$";
//电话 正确格式为:"XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"
public static final String TEL = "^(\\(\\d{3,4}-)|\\d{3.4}-)?\\d{7,8}$";
//验证身份证号 (15位或18位数字)
public static final String ID_CARD = "^\\d{15}|\\d{18}$";
// 验证一年的12个月 正确格式为:"01"~"09"和"1"~"12"
public static final String MONTH = "^(0?[1-9]|1[0-2])$";
// 验证一个月的31天 正确格式为;"01"~"09"和"1"~"31"
public static final String DAY = "^((0?[1-9])|((1|2)[0-9])|30|31)$";
// 匹配空行的正则表达式
public static final String EMPTY_LINE = "\\n[\\s| ]*\\r";
// 匹配html标签的正则表达式
public static final String HTML_TAG = "<(.*)>(.*)<\\/(.*)>|<(.*)\\/>";
// 匹配首尾空格的正则表达式
public static final String TRIM = "(^\\s*)|(\\s*$)";
}
package share.common.constant;
/**
* 短信常量类
*/
public class SmsConstants {
/** 接口异常错误码 */
public static final Integer SMS_ERROR_CODE = 400;
/** 短信发送队列key */
public static final String SMS_SEND_KEY = "sms_send_list";
/** 手机验证码redis key */
public static final String SMS_VALIDATE_PHONE = "sms:validate:code:";
/**
* ---------------------
* 短信模版配置开关常量
* ---------------------
*/
/** 验证码 */
public static final String SMS_CONFIG_VERIFICATION_CODE = "verificationCode";
// public static final Integer SMS_CONFIG_VERIFICATION_CODE_TEMP_ID = 518076;
/** 验证码模板ID */
public static final Integer SMS_CONFIG_VERIFICATION_CODE_TEMP_ID = 538393;
/** 支付成功短信提醒 */
public static final String SMS_CONFIG_LOWER_ORDER_SWITCH = "lowerOrderSwitch";
/** 支付成功短信提醒模版ID */
public static final Integer SMS_CONFIG_LOWER_ORDER_SWITCH_TEMP_ID = 520268;
/** 发货短信提醒 */
public static final String SMS_CONFIG_DELIVER_GOODS_SWITCH = "deliverGoodsSwitch";
/** 发货短信提醒模版ID */
public static final Integer SMS_CONFIG_DELIVER_GOODS_SWITCH_TEMP_ID = 520269;
/** 确认收货短信提醒 */
public static final String SMS_CONFIG_CONFIRM_TAKE_OVER_SWITCH = "confirmTakeOverSwitch";
/** 确认收货短信提醒模版ID */
public static final Integer SMS_CONFIG_CONFIRM_TAKE_OVER_SWITCH_TEMP_ID = 520271;
/** 用户下单管理员短信提醒 */
public static final String SMS_CONFIG_ADMIN_LOWER_ORDER_SWITCH = "adminLowerOrderSwitch";
/** 用户下单管理员短信提醒模版ID */
public static final Integer SMS_CONFIG_ADMIN_LOWER_ORDER_SWITCH_TEMP_ID = 520272;
/** 支付成功管理员短信提醒 */
public static final String SMS_CONFIG_ADMIN_PAY_SUCCESS_SWITCH = "adminPaySuccessSwitch";
/** 支付成功管理员短信提醒模版ID */
public static final Integer SMS_CONFIG_ADMIN_PAY_SUCCESS_SWITCH_TEMP_ID = 520273;
/** 用户确认收货管理员短信提醒 */
public static final String SMS_CONFIG_ADMIN_REFUND_SWITCH = "adminRefundSwitch";
/** 用户确认收货管理员短信提醒模版ID */
public static final Integer SMS_CONFIG_ADMIN_REFUND_SWITCH_TEMP_ID = 520422;
/** 用户发起退款管理员短信提醒 */
public static final String SMS_CONFIG_ADMIN_CONFIRM_TAKE_OVER_SWITCH = "adminConfirmTakeOverSwitch";
/** 用户发起退款管理员短信提醒模版ID */
public static final Integer SMS_CONFIG_ADMIN_CONFIRM_TAKE_OVER_SWITCH_TEMP_ID = 520274;
/** 改价短信提醒 */
public static final String SMS_CONFIG_PRICE_REVISION_SWITCH = "priceRevisionSwitch";
/** 改价短信提醒模版ID */
public static final Integer SMS_CONFIG_PRICE_REVISION_SWITCH_TEMP_ID = 528288;
/** 订单未支付 */
public static final String SMS_CONFIG_ORDER_PAY_FALSE = "orderPayFalse";
/** 订单未支付模版ID */
public static final Integer SMS_CONFIG_ORDER_PAY_FALSE_TEMP_ID = 528116;
/**
* 短信类型
* 短信模版配置开关常量
*/
/** 验证码 */
public static final int SMS_CONFIG_TYPE_VERIFICATION_CODE = 1;
/** 支付成功短信提醒 */
public static final int SMS_CONFIG_TYPE_LOWER_ORDER_SWITCH = 2;
/** 发货短信提醒 */
public static final int SMS_CONFIG_TYPE_DELIVER_GOODS_SWITCH = 3;
/** 确认收货短信提醒 */
public static final int SMS_CONFIG_TYPE_CONFIRM_TAKE_OVER_SWITCH = 4;
/** 用户下单管理员短信提醒 */
public static final int SMS_CONFIG_TYPE_ADMIN_LOWER_ORDER_SWITCH = 5;
/** 支付成功管理员短信提醒 */
public static final int SMS_CONFIG_TYPE_ADMIN_PAY_SUCCESS_SWITCH = 6;
/** 用户确认收货管理员短信提醒 */
public static final int SMS_CONFIG_TYPE_ADMIN_REFUND_SWITCH = 7;
/** 用户发起退款管理员短信提醒 */
public static final int SMS_CONFIG_TYPE_ADMIN_CONFIRM_TAKE_OVER_SWITCH = 8;
/** 改价短信提醒 */
public static final int SMS_CONFIG_TYPE_PRICE_REVISION_SWITCH = 9;
/** 订单未支付 */
public static final int SMS_CONFIG_TYPE_ORDER_PAY_FALSE = 10;
/**
* 分销关系绑定成功
*/
public static final int SMS_CONFIG_TYPE_BIND_SUCCESS_UP = 11;
/**
* 支付成功给上级发送消息
*/
public static final int SMS_CONFIG_TYPE_PAY_SUCCESS_UP = 12;
/**
* 分销关系绑定成功
*/
public static final int SMS_CONFIG_TYPE_BIND_SUCCESS_DOWN = 13;
/** 发送短信参数模板 */
public static final String SMS_COMMON_PARAM_FORMAT = "param[{}]";
}
package share.common.constant;
/**
*/
public class SmsConts {
public final static String BASE_URL = "http://sms.xiaoyantong.com/sms";
public final static String USERNAME = "332450";
public final static String PASSWORD = "ML4pI31j";
/**
* 接口返回状态:成功
*/
public final static Integer SUCCESS_CODE = 0;
/**
* 查询短信模板接口
*/
public final static String queryTemplate = "/api/queryTemplate";
/**
* 短信一对一发送接口
*/
public final static String sendMessageOne = "/api/sendMessageOne";
/**
* 查询签名
*/
public final static String querySignature = "/api/querySignature";
/**
* 短信一对一发送接口
*/
public final static String smsCodeTemp = "【消费保】您的验证码是:{0},有效期为{1}分钟。如非本人操作,可不予理会。";
}
......@@ -2,6 +2,7 @@ package share.common.core.domain;
import java.io.Serializable;
import share.common.constant.HttpStatus;
import share.common.exception.ExceptionCodeEnum;
/**
* 响应信息主体
......@@ -64,6 +65,11 @@ public class R<T> implements Serializable
return restResult(null, code, msg);
}
public static <T> R<T> fail(ExceptionCodeEnum exceptionCodeEnum)
{
return restResult(null, exceptionCodeEnum.getCode(), exceptionCodeEnum.getMessage());
}
private static <T> R<T> restResult(T data, int code, String msg)
{
R<T> apiResult = new R<>();
......
package share.common.core.redis;
public class AccessKey extends BasePrefix {
private AccessKey(int expireSeconds, String prefix) {
super(expireSeconds, prefix);
}
public static AccessKey withExpire(int expireSeconds) {
return new AccessKey(expireSeconds, "access");
}
}
package share.common.core.redis;
public class ActivityKey extends BasePrefix {
public ActivityKey(String prefix) {
super(prefix);
}
public static ActivityKey getActivityPre = new ActivityKey("activityList");
public static ActivityKey getActivityRelationPre = new ActivityKey("activityRelation");
public static ActivityKey getPurchaseSuccessUserListPre = new ActivityKey("purchaseSuccessUserList");
public static ActivityKey getPreferenceSuccessUserListPre = new ActivityKey("preferenceSuccessUserList");
}
package share.common.core.redis;
import org.apache.commons.lang3.StringUtils;
public abstract class BasePrefix {
private long expireSeconds;
private String prefix;
private String field;
public BasePrefix(String prefix) {//0代表永不过期
this(0, prefix);
}
public BasePrefix(String prefix, String field) {
this.prefix = prefix;
this.field = field;
}
public BasePrefix(long expireSeconds, String prefix) {
this.expireSeconds = expireSeconds;
this.prefix = prefix;
}
public BasePrefix(long expireSeconds, String prefix, String field) {
this.expireSeconds = expireSeconds;
this.prefix = prefix;
this.field = field;
}
public long expireSeconds() {//默认0代表永不过期
return expireSeconds;
}
public String getPrefix() {
String className = getClass().getSimpleName();
return className+"."+this.prefix;
}
public String getPrefixNoClass() {
return this.prefix;
}
public String getDynamicPrefix(String dynamicPrefix) {
String className = getClass().getSimpleName();
return className+"."+this.prefix+(StringUtils.isNotEmpty(dynamicPrefix)?dynamicPrefix:"");
}
public String getDynamicPrefixNoClass(String dynamicPrefix) {
return this.prefix+(StringUtils.isNotEmpty(dynamicPrefix)?dynamicPrefix:"");
}
public String getField() {
return this.field;
}
public String getDynamicField(String dynamicField) {
return this.field+(StringUtils.isNotEmpty(dynamicField)?dynamicField:"");
}
}
/**
*
*/
package share.common.enums;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public enum YesNoEnum {
yes(1,true,"是","激活","","","","","","",""),
no(0,false,"否","冻结","","","","","","","");
private Integer index;
private Boolean flag;
private String display;
private String display_2;
private String display_3;
private String display_4;
public String getDisplay_5() {
return display_5;
}
private String display_5;
private String display_6;
private String display_7;
private String display_8;
private String display_9;
public String getDisplay_8() {
return display_8;
}
public String getDisplay_6() {
return display_6;
}
public String getDisplay_9() {
return display_9;
}
private YesNoEnum(Integer index, Boolean flag, String display, String display_2, String display_3, String display_4, String display_5, String display_6, String display_7, String display_8, String display_9){
this.index = index;
this.flag = flag;
this.display =display;
this.display_2 = display_2;
this.display_3 = display_3;
this.display_4 = display_4;
this.display_5 = display_5;
this.display_6 = display_6;
this.display_7 = display_7;
this.display_8 = display_8;
this.display_9 = display_9;
}
public String getDisplay_7() {
return display_7;
}
public Integer getIndex() {
return index;
}
public Boolean getFlag() {
return flag;
}
public String getDisplay() {
return display;
}
public String getDisplay_2() {
return display_2;
}
public String getDisplay_3() {
return display_3;
}
public String getDisplay_4() {
return display_4;
}
public static String getNameByIndex(Integer index){
for (YesNoEnum yesNo : YesNoEnum.values()) {
if (yesNo.index.equals(index)){
return yesNo.display;
}
}
return "";
}
public static String getHaveNameByIndex(Integer index){
for (YesNoEnum yesNo : YesNoEnum.values()) {
if (yesNo.index.equals(index)){
return yesNo.display_3;
}
}
return "";
}
public static String getAgreeNameByIndex(Integer index){
for (YesNoEnum yesNo : YesNoEnum.values()) {
if (yesNo.index.equals(index)){
return yesNo.display_4;
}
}
return "";
}
public static String getSuccessNameByIndex(Integer index){
for (YesNoEnum yesNo : YesNoEnum.values()) {
if (yesNo.index.equals(index)){
return yesNo.display_8;
}
}
return "";
}
public static Integer getIndexByName(String name){
for (YesNoEnum yesNo : YesNoEnum.values()) {
if (yesNo.display_2.equals(name)){
return yesNo.index;
}
}
return null;
}
public static JSONArray getJsonArrayMeta(){
JSONArray array = new JSONArray();
for (YesNoEnum type: YesNoEnum.values()){
JSONObject object = new JSONObject();
object.put("name", type.display);
object.put("code", type.index);
array.add(object);
}
return array;
}
public static JSONArray getJsonArrayHaveMeta(){
JSONArray array = new JSONArray();
for (YesNoEnum type: YesNoEnum.values()){
JSONObject object = new JSONObject();
object.put("name", type.display_3);
object.put("code", type.index);
array.add(object);
}
return array;
}
public static JSONArray getJsonArrayMetaStr(){
JSONArray array = new JSONArray();
for (YesNoEnum type: YesNoEnum.values()){
JSONObject object = new JSONObject();
object.put("name", type.display);
object.put("code", type.index.toString());
array.add(object);
}
return array;
}
// public static List<OptionIntVo> getOptionVos() {
// YesNoEnum[] enumArr = YesNoEnum.values();
// List<OptionIntVo> optionList = Arrays.stream(enumArr).map(item ->{
// OptionIntVo optionVo = new OptionIntVo();
// optionVo.setCode(item.getIndex());
// optionVo.setName(item.getDisplay());
// return optionVo;
// }).collect(Collectors.toList());
// return optionList;
// }
}
package share.common.exception;
/**
* Exception 拦截
*/
public enum ExceptionCodeEnum implements ExceptionHandler{
// 数据操作错误定义
SUCCESS(200, "操作成功"),
FAILED(500, "操作失败"),
PRAM_NOT_MATCH(400, "参数不正确"),
VALIDATE_FAILED(400, "参数检验失败"),
UNAUTHORIZED(401, "未登录或token过期,请登录!"),
FORBIDDEN(403, "没有相关权限"),
NOT_FOUND(404, "没有找到相关数据"),
ERROR(500, "系统异常"),
ACCESS_LIMIT_REACHED(500104, "访问太频繁!")
;
private int code;
private String message;
private ExceptionCodeEnum(int code, String message){
this.code = code;
this.message = message;
}
@Override
public int getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}
package share.common.exception;
/**
* Exception 接口定义
*/
public interface ExceptionHandler {
int getCode();
String getMessage();
}
package share.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections4.CollectionUtils;
import share.common.core.redis.ActivityKey;
import share.common.core.redis.RedisUtil;
import java.util.ArrayList;
/**
* 通用工具类
*/
@Slf4j
public class CommonUtil {
/**
* 随机生成密码
*
* @param phone 手机号
* @return 密码
* 使用des方式加密
*/
public static String createPwd(String phone) {
String password = "Abc" + BaseUtil.randomCount(10000, 99999);
return BaseUtil.encryptPassword(password, phone);
}
/**
* 随机生成用户昵称
*
* @param phone 手机号
* @return 昵称
*/
public static String createNickName(String phone) {
return DigestUtils.md5Hex(phone + DateUtil.getNowTime()).
subSequence(0, 12).
toString();
}
/**
* 验证,活动的购买用户是否再次购买
*
* @param activityId 活动id
* @param activityId 用户id
* @param redisUtil redis工具类
* @return
*/
public static boolean checkPurchaseUser(Long activityId, Long userId, RedisUtil redisUtil) {
if (activityId == null || activityId < 0 || userId == null || redisUtil == null) {
log.error("CommonUtil method checkPurchaseUser param is null activityId-{},userId-{}", activityId, userId);
return false;
}
try {
boolean isOk = checkPurchaseUserInner(activityId, userId, redisUtil);
return isOk;
} catch (Exception e) {
log.error("CommonUtil method checkPurchaseUser error: ", e);
return false;
}
}
private static boolean checkPurchaseUserInner(Long activityId, Long userId, RedisUtil redisUtil) {
String purchaseKey = ActivityKey.getPurchaseSuccessUserListPre.getPrefixNoClass() + activityId;
ArrayList<String> userIdList = redisUtil.get(purchaseKey);
if (CollectionUtils.isNotEmpty(userIdList)) {
for (String u : userIdList) {
if (u.equals(String.valueOf(userId))) {
return true;
}
}
}
return false;
}
}
package share.common.utils;
import com.alibaba.fastjson2.JSON;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class JsonConvertUtil {
private static final Log log = LogFactory.getLog(JsonConvertUtil.class);
//将对象转json字符串
public static String write2JsonStr(Object o){
String resultStr = "";
if(null == o){
return resultStr;
}
try {
resultStr = JSON.toJSONString(o);
}catch (Exception e){
log.error("write2JsonStr() exception: " + e.getMessage());
resultStr = "";
}
return resultStr;
}
}
package share.common.utils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
/**
* Request工具类
*/
public class RequestUtil extends HttpServlet{
public static HttpServletRequest getRequest() {
if(RequestContextHolder.getRequestAttributes() != null){
return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
}
return null;
}
public static HashMap<String, Object> getRequestParamAndHeader(){
try{
HttpServletRequest request = getRequest();
if(request == null){
return null;
}
//request信息
HashMap<String, Object> data = new HashMap<>();
HashMap<String, Object> requestParams = new HashMap<>();
Enumeration<String> paraNames = request.getParameterNames();
if(paraNames != null){
for(Enumeration<String> enumeration =paraNames;enumeration.hasMoreElements();){
String key= enumeration.nextElement();
requestParams.put(key, request.getParameter(key));
}
}
HashMap<String, Object> requestFilter = new HashMap<>();
Enumeration<String> attributeNames = request.getAttributeNames();
if(attributeNames != null){
for ( Enumeration<String> attributeNames1 = attributeNames; attributeNames1.hasMoreElements();) {
String key= attributeNames1.nextElement();
if(key.contains("request_")){
requestFilter.put(key, request.getAttribute(key));
}
}
}
data.put("url", request.getRequestURL());
data.put("uri", request.getRequestURI());
data.put("method", request.getMethod());
data.put("request", requestParams);
data.put("request_filter", requestFilter);
//header 信息
Enumeration<String> headerNames = request.getHeaderNames();
HashMap<String, Object> headerParams = new HashMap<>();
if(headerNames != null){
for(Enumeration<String> enumeration = headerNames;enumeration.hasMoreElements();){
String key= enumeration.nextElement();
String value=request.getHeader(key);
headerParams.put(key, value);
}
}
data.put("header", headerParams);
return data;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
public static String getDomain(){
HttpServletRequest request = getRequest();
if(request == null){
return null;
}
return request.getServerName() + ":" + request.getServerPort();
}
public static String getUri(HttpServletRequest request){
String uri = request.getRequestURI();
List<String> list = BaseUtil.stringToArrayStrRegex(uri, "/");
list.removeIf(StringUtils::isNumeric); //去掉url中的数字参数
list.removeIf(c -> c.contains(","));// 去掉url中的逗号分隔参数
return StringUtils.join(list, "/");
}
}
package share.common.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import share.common.constant.SmsConts;
import share.common.utils.http.RestTemplateUtil;
import share.common.exception.base.BaseException;
/**
* @author wuwenlong
* @date 2022年10月13日 15:33
*/
@Component
public class SmsUtil {
@Autowired
private RestTemplateUtil restTemplateUtil;
/**
* post请求from表单模式提交
*/
public JSONObject postFrom(String url, JSONObject param) {
JSONObject result = restTemplateUtil.postHtoolJsonDataAndReturnJson(url, param);
return checkResult(result);
}
/**
* 检测结构请求返回的数据
*
* @param result 接口返回的结果
* @return JSONObject
* @author Mr.Zhang
* @since 2020-04-16
*/
private JSONObject checkResult(JSONObject result) {
if (result == null) {
throw new BaseException("短信平台接口异常!");
}
if (!SmsConts.SUCCESS_CODE.equals(result.getInt("code"))) {
throw new BaseException("短信平台接口: " + result.getStr("message"));
}
return result;
}
public String sign(long timestamp) {
return SecureUtil.md5(SmsConts.USERNAME + timestamp + SecureUtil.md5(SmsConts.PASSWORD));
}
public static void main(String[] args) {
Integer code = BaseUtil.randomCount(111111, 999999);
long timestamp = DateUtil.date().getTime();
JSONObject param = JSONUtil.createObj();
param.put("userName", SmsConts.USERNAME);
param.put("timestamp", timestamp);
param.put("sign", SecureUtil.md5(SmsConts.USERNAME + timestamp + SecureUtil.md5(SmsConts.PASSWORD)));
// JSONObject json = JSONUtil.createObj();
// json.put("phone", "18771045387");
// json.put("content", MessageFormat.format(SmsConts.smsCodeTemp, code.toString(), 3));
// JSONArray array = JSONUtil.createArray();
// array.add(json);
// param.put("messageList",array);
System.out.println(JSONUtil.toJsonStr(param));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
HttpEntity<JSONObject> requestEntity = new HttpEntity<>(param, headers);
RestTemplate restTemplate = new RestTemplate();
cn.hutool.json.JSONObject body = restTemplate.postForEntity(SmsConts.BASE_URL + SmsConts.querySignature, requestEntity, cn.hutool.json.JSONObject.class).getBody();
System.out.println(JSONUtil.toJsonStr(body));
}
}
package share.common.utils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.Xpp3Driver;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import share.common.utils.wx.WXPayXmlUtil;
import javax.servlet.http.HttpServletRequest;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* XML 工具类
*/
public class XmlUtil {
public static Map<String, String> xmlToMap(HttpServletRequest request) {
Map<String, String> map = new HashMap<>();
SAXReader reader = new SAXReader();
InputStream in = null;
try {
in = request.getInputStream();
Document doc = reader.read(in);
Element root = doc.getRootElement();
List<Element> list = root.elements();
for (Element element : list) {
map.put(element.getName(), element.getText());
}
} catch (IOException | DocumentException e) {
e.printStackTrace();
} finally {
try {
assert in != null;
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return map;
}
/**
* 将发送消息封装成对应的xml格式
*/
public static HashMap<String, Object> xmlToMap(String strxml) throws Exception {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
HashMap<String, Object> map = new HashMap<>();
SAXReader reader = new SAXReader();
InputStream inputStream = new ByteArrayInputStream(strxml.getBytes(StandardCharsets.UTF_8));
if (StringUtils.isBlank(strxml)) {
return null;
}
Document document = reader.read(inputStream);
Element root = document.getRootElement();
List<Element> list = root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
inputStream.close();
return map;
}
/**
* 将发送消息封装成对应的xml格式
*/
public static String objectToXml(Object object) {
XStream xstream = new XStream(new Xpp3Driver(new NoNameCoder())); //不需要转义
xstream.alias("xml", object.getClass());
return xstream.toXML(object);
}
/**
* 将Map转换为XML格式的字符串
*
* @param data Map类型数据
* @return XML格式的字符串
* @throws Exception
*/
public static String mapToXml(Map<String, String> data) throws Exception {
org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
org.w3c.dom.Element root = document.createElement("xml");
document.appendChild(root);
for (String key : data.keySet()) {
String value = data.get(key);
if (value == null) {
value = "";
}
value = value.trim();
org.w3c.dom.Element filed = document.createElement(key);
filed.appendChild(document.createTextNode(value));
root.appendChild(filed);
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(source, result);
String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
writer.close();
return output;
}
}
package share.common.utils.wx;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
/**
* AES加密工具类
*
*/
public class AESUtil {
public static boolean initialized = false;
/**
* AES解密
*
* @param content
* 密文
* @return
* @throws InvalidAlgorithmParameterException
* @throws NoSuchProviderException
*/
public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {
initialize();
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
Key sKeySpec = new SecretKeySpec(keyByte, "AES");
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
byte[] result = cipher.doFinal(content);
return result;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void initialize() {
if (initialized)
return;
Security.addProvider(new BouncyCastleProvider());
initialized = true;
}
// 生成iv
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(iv));
return params;
}
}
package share.common.utils.wx;
import org.w3c.dom.Document;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
/**
* 微信支付xml工具类
*/
public final class WXPayXmlUtil {
public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
documentBuilderFactory.setXIncludeAware(false);
documentBuilderFactory.setExpandEntityReferences(false);
return documentBuilderFactory.newDocumentBuilder();
}
public static Document newDocument() throws ParserConfigurationException {
return newDocumentBuilder().newDocument();
}
}
package share.common.utils.wx;
import java.nio.charset.Charset;
import java.util.Arrays;
/**
* 微信小程序加解密
*/
public class WxPKCS7Encoder {
private static final Charset CHARSET = Charset.forName("utf-8");
private static final int BLOCK_SIZE = 32;
/**
* 获得对明文进行补位填充的字节.
*
* @param count
* 需要进行填充补位操作的明文字节个数
* @return 补齐用的字节数组
*/
public static byte[] encode(int count) {
// 计算需要填充的位数
int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
if (amountToPad == 0) {
amountToPad = BLOCK_SIZE;
}
// 获得补位所用的字符
char padChr = chr(amountToPad);
String tmp = new String();
for (int index = 0; index < amountToPad; index++) {
tmp += padChr;
}
return tmp.getBytes(CHARSET);
}
/**
* 删除解密后明文的补位字符
*
* @param decrypted
* 解密后的明文
* @return 删除补位字符后的明文
*/
public static byte[] decode(byte[] decrypted) {
int pad = decrypted[decrypted.length - 1];
if (pad < 1 || pad > 32) {
pad = 0;
}
return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
}
/**
* 将数字转化成ASCII码对应的字符,用于对明文进行补码
*
* @param a
* 需要转化的数字
* @return 转化得到的字符
*/
public static char chr(int a) {
byte target = (byte) (a & 0xFF);
return (char) target;
}
}
package share.common.utils.wx;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import share.common.exception.base.BaseException;
/**
* 微信工具类
*/
public class WxUtil {
private static final String WATERMARK = "watermark";
private static final String APPID = "appid";
/**
* 解密数据
* @return
* @throws Exception
*/
public static String decrypt(String appId, String encryptedData, String sessionKey, String iv){
String result = "";
try {
AESUtil aes = new AESUtil();
byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
if(null != resultByte && resultByte.length > 0){
result = new String(WxPKCS7Encoder.decode(resultByte));
JSONObject jsonObject = JSONObject.parseObject(result);
String decryptAppid = jsonObject.getJSONObject(WATERMARK).getString(APPID);
if(!appId.equals(decryptAppid)){
result = "";
}
}
} catch (Exception e) {
result = "";
e.printStackTrace();
}
return result;
}
/**
* 检测结构请求返回的数据
* @param result 接口返回的结果
* @return JSONObject
*/
public static JSONObject checkResult(JSONObject result){
if(ObjectUtil.isNull(result)){
throw new BaseException("微信平台接口异常,没任何数据返回!");
}
if(result.containsKey("errcode") && result.getString("errcode").equals("0")){
return result;
}
if(result.containsKey("errmsg")){
throw new BaseException("微信接口调用失败:" + result.getString("errcode") + result.getString("errmsg"));
}
return result;
}
}
package share.common.vo;
import lombok.Data;
@Data
public class dateLimitUtilVo {
public dateLimitUtilVo() {}
public dateLimitUtilVo(String startTime, String endTime) {
this.startTime = startTime;
this.endTime = endTime;
}
private String startTime; //开始时间
private String endTime; //结束时间
}
......@@ -115,6 +115,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
// 静态资源,可匿名访问
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
.antMatchers("/front/**").permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
......
......@@ -16,7 +16,6 @@
</description>
<dependencies>
<!-- spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
......@@ -48,19 +47,6 @@
<groupId>share</groupId>
<artifactId>share-framework</artifactId>
</dependency>
<!-- 定时任务-->
<dependency>
<groupId>share</groupId>
<artifactId>share-quartz</artifactId>
</dependency>
<!-- 代码生成-->
<dependency>
<groupId>share</groupId>
<artifactId>share-generator</artifactId>
</dependency>
</dependencies>
<build>
......
......@@ -10,11 +10,11 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
* @author ruoyi
*/
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class ShareApplication
public class FrontApplication
{
public static void main(String[] args)
{
SpringApplication.run(ShareApplication.class, args);
SpringApplication.run(FrontApplication.class, args);
System.out.println("启动成功");
}
}
......@@ -8,11 +8,11 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
*
* @author ruoyi
*/
public class ShareServletInitializer extends SpringBootServletInitializer
public class FrontServletInitializer extends SpringBootServletInitializer
{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return application.sources(ShareApplication.class);
return application.sources(FrontApplication.class);
}
}
package share.web.controller.system;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import share.common.core.domain.R;
import share.common.core.redis.RedisUtil;
import share.common.utils.JsonConvertUtil;
import share.system.request.LoginMobileRequest;
import share.system.request.LoginRequest;
import share.system.response.LoginResponse;
import share.system.service.LoginService;
import share.system.service.SmsService;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
* 用户登陆 前端控制器
*/
@Slf4j
@RestController
@RequestMapping("/front/login")
@Api(tags = "用户 -- 登录注册")
public class LoginController {
@Autowired
private LoginService loginService;
@Autowired
private SmsService smsService;
@Resource
private RedisUtil redisUtil;
/**
* 手机号登录接口
*/
@ApiOperation(value = "手机号登录接口")
@RequestMapping(value = "/login/mobile", method = RequestMethod.POST)
public R<LoginResponse> phoneLogin(@RequestBody @Validated LoginMobileRequest loginRequest) {
if("1".equals(redisUtil.frontInOutLogSwitch())) {
log.info("LoginController method phoneLogin 入参 {}", JsonConvertUtil.write2JsonStr(loginRequest));
log.info("登录接口改造增加渠道参数" + JsonConvertUtil.write2JsonStr(loginRequest));
}
LoginResponse response = loginService.phoneLogin(loginRequest);
if("1".equals(redisUtil.frontInOutLogSwitch())) {
log.info("LoginController method phoneLogin 出参 {}", JsonConvertUtil.write2JsonStr(response));
}
return R.ok(response);
}
/**
* 账号密码登录
*/
@ApiOperation(value = "账号密码登录")
@RequestMapping(value = "/login", method = RequestMethod.POST)
public R<LoginResponse> login(@RequestBody @Validated LoginRequest loginRequest) {
if("1".equals(redisUtil.frontInOutLogSwitch())) {
log.info("LoginController method login 入参 {}", JsonConvertUtil.write2JsonStr(loginRequest));
}
LoginResponse response = loginService.login(loginRequest);
if("1".equals(redisUtil.frontInOutLogSwitch())) {
log.info("LoginController method login 出参 {}", JsonConvertUtil.write2JsonStr(response));
}
return R.ok(response);
}
/**
* 退出登录
*/
@ApiOperation(value = "退出")
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public R<String> loginOut(HttpServletRequest request){
loginService.loginOut(request);
return R.ok();
}
/**
* 发送短信登录验证码
* @param phone 手机号码
* @return 发送是否成功
*/
@ApiOperation(value = "发送短信登录验证码")
@RequestMapping(value = "/sendCode", method = RequestMethod.POST)
@ApiImplicitParams({
@ApiImplicitParam(name="phone", value="手机号码", required = true)
})
public R<Object> sendCode(@RequestParam String phone){
if(smsService.sendSmsCode(phone)){
return R.ok("发送成功");
}else{
return R.fail("发送失败");
}
}
}
......@@ -17,7 +17,7 @@ import share.common.core.controller.BaseController;
import share.common.core.domain.AjaxResult;
import share.common.enums.BusinessType;
import share.system.domain.SConsumer;
import share.system.service.ISConsumerService;
import share.system.service.SConsumerService;
import share.common.utils.poi.ExcelUtil;
import share.common.core.page.TableDataInfo;
......@@ -32,7 +32,7 @@ import share.common.core.page.TableDataInfo;
public class SConsumerController extends BaseController
{
@Autowired
private ISConsumerService sConsumerService;
private SConsumerService sConsumerService;
/**
* 查询会员用户列表
......
package share.web.controller.system;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import share.common.core.domain.R;
import share.common.core.redis.RedisUtil;
import share.common.utils.JsonConvertUtil;
import share.system.domain.TemplateMessage;
import share.system.request.RegisterThirdSConsumerRequest;
import share.system.request.WxBindingPhoneRequest;
import share.system.response.LoginResponse;
import share.system.service.SConsumerCenterService;
import share.system.service.SystemNotificationService;
import java.util.ArrayList;
import java.util.List;
/**
* 微信缓存表 前端控制器
*/
@Slf4j
@RestController("WeChatFrontController")
@RequestMapping("/front/wechat")
@Api(tags = "微信 -- 开放平台")
public class WeChatController {
@Autowired
private SConsumerCenterService sConsumerCenterService;
// @Autowired
// private SystemNotificationService systemNotificationService;
@Autowired
private RedisUtil redisUtil;
/**
* 微信登录小程序授权登录
*/
@ApiOperation(value = "微信登录小程序授权登录")
@RequestMapping(value = "/authorize/program/login", method = RequestMethod.POST)
public R<LoginResponse> programLogin(@RequestParam String code, @RequestBody @Validated RegisterThirdSConsumerRequest request) {
if("1".equals(redisUtil.frontInOutLogSwitch())) {
log.info("WeChatController method programLogin 入参 {}-------{}", code, JsonConvertUtil.write2JsonStr(request));
}
LoginResponse response = sConsumerCenterService.weChatAuthorizeProgramLogin(code, request);
if("1".equals(redisUtil.frontInOutLogSwitch())) {
log.info("WeChatController method programLogin 出参 {}", JsonConvertUtil.write2JsonStr(response));
}
return R.ok(response);
}
/**
* 微信注册绑定手机号
*/
@ApiOperation(value = "微信注册绑定手机号")
@RequestMapping(value = "/register/binding/phone", method = RequestMethod.POST)
public R<LoginResponse> registerBindingPhone(@RequestBody @Validated WxBindingPhoneRequest request) {
log.info("登录接口改造增加渠道参数" + JsonConvertUtil.write2JsonStr(request));
return R.ok(sConsumerCenterService.registerBindingPhone(request));
}
/**
* 微信手机号登录
*/
@ApiOperation(value = "微信手机号登录")
@RequestMapping(value = "/register/login/phone", method = RequestMethod.POST)
public R<LoginResponse> registerLoginPhone(@RequestBody @Validated WxBindingPhoneRequest request) {
log.info("登录接口改造增加渠道参数" + JsonConvertUtil.write2JsonStr(request));
return R.ok(sConsumerCenterService.registerLoginPhone(request));
}
/**
* 订阅消息模板列表
*/
@ApiOperation(value = "订阅消息模板列表")
@RequestMapping(value = "/program/my/temp/list", method = RequestMethod.GET)
@ApiImplicitParam(name = "type")
public R<List<TemplateMessage>> programMyTempList(@RequestParam(name = "type") String type) {
if("1".equals(redisUtil.frontInOutLogSwitch())) {
log.info("WeChatController method programMyTempList 入参 {}", type);
}
List<TemplateMessage> miniTempList = new ArrayList<>();//TODO 消息模版 systemNotificationService.getMiniTempList(type);
if("1".equals(redisUtil.frontInOutLogSwitch())) {
log.info("WeChatController method programMyTempList 出参 {}", JsonConvertUtil.write2JsonStr(miniTempList));
}
return R.ok(miniTempList);
}
}
package share.web.controller.tool;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import share.common.core.controller.BaseController;
import share.common.core.domain.R;
import share.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
/**
* swagger 用户测试方法
*
* @author ruoyi
*/
@Api("用户信息管理")
@RestController
@RequestMapping("/test/user")
public class TestController extends BaseController
{
private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
{
users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
}
@ApiOperation("获取用户列表")
@GetMapping("/list")
public R<List<UserEntity>> userList()
{
List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
return R.ok(userList);
}
@ApiOperation("获取用户详细")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
@GetMapping("/{userId}")
public R<UserEntity> getUser(@PathVariable Integer userId)
{
if (!users.isEmpty() && users.containsKey(userId))
{
return R.ok(users.get(userId));
}
else
{
return R.fail("用户不存在");
}
}
@ApiOperation("新增用户")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
})
@PostMapping("/save")
public R<String> save(UserEntity user)
{
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{
return R.fail("用户ID不能为空");
}
users.put(user.getUserId(), user);
return R.ok();
}
@ApiOperation("更新用户")
@PutMapping("/update")
public R<String> update(@RequestBody UserEntity user)
{
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{
return R.fail("用户ID不能为空");
}
if (users.isEmpty() || !users.containsKey(user.getUserId()))
{
return R.fail("用户不存在");
}
users.remove(user.getUserId());
users.put(user.getUserId(), user);
return R.ok();
}
@ApiOperation("删除用户信息")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
@DeleteMapping("/{userId}")
public R<String> delete(@PathVariable Integer userId)
{
if (!users.isEmpty() && users.containsKey(userId))
{
users.remove(userId);
return R.ok();
}
else
{
return R.fail("用户不存在");
}
}
}
@ApiModel(value = "UserEntity", description = "用户实体")
class UserEntity
{
@ApiModelProperty("用户ID")
private Integer userId;
@ApiModelProperty("用户名称")
private String username;
@ApiModelProperty("用户密码")
private String password;
@ApiModelProperty("用户手机")
private String mobile;
public UserEntity()
{
}
public UserEntity(Integer userId, String username, String password, String mobile)
{
this.userId = userId;
this.username = username;
this.password = password;
this.mobile = mobile;
}
public Integer getUserId()
{
return userId;
}
public void setUserId(Integer userId)
{
this.userId = userId;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public String getMobile()
{
return mobile;
}
public void setMobile(String mobile)
{
this.mobile = mobile;
}
}
package share.web.core.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import share.system.domain.vo.FrontTokenComponent;
import share.web.interceptor.AccessInterceptor;
import share.web.interceptor.FrontTokenInterceptor;
/**
* token验证拦截器
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
// 这里使用一个Bean为的是可以在拦截器中自由注入,也可以在拦截器中使用SpringUtil.getBean 获取
// 但是觉得这样更优雅
@Autowired
private FrontTokenComponent frontTokenComponent;
@Autowired
private AccessInterceptor accessInterceptor;
@Bean
public HandlerInterceptor frontTokenInterceptor(){
return new FrontTokenInterceptor(frontTokenComponent);
}
@Bean
public HandlerInterceptor AccessInterceptor(){
return new AccessInterceptor(frontTokenComponent);
}
// @Bean
// public ResponseFilter responseFilter(){ return new ResponseFilter(); }
// @Value("${swagger.basic.username}")
// private String username;
// @Value("${swagger.basic.password}")
// private String password;
// @Value("${swagger.basic.check}")
// private Boolean check;
@Override
public void addInterceptors(InterceptorRegistry registry) {
System.out.println("=====> FrontTokenComponent addInterceptors ");
registry.addInterceptor(frontTokenInterceptor())
.excludePathPatterns(
"/doc.html",
"/swagger-ui/**",
"/swagger-resources",
"/swagger-resources/configuration/ui",
"/swagger-resources/configuration/security",
"/v3/api-docs",
"/v2/api-docs",
"/webjars/**",
"/favicon.ico",
"/front/wechat/**",
"**"
).addPathPatterns("/**");
}
// @Override
// public void addInterceptors(InterceptorRegistry registry) {
// //添加token拦截器
// //addPathPatterns添加需要拦截的命名空间;
// //excludePathPatterns添加排除拦截命名空间
//
// //前端用户登录token
// registry.addInterceptor(frontTokenInterceptor()).
// addPathPatterns("/api/front/**").
// excludePathPatterns("/api/front/index").
// excludePathPatterns("/api/front/qrcode/**").
// excludePathPatterns("/api/front/login/mobile").
// excludePathPatterns("/api/front/login").
// excludePathPatterns("/api/front/sendCode").
// excludePathPatterns("/api/front/wechat/**").
// excludePathPatterns("/api/front/search/keyword").
// excludePathPatterns("/api/front/share").
// excludePathPatterns("/api/front/article/**").
// excludePathPatterns("/api/front/city/**").
// excludePathPatterns("/api/front/product/hot").
// excludePathPatterns("/api/front/product/good").
// excludePathPatterns("/api/front/products/**").
// excludePathPatterns("/api/front/reply/**").
// excludePathPatterns("/api/front/user/service/**").
// excludePathPatterns("/api/front/logistics").
// excludePathPatterns("/api/front/groom/list/**").
// excludePathPatterns("/api/front/config").
// excludePathPatterns("/api/front/category").
// excludePathPatterns("/api/front/seckill/*").
// excludePathPatterns("/api/front/seckill/list/*").
// excludePathPatterns("/api/front/seckill/detail/*").
// excludePathPatterns("/api/front/ios/*").
// excludePathPatterns("/api/front/ios/register/binding/phone").
// excludePathPatterns("api/front/combination/index").
// excludePathPatterns("api/front/seckill/index").
// excludePathPatterns("api/front/bargain/index").
// excludePathPatterns("api/front/combination/index").
// excludePathPatterns("api/front/index/product/*").
// excludePathPatterns("api/front/index/color/config").
// excludePathPatterns("api/front/image/domain").
// excludePathPatterns("api/front/product/leaderboard").
// excludePathPatterns("/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
// }
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("/**")
// .addResourceLocations("classpath:/static/");
// registry.addResourceHandler("doc.html")
// .addResourceLocations("classpath:/META-INF/resources/");
// registry.addResourceHandler("/webjars/**")
// .addResourceLocations("classpath:/META-INF/resources/webjars/");
// }
// @Bean
// public FilterRegistrationBean filterRegister()
// {
// //注册过滤器
// FilterRegistrationBean registration = new FilterRegistrationBean(responseFilter());
// registration.addUrlPatterns("/*");
// return registration;
// }
/* 必须在此处配置拦截器,要不然拦不到swagger的静态资源 */
// @Bean
// @ConditionalOnProperty(name = "swagger.basic.enable", havingValue = "true")
// public MappedInterceptor getMappedInterceptor() {
// return new MappedInterceptor(new String[]{"/doc.html", "/webjars/**"}, new SwaggerInterceptor(username, password, check));
// }
}
package share.web.interceptor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import share.common.annotation.AccessLimit;
import share.common.core.redis.AccessKey;
import share.common.core.domain.R;
import share.common.core.redis.RedisUtil;
import share.common.exception.ExceptionCodeEnum;
import share.system.domain.SConsumer;
import share.system.domain.vo.FrontTokenComponent;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
@Component
public class AccessInterceptor extends HandlerInterceptorAdapter{
@Resource
private RedisUtil redisUtil;
private FrontTokenComponent frontTokenComponent;
public AccessInterceptor(FrontTokenComponent tokenComponent) {
this.frontTokenComponent = tokenComponent;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if(handler instanceof HandlerMethod) {
HandlerMethod hm = (HandlerMethod)handler;
AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
if(accessLimit == null) {
return true;
}
int seconds = accessLimit.seconds();
int maxCount = accessLimit.maxCount();
boolean needLogin = accessLimit.needLogin();
String key = request.getRequestURI();
if(needLogin) {
String token = frontTokenComponent.getToken(request);
SConsumer user = frontTokenComponent.getLoginSConsumerEntry(request);
if(user == null) {
response.getWriter().write(JSONObject.toJSONString(R.fail(ExceptionCodeEnum.UNAUTHORIZED)));
return false;
}
key += "_" + user.getId();
}
AccessKey ak = AccessKey.withExpire(seconds);
Integer count = redisUtil.get(ak+key);
if(count == null) {
redisUtil.set(ak + key, 1, ak.expireSeconds());
}else if(count < maxCount) {
redisUtil.incr(ak + key, 1);
}else {
render(response, ExceptionCodeEnum.ACCESS_LIMIT_REACHED);
return false;
}
}
return true;
}
private void render(HttpServletResponse response, ExceptionCodeEnum cm)throws Exception {
response.setContentType("application/json;charset=UTF-8");
OutputStream out = response.getOutputStream();
String str = JSON.toJSONString(R.fail(cm));
out.write(str.getBytes("UTF-8"));
out.flush();
out.close();
}
}
package share.web.interceptor;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import share.common.core.domain.R;
import share.common.exception.ExceptionCodeEnum;
import share.common.utils.RequestUtil;
import share.system.domain.SConsumer;
import share.system.domain.vo.FrontTokenComponent;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 移动端管理端 token验证拦截器 使用前注意需要一个@Bean手动注解,否则注入无效
*/
public class FrontTokenInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(FrontTokenInterceptor.class);
ExecutorService logExecutor = new ThreadPoolExecutor(20, 20,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
private FrontTokenComponent frontTokenComponent;
public FrontTokenInterceptor(FrontTokenComponent tokenComponent) {
this.frontTokenComponent = tokenComponent;
}
//程序处理之前需要处理的业务
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("=====>FrontTokenInterceptor preHandle v1 : ");
logExecutor.execute(new Runnable() {
@Override
public void run() {
String url = request.getRequestURI();
logger.info("===> 请求url:"+url);
logger.info("===>请求Get参数:"+request.getQueryString());
try {
Map<String, String[]> map = request.getParameterMap();
logger.info("===>请求Post参数:"+ JSONObject.toJSONString(map));
}catch (Exception e){
e.printStackTrace();
}
}
});
response.setCharacterEncoding("UTF-8");
String token = frontTokenComponent.getToken(request);
logger.info("=====>FrontTokenInterceptor preHandle token : "+ token);
SConsumer userEntry = frontTokenComponent.getLoginSConsumerEntry(request);
if(userEntry!=null){
FrontTokenComponent.loginSConsumerEntryThreadLocal.set(userEntry);
}
/* SConsumer userEntry = new SConsumer();
userEntry.setUid(1520);
userEntry.setAccount("aaa");
userEntry.setNickname("nizbh");
userEntry.setRealName("relxiaohuige");
FrontTokenComponent.loginUserEntryThreadLocal.set(userEntry);*/
if(token == null || token.isEmpty() || userEntry == null){
//判断路由,部分路由不管用户是否登录都可以访问
boolean result = frontTokenComponent.checkRouter(RequestUtil.getUri(request));
if(result){
return true;
}
response.getWriter().write(JSONObject.toJSONString(R.fail(ExceptionCodeEnum.UNAUTHORIZED)));
return false;
}
Boolean result = frontTokenComponent.check(token, request, userEntry);
if(!result){
response.getWriter().write(JSONObject.toJSONString(R.fail(ExceptionCodeEnum.UNAUTHORIZED)));
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
if(FrontTokenComponent.loginSConsumerEntryThreadLocal.get()!=null) {
FrontTokenComponent.loginSConsumerEntryThreadLocal.remove();
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}
}
......@@ -6,9 +6,9 @@ spring:
druid:
# 主库数据源
master:
url: jdbc:mysql://129.211.46.84:3306/sharedb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
url: jdbc:mysql://127.0.0.1:3306/xzdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
username: root
password: whxz2019
password: 1234
# 从库数据源
slave:
# 从数据源开关/默认关闭
......
# 项目相关配置
ruoyi:
# 名称
name: Share
name: front
# 版本
version: 3.8.6
# 版权年份
......@@ -9,16 +9,20 @@ ruoyi:
# 实例演示开关
demoEnabled: true
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
profile: /home/share/uploadPath
profile: /home/gxpt/uploadPath
# 获取ip地址开关
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
captchaType: char
# 微信相关配置
wechat:
appId: wx0802dd3453f72cc9
appSecret: 0f36e45668b4cc714affc4fa6ecdb4bf
# 开发环境配置
server:
# 服务器的HTTP端口,默认为8080
port: 8882
port: 8883
servlet:
# 应用的访问路径
context-path: /
......@@ -70,13 +74,13 @@ spring:
# redis 配置
redis:
# 地址
host: 129.211.46.84
host: 127.0.0.1
# 端口,默认为6379
port: 6379
# 数据库索引
database: 0
# 密码
password: whxz2019
password:
# 连接超时时间
timeout: 10s
lettuce:
......@@ -119,7 +123,7 @@ swagger:
# 是否开启swagger
enabled: true
# 请求前缀
pathMapping: /dev-api
pathMapping: /
# 防止XSS攻击
xss:
......
......@@ -7,4 +7,4 @@ gen:
# 自动去除表前缀,默认是false
autoRemovePre: false
# 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
tablePrefix: sys_
\ No newline at end of file
tablePrefix: s_
\ No newline at end of file
......@@ -41,6 +41,17 @@
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.5.7</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package share.system.domain;
import java.math.BigDecimal;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import share.common.annotation.Excel;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import share.common.core.domain.BaseEntity;
/**
......@@ -12,167 +14,74 @@ import share.common.core.domain.BaseEntity;
* @author ruoyi
* @date 2023-09-27
*/
public class SConsumer extends BaseEntity
@Data
public class SConsumer
{
private static final long serialVersionUID = 1L;
/** 会员用户ID */
private Long id;
@ApiModelProperty(value = "用户账号")
private String account;
/** 微信用户openId */
@Excel(name = "微信用户openId")
@ApiModelProperty(value = "微信用户openId")
private String openId;
/** 用户昵称 */
@Excel(name = "用户昵称")
@ApiModelProperty(value = "用户昵称")
private String nickName;
@ApiModelProperty(value = "用户头像")
private String avatar;
/** 用户手机号 */
@Excel(name = "用户手机号")
@ApiModelProperty(value = "用户手机号")
private String phone;
/** 会员级别(会员类型) */
@Excel(name = "会员级别(会员类型)")
@ApiModelProperty(value = "会员级别(会员类型)")
private Integer level;
/** 会员角色类型(0:会员,1:保洁人员,2:后台管理人员) */
@Excel(name = "会员角色类型", readConverterExp = "0=:会员,1:保洁人员,2:后台管理人员")
@ApiModelProperty(value = "会员角色类型", example = "0=:会员,1:保洁人员,2:后台管理人员")
private Integer roleType;
/** 会员性别(0:未知,1:男,2:女) */
@Excel(name = "会员性别", readConverterExp = "0=:未知,1:男,2:女")
private Integer gender;
@ApiModelProperty(value = "会员性别", example = "0=:未知,1:男,2:女")
private Integer sex;
@ApiModelProperty(value = "详细地址")
private String addres;
/** 充值余额 */
@Excel(name = "充值余额")
@ApiModelProperty(value = "充值余额")
private BigDecimal amount;
/** 赠送余额 */
@Excel(name = "赠送余额")
@ApiModelProperty(value = "赠送余额")
private BigDecimal freeAmount;
/** 消费次数 */
@Excel(name = "消费次数")
@ApiModelProperty(value = "消费次数")
private Integer totalTimes;
/** 总消费时长(单位:小时) */
@Excel(name = "总消费时长(单位:小时)")
@ApiModelProperty(value = "总消费时长(单位:小时)")
private Integer duration;
public void setId(Long id)
{
this.id = id;
}
public Long getId()
{
return id;
}
public void setOpenId(String openId)
{
this.openId = openId;
}
public String getOpenId()
{
return openId;
}
public void setNickName(String nickName)
{
this.nickName = nickName;
}
public String getNickName()
{
return nickName;
}
public void setPhone(String phone)
{
this.phone = phone;
}
public String getPhone()
{
return phone;
}
public void setLevel(Integer level)
{
this.level = level;
}
public Integer getLevel()
{
return level;
}
public void setRoleType(Integer roleType)
{
this.roleType = roleType;
}
public Integer getRoleType()
{
return roleType;
}
public void setGender(Integer gender)
{
this.gender = gender;
}
public Integer getGender()
{
return gender;
}
public void setAmount(BigDecimal amount)
{
this.amount = amount;
}
public BigDecimal getAmount()
{
return amount;
}
public void setFreeAmount(BigDecimal freeAmount)
{
this.freeAmount = freeAmount;
}
public BigDecimal getFreeAmount()
{
return freeAmount;
}
public void setTotalTimes(Integer totalTimes)
{
this.totalTimes = totalTimes;
}
public Integer getTotalTimes()
{
return totalTimes;
}
public void setDuration(Integer duration)
{
this.duration = duration;
}
public Integer getDuration()
{
return duration;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("openId", getOpenId())
.append("nickName", getNickName())
.append("phone", getPhone())
.append("level", getLevel())
.append("roleType", getRoleType())
.append("gender", getGender())
.append("amount", getAmount())
.append("freeAmount", getFreeAmount())
.append("totalTimes", getTotalTimes())
.append("duration", getDuration())
.toString();
}
@ApiModelProperty(value = "1为正常,0为禁止")
private Integer status;
@ApiModelProperty(value = "用户密码")
@JsonIgnore
private String pwd;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "最后一次登录时间")
private Date lastLoginTime;
}
package share.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 用户token表
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("s_consumer_token")
@ApiModel(value="SConsumerToken对象", description="")
public class SConsumerToken implements Serializable {
private static final long serialVersionUID=1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty(value = "用户 id")
private Long uid;
@ApiModelProperty(value = "token")
private String token;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "到期事件")
private Date expiresTime;
@ApiModelProperty(value = "登录ip")
private String loginIp;
}
package share.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 通知设置表
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("eb_system_notification")
@ApiModel(value="SystemNotification对象", description="通知设置表")
public class SystemNotification implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "标识")
private String mark;
@ApiModelProperty(value = "通知类型")
private String type;
@ApiModelProperty(value = "通知场景说明")
private String description;
@ApiModelProperty(value = "公众号模板消息(0:不存在,1:开启,2:关闭)")
private Integer isWechat;
@ApiModelProperty(value = "模板消息id")
private Integer wechatId;
@ApiModelProperty(value = "小程序订阅消息(0:不存在,1:开启,2:关闭)")
private Integer isRoutine;
@ApiModelProperty(value = "订阅消息id")
private Integer routineId;
@ApiModelProperty(value = "发送短信(0:不存在,1:开启,2:关闭)")
private Integer isSms;
@ApiModelProperty(value = "短信id")
private Integer smsId;
@ApiModelProperty(value = "发送类型(1:用户,2:管理员)")
private Integer sendType;
@ApiModelProperty(value = "创建时间")
private Date createTime;
}
package share.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 微信模板
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("s_template_message")
@ApiModel(value="STemplateMessage对象", description="微信模板")
public class TemplateMessage implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "模板id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "0=订阅消息,1=微信模板消息")
private Boolean type;
@ApiModelProperty(value = "模板编号")
private String tempKey;
@ApiModelProperty(value = "模板名")
@JsonProperty
private String name;
@ApiModelProperty(value = "回复内容")
private String content;
@ApiModelProperty(value = "模板ID")
private String tempId;
@ApiModelProperty(value = "状态")
private Integer status;
@ApiModelProperty(value = "添加时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}
package share.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 微信异常表
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("eb_wechat_exceptions")
@ApiModel(value="WechatExceptions对象", description="微信异常表")
public class WechatExceptions implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "错误码")
private String errcode;
@ApiModelProperty(value = "错误信息")
private String errmsg;
@ApiModelProperty(value = "回复数据")
private String data;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
}
package share.system.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 微信订单表
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("eb_wechat_pay_info")
@ApiModel(value="WechatPayInfo对象", description="微信订单表")
public class WechatPayInfo implements Serializable {
private static final long serialVersionUID=1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "公众号唯一标识")
private String appId;
@ApiModelProperty(value = "商户号")
private String mchId;
@ApiModelProperty(value = "设备号,PC网页或公众号内支付可以传-WEB")
private String deviceInfo;
@ApiModelProperty(value = "用户的唯一标识")
private String openId;
@ApiModelProperty(value = "随机字符串")
private String nonceStr;
@ApiModelProperty(value = "签名")
private String sign;
@ApiModelProperty(value = "签名类型,默认为MD5,支持HMAC-SHA256和MD5")
private String signType;
@ApiModelProperty(value = "商品描述")
private String body;
@ApiModelProperty(value = "商品详细描述,对于使用单品优惠的商户,该字段必须按照规范上传")
private String detail;
@ApiModelProperty(value = "附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用")
private String attach;
@ApiModelProperty(value = "商户订单号,要求32个字符内")
private String outTradeNo;
@ApiModelProperty(value = "标价币种:CNY:人民币 GBP:英镑 HKD:港币 USD:美元 JPY:日元 CAD:加拿大元 AUD:澳大利亚元 EUR:欧元 NZD:新西兰元 KRW:韩元 THB:泰铢")
private String feeType;
@ApiModelProperty(value = "标价金额")
private Integer totalFee;
@ApiModelProperty(value = "终端IP")
private String spbillCreateIp;
@ApiModelProperty(value = "交易起始时间")
private String timeStart;
@ApiModelProperty(value = "交易结束时间")
private String timeExpire;
@ApiModelProperty(value = "通知地址")
private String notifyUrl;
@ApiModelProperty(value = "交易类型,取值为:JSAPI,NATIVE,APP等")
private String tradeType;
@ApiModelProperty(value = "商品ID")
private String productId;
@ApiModelProperty(value = "场景信息")
private String sceneInfo;
@ApiModelProperty(value = "错误代码")
private String errCode;
@ApiModelProperty(value = "预支付交易会话标识")
private String prepayId;
@ApiModelProperty(value = "二维码链接")
private String codeUrl;
@ApiModelProperty(value = "是否关注公众账号")
private String isSubscribe;
@ApiModelProperty(value = "交易状态")
private String tradeState;
@ApiModelProperty(value = "付款银行")
private String bankType;
@ApiModelProperty(value = "现金支付金额")
private Integer cashFee;
@ApiModelProperty(value = "代金券金额")
private Integer couponFee;
@ApiModelProperty(value = "微信支付订单号")
private String transactionId;
@ApiModelProperty(value = "支付完成时间")
private String timeEnd;
@ApiModelProperty(value = "交易状态描述")
private String tradeStateDesc;
}
package share.system.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 微信统一下单对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="CreateOrderRequestVo对象", description="微信统一下单对象")
public class CreateOrderRequestVo {
@ApiModelProperty(value = "appId,公众号名称,由商户传入", required = true)
private String appid;
@ApiModelProperty(value = "直连商户的商户号,由微信支付生成并下发", required = true)
private String mch_id;
@ApiModelProperty(value = "终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传 WEB")
private String device_info = "WEB";
@ApiModelProperty(value = "随机字符串,不长于32位", required = true)
private String nonce_str;
@ApiModelProperty(value = "签名", required = true)
private String sign;
@ApiModelProperty(value = "签名类型,默认为MD5,支持HMAC-SHA256和MD5。")
private String sign_type;
@ApiModelProperty(value = "商品简单描述,该字段须严格按照规范传递", required = true)
private String body;
@ApiModelProperty(value = "商品简单描述")
private String detail;
@ApiModelProperty(value = "附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据, String(127)")
private String attach;
@ApiModelProperty(value = "商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号", required = true)
private String out_trade_no;
@ApiModelProperty(value = "符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型")
private String fee_type = "CNY";
@ApiModelProperty(value = "订单总金额,单位为分", required = true)
private int total_fee;
@ApiModelProperty(value = "必须传正确的用户端IP,支持ipv4、ipv6格式,获取方式详见获取用户ip指引", required = true)
private String spbill_create_ip;
@ApiModelProperty(value = "订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则")
private String time_start;
@ApiModelProperty(value = "订单失效时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则")
private String time_expire;
@ApiModelProperty(value = "商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠")
private String goods_tag;
@ApiModelProperty(value = "接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。")
private String notify_url;
@ApiModelProperty(value = "JSAPI -JSAPI支付(或小程序支付), NATIVE -Native支付, APP -APP支付,MWEB--H5支付", required = true)
private String trade_type;
@ApiModelProperty(value = "trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义。")
private String product_id;
@ApiModelProperty(value = "no_credit--指定不能使用信用卡支付")
private String limit_pay;
@ApiModelProperty(value = "trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。openid如何获取,可参考【获取openid】。企业号请使用【企业号OAuth2.0接口】获取企业号内成员userid,再调用【企业号userid转openid接口】进行转换")
private String openid;
@ApiModelProperty(value = "Y,传入Y时,支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能,传此字段才可生效")
private String receipt = "N";
@ApiModelProperty(value = "该字段用于上报支付的场景信息,针对H5支付有以下三种场景,请根据对应场景上报,H5支付不建议在APP端使用,针对场景1,2请接入APP支付,不然可能会出现兼容性问题")
private String scene_info;
}
package share.system.domain.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 统一下单返回对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="CreateOrderResponseVo对象", description="统一下单返回对象")
public class CreateOrderResponseVo {
@ApiModelProperty(value = "调用接口提交的公众账号ID")
@JsonProperty(value = "appid")
private String appId;
@ApiModelProperty(value = "调用接口提交的商户号")
@JsonProperty(value = "mch_id")
private String mchId;
@ApiModelProperty(value = "调用接口提交的终端设备号")
@JsonProperty(value = "device_info")
private String deviceInfo;
@ApiModelProperty(value = "微信返回的随机字符串")
@JsonProperty(value = "nonce_str")
private String nonceStr;
@ApiModelProperty(value = "微信返回的签名")
private String sign;
@ApiModelProperty(value = "SUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查看trade_state来判断")
@JsonProperty(value = "return_code")
private String returnCode;
@ApiModelProperty(value = "当return_code为FAIL时返回信息为错误原因 ,例如 签名失败 参数格式校验错误")
@JsonProperty(value = "return_msg")
private String returnMsg;
@ApiModelProperty(value = "SUCCESS/FAIL 业务结果")
@JsonProperty(value = "result_code")
private String resultCode;
@ApiModelProperty(value = "详细参见错误列表")
@JsonProperty(value = "err_code")
private String errCode;
@ApiModelProperty(value = "错误返回的信息描述")
@JsonProperty(value = "err_code_des")
private String errCodeDes;
@ApiModelProperty(value = "调用接口提交的交易类型,取值如下:JSAPI,NATIVE,APP,,H5支付固定传MWEB")
@JsonProperty(value = "trade_type")
private String tradeType;
@ApiModelProperty(value = "微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时,针对H5支付此参数无特殊用途")
@JsonProperty(value = "prepay_id")
private String prepayId;
@ApiModelProperty(value = "mweb_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,mweb_url的有效期为5分钟")
@JsonProperty(value = "mweb_url")
private String mWebUrl;
@ApiModelProperty(value = "该字段用于上报支付的场景信息,针对H5支付有以下三种场景,请根据对应场景上报,H5支付不建议在APP端使用,针对场景1,2请接入APP支付,不然可能会出现兼容性问题")
@JsonProperty(value = "scene_info")
private String extra;
private Object transJsConfig;
}
package share.system.domain.vo;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import share.common.constant.Constants;
import share.common.core.redis.RedisUtil;
import share.common.utils.RequestUtil;
import share.system.domain.SConsumer;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* token验证处理
*/
@Component
public class FrontTokenComponent {
private static final Logger logger = LoggerFactory.getLogger(FrontTokenComponent.class);
public static ThreadLocal<SConsumer> loginSConsumerEntryThreadLocal = new ThreadLocal<>();
@Resource
private RedisUtil redisUtil;
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
private static final Long MILLIS_MINUTE = 60 * 1000L;
// private static final int expireTime = 30;
private static final int expireTime = 5 * 60;
/**
* 获取用户身份信息
*
* @return 用户信息
*/
public LoginSConsumerVo getLoginSConsumer(HttpServletRequest request) {
// 获取请求携带的令牌
String token = getToken(request);
if (StrUtil.isNotEmpty(token)) {
String userKey = getTokenKey(token);
return redisUtil.get(userKey);
}
return null;
}
/**
* 设置用户身份信息
*/
public void setLoginSConsumer(LoginSConsumerVo loginSConsumer) {
if (ObjectUtil.isNotNull(loginSConsumer) && StrUtil.isNotEmpty(loginSConsumer.getToken())) {
refreshToken(loginSConsumer);
}
}
/**
* 删除用户身份信息
*/
public void delLoginSConsumer(String token) {
if (StrUtil.isNotEmpty(token)) {
String userKey = getTokenKey(token);
redisUtil.delete(userKey);
}
}
/**
* 获取用户身份信息
*
* @return 用户信息
*/
public SConsumer getLoginSConsumerEntry(HttpServletRequest request) {
// 获取请求携带的令牌
String uuid = request.getHeader(Constants.HEADER_AUTHORIZATION_KEY);
System.out.println("====>uuid : "+uuid);
if (StrUtil.isNotEmpty(uuid)) {
String token = getWxTokenKey(uuid);
return redisUtil.get(token);
}
return null;
}
/**
* wx小程序 用户登录信息给serivce 提供
* @return
*/
public static SConsumer getWxSConsumerEntry(){
return loginSConsumerEntryThreadLocal.get();
}
/**
* 创建令牌
*
* @param user 用户信息
* @return 令牌
*/
public String createToken(SConsumer user) {
String token = UUID.randomUUID().toString().replace("-", "");
redisUtil.set(getTokenKey(token), user.getId(), Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
redisUtil.set(getWxTokenKey(token), user, Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
redisUtil.set(getSConsumerTokenBySConsumerId(user.getId()),getWxTokenKey(token) ,Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
return token;
}
public void refreshSConsumerByToken(SConsumer user){
Long userId = user.getId();
String token = redisUtil.get(getSConsumerTokenBySConsumerId(userId));
redisUtil.set(token, user, Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
redisUtil.set(getSConsumerTokenBySConsumerId(user.getId()),getWxTokenKey(token) ,Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
}
public SConsumer getSConsumerBySConsumerId(Long userId){
String token = redisUtil.get(getSConsumerTokenBySConsumerId(userId));
return (SConsumer)redisUtil.get(token);
}
/**
* 验证令牌有效期,相差不足20分钟,自动刷新缓存
*
* @param loginSConsumer LoginSConsumerVo
*/
public void verifyToken(LoginSConsumerVo loginSConsumer) {
long expireTime = loginSConsumer.getExpireTime();
long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
{
refreshToken(loginSConsumer);
}
}
/**
* 刷新令牌有效期
*
* @param loginSConsumer 登录信息
*/
public void refreshToken(LoginSConsumerVo loginSConsumer) {
loginSConsumer.setLoginTime(System.currentTimeMillis());
loginSConsumer.setExpireTime(loginSConsumer.getLoginTime() + expireTime * MILLIS_MINUTE);
// 根据uuid将loginSConsumer缓存
String userKey = getTokenKey(loginSConsumer.getToken());
redisUtil.set(userKey, loginSConsumer, (long) expireTime, TimeUnit.MINUTES);
}
/**
* 获取请求token
*
* @param request HttpServletRequest
* @return token
*/
public String getToken(HttpServletRequest request) {
String token = request.getHeader(Constants.HEADER_AUTHORIZATION_KEY);
if (StrUtil.isNotEmpty(token) && token.startsWith(Constants.USER_TOKEN_REDIS_KEY_PREFIX)) {
token = token.replace(Constants.USER_TOKEN_REDIS_KEY_PREFIX, "");
}
return token;
}
private String getTokenKey(String uuid) {
return Constants.USER_TOKEN_REDIS_KEY_PREFIX + uuid;
}
private String getSConsumerTokenBySConsumerId(Long userId){
return Constants.WX_TOKEN_BY_USERID+userId;
}
/**
* 2022-07-07 整理
* @param uuid
* @return
*/
private String getWxTokenKey(String uuid) {
return Constants.WX_USER_TOKEN_REDIS_KEY_PREFIX + uuid;
}
/**
* 推出登录
* @param request HttpServletRequest
*/
public void logout(HttpServletRequest request) {
String token = getToken(request);
Integer userId = getSConsumerId();
delLoginSConsumer(token);
}
/**
* 获取当前登录用户id
*/
public Integer getSConsumerId() {
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
String token = getToken(request);
if (StrUtil.isEmpty(token)) {
return null;
// throw new CrmebException("登录信息已过期,请重新登录!");
}
return redisUtil.get(getTokenKey(token));
}
//路由在此处,则返回true,无论用户是否登录都可以访问
public boolean checkRouter(String uri) {
logger.info("=====>url : "+uri);
String[] routerList = {
"/front/product/detail",
"/front/coupons",
"/front/index",
"/front/bargain/list",
"/front/combination/list",
"/front/index/product",
"/front/combination/index",
"/front/bargain/index",
"/front/index/color/config",
"/front/product/list",
"/front/product/sku/detail",
"/front/index/get/version",
"/front/image/domain",
"/front/product/leaderboard",
"/front/category",
"/front/vip/config/list",
"/front/vip/config/info",
"/front/vip/config/infoByIosId",
"/front/store/equity/list",
"/front/store/equity/detail",
"/front/seckill/appoint/success",
"/front/preference/list",
"/front/invite/vipList",
"/front/seckill/list",
"/front/seckill/cur/time",
"/front/get/common/code",
"/front/get/seckill/code",
"/front/xfbVisitInfo/save"
};
return ArrayUtils.contains(routerList, uri);
}
public Boolean check(String token, HttpServletRequest request, SConsumer user){
try {
boolean exists = redisUtil.exists(getTokenKey(token));
if(exists){
Long uid = redisUtil.get(getTokenKey(token));
redisUtil.set(getTokenKey(token), uid, Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
redisUtil.set(getWxTokenKey(token), user, Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
redisUtil.set(getSConsumerTokenBySConsumerId(uid),getWxTokenKey(token) ,Constants.TOKEN_EXPRESS_MINUTES, TimeUnit.MINUTES);
}else{
//判断路由,部分路由不管用户是否登录/token过期都可以访问
exists = checkRouter(RequestUtil.getUri(request));
}
return exists;
}catch (Exception e){
return false;
}
}
}
package share.system.domain.vo;
import java.io.Serializable;
/**
* 登录用户身份权限
*/
public class LoginSConsumerVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户唯一标识
*/
private String token;
/**
* 登陆时间
*/
private Long loginTime;
/**
* 过期时间
*/
private Long expireTime;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地点
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
public LoginSConsumerVo() {
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public Long getLoginTime() {
return loginTime;
}
public void setLoginTime(Long loginTime) {
this.loginTime = loginTime;
}
public Long getExpireTime() {
return expireTime;
}
public void setExpireTime(Long expireTime) {
this.expireTime = expireTime;
}
public String getIpaddr() {
return ipaddr;
}
public void setIpaddr(String ipaddr) {
this.ipaddr = ipaddr;
}
public String getLoginLocation() {
return loginLocation;
}
public void setLoginLocation(String loginLocation) {
this.loginLocation = loginLocation;
}
public String getBrowser() {
return browser;
}
public void setBrowser(String browser) {
this.browser = browser;
}
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
}
package share.system.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 微信公众号私有模板消息Vo对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="PublicMyTemplateVo对象", description="微信公众号私有模板消息Vo对象")
public class PublicMyTemplateVo {
@ApiModelProperty(value = "模板ID")
private String template_id;
@ApiModelProperty(value = "模板ID")
private String title;
@ApiModelProperty(value = "一级行业")
private String primary_industry;
@ApiModelProperty(value = "二级行业")
private String deputy_industry;
@ApiModelProperty(value = "模板内容")
private String content;
@ApiModelProperty(value = "模板示例")
private String example;
}
package share.system.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 微信小程序订阅消息Vo对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="RoutineMyTemplateVo对象", description="微信小程序订阅消息Vo对象")
public class RoutineMyTemplateVo {
@ApiModelProperty(value = "模板ID")
private String priTmplId;
@ApiModelProperty(value = "模板标题")
private String title;
@ApiModelProperty(value = "模板内容")
private String content;
@ApiModelProperty(value = "模板示例")
private String example;
@ApiModelProperty(value = "类型")
private String type;
}
package share.system.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 微信小程序订阅消息Vo对象(从微信获取的)
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="RoutineTemplateKeyVo对象", description="微信小程序订阅消息KeyVo对象(从微信获取的)")
public class RoutineTemplateKeyVo {
@ApiModelProperty(value = "关键词 id,选用模板时需要")
private Integer kid;
@ApiModelProperty(value = "关键词内容")
private String name;
@ApiModelProperty(value = "关键词内容对应的示例")
private String example;
@ApiModelProperty(value = "参数类型")
private String rule;
}
package share.system.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 微信模板发送数据类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="SendTemplateMessageItemVo对象", description="微信模板发送数据类")
public class SendTemplateMessageItemVo {
public SendTemplateMessageItemVo() {}
public SendTemplateMessageItemVo(String value) {
this.value = value;
}
@ApiModelProperty(value = "显示的文字内容", required = true)
private String value;
@ApiModelProperty(value = "颜色")
private String color = "#173177";
}
package share.system.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.util.HashMap;
/**
* 微信模板发送类
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="SendTemplateMessageVo对象", description="微信模板发送类")
public class TemplateMessageVo {
@ApiModelProperty(value = "OPENID", required = true)
private String touser;
@ApiModelProperty(value = "模板ID", required = true)
private String template_id;
@ApiModelProperty(value = "模板跳转链接(海外帐号没有跳转能力)")
private String url;
@ApiModelProperty(value = "发送内容")
private HashMap<String, SendTemplateMessageItemVo> data;
}
package share.system.domain.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 小程序accessTokenVo对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="WeChatAccessTokenVo", description="微信accessTokenVo对象")
public class WeChatAccessTokenVo implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "获取到的凭证")
@TableField(value = "access_token")
private String accessToken;
@ApiModelProperty(value = "凭证有效时间,单位:秒。目前是7200秒之内的值。")
@TableField(value = "expires_in")
private Integer expiresIn;
@ApiModelProperty(value = "错误码")
@TableField(value = "errcode")
private Integer errCode;
@ApiModelProperty(value = "错误信息")
@TableField(value = "errmsg")
private String errMsg;
/**
* errcode 的合法值
* -1 系统繁忙,此时请开发者稍候再试
* 0 请求成功
* 40001 AppSecret 错误或者 AppSecret 不属于这个小程序,请开发者确认 AppSecret 的正确性
* 40002 请确保 grant_type 字段值为 client_credential
* 40013 不合法的 AppID,请开发者检查 AppID 的正确性,避免异常字符,注意大小写
*/
}
package share.system.domain.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 获取微信用户信息
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="WeChatAuthorizeLoginUserInfoVo对象", description="获取微信用户信息")
public class WeChatAuthorizeLoginUserInfoVo implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "用户的唯一标识")
@TableField(value = "openId")
private String openId;
@ApiModelProperty(value = "用户昵称")
@TableField(value = "nickname")
private String nickName;
@ApiModelProperty(value = "性别")
private String sex;
@ApiModelProperty(value = "用户个人资料填写的省份")
private String province;
@ApiModelProperty(value = "普通用户个人资料填写的城市")
private String city;
@ApiModelProperty(value = "国家,如中国为CN")
private String country;
@ApiModelProperty(value = "用户头像")
private String headimgurl;
@ApiModelProperty(value = "用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)")
private String privilege;
@ApiModelProperty(value = "只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。")
@TableField(value = "unionid")
private String unionId;
}
package share.system.domain.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 微信小程序用户授权返回数据
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="WeChatMiniAuthorizeVo对象", description="微信小程序用户授权返回数据")
public class WeChatMiniAuthorizeVo implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "会话密钥")
@TableField(value = "session_key")
private String sessionKey;
@ApiModelProperty(value = "用户唯一标识")
@TableField(value = "openid")
private String openId;
@ApiModelProperty(value = "用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回")
@TableField(value = "unionid")
private String unionId;
@ApiModelProperty(value = "错误码")
@TableField(value = "errcode")
private String errCode;
@ApiModelProperty(value = "错误信息")
@TableField(value = "errmsg")
private String errMsg;
}
package share.system.domain.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 微信用户授权返回数据
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="WeChatAuthorizeLoginGetOpenIdResponse对象", description="微信开放平台获取accessToken对象")
public class WeChatOauthToken implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "accessToken接口调用凭证")
@TableField(value = "access_token")
private String accessToken;
@ApiModelProperty(value = "access_token 接口调用凭证超时时间,单位(秒)")
@TableField(value = "expires_in")
private String expiresIn;
@ApiModelProperty(value = "用户刷新access_token")
@TableField(value = "refresh_token")
private String refreshToken;
@ApiModelProperty(value = "用户OpenId")
@TableField(value = "openid")
private String openId;
@ApiModelProperty(value = "用户授权的作用域,使用逗号(,)分隔")
private String scope;
}
package share.system.domain.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 微信退款返回对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="WxRefundResponseVo", description="微信退款返回对象")
public class WxRefundResponseVo {
@ApiModelProperty(value = "SUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查看trade_state来判断")
@JsonProperty(value = "return_code")
private String returnCode;
@ApiModelProperty(value = "当return_code为FAIL时返回信息为错误原因 ,例如 签名失败 参数格式校验错误")
@JsonProperty(value = "return_msg")
private String returnMsg;
@ApiModelProperty(value = "SUCCESS/FAIL 业务结果")
@JsonProperty(value = "result_code")
private String resultCode;
@ApiModelProperty(value = "详细参见错误列表")
@JsonProperty(value = "err_code")
private String errCode;
@ApiModelProperty(value = "错误返回的信息描述")
@JsonProperty(value = "err_code_des")
private String errCodeDes;
@ApiModelProperty(value = "调用接口提交的公众账号ID")
@JsonProperty(value = "appid")
private String appId;
@ApiModelProperty(value = "调用接口提交的商户号")
@JsonProperty(value = "mch_id")
private String mchId;
@ApiModelProperty(value = "微信返回的随机字符串")
@JsonProperty(value = "nonce_str")
private String nonceStr;
@ApiModelProperty(value = "微信返回的签名")
private String sign;
@ApiModelProperty(value = "微信支付订单号")
@JsonProperty(value = "transaction_id")
private String transactionId;
@ApiModelProperty(value = "商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号", required = true)
@JsonProperty(value = "out_trade_no")
private String outTradeNo;
@ApiModelProperty(value = "商户退款单号,同一退款单号多次请求只退一笔。")
@JsonProperty(value = "out_refund_no")
private String outRefundNo;
@ApiModelProperty(value = "微信退款单号")
@JsonProperty(value = "refund_id")
private String refundId;
@ApiModelProperty(value = "退款总金额,单位为分,可以做部分退款")
@JsonProperty(value = "refund_fee")
private Integer refundFee;
@ApiModelProperty(value = "应结退款金额")
@JsonProperty(value = "settlement_refund_fee")
private Integer settlementRefundFee;
@ApiModelProperty(value = "标价金额")
@JsonProperty(value = "total_fee")
private Integer totalFee;
@ApiModelProperty(value = "应结订单金额")
@JsonProperty(value = "settlement_total_fee")
private Integer settlementTotalFee;
@ApiModelProperty(value = "标价币种,订单金额货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型")
@JsonProperty(value = "fee_type")
private String feeType;
@ApiModelProperty(value = "现金支付金额")
@JsonProperty(value = "cash_fee")
private Integer cashFee;
@ApiModelProperty(value = "现金支付币种,订单金额货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型")
@JsonProperty(value = "cash_fee_type")
private String cashFeeType;
@ApiModelProperty(value = "现金退款金额")
@JsonProperty(value = "cash_refund_fee")
private Integer cashRefundFee;
}
package share.system.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 调用微信退款所需要的参数
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="WxRefundVo", description="调用微信退款所需要的参数")
public class WxRefundVo {
@ApiModelProperty(value = "appId,公众号名称,由商户传入", required = true)
private String appid;
@ApiModelProperty(value = "直连商户的商户号,由微信支付生成并下发", required = true)
private String mch_id;
@ApiModelProperty(value = "随机字符串,不长于32位", required = true)
private String nonce_str;
@ApiModelProperty(value = "签名", required = true)
private String sign;
@ApiModelProperty(value = "签名类型,目前支持HMAC-SHA256和MD5,默认为MD5")
private String sign_type = "MD5";
@ApiModelProperty(value = "微信支付订单号:微信生成的订单号,在支付通知中有返回")
private String transaction_id;
@ApiModelProperty(value = "商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号", required = true)
private String out_trade_no;
@ApiModelProperty(value = "商户退款单号,同一退款单号多次请求只退一笔。")
private String out_refund_no;
@ApiModelProperty(value = "订单总金额,单位为分", required = true)
private int total_fee;
@ApiModelProperty(value = "退款金额,单位为分", required = true)
private int refund_fee;
@ApiModelProperty(value = "退款货币种类:符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型")
private String refund_fee_type = "CNY";
@ApiModelProperty(value = "退款结果通知url")
private String notify_url;
}
package share.system.mapper;
import java.util.List;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import share.system.domain.SConsumer;
/**
......@@ -9,7 +11,7 @@ import share.system.domain.SConsumer;
* @author ruoyi
* @date 2023-09-27
*/
public interface SConsumerMapper
public interface SConsumerMapper extends BaseMapper<SConsumer>
{
/**
* 查询会员用户
......
package share.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import share.system.domain.SConsumerToken;
/**
* Mapper 接口
*/
public interface SConsumerTokenMapper extends BaseMapper<SConsumerToken> {
}
package share.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import share.system.domain.WechatExceptions;
/**
* 微信异常表 Mapper 接口
*/
public interface WechatExceptionsMapper extends BaseMapper<WechatExceptions> {
}
package share.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import share.system.domain.WechatPayInfo;
/**
* 微信订单表 Mapper 接口
*
*/
public interface WechatPayInfoMapper extends BaseMapper<WechatPayInfo> {
}
package share.system.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import share.common.constant.RegularConstants;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
/**
* 手机号注册
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="LoginMobileRequest对象", description="手机号注册")
public class LoginMobileRequest implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "手机号", required = true)
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = RegularConstants.PHONE_TWO, message = "手机号码格式错误")
private String phone;
@ApiModelProperty(value = "验证码", required = true)
@Pattern(regexp = RegularConstants.VALIDATE_CODE_NUM_SIX, message = "验证码格式错误,验证码必须为6位数字")
private String captcha;
@ApiModelProperty(value = "推广人id")
@JsonProperty(value = "spread_spid")
private Integer spreadPid;
@ApiModelProperty(value = "拓客渠道")
private String channel;
}
package share.system.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import share.common.constant.RegularConstants;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
/**
* 移动端手机密码登录请求对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="LoginRequest对象", description="移动端手机密码登录请求对象")
public class LoginRequest implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "手机号", required = true, example = "18888888")
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = RegularConstants.PHONE_TWO, message = "手机号码格式错误")
@JsonProperty(value = "account")
private String phone;
@ApiModelProperty(value = "密码", required = true, example = "1~[6,18]")
// @Pattern(regexp = RegularConstants.PASSWORD, message = "密码格式错误,密码必须以字母开头,长度在6~18之间,只能包含字符、数字和下划线")
private String password;
@ApiModelProperty(value = "推广人id")
@JsonProperty(value = "spread_spid")
private Integer spreadPid = 0;
}
package share.system.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 系统通知详情请求对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="NotificationInfoRequest对象", description="系统通知详情请求对象")
public class NotificationInfoRequest implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "通知id")
@NotNull(message = "通知id不能为空")
private Integer id;
@ApiModelProperty(value = "wechat-公众号模板消息,routine-小程序订阅消息,sms-短信")
@NotEmpty(message = "详情类型不能为空")
private String detailType;
}
package share.system.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Range;
import java.io.Serializable;
/**
* 系统通知查询对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="NotificationSearchRequest对象", description="系统通知查询对象")
public class NotificationSearchRequest implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "发送类型(1:通知会员,2:通知平台)")
@Range(min = 1, max = 2, message = "未知的发送类型")
private Integer sendType;
}
package share.system.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 系统通知修改请求对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="NotificationUpdateRequest对象", description="系统通知修改请求对象")
public class NotificationUpdateRequest implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "通知id")
@NotNull(message = "通知id不能为空")
private Integer id;
@ApiModelProperty(value = "wechat-公众号模板消息,routine-小程序订阅消息,sms-短信")
@NotEmpty(message = "详情类型不能为空")
private String detailType;
@ApiModelProperty(value = "模板id(wechat、routine)")
private String tempId;
@ApiModelProperty(value = "状态,1-开启,2-关闭")
@NotNull(message = "状态不能为空")
private Integer status;
}
package share.system.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 用户地址表
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="RegisterThirdSConsumerRequest对象", description="三方用户注册对象")
public class RegisterThirdSConsumerRequest implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "用户昵称", required = true)
private String nickName;
@ApiModelProperty(value = "性别", required = true)
private String sex;
@ApiModelProperty(value = "用户个人资料填写的省份")
private String province;
@ApiModelProperty(value = "普通用户个人资料填写的城市")
private String city;
@ApiModelProperty(value = "国家,如中国为CN")
private String country;
@ApiModelProperty(value = "微信小程序用户头像", required = true)
private String avatar;
@ApiModelProperty(value = "用户openId")
private String openId;
}
package share.system.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import share.common.constant.RegularConstants;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
/**
* 微信绑定手机号请求对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="WxBindingPhoneRequest", description="微信绑定手机号请求对象")
public class WxBindingPhoneRequest implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "手机号", required = true)
@Pattern(regexp = RegularConstants.PHONE_TWO, message = "请输入正确的手机号")
private String phone;
@ApiModelProperty(value = "验证码", required = true)
@Pattern(regexp = RegularConstants.VALIDATE_CODE_NUM_SIX, message = "请输入6位验证码")
private String captcha;
@ApiModelProperty(value = "类型:public-公众号,routine-小程序,iosWx-苹果微信,androidWx-安卓微信, ios-ios登录")
@NotBlank(message = "类型不能为空")
private String type;
@ApiModelProperty(value = "新用户登录时返回的key")
@NotBlank(message = "key不能为空")
private String key;
@ApiModelProperty(value = "小程序获取手机号加密数据")
private String encryptedData;
@ApiModelProperty(value = "加密算法的初始向量")
private String iv;
@ApiModelProperty(value = "小程序code")
private String code;
}
package share.system.response;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* Login Response
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="LoginResponse", description="用户登录返回数据")
public class LoginResponse implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "用户登录密钥")
private String token;
@ApiModelProperty(value = "状态:login-登录,register-注册,start-注册起始页")
private String type;
@ApiModelProperty(value = "注册key")
private String key;
@ApiModelProperty(value = "登录用户Uid")
private Long uid;
@ApiModelProperty(value = "登录用户昵称")
private String nikeName;
@ApiModelProperty(value = "登录用户手机号")
private String phone;
@ApiModelProperty(value = "openId")
private String openId;
@ApiModelProperty(value = "vipUserId")
private String vipUserId;
}
package share.system.response;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 系统通知详情相应对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="NotificationInfoResponse对象", description="系统通知详情相应对象")
public class NotificationInfoResponse implements Serializable {
private static final long serialVersionUID = -3214167698001861141L;
@ApiModelProperty(value = "id")
private Integer id;
@ApiModelProperty(value = "模板id(公用)")
private String tempId;
@ApiModelProperty(value = "模板说明(短信)")
private String title;
@ApiModelProperty(value = "模板编号(公用)")
private String tempKey;
@ApiModelProperty(value = "内容(公用)")
private String content;
@ApiModelProperty(value = "模板名")
private String name;
@ApiModelProperty(value = "状态,1-开启,2-关闭")
private Integer status;
}
package share.system.response;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
* 微信公众号js-sdk响应对象
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="WeChatJsSdkConfigResponse对象", description="微信公众号js-sdk响应对象对象")
public class WeChatJsSdkConfigResponse implements Serializable {
private static final long serialVersionUID=1L;
@ApiModelProperty(value = "url")
private String url;
@ApiModelProperty(value = "jsApiTicket")
private String jsApiTicket;
@ApiModelProperty(value = "nonceStr")
private String nonceStr;
@ApiModelProperty(value = "timestamp")
private Long timestamp;
@ApiModelProperty(value = "signature")
private String signature;
@ApiModelProperty(value = "jsApiList")
private List<String> jsApiList;
@ApiModelProperty(value = "debug")
private Boolean debug;
@ApiModelProperty(value = "appid")
private String appId;
}
package share.system.service;
import share.system.request.LoginMobileRequest;
import share.system.request.LoginRequest;
import share.system.response.LoginResponse;
import javax.servlet.http.HttpServletRequest;
/**
* 移动端登录服务类
*/
public interface LoginService {
/**
* 账号密码登录
* @return LoginResponse
*/
LoginResponse login(LoginRequest loginRequest);
/**
* 手机号验证码登录
*/
LoginResponse phoneLogin(LoginMobileRequest loginRequest);
/**
* 推出登录
* @param request HttpServletRequest
*/
void loginOut(HttpServletRequest request);
}
package share.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.github.pagehelper.PageInfo;
import share.system.domain.SConsumer;
import share.system.request.RegisterThirdSConsumerRequest;
import share.system.request.WxBindingPhoneRequest;
import share.system.response.LoginResponse;
import java.math.BigDecimal;
import java.util.List;
/**
* 用户中心 服务类
*/
public interface SConsumerCenterService extends IService<SConsumer> {
/**
* 微信登录小程序授权登录
* @param code code
* @param request 用户参数
* @return LoginResponse
*/
LoginResponse weChatAuthorizeProgramLogin(String code, RegisterThirdSConsumerRequest request);
/**
* 微信注册绑定手机号
* @param request 请求参数
* @return 登录信息
*/
LoginResponse registerBindingPhone(WxBindingPhoneRequest request);
/**
* 微信手机号登录
* @param request 请求参数
* @return 登录信息
*/
LoginResponse registerLoginPhone(WxBindingPhoneRequest request);
}
package share.system.service;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.IService;
import share.system.domain.SConsumer;
import share.system.request.RegisterThirdSConsumerRequest;
/**
* 会员用户Service接口
......@@ -9,7 +12,7 @@ import share.system.domain.SConsumer;
* @author ruoyi
* @date 2023-09-27
*/
public interface ISConsumerService
public interface SConsumerService extends IService<SConsumer>
{
/**
* 查询会员用户
......@@ -58,4 +61,27 @@ public interface ISConsumerService
* @return 结果
*/
public int deleteSConsumerById(Long id);
/**
* 检测手机验证码key
*
* @param phone String 手机号
* @return String
*/
String getValidateCodeRedisKey(String phone);
/**
* TODO 手机号注册,待实现
* @param phone 手机号
* @param channel 渠道
* @return
*/
SConsumer registerPhone(String phone, String channel);
SConsumer getByPhone(String phone);
Long saveSConsumer(SConsumer sConsumer);
SConsumer registerByThird(RegisterThirdSConsumerRequest thirdUserRequest);
}
package share.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import share.system.domain.SConsumerToken;
/**
* UserTokenService 接口实现
*/
public interface SConsumerTokenService extends IService<SConsumerToken> {
/**
* 获取UserToken
* @param token 微信为openid
* @return UserToken
*/
SConsumerToken getByOpenid(String token);
void bind(String openId, Long uid);
SConsumerToken getTokenByUserId(Long userId);
void deleteTokenById(Long userId);
}
\ No newline at end of file
package share.system.service;
import cn.hutool.json.JSONArray;
/**
* @author wuwenlong
* @date 2023年10月13日 15:30
*/
public interface SmsService {
/**
* 查询短信模板接口
* @param
*/
JSONArray queryTemplate();
/**
* 发送短信验证码
* @param phone
* @return
*/
boolean sendSmsCode(String phone);
}
package share.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import share.system.domain.SystemNotification;
import share.system.domain.TemplateMessage;
import share.system.request.NotificationInfoRequest;
import share.system.request.NotificationSearchRequest;
import share.system.request.NotificationUpdateRequest;
import share.system.response.NotificationInfoResponse;
import java.util.List;
/**
* 短信模板表
*/
public interface SystemNotificationService {
/**
* 系统通知列表
* @param request 查询对象
* @return List
*/
List<SystemNotification> getList(NotificationSearchRequest request);
/**
* 公众号模板开关
* @param id 通知id
* @return Boolean
*/
Boolean wechatSwitch(Integer id);
/**
* 小程序订阅模板开关
* @param id 通知id
* @return Boolean
*/
Boolean routineSwitch(Integer id);
/**
* 发送短信开关
* @param id 通知id
* @return Boolean
*/
Boolean smsSwitch(Integer id);
/**
* 通知详情
* @param request 详情请求参数
* @return NotificationInfoResponse
*/
NotificationInfoResponse getDetail(NotificationInfoRequest request);
/**
* 根据标识查询信息
* @param mark 标识
* @return SystemNotification
*/
SystemNotification getByMark(String mark);
/**
* 获取微信相关列表
* @param type routine-小程序,public-公众号
*/
List<SystemNotification> getListByWechat(String type);
/**
* 修改通知
* @param request 请求参数
* @return Boolean
*/
Boolean modify(NotificationUpdateRequest request);
/**
* 获取小程序订阅模板编号(小程序端调用)
* @param type 场景类型(支付之前:beforePay|支付成功:afterPay|申请退款:refundApply|充值之前:beforeRecharge|创建砍价:createBargain|参与拼团:pink|取消拼团:cancelPink)
* @return List
*/
List<TemplateMessage> getMiniTempList(String type);
}
\ No newline at end of file
package share.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import share.system.domain.WechatExceptions;
/**
* 微信异常服务类
*/
public interface WechatExceptionsService extends IService<WechatExceptions> {
/**
* 自动删除日志
*/
void autoDeleteLog();
}
\ No newline at end of file
package share.system.service;
import com.alibaba.fastjson.JSONObject;
import share.system.domain.vo.*;
import share.system.response.WeChatJsSdkConfigResponse;
import java.util.List;
import java.util.Map;
/**
* 微信公用服务
*/
public interface WechatNewService {
/**
* 获取公众号accessToken
* @return 公众号accessToken
*/
String getPublicAccessToken();
/**
* 获取小程序accessToken
* @return 小程序accessToken
*/
String getMiniAccessToken();
/**
* 获取开放平台access_token
* 通过 code 获取
* 公众号使用
* @return 开放平台accessToken对象
*/
WeChatOauthToken getOauth2AccessToken(String code);
/**
* 获取开放平台用户信息
* @param accessToken 调用凭证
* @param openid 普通用户的标识,对当前开发者帐号唯一
* 公众号使用
* @return 开放平台用户信息对象
*/
WeChatAuthorizeLoginUserInfoVo getSnsUserInfo(String accessToken, String openid);
/**
* 小程序登录凭证校验
* @return 小程序登录校验对象
*/
WeChatMiniAuthorizeVo miniAuthCode(String code);
/**
* 获取微信公众号js配置参数
* @return WeChatJsSdkConfigResponse
*/
WeChatJsSdkConfigResponse getJsSdkConfig(String url);
/**
* 生成小程序码
* @param page 必须是已经发布的小程序存在的页面
* @param scene 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~,其它字符请自行编码为合法字符
* @return 小程序码
*/
String createQrCode(String page, String scene);
/**
* 自定义参数生成小程序码
* @return
*/
String createQrCodeCustomParam(Map<String, Object> param);
/**
* 微信预下单接口(统一下单)
* @param unifiedorderVo 预下单请求对象
* @return 微信预下单返回对象
*/
CreateOrderResponseVo payUnifiedorder(CreateOrderRequestVo unifiedorderVo);
/**
* 微信支付查询订单
* @return 支付订单查询结果
*/
MyRecord payOrderQuery(Map<String, String> payVo);
/**
* 微信公众号发送模板消息
* @param templateMessage 模板消息对象
* @return 是否发送成功
*/
Boolean sendPublicTemplateMessage(TemplateMessageVo templateMessage);
/**
* 微信小程序发送订阅消息
* @param templateMessage 消息对象
* @return 是否发送成功
*/
Boolean sendMiniSubscribeMessage(TemplateMessageVo templateMessage);
/**
* 获取微信公众号自定义菜单配置
* (使用本自定义菜单查询接口可以获取默认菜单和全部个性化菜单信息)
* @return 公众号自定义菜单
*/
JSONObject getPublicCustomMenu();
/**
* 创建微信自定义菜单
* @param data 菜单json字符串
* @return 创建结果
*/
Boolean createPublicCustomMenu(String data);
/**
* 删除微信自定义菜单
* @return 删除结果
*/
Boolean deletePublicCustomMenu();
/**
* 企业号上传其他类型永久素材
* 获取url
* @param type 素材类型:图片(image)、语音(voice)、视频(video),普通文件(file)
*/
String qyapiAddMaterialUrl(String type);
/**
* 微信申请退款
* @param wxRefundVo 微信申请退款对象
* @param path 商户p12证书绝对路径
* @return 申请退款结果对象
*/
WxRefundResponseVo payRefund(WxRefundVo wxRefundVo, String path);
/**
* 获取我的公众号模板消息列表
* @return List
*/
List<PublicMyTemplateVo> getPublicMyTemplateList();
/**
* 删除微信公众号模板消息
* @return Boolean
*/
Boolean delPublicMyTemplate(String templateId);
/**
* 添加公众号模板消息
* @param templateIdShort 模板库中模板的编号,有“TM**”和“OPENTMTM**”等形式
* @return 公众号模板编号(自己的)
*/
String apiAddPublicTemplate(String templateIdShort);
/**
* 获取当前帐号下的个人模板列表(订阅消息)
* @return List
*/
List<RoutineMyTemplateVo> getRoutineMyTemplateList();
/**
* 删除微信小程序订阅消息
* @return Boolean
*/
Boolean delRoutineMyTemplate(String priTmplId);
/**
* 获取小程序平台上的标准模板
* @param tempKey 模板编号
* @return List
*/
List<RoutineTemplateKeyVo> getRoutineTemplateByWechat(String tempKey);
/**
* 添加小程序订阅消息
* @param tempKey 模板编号
* @param kidList 小程序订阅消息模板kid数组
* @return 小程序订阅消息模板编号(自己的)
*/
String apiAddRoutineTemplate(String tempKey, List<Integer> kidList);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment