微信小程序登录
This commit is contained in:
parent
91dab3510d
commit
2f68392778
@ -179,6 +179,12 @@
|
|||||||
<version>${wechatpay-apiv3.version}</version>
|
<version>${wechatpay-apiv3.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- redis 缓存操作 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- httpclient 依赖-->
|
<!-- httpclient 依赖-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
package com.yf.exam.ability;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通用常量
|
|
||||||
* @author bool
|
|
||||||
*/
|
|
||||||
public class Constant {
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文件上传路径
|
|
||||||
*/
|
|
||||||
public static final String FILE_PREFIX = "/upload/file/";
|
|
||||||
}
|
|
||||||
@ -1,16 +1,14 @@
|
|||||||
package com.yf.exam.ability.shiro.aop;
|
package com.yf.exam.ability.shiro.aop;
|
||||||
|
|
||||||
|
|
||||||
import com.yf.exam.ability.shiro.jwt.JwtToken;
|
import com.yf.exam.ability.shiro.jwt.JwtToken;
|
||||||
import com.yf.exam.aspect.utils.InjectUtils;
|
import com.yf.exam.aspect.utils.InjectUtils;
|
||||||
import com.yf.exam.modules.Constant;
|
import com.yf.exam.constant.Constants;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
|
|
||||||
|
|
||||||
import javax.servlet.ServletRequest;
|
import javax.servlet.ServletRequest;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 鉴权登录拦截器
|
* 鉴权登录拦截器
|
||||||
@ -42,7 +40,7 @@ public class JwtFilter extends BasicHttpAuthenticationFilter {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
|
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
|
||||||
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
|
||||||
String token = httpServletRequest.getHeader(Constant.TOKEN);
|
String token = httpServletRequest.getHeader(Constants.TOKEN);
|
||||||
|
|
||||||
JwtToken jwtToken = new JwtToken(token);
|
JwtToken jwtToken = new JwtToken(token);
|
||||||
// 提交给realm进行登入,如果错误他会抛出异常并被捕获
|
// 提交给realm进行登入,如果错误他会抛出异常并被捕获
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
package com.yf.exam.ability.upload.controller;
|
package com.yf.exam.ability.upload.controller;
|
||||||
|
|
||||||
|
|
||||||
import com.yf.exam.ability.Constant;
|
|
||||||
import com.yf.exam.ability.upload.dto.UploadReqDTO;
|
import com.yf.exam.ability.upload.dto.UploadReqDTO;
|
||||||
import com.yf.exam.ability.upload.dto.UploadRespDTO;
|
import com.yf.exam.ability.upload.dto.UploadRespDTO;
|
||||||
import com.yf.exam.ability.upload.service.UploadService;
|
import com.yf.exam.ability.upload.service.UploadService;
|
||||||
|
import com.yf.exam.constant.Constants;
|
||||||
import com.yf.exam.core.api.ApiRest;
|
import com.yf.exam.core.api.ApiRest;
|
||||||
import com.yf.exam.core.api.controller.BaseController;
|
import com.yf.exam.core.api.controller.BaseController;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
@ -16,9 +17,6 @@ import org.springframework.web.bind.annotation.ModelAttribute;
|
|||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 本地文件上传下载请求类
|
* 本地文件上传下载请求类
|
||||||
* @author bool
|
* @author bool
|
||||||
@ -49,7 +47,7 @@ public class UploadController extends BaseController {
|
|||||||
* @param request
|
* @param request
|
||||||
* @param response
|
* @param response
|
||||||
*/
|
*/
|
||||||
@GetMapping(Constant.FILE_PREFIX+"**")
|
@GetMapping(Constants.FILE_PREFIX+"**")
|
||||||
@ApiOperation(value = "文件下载", notes = "文件下载")
|
@ApiOperation(value = "文件下载", notes = "文件下载")
|
||||||
public void download(HttpServletRequest request, HttpServletResponse response) {
|
public void download(HttpServletRequest request, HttpServletResponse response) {
|
||||||
uploadService.download(request, response);
|
uploadService.download(request, response);
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.yf.exam.ability.upload.service.impl;
|
package com.yf.exam.ability.upload.service.impl;
|
||||||
|
|
||||||
import com.yf.exam.ability.Constant;
|
|
||||||
import com.yf.exam.ability.upload.config.UploadConfig;
|
import com.yf.exam.ability.upload.config.UploadConfig;
|
||||||
import com.yf.exam.ability.upload.config.UploadPathConfig;
|
import com.yf.exam.ability.upload.config.UploadPathConfig;
|
||||||
import com.yf.exam.ability.upload.dto.UploadReqDTO;
|
import com.yf.exam.ability.upload.dto.UploadReqDTO;
|
||||||
@ -155,7 +154,7 @@ public class UploadServiceImpl implements UploadService {
|
|||||||
*/
|
*/
|
||||||
public String getRealPath(String uri){
|
public String getRealPath(String uri){
|
||||||
|
|
||||||
String regx = Constant.FILE_PREFIX+"(.*)";
|
String regx = Constants.FILE_PREFIX+"(.*)";
|
||||||
|
|
||||||
// 查找全部变量
|
// 查找全部变量
|
||||||
Pattern pattern = Pattern.compile(regx);
|
Pattern pattern = Pattern.compile(regx);
|
||||||
|
|||||||
@ -0,0 +1,48 @@
|
|||||||
|
package com.yf.exam.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 微信小程序参数配置类
|
||||||
|
* @Author 纪寒
|
||||||
|
* @Date 2022-09-02 10:52:38
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "applet-chat-config")
|
||||||
|
public class AppletChatConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序id
|
||||||
|
*/
|
||||||
|
private String appletId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序secret
|
||||||
|
*/
|
||||||
|
private String secret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语
|
||||||
|
*/
|
||||||
|
private String lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 授权类型
|
||||||
|
*/
|
||||||
|
private String grantType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信小程序事件回调令牌
|
||||||
|
*/
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信小程序事件回调消息加密密钥
|
||||||
|
*/
|
||||||
|
private String encodingAesKey;
|
||||||
|
|
||||||
|
}
|
||||||
@ -50,6 +50,9 @@ public class ShiroConfig {
|
|||||||
map.put("/exam/api/sys/user/quick-reg", "anon");
|
map.put("/exam/api/sys/user/quick-reg", "anon");
|
||||||
map.put("/exam/api/sys/user/info", "anon");
|
map.put("/exam/api/sys/user/info", "anon");
|
||||||
|
|
||||||
|
// 小程序接口
|
||||||
|
map.put("/examApplet/**", "anon");
|
||||||
|
|
||||||
// 获取网站基本信息
|
// 获取网站基本信息
|
||||||
map.put("/exam/api/sys/config/detail", "anon");
|
map.put("/exam/api/sys/config/detail", "anon");
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package com.yf.exam.config;
|
|||||||
|
|
||||||
import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
|
import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import java.util.Collections;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -16,8 +17,6 @@ import springfox.documentation.spi.DocumentationType;
|
|||||||
import springfox.documentation.spring.web.plugins.Docket;
|
import springfox.documentation.spring.web.plugins.Docket;
|
||||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swagger配置
|
* Swagger配置
|
||||||
* @author bool
|
* @author bool
|
||||||
@ -37,7 +36,8 @@ public class SwaggerConfig {
|
|||||||
.groupName("考试模块接口")
|
.groupName("考试模块接口")
|
||||||
.select()
|
.select()
|
||||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||||
.paths(PathSelectors.ant("/exam/api/**"))
|
//.paths(PathSelectors.ant("/exam/api/**"))
|
||||||
|
.paths(PathSelectors.any())
|
||||||
.build()
|
.build()
|
||||||
.securitySchemes(Collections.singletonList(securityScheme()));
|
.securitySchemes(Collections.singletonList(securityScheme()));
|
||||||
}
|
}
|
||||||
|
|||||||
578
exam-admin/src/main/java/com/yf/exam/config/XinYiLuConfig.java
Normal file
578
exam-admin/src/main/java/com/yf/exam/config/XinYiLuConfig.java
Normal file
@ -0,0 +1,578 @@
|
|||||||
|
package com.yf.exam.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取项目相关配置
|
||||||
|
*
|
||||||
|
* @author xinyilu
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "xinyilu")
|
||||||
|
public class XinYiLuConfig {
|
||||||
|
/**
|
||||||
|
* 项目名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本
|
||||||
|
*/
|
||||||
|
private String version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版权年份
|
||||||
|
*/
|
||||||
|
private String copyrightYear;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例演示开关
|
||||||
|
*/
|
||||||
|
private boolean demoEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传路径
|
||||||
|
*/
|
||||||
|
private static String profile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取地址开关
|
||||||
|
*/
|
||||||
|
private static boolean addressEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证码类型
|
||||||
|
*/
|
||||||
|
private static String captchaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 柏杏家医云小程序图片存放路径
|
||||||
|
*/
|
||||||
|
private String nurserAppletPicture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 护理站图片上传存放路径
|
||||||
|
*/
|
||||||
|
private String nurserStationPictureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 护理站图片上传存放路径
|
||||||
|
*/
|
||||||
|
private String nurserStationIntroducePictureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 护理站项目图片上传存放路径
|
||||||
|
*/
|
||||||
|
private String nurserStationItemPictureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品图片路径上传存放路径
|
||||||
|
*/
|
||||||
|
private String goodsPictureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品属性图片地址
|
||||||
|
*/
|
||||||
|
private String attributePitureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改会员App用户头像上传
|
||||||
|
*/
|
||||||
|
private String headPictureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 评价信息图片上传路径
|
||||||
|
*/
|
||||||
|
private String evaluatePictureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务完成上传图片
|
||||||
|
*/
|
||||||
|
private String appointmentOrderDetailsUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 护理机构上传图片
|
||||||
|
*/
|
||||||
|
private String nurseStationClassifyUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 海报图片存放路径
|
||||||
|
*/
|
||||||
|
private String posterPictureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 海报视频存放路径
|
||||||
|
*/
|
||||||
|
private String posterVideoUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资讯主缩略图地址
|
||||||
|
*/
|
||||||
|
private String leadThumbnailUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品分类图片地址
|
||||||
|
*/
|
||||||
|
private String goodsCategoryPicture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 护理员App人员头像的上传路径图片上传路径
|
||||||
|
*/
|
||||||
|
private String nurseStationAppPersonUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取管理端富文本的上传路径
|
||||||
|
*/
|
||||||
|
private String richTextPictureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 护理项目分类图标存放地址存放路径
|
||||||
|
*/
|
||||||
|
private String nurseItemClassifyUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线客服群二维码存放路径
|
||||||
|
*/
|
||||||
|
private String groupQrCodeUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 科室人员证书图片存放路径
|
||||||
|
*/
|
||||||
|
private String certificateUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 健康咨询 科室人员头像地址
|
||||||
|
*/
|
||||||
|
private String personPictureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 护理人员证书地址
|
||||||
|
*/
|
||||||
|
private String personCertificateUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核护理人员证书地址
|
||||||
|
*/
|
||||||
|
private String personCertificateCheckUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医路
|
||||||
|
*/
|
||||||
|
private String yiLuYouPinStoreName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 护理员App上传路径
|
||||||
|
*/
|
||||||
|
private String appFileName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 泉医到家App文件存放路径
|
||||||
|
*/
|
||||||
|
private String appFilePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 培训分类图片路径
|
||||||
|
*/
|
||||||
|
private String trainingCategoryPictureUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 培训项目logo图片路径
|
||||||
|
*/
|
||||||
|
private String trainingItemCoverUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 培训项目海报图片路径
|
||||||
|
*/
|
||||||
|
private String trainingItemPosterUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 培训项目海报图片路径
|
||||||
|
*/
|
||||||
|
private String trainingItemContentUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 培训项目章节视频存放地址
|
||||||
|
*/
|
||||||
|
private String itemDirectoryUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信好有邀请二维码存放路径
|
||||||
|
*/
|
||||||
|
private String personalWeChatCodeUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 护理站二维码存放路径
|
||||||
|
*/
|
||||||
|
private String stationWechatCodeUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实人认证身份证照片地址
|
||||||
|
*/
|
||||||
|
private String cardNoPicUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预约订单护理项目告知书签字图片地址
|
||||||
|
*/
|
||||||
|
private String itemInformUrl;
|
||||||
|
|
||||||
|
public String getItemInformUrl() {
|
||||||
|
return itemInformUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemInformUrl(String itemInformUrl) {
|
||||||
|
this.itemInformUrl = itemInformUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCardNoPicUrl() {
|
||||||
|
return cardNoPicUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCardNoPicUrl(String cardNoPicUrl) {
|
||||||
|
this.cardNoPicUrl = cardNoPicUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStationWechatCodeUrl() {
|
||||||
|
return stationWechatCodeUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStationWechatCodeUrl(String stationWechatCodeUrl) {
|
||||||
|
this.stationWechatCodeUrl = stationWechatCodeUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPersonalWeChatCodeUrl() {
|
||||||
|
return personalWeChatCodeUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonalWeChatCodeUrl(String personalWeChatCodeUrl) {
|
||||||
|
this.personalWeChatCodeUrl = personalWeChatCodeUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppFilePath() {
|
||||||
|
return appFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppFilePath(String appFilePath) {
|
||||||
|
this.appFilePath = appFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getYiLuYouPinStoreName() {
|
||||||
|
return yiLuYouPinStoreName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYiLuYouPinStoreName(String yiLuYouPinStoreName) {
|
||||||
|
this.yiLuYouPinStoreName = yiLuYouPinStoreName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVersion(String version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCopyrightYear() {
|
||||||
|
return copyrightYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCopyrightYear(String copyrightYear) {
|
||||||
|
this.copyrightYear = copyrightYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDemoEnabled() {
|
||||||
|
return demoEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDemoEnabled(boolean demoEnabled) {
|
||||||
|
this.demoEnabled = demoEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getProfile() {
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProfile(String profile) {
|
||||||
|
XinYiLuConfig.profile = profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAddressEnabled() {
|
||||||
|
return addressEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddressEnabled(boolean addressEnabled) {
|
||||||
|
XinYiLuConfig.addressEnabled = addressEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCaptchaType() {
|
||||||
|
return captchaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCaptchaType(String captchaType) {
|
||||||
|
XinYiLuConfig.captchaType = captchaType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取导入上传路径
|
||||||
|
*/
|
||||||
|
public static String getImportPath() {
|
||||||
|
return getProfile() + "/import";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取头像上传路径
|
||||||
|
*/
|
||||||
|
public static String getAvatarPath() {
|
||||||
|
return getProfile() + "/avatar";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取下载路径
|
||||||
|
*/
|
||||||
|
public static String getDownloadPath() {
|
||||||
|
return getProfile() + "/download/";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上传路径
|
||||||
|
*/
|
||||||
|
public static String getUploadPath() {
|
||||||
|
return getProfile() + "/upload";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNurserAppletPicture() {
|
||||||
|
return nurserAppletPicture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNurserAppletPicture(String nurserAppletPicture) {
|
||||||
|
this.nurserAppletPicture = nurserAppletPicture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNurserStationPictureUrl() {
|
||||||
|
return nurserStationPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNurserStationPictureUrl(String nurserStationPictureUrl) {
|
||||||
|
this.nurserStationPictureUrl = nurserStationPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNurserStationIntroducePictureUrl() {
|
||||||
|
return nurserStationIntroducePictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNurserStationIntroducePictureUrl(String nurserStationIntroducePictureUrl) {
|
||||||
|
this.nurserStationIntroducePictureUrl = nurserStationIntroducePictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNurserStationItemPictureUrl() {
|
||||||
|
return nurserStationItemPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNurserStationItemPictureUrl(String nurserStationItemPictureUrl) {
|
||||||
|
this.nurserStationItemPictureUrl = nurserStationItemPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGoodsPictureUrl() {
|
||||||
|
return goodsPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoodsPictureUrl(String goodsPictureUrl) {
|
||||||
|
this.goodsPictureUrl = goodsPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeadPictureUrl() {
|
||||||
|
return headPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeadPictureUrl(String headPictureUrl) {
|
||||||
|
this.headPictureUrl = headPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppointmentOrderDetailsUrl() {
|
||||||
|
return appointmentOrderDetailsUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppointmentOrderDetailsUrl(String appointmentOrderDetailsUrl) {
|
||||||
|
this.appointmentOrderDetailsUrl = appointmentOrderDetailsUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttributePitureUrl() {
|
||||||
|
return attributePitureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttributePitureUrl(String attributePitureUrl) {
|
||||||
|
this.attributePitureUrl = attributePitureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getAppFileName() {
|
||||||
|
return appFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppFileName(String appFileName) {
|
||||||
|
this.appFileName = appFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNurseStationAppPersonUrl() {
|
||||||
|
return nurseStationAppPersonUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNurseStationAppPersonUrl(String nurseStationAppPersonUrl) {
|
||||||
|
this.nurseStationAppPersonUrl = nurseStationAppPersonUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEvaluatePictureUrl() {
|
||||||
|
return evaluatePictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEvaluatePictureUrl(String evaluatePictureUrl) {
|
||||||
|
this.evaluatePictureUrl = evaluatePictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRichTextPictureUrl() {
|
||||||
|
return richTextPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRichTextPictureUrl(String richTextPictureUrl) {
|
||||||
|
this.richTextPictureUrl = richTextPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGoodsCategoryPicture() {
|
||||||
|
return goodsCategoryPicture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoodsCategoryPicture(String goodsCategoryPicture) {
|
||||||
|
this.goodsCategoryPicture = goodsCategoryPicture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNurseStationClassifyUrl() {
|
||||||
|
return nurseStationClassifyUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNurseStationClassifyUrl(String nurseStationClassifyUrl) {
|
||||||
|
this.nurseStationClassifyUrl = nurseStationClassifyUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNurseItemClassifyUrl() {
|
||||||
|
return nurseItemClassifyUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNurseItemClassifyUrl(String nurseItemClassifyUrl) {
|
||||||
|
this.nurseItemClassifyUrl = nurseItemClassifyUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPosterPictureUrl() {
|
||||||
|
return posterPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosterPictureUrl(String posterPictureUrl) {
|
||||||
|
this.posterPictureUrl = posterPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLeadThumbnailUrl() {
|
||||||
|
return leadThumbnailUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLeadThumbnailUrl(String leadThumbnailUrl) {
|
||||||
|
this.leadThumbnailUrl = leadThumbnailUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getPosterVideoUrl() {
|
||||||
|
return posterVideoUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosterVideoUrl(String posterVideoUrl) {
|
||||||
|
this.posterVideoUrl = posterVideoUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getGroupQrCodeUrl() {
|
||||||
|
return groupQrCodeUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupQrCodeUrl(String groupQrCodeUrl) {
|
||||||
|
this.groupQrCodeUrl = groupQrCodeUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getCertificateUrl() {
|
||||||
|
return certificateUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCertificateUrl(String certificateUrl) {
|
||||||
|
this.certificateUrl = certificateUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPersonPictureUrl() {
|
||||||
|
return personPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonPictureUrl(String personPictureUrl) {
|
||||||
|
this.personPictureUrl = personPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPersonCertificateUrl() {
|
||||||
|
return personCertificateUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonCertificateUrl(String personCertificateUrl) {
|
||||||
|
this.personCertificateUrl = personCertificateUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPersonCertificateCheckUrl() {
|
||||||
|
return personCertificateCheckUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonCertificateCheckUrl(String personCertificateCheckUrl) {
|
||||||
|
this.personCertificateCheckUrl = personCertificateCheckUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTrainingCategoryPictureUrl() {
|
||||||
|
return trainingCategoryPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTrainingCategoryPictureUrl(String trainingCategoryPictureUrl) {
|
||||||
|
this.trainingCategoryPictureUrl = trainingCategoryPictureUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTrainingItemCoverUrl() {
|
||||||
|
return trainingItemCoverUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTrainingItemCoverUrl(String trainingItemCoverUrl) {
|
||||||
|
this.trainingItemCoverUrl = trainingItemCoverUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTrainingItemPosterUrl() {
|
||||||
|
return trainingItemPosterUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTrainingItemPosterUrl(String trainingItemPosterUrl) {
|
||||||
|
this.trainingItemPosterUrl = trainingItemPosterUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTrainingItemContentUrl() {
|
||||||
|
return trainingItemContentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTrainingItemContentUrl(String trainingItemContentUrl) {
|
||||||
|
this.trainingItemContentUrl = trainingItemContentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getItemDirectoryUrl() {
|
||||||
|
return itemDirectoryUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemDirectoryUrl(String itemDirectoryUrl) {
|
||||||
|
this.itemDirectoryUrl = itemDirectoryUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,7 +5,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description 新医路商户号微信支付参数配置类
|
* @Description 山东省公共卫生学会商户号微信支付参数配置类
|
||||||
* @Author 纪寒
|
* @Author 纪寒
|
||||||
* @Date 2022-10-17 16:55:04
|
* @Date 2022-10-17 16:55:04
|
||||||
* @Version 1.0
|
* @Version 1.0
|
||||||
@ -16,27 +16,27 @@ import org.springframework.stereotype.Component;
|
|||||||
public class XylWeChatPaymentConfig {
|
public class XylWeChatPaymentConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新医路商户号
|
* 山东省公共卫生学会商户号
|
||||||
*/
|
*/
|
||||||
private String xylMchId;
|
private String xylMchId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新医路API证书序号getXylVerifier
|
* 山东省公共卫生学会证书序号getXylVerifier
|
||||||
*/
|
*/
|
||||||
private String xylMchSerialNo;
|
private String xylMchSerialNo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新医路私钥文件
|
* 山东省公共卫生学会私钥文件
|
||||||
*/
|
*/
|
||||||
private String xylPrivateKeyPath;
|
private String xylPrivateKeyPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新医路API V3版本密钥
|
* 山东省公共卫生学会API V3版本密钥
|
||||||
*/
|
*/
|
||||||
private String xylPaymentKey;
|
private String xylPaymentKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新医路支付回调地址
|
* 山东省公共卫生学会支付回调地址
|
||||||
*/
|
*/
|
||||||
private String xylWeChatNotifyUrl;
|
private String xylWeChatNotifyUrl;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description 新医路商户号微信支付核心配置类
|
* @Description 山东省公共卫生学会商户号微信支付核心配置类
|
||||||
* @Author 纪寒
|
* @Author 纪寒
|
||||||
* @Date 2022-10-17 18:56:22
|
* @Date 2022-10-17 18:56:22
|
||||||
* @Version 1.0
|
* @Version 1.0
|
||||||
@ -32,7 +32,7 @@ public class XylWeChatPaymentUtilConfig {
|
|||||||
private XylWeChatPaymentConfig xylWeChatPaymentConfig;
|
private XylWeChatPaymentConfig xylWeChatPaymentConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取新医路签名信息
|
* 获取山东省公共卫生学会签名信息
|
||||||
*
|
*
|
||||||
* @return 签名信息
|
* @return 签名信息
|
||||||
* @throws Exception 异常信息
|
* @throws Exception 异常信息
|
||||||
@ -54,36 +54,36 @@ public class XylWeChatPaymentUtilConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取新医路商户号带有签名的http请求对象
|
* 获取山东省公共卫生学会商户号带有签名的http请求对象
|
||||||
*
|
*
|
||||||
* @return CloseableHttpClient对象
|
* @return CloseableHttpClient对象
|
||||||
*/
|
*/
|
||||||
@Bean(name = "xinYiLuWeChatPayClient")
|
@Bean(name = "xinYiLuWeChatPayClient")
|
||||||
public CloseableHttpClient getXinYiLuWeChatPayClient(Verifier xylVerifier) {
|
public CloseableHttpClient getXinYiLuWeChatPayClient(Verifier xylVerifier) {
|
||||||
log.info("开始获取新医路商户带有签名信息的http请求对象........");
|
log.info("开始获取山东省公共卫生学会商户带有签名信息的http请求对象........");
|
||||||
//获取商户私钥
|
//获取商户私钥
|
||||||
PrivateKey privateKey = getPrivateKey(xylWeChatPaymentConfig.getXylPrivateKeyPath());
|
PrivateKey privateKey = getPrivateKey(xylWeChatPaymentConfig.getXylPrivateKeyPath());
|
||||||
CloseableHttpClient closeableHttpClient = null;
|
CloseableHttpClient closeableHttpClient = null;
|
||||||
try {
|
try {
|
||||||
log.info("新医路签名验证证书,xinYiLuCertificatesVerifier:{}", xylVerifier);
|
log.info("山东省公共卫生学会签名验证证书,xinYiLuCertificatesVerifier:{}", xylVerifier);
|
||||||
//通过WeChatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
|
//通过WeChatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
|
||||||
closeableHttpClient = WechatPayHttpClientBuilder.create()
|
closeableHttpClient = WechatPayHttpClientBuilder.create()
|
||||||
.withMerchant(xylWeChatPaymentConfig.getXylMchId(), xylWeChatPaymentConfig.getXylMchSerialNo(), privateKey)
|
.withMerchant(xylWeChatPaymentConfig.getXylMchId(), xylWeChatPaymentConfig.getXylMchSerialNo(), privateKey)
|
||||||
.withValidator(new WechatPay2Validator(xylVerifier)).build();
|
.withValidator(new WechatPay2Validator(xylVerifier)).build();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("新医路验证签名信息失败,失败信息:{}", e.getMessage());
|
log.error("山东省公共卫生学会验证签名信息失败,失败信息:{}", e.getMessage());
|
||||||
}
|
}
|
||||||
return closeableHttpClient;
|
return closeableHttpClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取新医路商户号无签名的http请求对象
|
* 获取山东省公共卫生学会商户号无签名的http请求对象
|
||||||
*
|
*
|
||||||
* @return CloseableHttpClient对象
|
* @return CloseableHttpClient对象
|
||||||
*/
|
*/
|
||||||
@Bean(name = "xinYiLuWeChatPayNoSignClient")
|
@Bean(name = "xinYiLuWeChatPayNoSignClient")
|
||||||
public CloseableHttpClient getXinYiLuWeChatPayNoSignClient() {
|
public CloseableHttpClient getXinYiLuWeChatPayNoSignClient() {
|
||||||
log.info("获取新医路商户的无签名信息的http请求对象.........");
|
log.info("获取山东省公共卫生学会商户的无签名信息的http请求对象.........");
|
||||||
//获取商户私钥
|
//获取商户私钥
|
||||||
PrivateKey privateKey = getPrivateKey(xylWeChatPaymentConfig.getXylPrivateKeyPath());
|
PrivateKey privateKey = getPrivateKey(xylWeChatPaymentConfig.getXylPrivateKeyPath());
|
||||||
//通过WeChatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
|
//通过WeChatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
|
||||||
@ -102,8 +102,8 @@ public class XylWeChatPaymentUtilConfig {
|
|||||||
try {
|
try {
|
||||||
return PemUtil.loadPrivateKey(new ClassPathResource(filename).getInputStream());
|
return PemUtil.loadPrivateKey(new ClassPathResource(filename).getInputStream());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("新医路商户私钥文件不存在,错误原因:{}", e.getMessage());
|
log.error("山东省公共卫生学会商户私钥文件不存在,错误原因:{}", e.getMessage());
|
||||||
throw new ServiceException("新医路商户私钥文件不存在,请联系管理员!");
|
throw new ServiceException("山东省公共卫生学会商户私钥文件不存在,请联系管理员!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,21 @@ package com.yf.exam.constant;
|
|||||||
*/
|
*/
|
||||||
public class Constants {
|
public class Constants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UTF-8 字符集
|
||||||
|
*/
|
||||||
|
public static final String UTF8 = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话
|
||||||
|
*/
|
||||||
|
public static final String TOKEN = "token";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上传路径
|
||||||
|
*/
|
||||||
|
public static final String FILE_PREFIX = "/upload/file/";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 身份证正面照片路径上传
|
* 身份证正面照片路径上传
|
||||||
*/
|
*/
|
||||||
@ -42,6 +57,11 @@ public class Constants {
|
|||||||
*/
|
*/
|
||||||
public static final String sign_picture_type = "signPictureUrl";
|
public static final String sign_picture_type = "signPictureUrl";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信小程序ACCESS_TOKEN前缀
|
||||||
|
*/
|
||||||
|
public static final String EXAM_APPLET_ACCESS_TOKEN = "EXAM_APPLET_ACCESS_TOKEN:";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
165
exam-admin/src/main/java/com/yf/exam/core/domain/AjaxResult.java
Normal file
165
exam-admin/src/main/java/com/yf/exam/core/domain/AjaxResult.java
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
package com.yf.exam.core.domain;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作消息提醒
|
||||||
|
*
|
||||||
|
* @author xinyilu
|
||||||
|
*/
|
||||||
|
public class AjaxResult extends HashMap<String, Object> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态码
|
||||||
|
*/
|
||||||
|
public static final String CODE_TAG = "code";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回内容
|
||||||
|
*/
|
||||||
|
public static final String MSG_TAG = "msg";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据对象
|
||||||
|
*/
|
||||||
|
public static final String DATA_TAG = "data";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 成功默认消息
|
||||||
|
*/
|
||||||
|
private static final Integer CODE_SUCCESS = 0;
|
||||||
|
private static final String MSG_SUCCESS = "操作成功!";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 失败默认消息
|
||||||
|
*/
|
||||||
|
private static final Integer CODE_FAILURE = 1;
|
||||||
|
private static final String MSG_FAILURE = "请求失败!";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
|
||||||
|
*/
|
||||||
|
public AjaxResult() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化一个新创建的 AjaxResult 对象
|
||||||
|
*
|
||||||
|
* @param code 状态码
|
||||||
|
* @param msg 返回内容
|
||||||
|
*/
|
||||||
|
public AjaxResult(int code, String msg) {
|
||||||
|
super.put(CODE_TAG, code);
|
||||||
|
super.put(MSG_TAG, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化一个新创建的 AjaxResult 对象
|
||||||
|
*
|
||||||
|
* @param code 状态码
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @param data 数据对象
|
||||||
|
*/
|
||||||
|
public AjaxResult(int code, String msg, Object data) {
|
||||||
|
super.put(CODE_TAG, code);
|
||||||
|
super.put(MSG_TAG, msg);
|
||||||
|
if (!(data == null)) {
|
||||||
|
super.put(DATA_TAG, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功消息
|
||||||
|
*
|
||||||
|
* @return 成功消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult success() {
|
||||||
|
return AjaxResult.success("操作成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功数据
|
||||||
|
*
|
||||||
|
* @return 成功消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult success(Object data) {
|
||||||
|
return AjaxResult.success("操作成功", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功消息
|
||||||
|
*
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @return 成功消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult success(String msg) {
|
||||||
|
return AjaxResult.success(msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功消息
|
||||||
|
*
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @param data 数据对象
|
||||||
|
* @return 成功消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult success(String msg, Object data) {
|
||||||
|
return new AjaxResult(CODE_SUCCESS, msg, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回错误消息
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static AjaxResult error() {
|
||||||
|
return AjaxResult.error("操作失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回错误消息
|
||||||
|
*
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @return 警告消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult error(String msg) {
|
||||||
|
return AjaxResult.error(msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回错误消息
|
||||||
|
*
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @param data 数据对象
|
||||||
|
* @return 警告消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult error(String msg, Object data) {
|
||||||
|
return new AjaxResult(CODE_FAILURE, msg, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回错误消息
|
||||||
|
*
|
||||||
|
* @param code 状态码
|
||||||
|
* @param msg 返回内容
|
||||||
|
* @return 警告消息
|
||||||
|
*/
|
||||||
|
public static AjaxResult error(int code, String msg) {
|
||||||
|
return new AjaxResult(code, msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 方便链式调用
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param value 值
|
||||||
|
* @return 数据对象
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AjaxResult put(String key, Object value) {
|
||||||
|
super.put(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
226
exam-admin/src/main/java/com/yf/exam/core/redis/RedisCache.java
Normal file
226
exam-admin/src/main/java/com/yf/exam/core/redis/RedisCache.java
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
package com.yf.exam.core.redis;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import org.springframework.data.redis.core.BoundSetOperations;
|
||||||
|
import org.springframework.data.redis.core.HashOperations;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.ValueOperations;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* spring redis 工具类
|
||||||
|
*
|
||||||
|
* @author xinyilu
|
||||||
|
**/
|
||||||
|
@SuppressWarnings(value = {"unchecked", "rawtypes"})
|
||||||
|
@Component
|
||||||
|
public class RedisCache {
|
||||||
|
@Resource
|
||||||
|
public RedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存基本的对象,Integer、String、实体类等
|
||||||
|
*
|
||||||
|
* @param key 缓存的键值
|
||||||
|
* @param value 缓存的值
|
||||||
|
*/
|
||||||
|
public <T> void setCacheObject(final String key, final T value) {
|
||||||
|
redisTemplate.opsForValue().set(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存基本的对象,Integer、String、实体类等
|
||||||
|
*
|
||||||
|
* @param key 缓存的键值
|
||||||
|
* @param value 缓存的值
|
||||||
|
* @param timeout 时间
|
||||||
|
* @param timeUnit 时间颗粒度
|
||||||
|
*/
|
||||||
|
public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
|
||||||
|
redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置有效时间
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param timeout 超时时间
|
||||||
|
* @return true=设置成功;false=设置失败
|
||||||
|
*/
|
||||||
|
public boolean expire(final String key, final long timeout) {
|
||||||
|
return expire(key, timeout, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置有效时间
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param timeout 超时时间
|
||||||
|
* @param unit 时间单位
|
||||||
|
* @return true=设置成功;false=设置失败
|
||||||
|
*/
|
||||||
|
public boolean expire(final String key, final long timeout, final TimeUnit unit) {
|
||||||
|
return redisTemplate.expire(key, timeout, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的基本对象。
|
||||||
|
*
|
||||||
|
* @param key 缓存键值
|
||||||
|
* @return 缓存键值对应的数据
|
||||||
|
*/
|
||||||
|
public <T> T getCacheObject(final String key) {
|
||||||
|
ValueOperations<String, T> operation = redisTemplate.opsForValue();
|
||||||
|
return operation.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除单个对象
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
public boolean deleteObject(final String key) {
|
||||||
|
return redisTemplate.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除集合对象
|
||||||
|
*
|
||||||
|
* @param collection 多个对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public long deleteObject(final Collection collection) {
|
||||||
|
return redisTemplate.delete(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存List数据
|
||||||
|
*
|
||||||
|
* @param key 缓存的键值
|
||||||
|
* @param dataList 待缓存的List数据
|
||||||
|
* @return 缓存的对象
|
||||||
|
*/
|
||||||
|
public <T> long setCacheList(final String key, final List<T> dataList) {
|
||||||
|
Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
|
||||||
|
return count == null ? 0 : count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的list对象
|
||||||
|
*
|
||||||
|
* @param key 缓存的键值
|
||||||
|
* @return 缓存键值对应的数据
|
||||||
|
*/
|
||||||
|
public <T> List<T> getCacheList(final String key) {
|
||||||
|
return redisTemplate.opsForList().range(key, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存Set
|
||||||
|
*
|
||||||
|
* @param key 缓存键值
|
||||||
|
* @param dataSet 缓存的数据
|
||||||
|
* @return 缓存数据的对象
|
||||||
|
*/
|
||||||
|
public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
|
||||||
|
BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
|
||||||
|
Iterator<T> it = dataSet.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
setOperation.add(it.next());
|
||||||
|
}
|
||||||
|
return setOperation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的set
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public <T> Set<T> getCacheSet(final String key) {
|
||||||
|
return redisTemplate.opsForSet().members(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存Map
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param dataMap
|
||||||
|
*/
|
||||||
|
public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
|
||||||
|
if (dataMap != null) {
|
||||||
|
redisTemplate.opsForHash().putAll(key, dataMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的Map
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public <T> Map<String, T> getCacheMap(final String key) {
|
||||||
|
return redisTemplate.opsForHash().entries(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 往Hash中存入数据
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param hKey Hash键
|
||||||
|
* @param value 值
|
||||||
|
*/
|
||||||
|
public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
|
||||||
|
redisTemplate.opsForHash().put(key, hKey, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Hash中的数据
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param hKey Hash键
|
||||||
|
* @return Hash中的对象
|
||||||
|
*/
|
||||||
|
public <T> T getCacheMapValue(final String key, final String hKey) {
|
||||||
|
HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
|
||||||
|
return opsForHash.get(key, hKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除Hash中的数据
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param hKey
|
||||||
|
*/
|
||||||
|
public void delCacheMapValue(final String key, final String hKey) {
|
||||||
|
HashOperations hashOperations = redisTemplate.opsForHash();
|
||||||
|
hashOperations.delete(key, hKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取多个Hash中的数据
|
||||||
|
*
|
||||||
|
* @param key Redis键
|
||||||
|
* @param hKeys Hash键集合
|
||||||
|
* @return Hash对象集合
|
||||||
|
*/
|
||||||
|
public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
|
||||||
|
return redisTemplate.opsForHash().multiGet(key, hKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得缓存的基本对象列表
|
||||||
|
*
|
||||||
|
* @param pattern 字符串前缀
|
||||||
|
* @return 对象列表
|
||||||
|
*/
|
||||||
|
public Collection<String> keys(final String pattern) {
|
||||||
|
return redisTemplate.keys(pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,277 @@
|
|||||||
|
package com.yf.exam.core.utils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.yf.exam.config.AppletChatConfig;
|
||||||
|
import com.yf.exam.config.XinYiLuConfig;
|
||||||
|
import com.yf.exam.constant.Constants;
|
||||||
|
import com.yf.exam.core.exception.ServiceException;
|
||||||
|
import com.yf.exam.core.utils.http.HttpUtils;
|
||||||
|
import com.yf.exam.modules.applet.entity.AppletAccessToken;
|
||||||
|
import com.yf.exam.modules.applet.vo.AppletLoginVO;
|
||||||
|
import com.yf.exam.modules.applet.vo.AppletPhoneVO;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 微信小程序工具类
|
||||||
|
* @Author 纪寒
|
||||||
|
* @Date 2022-08-17 16:11:10
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class AppletChatUtil {
|
||||||
|
|
||||||
|
private static RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
private static AppletChatConfig appletChatConfig;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
public void redisTemplate(RedisTemplate<String, Object> redisTemplate) {
|
||||||
|
AppletChatUtil.redisTemplate = redisTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
public void appletChatConfig(AppletChatConfig appletChatConfig) {
|
||||||
|
AppletChatUtil.appletChatConfig = appletChatConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功状态码
|
||||||
|
*/
|
||||||
|
private static final int SUCCESS_CODE = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序登录url
|
||||||
|
*/
|
||||||
|
private static final String APPLET_LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序accessToken的url
|
||||||
|
*/
|
||||||
|
private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序获取用户手机号的url
|
||||||
|
*/
|
||||||
|
private static final String PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取小程序二维码接口地址
|
||||||
|
*/
|
||||||
|
private static final String GET_APPLET_CODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON数据格式标识
|
||||||
|
*/
|
||||||
|
private static final String JSON_DATA_FORMAT = "Content-Type: application/json; encoding=utf-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成小程序二维码图片失败标识
|
||||||
|
*/
|
||||||
|
private static final String FAIL = "FAIL";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据登录编码获取微信用户信息
|
||||||
|
*
|
||||||
|
* @param appletId 小程序id
|
||||||
|
* @param secret 小程序秘钥
|
||||||
|
* @param code 登录凭证码
|
||||||
|
* @param grantType 授权类型
|
||||||
|
* @return 登录信息
|
||||||
|
*/
|
||||||
|
public static AppletLoginVO getAppletLoginInfo(String appletId, String secret, String code, String grantType) {
|
||||||
|
//请求地址
|
||||||
|
String appletLoginUrl = APPLET_LOGIN_URL
|
||||||
|
+ "?appid=" + appletId
|
||||||
|
+ "&secret=" + secret
|
||||||
|
+ "&js_code=" + code
|
||||||
|
+ "&grant_type=" + grantType;
|
||||||
|
//发送请求
|
||||||
|
String result = HttpUtils.sendGet(appletLoginUrl);
|
||||||
|
if (StringUtils.isBlank(result)) {
|
||||||
|
throw new ServiceException("获取微信小程序用户信息失败");
|
||||||
|
}
|
||||||
|
return JSON.parseObject(result, AppletLoginVO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取微信小程序的accessToken
|
||||||
|
*
|
||||||
|
* @param appletId 小程序id
|
||||||
|
* @param secret 小程序秘钥
|
||||||
|
* @return accessToken信息
|
||||||
|
*/
|
||||||
|
public static AppletAccessToken getAppletAccessToken(String appletId, String secret) {
|
||||||
|
//请求路径
|
||||||
|
String accessTokenUrl = ACCESS_TOKEN_URL + "&appid=" + appletId + "&secret=" + secret;
|
||||||
|
//发送请求
|
||||||
|
String result = HttpUtils.sendGet(accessTokenUrl);
|
||||||
|
if (StringUtils.isBlank(result)) {
|
||||||
|
throw new ServiceException("获取微信小程序accessToken信息失败");
|
||||||
|
}
|
||||||
|
return JSON.parseObject(result, AppletAccessToken.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取微信小程序的手机号码
|
||||||
|
*
|
||||||
|
* @param code 登录凭证
|
||||||
|
* @param accessToken 小程序accessToken
|
||||||
|
* @return 手机信息
|
||||||
|
*/
|
||||||
|
public static AppletPhoneVO getAppletPhoneInfo(String code, String accessToken) {
|
||||||
|
//请求地址
|
||||||
|
String phoneUrl = PHONE_NUMBER_URL + accessToken;
|
||||||
|
//请求参数
|
||||||
|
Map<String, Object> paramMap = new HashMap<>();
|
||||||
|
paramMap.put("code", code);
|
||||||
|
String param = JSON.toJSONString(paramMap);
|
||||||
|
//发送POST请求
|
||||||
|
String result = HttpUtils.sendPostJson(phoneUrl, param);
|
||||||
|
if (StringUtils.isBlank(result)) {
|
||||||
|
throw new ServiceException("获取微信小程序手机号失败");
|
||||||
|
}
|
||||||
|
return JSON.parseObject(result, AppletPhoneVO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归获取小程序二维码信息
|
||||||
|
*
|
||||||
|
* @param weChatCodeId 输入id
|
||||||
|
* @param failFlag 调用失败标识
|
||||||
|
* @param fileName 文件名称
|
||||||
|
* @param appletPageUrl 二维码跳转路径
|
||||||
|
* @param filePathWeChatCodeUrl 文件保存路径
|
||||||
|
* @return java.lang.String 二维码地址
|
||||||
|
*/
|
||||||
|
public static String createAppletCode(Long weChatCodeId, boolean failFlag, String fileName, String appletPageUrl, String filePathWeChatCodeUrl) {
|
||||||
|
if (BooleanUtils.isTrue(failFlag)) {
|
||||||
|
//删除原有Redis中的key值
|
||||||
|
String accessTokenKey = Constants.EXAM_APPLET_ACCESS_TOKEN + "accessToken";
|
||||||
|
Object object = redisTemplate.opsForValue().get(accessTokenKey);
|
||||||
|
if (Objects.nonNull(object)) {
|
||||||
|
redisTemplate.delete(accessTokenKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//删除原有Redis中缓存的AccessToken
|
||||||
|
String appletAccessToken = getAppletAccessToken();
|
||||||
|
if (StringUtils.isBlank(appletAccessToken)) {
|
||||||
|
throw new ServiceException("获取小程序凭证信息失败,请联系管理员!");
|
||||||
|
}
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.put("scene", weChatCodeId);
|
||||||
|
params.put("page", appletPageUrl);
|
||||||
|
String body = JSON.toJSONString(params);
|
||||||
|
String filePath = XinYiLuConfig.getProfile() + filePathWeChatCodeUrl + "/" + weChatCodeId;
|
||||||
|
//调用微信接口获取小程序二维码并将其上传到服务器中
|
||||||
|
return getAppletCodePicture(appletAccessToken, body, filePath, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据小程序AccessToken获取小程序的二维码图片
|
||||||
|
*
|
||||||
|
* @param accessToken 微信小程序的accessToken
|
||||||
|
* @param body 接口传输参数
|
||||||
|
* @param filePath 文件路径
|
||||||
|
* @param fileName 文件名称
|
||||||
|
* @return 小程序的二维码图片
|
||||||
|
*/
|
||||||
|
public static String getAppletCodePicture(String accessToken, String body, String filePath, String fileName) {
|
||||||
|
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
||||||
|
HttpPost httpPost = new HttpPost(GET_APPLET_CODE_URL + accessToken);
|
||||||
|
try {
|
||||||
|
StringEntity entity = new StringEntity(body, "UTF-8");
|
||||||
|
entity.setContentType("image/png");
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
HttpResponse response = httpClient.execute(httpPost);
|
||||||
|
String contentType = response.getEntity().getContentType().toString();
|
||||||
|
if (StringUtils.equals(contentType, JSON_DATA_FORMAT)) {
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
String absolutePath = getAbsoluteFile(filePath, fileName).getAbsolutePath();
|
||||||
|
try (InputStream inputStream = response.getEntity().getContent(); FileOutputStream out = new FileOutputStream(absolutePath)) {
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = inputStream.read(buffer)) != -1) {
|
||||||
|
out.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
return absolutePath;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取小程序二维码接口调用失败,失败原因为:{}", e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建文件路径
|
||||||
|
*
|
||||||
|
* @param uploadDir 路径名称
|
||||||
|
* @param fileName 文件名称
|
||||||
|
* @return File 文件目录
|
||||||
|
*/
|
||||||
|
public static File getAbsoluteFile(String uploadDir, String fileName) {
|
||||||
|
File file = new File(uploadDir + File.separator + fileName);
|
||||||
|
if (!file.exists()) {
|
||||||
|
if (!file.getParentFile().exists()) {
|
||||||
|
boolean mkdirs = file.getParentFile().mkdirs();
|
||||||
|
if (BooleanUtils.isFalse(mkdirs)) {
|
||||||
|
throw new ServiceException("文件路径创建失败,请联系管理员!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取小程序AccessToken方法
|
||||||
|
*
|
||||||
|
* @return 小程序的AccessToken
|
||||||
|
*/
|
||||||
|
public static String getAppletAccessToken() {
|
||||||
|
String accessToken;
|
||||||
|
String accessTokenKey = Constants.EXAM_APPLET_ACCESS_TOKEN + "accessToken";
|
||||||
|
//从Redis中取出accessToken
|
||||||
|
Object object = redisTemplate.opsForValue().get(accessTokenKey);
|
||||||
|
if (Objects.isNull(object)) {
|
||||||
|
//没有,获取accessToken
|
||||||
|
AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(appletChatConfig.getAppletId(), appletChatConfig.getSecret());
|
||||||
|
if (Objects.isNull(appletAccessToken)) {
|
||||||
|
throw new ServiceException("获取微信小程序accessToken信息失败");
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != SUCCESS_CODE) {
|
||||||
|
throw new ServiceException("获取微信小程序accessToken信息失败,失败信息为:" + appletAccessToken.getErrmsg());
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(appletAccessToken.getAccessToken())) {
|
||||||
|
throw new ServiceException("accessToken信息为空");
|
||||||
|
}
|
||||||
|
//存入Redis中
|
||||||
|
redisTemplate.opsForValue().set(accessTokenKey, appletAccessToken.getAccessToken(), 3600, TimeUnit.SECONDS);
|
||||||
|
accessToken = appletAccessToken.getAccessToken();
|
||||||
|
} else {
|
||||||
|
accessToken = (String) object;
|
||||||
|
}
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package com.yf.exam.core.utils.http;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用http工具封装
|
||||||
|
*
|
||||||
|
* @author xinyilu
|
||||||
|
*/
|
||||||
|
public class HttpHelper {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
|
||||||
|
|
||||||
|
public static String getBodyString(ServletRequest request) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try (InputStream inputStream = request.getInputStream()) {
|
||||||
|
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||||
|
String line = "";
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
sb.append(line);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.warn("getBodyString出现问题!");
|
||||||
|
} finally {
|
||||||
|
if (reader != null) {
|
||||||
|
try {
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.error(ExceptionUtils.getMessage(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,297 @@
|
|||||||
|
package com.yf.exam.core.utils.http;
|
||||||
|
|
||||||
|
import com.yf.exam.constant.Constants;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.net.ConnectException;
|
||||||
|
import java.net.SocketTimeoutException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.http.Consts;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.client.utils.HttpClientUtils;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用http发送方法
|
||||||
|
*
|
||||||
|
* @author xinyilu
|
||||||
|
*/
|
||||||
|
public class HttpUtils {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向指定 URL 发送GET方法的请求
|
||||||
|
*
|
||||||
|
* @param url 发送请求的 URL
|
||||||
|
* @return 所代表远程资源的响应结果
|
||||||
|
*/
|
||||||
|
public static String sendGet(String url) {
|
||||||
|
return sendGet(url, StringUtils.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向指定 URL 发送GET方法的请求
|
||||||
|
*
|
||||||
|
* @param url 发送请求的 URL
|
||||||
|
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
|
||||||
|
* @return 所代表远程资源的响应结果
|
||||||
|
*/
|
||||||
|
public static String sendGet(String url, String param) {
|
||||||
|
return sendGet(url, param, Constants.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向指定 URL 发送GET方法的请求
|
||||||
|
*
|
||||||
|
* @param url 发送请求的 URL
|
||||||
|
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
|
||||||
|
* @param contentType 编码类型
|
||||||
|
* @return 所代表远程资源的响应结果
|
||||||
|
*/
|
||||||
|
public static String sendGet(String url, String param, String contentType) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
BufferedReader in = null;
|
||||||
|
try {
|
||||||
|
String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
|
||||||
|
log.info("sendGet - {}", urlNameString);
|
||||||
|
URL realUrl = new URL(urlNameString);
|
||||||
|
URLConnection connection = realUrl.openConnection();
|
||||||
|
connection.setRequestProperty("accept", "*/*");
|
||||||
|
connection.setRequestProperty("connection", "Keep-Alive");
|
||||||
|
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||||
|
connection.connect();
|
||||||
|
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
|
||||||
|
String line;
|
||||||
|
while ((line = in.readLine()) != null) {
|
||||||
|
result.append(line);
|
||||||
|
}
|
||||||
|
log.info("recv - {}", result);
|
||||||
|
} catch (ConnectException e) {
|
||||||
|
log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
|
||||||
|
} catch (SocketTimeoutException e) {
|
||||||
|
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (in != null) {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向指定 URL 发送POST方法的请求
|
||||||
|
*
|
||||||
|
* @param url 发送请求的 URL
|
||||||
|
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
|
||||||
|
* @return 所代表远程资源的响应结果
|
||||||
|
*/
|
||||||
|
public static String sendPost(String url, String param) {
|
||||||
|
PrintWriter out = null;
|
||||||
|
BufferedReader in = null;
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
try {
|
||||||
|
log.info("sendPost - {}", url);
|
||||||
|
URL realUrl = new URL(url);
|
||||||
|
URLConnection conn = realUrl.openConnection();
|
||||||
|
conn.setRequestProperty("accept", "*/*");
|
||||||
|
conn.setRequestProperty("connection", "Keep-Alive");
|
||||||
|
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||||
|
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||||
|
conn.setRequestProperty("contentType", "utf-8");
|
||||||
|
conn.setDoOutput(true);
|
||||||
|
conn.setDoInput(true);
|
||||||
|
out = new PrintWriter(conn.getOutputStream());
|
||||||
|
out.print(param);
|
||||||
|
out.flush();
|
||||||
|
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
|
||||||
|
String line;
|
||||||
|
while ((line = in.readLine()) != null) {
|
||||||
|
result.append(line);
|
||||||
|
}
|
||||||
|
log.info("recv - {}", result);
|
||||||
|
} catch (ConnectException e) {
|
||||||
|
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
|
||||||
|
} catch (SocketTimeoutException e) {
|
||||||
|
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (out != null) {
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
if (in != null) {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sendSSLPost(String url, String param) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
String urlNameString = url + "?" + param;
|
||||||
|
try {
|
||||||
|
log.info("sendSSLPost - {}", urlNameString);
|
||||||
|
SSLContext sc = SSLContext.getInstance("SSL");
|
||||||
|
sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());
|
||||||
|
URL console = new URL(urlNameString);
|
||||||
|
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
|
||||||
|
conn.setRequestProperty("accept", "*/*");
|
||||||
|
conn.setRequestProperty("connection", "Keep-Alive");
|
||||||
|
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||||
|
conn.setRequestProperty("Accept-Charset", "utf-8");
|
||||||
|
conn.setRequestProperty("contentType", "utf-8");
|
||||||
|
conn.setDoOutput(true);
|
||||||
|
conn.setDoInput(true);
|
||||||
|
|
||||||
|
conn.setSSLSocketFactory(sc.getSocketFactory());
|
||||||
|
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
|
||||||
|
conn.connect();
|
||||||
|
InputStream is = conn.getInputStream();
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||||
|
String ret = "";
|
||||||
|
while ((ret = br.readLine()) != null) {
|
||||||
|
if (ret != null && !"".equals(ret.trim())) {
|
||||||
|
result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("recv - {}", result);
|
||||||
|
conn.disconnect();
|
||||||
|
br.close();
|
||||||
|
} catch (ConnectException e) {
|
||||||
|
log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
|
||||||
|
} catch (SocketTimeoutException e) {
|
||||||
|
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TrustAnyTrustManager implements X509TrustManager {
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return new X509Certificate[]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TrustAnyHostnameVerifier implements HostnameVerifier {
|
||||||
|
@Override
|
||||||
|
public boolean verify(String hostname, SSLSession session) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将通知参数转化为字符串
|
||||||
|
*
|
||||||
|
* @param request 请求信息
|
||||||
|
* @return 请求参数信息
|
||||||
|
*/
|
||||||
|
public static String readRequestData(HttpServletRequest request) {
|
||||||
|
BufferedReader br = null;
|
||||||
|
try {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
br = request.getReader();
|
||||||
|
for (String line; (line = br.readLine()) != null; ) {
|
||||||
|
if (result.length() > 0) {
|
||||||
|
result.append("\n");
|
||||||
|
}
|
||||||
|
result.append(line);
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
if (br != null) {
|
||||||
|
try {
|
||||||
|
br.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送json格式的POST类型的http请求
|
||||||
|
*
|
||||||
|
* @param url 请求地址
|
||||||
|
* @param param json格式的请求参数
|
||||||
|
* @return String 返回值信息
|
||||||
|
*/
|
||||||
|
public static String sendPostJson(String url, String param) {
|
||||||
|
String result = null;
|
||||||
|
CloseableHttpClient httpClient = null;
|
||||||
|
CloseableHttpResponse response = null;
|
||||||
|
try {
|
||||||
|
httpClient = HttpClients.createDefault();
|
||||||
|
// 字符串编码
|
||||||
|
StringEntity entity = new StringEntity(param, Consts.UTF_8);
|
||||||
|
// 设置content-type
|
||||||
|
entity.setContentType("application/json");
|
||||||
|
HttpPost httpPost = new HttpPost(url);
|
||||||
|
httpPost.setConfig(RequestConfig.custom().setSocketTimeout(10000).setConnectTimeout(10000).build());
|
||||||
|
// 防止被当成攻击添加的
|
||||||
|
httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/54.0.2840.87 Safari/537.36");
|
||||||
|
// 接收参数设置
|
||||||
|
httpPost.setHeader("Accept", "application/json");
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
response = httpClient.execute(httpPost);
|
||||||
|
HttpEntity httpEntity = response.getEntity();
|
||||||
|
result = EntityUtils.toString(httpEntity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("post请求发送失败,请求路径:[{}],请求参数:[{}],异常信息:[{}]", url, param, e);
|
||||||
|
} finally {
|
||||||
|
HttpClientUtils.closeQuietly(response);
|
||||||
|
HttpClientUtils.closeQuietly(httpClient);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
package com.yf.exam.core.utils.regex;
|
||||||
|
|
||||||
|
import com.yf.exam.core.exception.ServiceException;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 正则表达式工具类
|
||||||
|
* @Author 纪寒
|
||||||
|
* @Date 2022-08-24 13:58:48
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class RegexUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验手机号码
|
||||||
|
*
|
||||||
|
* @param phone 手机号码
|
||||||
|
* @return 校验结果
|
||||||
|
*/
|
||||||
|
public boolean regexPhone(String phone) {
|
||||||
|
if (StringUtils.isBlank(phone)) {
|
||||||
|
throw new ServiceException("手机号码不能为空!");
|
||||||
|
}
|
||||||
|
//校验手机号
|
||||||
|
String regex = "^(((13[0-9]{1})|(14[0-9]{1})|(15[0-9]{1})|(16[2567]{1})|(17[0-9]{1})|(18[0-9]{1})|(19[0-9]{1}))+\\d{8})$";
|
||||||
|
return Pattern.matches(regex, phone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验身份证号码
|
||||||
|
*
|
||||||
|
* @param cardNo 身份证号码
|
||||||
|
* @return 校验结果
|
||||||
|
*/
|
||||||
|
public boolean regexCardNo(String cardNo) {
|
||||||
|
if (StringUtils.isBlank(cardNo)) {
|
||||||
|
throw new ServiceException("身份证号不能为空!");
|
||||||
|
}
|
||||||
|
//校验身份证号码
|
||||||
|
String regex = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|" +
|
||||||
|
"(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";
|
||||||
|
return Pattern.matches(regex, cardNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验座机手机号码
|
||||||
|
*
|
||||||
|
* @param seatNumber 座机手机号码
|
||||||
|
* @return 校验结果
|
||||||
|
*/
|
||||||
|
public boolean regexSeatNumber(String seatNumber) {
|
||||||
|
if (StringUtils.isBlank(seatNumber)) {
|
||||||
|
throw new ServiceException("手机号码不能为空!");
|
||||||
|
}
|
||||||
|
//校验座机手机号
|
||||||
|
String regex = "^(([0-9]{4,13}))";
|
||||||
|
return Pattern.matches(regex, seatNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,14 +0,0 @@
|
|||||||
package com.yf.exam.modules;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通用常量
|
|
||||||
* @author bool
|
|
||||||
*/
|
|
||||||
public class Constant {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 会话
|
|
||||||
*/
|
|
||||||
public static final String TOKEN = "token";
|
|
||||||
}
|
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
package com.yf.exam.modules.applet.controller;
|
||||||
|
|
||||||
|
import com.yf.exam.core.api.controller.BaseController;
|
||||||
|
import com.yf.exam.core.domain.AjaxResult;
|
||||||
|
import com.yf.exam.core.utils.regex.RegexUtil;
|
||||||
|
import com.yf.exam.modules.applet.service.AppletLoginService;
|
||||||
|
import com.yf.exam.modules.sys.user.dto.SysUserDTO;
|
||||||
|
import com.yf.exam.modules.sys.user.service.SysUserService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 微信小程序登录注册控制器
|
||||||
|
* @author: haown
|
||||||
|
* @create: 2025-08-11 16:05
|
||||||
|
**/
|
||||||
|
@Api(tags={"微信小程序"})
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/examApplet")
|
||||||
|
public class AppletLoginController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AppletLoginService appletLoginService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SysUserService sysUserService;
|
||||||
|
@Resource
|
||||||
|
private RegexUtil regexUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册用户信息
|
||||||
|
*
|
||||||
|
* @param reqDTO 输入参数
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@ApiOperation(value = "注册用户信息")
|
||||||
|
@PostMapping("/register")
|
||||||
|
public AjaxResult registerUserInfo(@RequestBody SysUserDTO reqDTO) {
|
||||||
|
//校验手机号
|
||||||
|
boolean regexPhone = regexUtil.regexPhone(StringUtils.isBlank(reqDTO.getPhone()) ? "" : reqDTO.getPhone());
|
||||||
|
if (BooleanUtils.isFalse(regexPhone)) {
|
||||||
|
return AjaxResult.error("您输入的手机号不正确,请重新输入!");
|
||||||
|
}
|
||||||
|
//校验身份证号
|
||||||
|
boolean cardNo = regexUtil.regexCardNo(StringUtils.isBlank(reqDTO.getUserName()) ? "" : reqDTO.getUserName());
|
||||||
|
if (BooleanUtils.isFalse(cardNo)) {
|
||||||
|
return AjaxResult.error("您输入的身份证号不正确,请重新输入!");
|
||||||
|
}
|
||||||
|
return AjaxResult.success(sysUserService.reg(reqDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据登录凭证获取用户的登录信息
|
||||||
|
*
|
||||||
|
* @param loginCode 登录凭证
|
||||||
|
* @return 微信用户登录信息
|
||||||
|
*/
|
||||||
|
@ApiOperation(value = "根据登录凭证获取用户的登录信息")
|
||||||
|
@GetMapping("/appletLogin")
|
||||||
|
public AjaxResult appletLogin(@RequestParam("loginCode") String loginCode) {
|
||||||
|
if (StringUtils.isBlank(loginCode)) {
|
||||||
|
return AjaxResult.error("登录凭证编码不能为空!");
|
||||||
|
}
|
||||||
|
//if (StringUtils.isBlank(phoneCode)) {
|
||||||
|
// return AjaxResult.error("获取手机号凭证不存在");
|
||||||
|
//}
|
||||||
|
return appletLoginService.appletLogin(loginCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据openid判断当前用户信息是否存在,微信小程序登录页使用
|
||||||
|
*
|
||||||
|
* @param openId 微信用户的openid
|
||||||
|
* @return 标识,LOGIN:已登录,NOT_LOGIN:未登录
|
||||||
|
*/
|
||||||
|
@GetMapping("/existUserInfo")
|
||||||
|
public AjaxResult existUserInfo(String openId) {
|
||||||
|
if (StringUtils.isBlank(openId)) {
|
||||||
|
return AjaxResult.error("用户微信唯一标识不存在!");
|
||||||
|
}
|
||||||
|
return appletLoginService.existUserInfo(openId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package com.yf.exam.modules.applet.entity;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.annotation.JSONField;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 微信小程序accessToken信息实体类
|
||||||
|
* @Author 纪寒
|
||||||
|
* @Date 2022-08-17 17:05:10
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AppletAccessToken implements Serializable {
|
||||||
|
private static final long serialVersionUID = 7351002130502802480L;
|
||||||
|
/**
|
||||||
|
* accessToken值
|
||||||
|
*/
|
||||||
|
@JSONField(name = "access_token")
|
||||||
|
private String accessToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* access_token有效时间,有效时间为7200秒
|
||||||
|
*/
|
||||||
|
@JSONField(name = "expires_in")
|
||||||
|
private String expiresIn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误状态码
|
||||||
|
* 40001:AppSecret 错误或者 AppSecret 不属于这个小程序,请开发者确认 AppSecret 的正确性
|
||||||
|
* 40002:请确保 grant_type 字段值为 client_credential
|
||||||
|
* 40013:不合法的 AppID,请开发者检查 AppID 的正确性,避免异常字符,注意大小写
|
||||||
|
*/
|
||||||
|
private Integer errcode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误状态值
|
||||||
|
* 40001:AppSecret 错误或者 AppSecret 不属于这个小程序,请开发者确认 AppSecret 的正确性
|
||||||
|
* 40002:请确保 grant_type 字段值为 client_credential
|
||||||
|
* 40013:不合法的 AppID,请开发者检查 AppID 的正确性,避免异常字符,注意大小写
|
||||||
|
*/
|
||||||
|
private String errmsg;
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package com.yf.exam.modules.applet.service;
|
||||||
|
|
||||||
|
import com.yf.exam.core.domain.AjaxResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 微信小程序登录注册业务层
|
||||||
|
* @author: haown
|
||||||
|
* @create: 2025-08-11 16:05
|
||||||
|
**/
|
||||||
|
public interface AppletLoginService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据登录凭证获取用户的登录信息
|
||||||
|
*
|
||||||
|
* @param loginCode 登录凭证
|
||||||
|
* @return 微信用户登录信息
|
||||||
|
*/
|
||||||
|
AjaxResult appletLogin(String loginCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据openid判断当前用户信息是否存在,微信小程序登录页使用
|
||||||
|
*
|
||||||
|
* @param openId 微信用户的openid
|
||||||
|
* @return 用户列表
|
||||||
|
*/
|
||||||
|
AjaxResult existUserInfo(String openId);
|
||||||
|
}
|
||||||
@ -0,0 +1,147 @@
|
|||||||
|
package com.yf.exam.modules.applet.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.yf.exam.config.AppletChatConfig;
|
||||||
|
import com.yf.exam.constant.Constants;
|
||||||
|
import com.yf.exam.core.domain.AjaxResult;
|
||||||
|
import com.yf.exam.core.utils.AppletChatUtil;
|
||||||
|
import com.yf.exam.modules.applet.service.AppletLoginService;
|
||||||
|
import com.yf.exam.modules.applet.vo.AppletLoginVO;
|
||||||
|
import com.yf.exam.modules.sys.user.entity.SysUser;
|
||||||
|
import com.yf.exam.modules.sys.user.service.SysUserService;
|
||||||
|
import com.yf.exam.modules.utils.AppletAccessTokenUtil;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 微信小程序登录注册业务层实现类
|
||||||
|
* @Author 纪寒
|
||||||
|
* @Date 2022-09-02 10:55:29
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class AppletLoginServiceImpl implements AppletLoginService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
@Resource
|
||||||
|
private AppletChatConfig appletChatConfig;
|
||||||
|
@Resource
|
||||||
|
private AppletAccessTokenUtil appletAccessTokenUtil;
|
||||||
|
@Resource
|
||||||
|
private SysUserService sysUserService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功状态码
|
||||||
|
*/
|
||||||
|
private static final int SUCCESS_CODE = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回成功状态码
|
||||||
|
*/
|
||||||
|
private static final String OK = "ok";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取微信小程序access_token错误码
|
||||||
|
*/
|
||||||
|
private static final int ERROR_ACCESS_CODE = 40001;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据登录凭证获取用户的登录信息
|
||||||
|
*
|
||||||
|
* @param loginCode 登录凭证
|
||||||
|
* @return 微信用户登录信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AjaxResult appletLogin(String loginCode) {
|
||||||
|
//根据code获取用户的微信unionId以及openId等信息
|
||||||
|
AppletLoginVO appletLoginInfo = AppletChatUtil.getAppletLoginInfo(appletChatConfig.getAppletId(), appletChatConfig.getSecret(), loginCode, appletChatConfig.getGrantType());
|
||||||
|
if (Objects.isNull(appletLoginInfo)) {
|
||||||
|
return AjaxResult.error("获取微信小程序用户信息失败");
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(appletLoginInfo.getErrcode()) && appletLoginInfo.getErrcode() != SUCCESS_CODE) {
|
||||||
|
return AjaxResult.error("获取微信小程序用户信息失败,失败信息为:" + appletLoginInfo.getErrmsg());
|
||||||
|
}
|
||||||
|
//获取微信accessToken
|
||||||
|
String accessToken;
|
||||||
|
String accessTokenKey = Constants.EXAM_APPLET_ACCESS_TOKEN + "accessToken";
|
||||||
|
//从Redis中取出accessToken
|
||||||
|
Object object = redisTemplate.opsForValue().get(accessTokenKey);
|
||||||
|
if (Objects.isNull(object)) {
|
||||||
|
//没有,获取accessToken
|
||||||
|
accessToken = appletAccessTokenUtil.getAppletAccessToken();
|
||||||
|
} else {
|
||||||
|
accessToken = (String) object;
|
||||||
|
}
|
||||||
|
//获取用户手机号
|
||||||
|
|
||||||
|
//AppletPhoneVO appletPhoneInfo = AppletChatUtil.getAppletPhoneInfo(phoneCode, accessToken);
|
||||||
|
//if (Objects.isNull(appletPhoneInfo)) {
|
||||||
|
// return AjaxResult.error("获取用户手机号失败");
|
||||||
|
//}
|
||||||
|
//if (Objects.nonNull(appletPhoneInfo.getErrcode()) && appletPhoneInfo.getErrcode() == ERROR_ACCESS_CODE) {
|
||||||
|
// //当前Redis缓存中的access_token无效直接删除
|
||||||
|
// if (Objects.nonNull(object)) {
|
||||||
|
// redisTemplate.delete(accessTokenKey);
|
||||||
|
// //删除之后重新获取获取accessToken
|
||||||
|
// accessToken = appletAccessTokenUtil.getAppletAccessToken();
|
||||||
|
// appletPhoneInfo = AppletChatUtil.getAppletPhoneInfo(phoneCode, accessToken);
|
||||||
|
// if (Objects.isNull(appletPhoneInfo)) {
|
||||||
|
// return AjaxResult.error("获取用户手机号失败");
|
||||||
|
// }
|
||||||
|
// if (Objects.nonNull(appletPhoneInfo.getErrcode()) && appletPhoneInfo.getErrcode() == ERROR_ACCESS_CODE) {
|
||||||
|
// return AjaxResult.error("登录失败!");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//if (StringUtils.isNotBlank(appletPhoneInfo.getErrmsg()) && !OK.equals(appletPhoneInfo.getErrmsg())) {
|
||||||
|
// return AjaxResult.error("获取用户手机号失败,失败信息为:" + appletPhoneInfo.getErrmsg());
|
||||||
|
//}
|
||||||
|
// 根据手机号和openid判断当前用户是否存在
|
||||||
|
//String phone = StringUtils.isBlank(appletPhoneInfo.getPhoneInfo().getPhoneNumber()) ? "" : appletPhoneInfo.getPhoneInfo().getPhoneNumber();
|
||||||
|
String openId = StringUtils.isBlank(appletLoginInfo.getOpenid()) ? "" : appletLoginInfo.getOpenid();
|
||||||
|
QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.lambda()
|
||||||
|
//.eq(SysUser::getPhone, phone)
|
||||||
|
.eq(SysUser::getOpenid, openId);
|
||||||
|
SysUser userByPhone = sysUserService.getOne(wrapper, false);
|
||||||
|
|
||||||
|
SysUser user = new SysUser();
|
||||||
|
// 考生信息为空,返回openId
|
||||||
|
if (Objects.isNull(userByPhone)) {
|
||||||
|
return AjaxResult.success("您还未注册,请注册后使用!", openId);
|
||||||
|
}
|
||||||
|
//更新用户的openid等微信标识信息
|
||||||
|
user.setId(userByPhone.getId());
|
||||||
|
user.setOpenid(openId);
|
||||||
|
user.setPhone(StringUtils.isBlank(userByPhone.getPhone()) ? "" : userByPhone.getPhone());
|
||||||
|
user.setUpdateTime(new Date());
|
||||||
|
sysUserService.updateById(user);
|
||||||
|
return AjaxResult.success(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据openid判断当前用户信息是否存在,微信小程序登录页使用
|
||||||
|
*
|
||||||
|
* @param openId 微信用户的openid
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AjaxResult existUserInfo(String openId) {
|
||||||
|
QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.lambda().eq(SysUser::getOpenid, openId);
|
||||||
|
SysUser user = sysUserService.getOne(wrapper, false);
|
||||||
|
if (Objects.nonNull(user) && StringUtils.isNotBlank(user.getOpenid())) {
|
||||||
|
return AjaxResult.success("LOGIN");
|
||||||
|
}
|
||||||
|
return AjaxResult.success("NOT_LOGIN");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package com.yf.exam.modules.applet.vo;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 微信小程序用户信息实体类
|
||||||
|
* @Author 纪寒
|
||||||
|
* @Date 2022-08-17 16:12:22
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AppletLoginVO implements Serializable {
|
||||||
|
private static final long serialVersionUID = 3407837292456224369L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序unionid
|
||||||
|
*/
|
||||||
|
private String unionid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序openid
|
||||||
|
*/
|
||||||
|
private String openid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误状态码,40029:js_code无效,45011:API 调用太频繁,请稍候再试
|
||||||
|
* 40226:高风险等级用户,小程序登录拦截 ,-1:系统繁忙,此时请开发者稍候再试
|
||||||
|
*/
|
||||||
|
private Integer errcode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态信息,取值有,40029:code 无效,
|
||||||
|
* 45011:api minute-quota reach limit mustslower retry next minute
|
||||||
|
* 40226:code blocked
|
||||||
|
* -1:system error
|
||||||
|
*/
|
||||||
|
private String errmsg;
|
||||||
|
}
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
package com.yf.exam.modules.applet.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 获取小程序用户手机号实体类
|
||||||
|
* @Author 纪寒
|
||||||
|
* @Date 2022-08-17 17:44:53
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public class AppletPhoneVO implements Serializable {
|
||||||
|
private static final long serialVersionUID = -135523900524315866L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误编码,
|
||||||
|
* 0:成功
|
||||||
|
* -1:系统繁忙,此时请开发者稍候再试
|
||||||
|
* 40029:不合法的code(code不存在、已过期或者使用过)
|
||||||
|
*/
|
||||||
|
@JsonProperty("errcode")
|
||||||
|
private Integer errcode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回提示信息,ok:成功
|
||||||
|
*/
|
||||||
|
@JsonProperty("errmsg")
|
||||||
|
private String errmsg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电话信息实体类
|
||||||
|
*/
|
||||||
|
@JsonProperty("phone_info")
|
||||||
|
private PhoneInfoDTO phoneInfo;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public static class PhoneInfoDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户绑定的手机号(国外手机号会有区号)
|
||||||
|
*/
|
||||||
|
@JsonProperty("phoneNumber")
|
||||||
|
private String phoneNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 没有区号的手机号
|
||||||
|
*/
|
||||||
|
@JsonProperty("purePhoneNumber")
|
||||||
|
private String purePhoneNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 区号
|
||||||
|
*/
|
||||||
|
@JsonProperty("countryCode")
|
||||||
|
private Integer countryCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据水印
|
||||||
|
*/
|
||||||
|
@JsonProperty("watermark")
|
||||||
|
private WatermarkDTO watermark;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public static class WatermarkDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户获取手机号操作的时间戳
|
||||||
|
*/
|
||||||
|
@JsonProperty("timestamp")
|
||||||
|
private Integer timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序appid
|
||||||
|
*/
|
||||||
|
@JsonProperty("appid")
|
||||||
|
private String appid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -55,7 +55,7 @@ public class SysUserController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户登录
|
* 用户退出
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@CrossOrigin
|
@CrossOrigin
|
||||||
|
|||||||
@ -40,6 +40,9 @@ public class SysUserDTO extends UserAttachment implements Serializable {
|
|||||||
@ApiModelProperty(value = "密码盐", required=true)
|
@ApiModelProperty(value = "密码盐", required=true)
|
||||||
private String salt;
|
private String salt;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "用户微信openid", required=true)
|
||||||
|
private String openid;
|
||||||
|
|
||||||
@ApiModelProperty(value = "角色列表", required=true)
|
@ApiModelProperty(value = "角色列表", required=true)
|
||||||
private String roleIds;
|
private String roleIds;
|
||||||
|
|
||||||
|
|||||||
@ -26,4 +26,7 @@ public class SysUserLoginReqDTO implements Serializable {
|
|||||||
@ApiModelProperty(value = "密码", required=true)
|
@ApiModelProperty(value = "密码", required=true)
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "用户微信openid", required=true)
|
||||||
|
private String openid;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,9 @@ public class SysUserLoginDTO extends UserAttachment implements Serializable {
|
|||||||
@ApiModelProperty(value = "手机号", required=true)
|
@ApiModelProperty(value = "手机号", required=true)
|
||||||
private String phone;
|
private String phone;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "用户微信openid", required=true)
|
||||||
|
private String openid;
|
||||||
|
|
||||||
@ApiModelProperty(value = "角色列表", required=true)
|
@ApiModelProperty(value = "角色列表", required=true)
|
||||||
private String roleIds;
|
private String roleIds;
|
||||||
|
|
||||||
|
|||||||
@ -68,6 +68,11 @@ public class SysUser extends UserAttachment {
|
|||||||
@TableField("depart_id")
|
@TableField("depart_id")
|
||||||
private String departId;
|
private String departId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户微信openid
|
||||||
|
*/
|
||||||
|
private String openid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -142,8 +142,6 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(SysUserDTO reqDTO) {
|
public void update(SysUserDTO reqDTO) {
|
||||||
|
|
||||||
|
|
||||||
String pass = reqDTO.getPassword();
|
String pass = reqDTO.getPassword();
|
||||||
if(!StringUtils.isBlank(pass)){
|
if(!StringUtils.isBlank(pass)){
|
||||||
PassInfo passInfo = PassHandler.buildPassword(pass);
|
PassInfo passInfo = PassHandler.buildPassword(pass);
|
||||||
|
|||||||
@ -0,0 +1,64 @@
|
|||||||
|
package com.yf.exam.modules.utils;
|
||||||
|
|
||||||
|
import com.yf.exam.config.AppletChatConfig;
|
||||||
|
import com.yf.exam.constant.Constants;
|
||||||
|
import com.yf.exam.core.exception.ServiceException;
|
||||||
|
import com.yf.exam.core.utils.AppletChatUtil;
|
||||||
|
import com.yf.exam.modules.applet.entity.AppletAccessToken;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description 获取小程序AccessToken公共方法
|
||||||
|
* @Author 纪寒
|
||||||
|
* @Date 2023-02-27 18:02:05
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class AppletAccessTokenUtil {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
@Resource
|
||||||
|
private AppletChatConfig appletChatConfig;
|
||||||
|
/**
|
||||||
|
* 返回成功状态码
|
||||||
|
*/
|
||||||
|
private static final int SUCCESS_CODE = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取小程序AccessToken方法
|
||||||
|
*
|
||||||
|
* @return 小程序的AccessToken
|
||||||
|
*/
|
||||||
|
public String getAppletAccessToken() {
|
||||||
|
String accessToken;
|
||||||
|
String accessTokenKey = Constants.EXAM_APPLET_ACCESS_TOKEN + "accessToken";
|
||||||
|
//从Redis中取出accessToken
|
||||||
|
Object object = redisTemplate.opsForValue().get(accessTokenKey);
|
||||||
|
if (Objects.isNull(object)) {
|
||||||
|
//没有,获取accessToken
|
||||||
|
AppletAccessToken appletAccessToken = AppletChatUtil.getAppletAccessToken(appletChatConfig.getAppletId(), appletChatConfig.getSecret());
|
||||||
|
if (Objects.isNull(appletAccessToken)) {
|
||||||
|
throw new ServiceException("获取微信小程序accessToken信息失败");
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(appletAccessToken.getErrcode()) && appletAccessToken.getErrcode() != SUCCESS_CODE) {
|
||||||
|
throw new ServiceException("获取微信小程序accessToken信息失败,失败信息为:" + appletAccessToken.getErrmsg());
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(appletAccessToken.getAccessToken())) {
|
||||||
|
throw new ServiceException("accessToken信息为空");
|
||||||
|
}
|
||||||
|
//存入Redis中
|
||||||
|
redisTemplate.opsForValue().set(accessTokenKey, appletAccessToken.getAccessToken(), 3600, TimeUnit.SECONDS);
|
||||||
|
accessToken = appletAccessToken.getAccessToken();
|
||||||
|
} else {
|
||||||
|
accessToken = (String) object;
|
||||||
|
}
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
28
exam-admin/src/main/resources/apiclient_key.pem
Normal file
28
exam-admin/src/main/resources/apiclient_key.pem
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQChOQsrP6xr7VpH
|
||||||
|
LB6kMpx0wB9QXio6Fk89GwD1rFnR/8Eym6mUbv9BR7NddJ3LL1UCSQ3b1DXuDz64
|
||||||
|
/s8nwvJmIABsgBmKS7Krb3qd7ua2NL7KodjnQuj4X3NOUQ2bPh21y5sOk6cVOObM
|
||||||
|
4g2jvaPUk52y+kDXx/8IWLIms0hPqRkgCXVtTDrtgab4wABrfha3ifiC6qHuaeza
|
||||||
|
ogo9he09QfWKPlZyW/OkwON4i0mMI0lAUaMnfSJX5QBLFwZYUHgR/8H/aMRLXnOx
|
||||||
|
W/tz1bvV2SgKwpH7TalRu2Avl9t5M1lPWTbxl4vEV6em3ijqzldpIOljwJ20cL6g
|
||||||
|
BbgJm2Y9AgMBAAECggEAOaVU2gTtWLXIZtRerGUwTgp359uTi6t4b6fdIvqaLx0c
|
||||||
|
bkT8UIeTmzrQ5mSRGxp0cdm/K8/n7JPk4G6zkUsCMwPUQvdWqn1AiE3W8Ot/8LxR
|
||||||
|
T9Co5p+k/1HZv7H5hH2kT+FaMs8Wmd77n1xgdiCTmKmjZGBYmQ74oHpeULof6+NA
|
||||||
|
JX2LEMXBjSvcsEj2ppml1M9XjZzB7zPQPqVPGL5hTAqQpT179/iy8aPdzBZRKAFY
|
||||||
|
liajWYlRVMseu1S21PaOygNpRhvLj+LQB+dfQ+s5jYIhBvVjJ4mNFK+ro1KrbFEa
|
||||||
|
g2pKYFqcY9B4uOEB12K1bA4lxWPDjZvi5L71ncB8wQKBgQDTMDnOH+IQ/jrVbnX3
|
||||||
|
YM24gKoJiKzbXcGSeg5jciGpAQ2JGtKw3xbZB54yXCwvJXssXkSfKmW9qKR299pG
|
||||||
|
TloaKHbhHxvX1jECpFmvRTLEhKb6uWcy779NFv+443nM/G0cB+vxhezj4tqE6Qqw
|
||||||
|
ijbDD+QS26Dm+ZfEQTaH1DaLbQKBgQDDbq8PEsL3uaoPg8gmyKJx9hmUW2nn3Tto
|
||||||
|
CgOI7PVQbvwOIoI8phuc1VLatnxjx3SeMasGoWoVk7/hc0ZXHvo0QsQWZt74McSC
|
||||||
|
mV2ub7L6BLyvrpsufEJZlUIiQXDIHDcucszgRaYJk4rJKmCh1R7c6dewAVE/TqTW
|
||||||
|
7GrwUBI0EQKBgBRSFZ3Rz4zXCY4z3MH63JCeQL4+GnPZJ6ESgYPsHXUHlufUXuWJ
|
||||||
|
8cbcRsqNt+qpbpqsT2oJSFThf0G7Q5N0QpM1xYqP1bwE7h5U9hQ5UlM6eF6zrExo
|
||||||
|
aT3fsqd1q+ifeVgzIu7QdiTPVTtouRCXnAFU7BssauUOqx3FMJwNPVpZAoGAYMZ9
|
||||||
|
j6RFwbBB4z7prTLrJi2sywddcUDfOwzCZVqZu8PJsyIphejngYktZzq4bByHxhJo
|
||||||
|
U3c49ghdG0IfEeM4GQr62PEF9reGTPmvJ0MOyLnxyblYBPPpUz0TK61mMOGv/aNB
|
||||||
|
islSiCl0r1r50QmdJ93wParZVdUW0YrvBaNQ8FECgYAm1j0tfGsMmocMYSoeMGt5
|
||||||
|
wRetXbkrKfMbNh6GALiNClEj6tFYKMbuQOuUzADYDxHHz/SPNozuP7Ax/NI95rtw
|
||||||
|
mGZcMx/KhKZQvZkAwCWUqRSn6cDPtqH4KNta7QZ8G36XtdPRP1a/h8g96cEiB/CV
|
||||||
|
zQPps/kR9HNAJfr0sBPEWA==
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
@ -28,20 +28,69 @@ server:
|
|||||||
enabled: true
|
enabled: true
|
||||||
min-response-size: 10
|
min-response-size: 10
|
||||||
mime-types: application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css
|
mime-types: application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css
|
||||||
|
# redis 配置
|
||||||
# 新医路微信商户号配置参数
|
redis:
|
||||||
|
# 地址
|
||||||
|
host: localhost
|
||||||
|
# 端口,默认为6379
|
||||||
|
port: 6379
|
||||||
|
# 数据库索引
|
||||||
|
database: 2
|
||||||
|
# 密码
|
||||||
|
password:
|
||||||
|
# 连接超时时间
|
||||||
|
timeout: 10s
|
||||||
|
lettuce:
|
||||||
|
pool:
|
||||||
|
# 连接池中的最小空闲连接
|
||||||
|
min-idle: 0
|
||||||
|
# 连接池中的最大空闲连接
|
||||||
|
max-idle: 8
|
||||||
|
# 连接池的最大数据库连接数
|
||||||
|
max-active: 8
|
||||||
|
# #连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||||
|
max-wait: -1ms
|
||||||
|
# 考试系统微信小程序参数配置信息
|
||||||
|
exam-applet-chat-config:
|
||||||
|
# 微信小程序
|
||||||
|
applet-id: wx26b9ecdba54bc588
|
||||||
|
# 微信小程序密钥
|
||||||
|
secret: ccd19a0bb2bc74f38b083c902daf48a7
|
||||||
|
# 微信小程序返回国家语言
|
||||||
|
lang: zh_CN
|
||||||
|
# 微信小程序授权类型
|
||||||
|
grant-type: authorization_code
|
||||||
|
# 微信小程序事件回调令牌
|
||||||
|
token: Yw3vfW1ILpc34qAVDtTpB2hesAMCpvW0
|
||||||
|
# 山东省公共卫生学会微信商户号配置参数
|
||||||
xyl-we-chat-config:
|
xyl-we-chat-config:
|
||||||
# 新医路商户号 1633348407 山东新医路信息科技有限公司 山东柏杏新医健康服务有限公司
|
# 山东省公共卫生学会商户号 1724506668 山东省公共卫生学会
|
||||||
xyl-mch-id: 1690248007
|
xyl-mch-id: 1724506668
|
||||||
# 新医路商户号API证书序号 7C6A18FC8E1F0445901B1BE1C4DD1ACE284C3D79
|
# 山东省公共卫生学会商户号API证书序号 2C1188B1E533743F24AA43D374118B5D4A4FABC1
|
||||||
xyl-mch-serial-no: 760D3316C2F3DF8D1DB05B56A37BFCD3C34EEDA8
|
xyl-mch-serial-no: 2C1188B1E533743F24AA43D374118B5D4A4FABC1
|
||||||
# 新医路商户私钥文件
|
# 山东省公共卫生学会商户私钥文件
|
||||||
xyl-private-key-path: baixing_apiclient_key.pem
|
xyl-private-key-path: apiclient_key.pem
|
||||||
# 新医路API V3版本密钥 Xyl699003981qazVFR4xsw23edcASDFG
|
# 山东省公共卫生学会API V3版本密钥 Xyl699003981qazVFR4xsw23edcASDFG
|
||||||
xyl-payment-key: baixingXINYIHULIZHAN202400000000
|
xyl-payment-key: gonggongweishengXUEHUI2025081100
|
||||||
# 新医路微信支付回调地址 https://quanyidaojia.xinelu.cn
|
# 山东省公共卫生学会微信支付回调地址 https://quanyidaojia.xinelu.cn
|
||||||
xyl-wechat-notify-url: http://8.131.93.145:54097
|
xyl-wechat-notify-url: http://8.131.93.145:54097
|
||||||
# h5支付接口地址
|
# 微信支付接口地址,包含小程序和App支付接口地址
|
||||||
we-chat-payment-url-config:
|
we-chat-payment-url-config:
|
||||||
# h5下单接口地址
|
# 小程序JSAPI下单接口地址
|
||||||
h5-palce-order-url: https://api.mch.weixin.qq.com/v3/pay/transactions/h5
|
jsapi-palce-order-url: https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi
|
||||||
|
# 微信支付订单号查询接口地址
|
||||||
|
query-order-no-url: https://api.mch.weixin.qq.com/v3/pay/transactions/id/%s
|
||||||
|
# 商户订单号接口查询
|
||||||
|
query-mch-id-url: https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s
|
||||||
|
# 关闭订单接口地址
|
||||||
|
close-order-url: https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s/close
|
||||||
|
# 申请退款接口地址
|
||||||
|
refund-apply-url: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
|
||||||
|
# 查询单笔退款接口地址
|
||||||
|
refund-query-order-url: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/%s
|
||||||
|
# 申请交易账单接口地址
|
||||||
|
trade-apply-bill-url: https://api.mch.weixin.qq.com/v3/bill/tradebill
|
||||||
|
# 申请资金账单接口地址
|
||||||
|
capital-apply-bill-url: https://api.mch.weixin.qq.com/v3/bill/fundflowbill
|
||||||
|
# App下单接口地址
|
||||||
|
app-place-order-url: https://api.mch.weixin.qq.com/v3/pay/transactions/app
|
||||||
|
|||||||
@ -29,13 +29,14 @@
|
|||||||
<result column="photo" property="photo" />
|
<result column="photo" property="photo" />
|
||||||
<result column="certificate" property="certificate" />
|
<result column="certificate" property="certificate" />
|
||||||
<result column="physical_report" property="physicalReport" />
|
<result column="physical_report" property="physicalReport" />
|
||||||
|
<result column="openid" property="openid" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<!-- 通用查询结果列 -->
|
<!-- 通用查询结果列 -->
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
`id`,`user_name`,`real_name`,phone,`password`,`salt`,`role_ids`,`depart_id`,`create_time`,`update_time`,`state`,
|
`id`,`user_name`,`real_name`,phone,`password`,`salt`,`role_ids`,`depart_id`,`create_time`,`update_time`,`state`,
|
||||||
`email`,`address`,`education`,`graduate_school`,`major`,`reg_type`,`train_institution`,`train_start_date`,`train_end_date`,
|
`email`,`address`,`education`,`graduate_school`,`major`,`reg_type`,`train_institution`,`train_start_date`,`train_end_date`,
|
||||||
`card_front`,`card_back`,`card_copy`,`photo`,`certificate`,`physical_report`
|
`card_front`,`card_back`,`card_copy`,`photo`,`certificate`,`physical_report`,`openid`
|
||||||
|
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user