添加小程序后端服务
This commit is contained in:
parent
ec838ac8c3
commit
ae57510418
120
carpool-wx-api/pom.xml
Normal file
120
carpool-wx-api/pom.xml
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ruoyi</artifactId>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
<version>3.7.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>carpool-wx-api</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<!-- SpringBoot Web容器 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- SpringBoot 拦截器 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<!-- swagger2-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
</dependency>
|
||||
<!--防止进入swagger页面报类型转换错误,排除2.9.2中的引用,手动增加1.5.21版本-->
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
<version>1.5.21</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
<version>1.5.21</version>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-UI-->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>swagger-bootstrap-ui</artifactId>
|
||||
<version>1.9.3</version>
|
||||
</dependency>
|
||||
<!-- 糊涂工具包 -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java-pay-spring-boot-starter</artifactId>
|
||||
<version>3.5.4.B</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
|
||||
<version>3.5.4.B</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-mp</artifactId>
|
||||
<version>3.5.5.B</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.validation</groupId>
|
||||
<artifactId>jakarta.validation-api</artifactId>
|
||||
<version>2.0.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<configuration>
|
||||
<fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<warName>${project.artifactId}</warName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,27 @@
|
||||
package vip.carpool;
|
||||
|
||||
import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
public class GatewayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
SpringApplication.run(GatewayApplication.class, args);
|
||||
System.out.println("(♥◠‿◠)ノ゙ api网关启动成功 ლ(´ڡ`ლ)゙ \n" +
|
||||
" .-------. ____ __ \n" +
|
||||
" | _ _ \\ \\ \\ / / \n" +
|
||||
" | ( ' ) | \\ _. / ' \n" +
|
||||
" |(_ o _) / _( )_ .' \n" +
|
||||
" | (_,_).' __ ___(_ o _)' \n" +
|
||||
" | |\\ \\ | || |(_,_)' \n" +
|
||||
" | | \\ `' /| `-' / \n" +
|
||||
" | | \\ / \\ / \n" +
|
||||
" ''-' `'-' `-..-' ");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package vip.carpool.api.gateway.common.api;
|
||||
|
||||
|
||||
public enum ApiCode {
|
||||
|
||||
SUCCESS(200, "操作成功"),
|
||||
|
||||
UNAUTHORIZED(401, "非法访问"),
|
||||
|
||||
NOT_PERMISSION(403, "没有权限"),
|
||||
|
||||
NOT_FOUND(404, "你请求的路径不存在"),
|
||||
|
||||
FAIL(500, "操作失败"),
|
||||
|
||||
SYSTEM_EXCEPTION(5000,"系统异常!"),
|
||||
|
||||
PARAMETER_EXCEPTION(5001,"请求参数校验异常"),
|
||||
|
||||
PARAMETER_PARSE_EXCEPTION(5002,"请求参数解析异常"),
|
||||
|
||||
HTTP_MEDIA_TYPE_EXCEPTION(5003,"HTTP Media 类型异常"),
|
||||
|
||||
SYSTEM_LOGIN_EXCEPTION(5005,"系统登录异常"),
|
||||
|
||||
;
|
||||
|
||||
private final int code;
|
||||
private final String msg;
|
||||
|
||||
ApiCode(final int code, final String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public static ApiCode getApiCode(int code) {
|
||||
ApiCode[] ecs = ApiCode.values();
|
||||
for (ApiCode ec : ecs) {
|
||||
if (ec.getCode() == code) {
|
||||
return ec;
|
||||
}
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
|
||||
package vip.carpool.api.gateway.common.api;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
@Slf4j
|
||||
public class ApiController {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 请求成功
|
||||
* </p>
|
||||
*
|
||||
* @param data 数据内容
|
||||
* @param <T> 对象泛型
|
||||
* @return
|
||||
*/
|
||||
protected <T> ApiResult<T> ok(T data) {
|
||||
return ApiResult.ok(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 请求失败
|
||||
* </p>
|
||||
*
|
||||
* @param msg 提示内容
|
||||
* @return
|
||||
*/
|
||||
protected ApiResult<Object> fail(String msg) {
|
||||
return ApiResult.fail(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 请求失败
|
||||
* </p>
|
||||
*
|
||||
* @param apiCode 请求错误码
|
||||
* @return
|
||||
*/
|
||||
protected ApiResult<Object> fail(ApiCode apiCode) {
|
||||
return ApiResult.fail(apiCode);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package vip.carpool.api.gateway.common.api;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
public class ApiResult<T> implements Serializable {
|
||||
|
||||
private int code;
|
||||
|
||||
private T data;
|
||||
|
||||
private String msg;
|
||||
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date time;
|
||||
|
||||
public ApiResult() {
|
||||
|
||||
}
|
||||
|
||||
public static ApiResult result(boolean flag) {
|
||||
if (flag) {
|
||||
return ok();
|
||||
}
|
||||
return fail("");
|
||||
}
|
||||
|
||||
public static ApiResult result(ApiCode apiCode) {
|
||||
return result(apiCode, null);
|
||||
}
|
||||
|
||||
public static ApiResult result(ApiCode apiCode, String msg) {
|
||||
return result(apiCode, msg);
|
||||
}
|
||||
|
||||
public static ApiResult result(ApiCode apiCode, Object data) {
|
||||
return result(apiCode, null, data);
|
||||
}
|
||||
|
||||
public static ApiResult result(ApiCode apiCode, String msg, Object data) {
|
||||
String message = apiCode.getMsg();
|
||||
if (StringUtils.isNotBlank(msg)) {
|
||||
message = msg;
|
||||
}
|
||||
return ApiResult.builder()
|
||||
.code(apiCode.getCode())
|
||||
.msg(message)
|
||||
.data(data)
|
||||
.time(new Date())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static ApiResult ok() {
|
||||
return ok(null);
|
||||
}
|
||||
|
||||
public static ApiResult ok(Object data) {
|
||||
return result(ApiCode.SUCCESS, data);
|
||||
}
|
||||
|
||||
public static ApiResult ok(String key, Object value) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(key, value);
|
||||
return ok(map);
|
||||
}
|
||||
|
||||
public static ApiResult fail(ApiCode apiCode) {
|
||||
return result(apiCode, null);
|
||||
}
|
||||
|
||||
public static ApiResult fail(String msg) {
|
||||
return result(ApiCode.FAIL, msg, null);
|
||||
|
||||
}
|
||||
|
||||
public static ApiResult fail(ApiCode apiCode, Object data) {
|
||||
if (ApiCode.SUCCESS == apiCode) {
|
||||
throw new RuntimeException("失败结果状态码不能为" + ApiCode.SUCCESS.getCode());
|
||||
}
|
||||
return result(apiCode, data);
|
||||
|
||||
}
|
||||
|
||||
public static ApiResult fail(String key, Object value) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(key, value);
|
||||
return result(ApiCode.FAIL, map);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package vip.carpool.api.gateway.common.builder;
|
||||
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
public abstract class AbstractBuilder {
|
||||
protected final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
public abstract WxMpXmlOutMessage build(String content,
|
||||
WxMpXmlMessage wxMessage, WxMpService service);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package vip.carpool.api.gateway.common.builder;
|
||||
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
public class ImageBuilder extends AbstractBuilder {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
|
||||
WxMpService service) {
|
||||
|
||||
WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId(content)
|
||||
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
|
||||
.build();
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package vip.carpool.api.gateway.common.builder;
|
||||
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
public class TextBuilder extends AbstractBuilder {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage build(String content, WxMpXmlMessage wxMessage,
|
||||
WxMpService service) {
|
||||
WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content(content)
|
||||
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
|
||||
.build();
|
||||
return m;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package vip.carpool.api.gateway.common.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
/**
|
||||
* 跨域配置
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Configuration
|
||||
public class CorsConfig {
|
||||
// 设置允许跨域的源
|
||||
private static String[] originsVal = new String[]{
|
||||
"127.0.0.1:8006",
|
||||
"localhost:8006",
|
||||
"carpool.vip"
|
||||
};
|
||||
|
||||
/**
|
||||
* 跨域过滤器
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
this.addAllowedOrigins(corsConfiguration);
|
||||
corsConfiguration.addAllowedHeader("*");
|
||||
corsConfiguration.addAllowedMethod("*");
|
||||
corsConfiguration.addAllowedOrigin("*");
|
||||
source.registerCorsConfiguration("/**", corsConfiguration);
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
|
||||
private void addAllowedOrigins(CorsConfiguration corsConfiguration) {
|
||||
for (String origin : originsVal) {
|
||||
corsConfiguration.addAllowedOrigin("http://" + origin);
|
||||
corsConfiguration.addAllowedOrigin("https://" + origin);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package vip.carpool.api.gateway.common.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
/**
|
||||
* @ClassName SwaggerConfiguration
|
||||
* @author 刘荣华
|
||||
**/
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class SwaggerConfiguration {
|
||||
@Bean
|
||||
public Docket createRestApi() {
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage("vip.carpool.api.gateway"))
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.title("API网关")
|
||||
.description("API网关")
|
||||
.termsOfServiceUrl("https://carpool.vip/gateway/")
|
||||
.version("1.0")
|
||||
.build();
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package vip.carpool.api.gateway.common.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
|
||||
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import vip.carpool.api.gateway.common.handler.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static me.chanjar.weixin.common.api.WxConsts.EventType;
|
||||
import static me.chanjar.weixin.common.api.WxConsts.EventType.SUBSCRIBE;
|
||||
import static me.chanjar.weixin.common.api.WxConsts.EventType.UNSUBSCRIBE;
|
||||
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
|
||||
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType.EVENT;
|
||||
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.CustomerService.*;
|
||||
import static me.chanjar.weixin.mp.constant.WxMpEventConstants.POI_CHECK_NOTIFY;
|
||||
|
||||
/**
|
||||
* wechat mp configuration
|
||||
*
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(WxMpProperties.class)
|
||||
public class WxMpConfiguration {
|
||||
@Autowired
|
||||
private LogHandler logHandler;
|
||||
private NullHandler nullHandler;
|
||||
private KfSessionHandler kfSessionHandler;
|
||||
private StoreCheckNotifyHandler storeCheckNotifyHandler;
|
||||
private LocationHandler locationHandler;
|
||||
private MenuHandler menuHandler;
|
||||
private MsgHandler msgHandler;
|
||||
private UnsubscribeHandler unsubscribeHandler;
|
||||
private SubscribeHandler subscribeHandler;
|
||||
private ScanHandler scanHandler;
|
||||
private WxMpProperties properties;
|
||||
|
||||
@Bean
|
||||
public WxMpService wxMpService() {
|
||||
// 代码里 getConfigs()处报错的同学,请注意仔细阅读项目说明,你的IDE需要引入lombok插件!!!!
|
||||
final List<WxMpProperties.MpConfig> configs = this.properties.getConfigs();
|
||||
if (configs == null) {
|
||||
throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!");
|
||||
}
|
||||
|
||||
WxMpService service = new WxMpServiceImpl();
|
||||
service.setMultiConfigStorages(configs
|
||||
.stream().map(a -> {
|
||||
WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
|
||||
configStorage.setAppId(a.getAppId());
|
||||
configStorage.setSecret(a.getSecret());
|
||||
configStorage.setToken(a.getToken());
|
||||
configStorage.setAesKey(a.getAesKey());
|
||||
return configStorage;
|
||||
}).collect(Collectors.toMap(WxMpDefaultConfigImpl::getAppId, a -> a, (o, n) -> o)));
|
||||
return service;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WxMpMessageRouter messageRouter(WxMpService wxMpService) {
|
||||
final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);
|
||||
|
||||
// 记录所有事件的日志 (异步执行)
|
||||
newRouter.rule().handler(this.logHandler).next();
|
||||
|
||||
// 接收客服会话管理事件
|
||||
newRouter.rule().async(false).msgType(EVENT).event(KF_CREATE_SESSION)
|
||||
.handler(this.kfSessionHandler).end();
|
||||
newRouter.rule().async(false).msgType(EVENT).event(KF_CLOSE_SESSION)
|
||||
.handler(this.kfSessionHandler).end();
|
||||
newRouter.rule().async(false).msgType(EVENT).event(KF_SWITCH_SESSION)
|
||||
.handler(this.kfSessionHandler).end();
|
||||
|
||||
// 门店审核事件
|
||||
newRouter.rule().async(false).msgType(EVENT).event(POI_CHECK_NOTIFY).handler(this.storeCheckNotifyHandler).end();
|
||||
|
||||
// 自定义菜单事件
|
||||
newRouter.rule().async(false).msgType(EVENT).event(EventType.CLICK).handler(this.menuHandler).end();
|
||||
|
||||
// 点击菜单连接事件
|
||||
newRouter.rule().async(false).msgType(EVENT).event(EventType.VIEW).handler(this.nullHandler).end();
|
||||
|
||||
// 关注事件
|
||||
newRouter.rule().async(false).msgType(EVENT).event(SUBSCRIBE).handler(this.subscribeHandler).end();
|
||||
|
||||
// 取消关注事件
|
||||
newRouter.rule().async(false).msgType(EVENT).event(UNSUBSCRIBE).handler(this.unsubscribeHandler).end();
|
||||
|
||||
// 上报地理位置事件
|
||||
newRouter.rule().async(false).msgType(EVENT).event(EventType.LOCATION).handler(this.locationHandler).end();
|
||||
|
||||
// 接收地理位置消息
|
||||
newRouter.rule().async(false).msgType(XmlMsgType.LOCATION).handler(this.locationHandler).end();
|
||||
|
||||
// 扫码事件
|
||||
newRouter.rule().async(false).msgType(EVENT).event(EventType.SCAN).handler(this.scanHandler).end();
|
||||
|
||||
// 默认
|
||||
newRouter.rule().async(false).handler(this.msgHandler).end();
|
||||
|
||||
return newRouter;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package vip.carpool.api.gateway.common.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import vip.carpool.api.gateway.common.utils.JsonUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* wechat mp properties
|
||||
*
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "wx.mp")
|
||||
public class WxMpProperties {
|
||||
private List<MpConfig> configs;
|
||||
|
||||
@Data
|
||||
public static class MpConfig {
|
||||
/**
|
||||
* 设置微信公众号的appid
|
||||
*/
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 设置微信公众号的app secret
|
||||
*/
|
||||
private String secret;
|
||||
|
||||
/**
|
||||
* 设置微信公众号的token
|
||||
*/
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* 设置微信公众号的EncodingAESKey
|
||||
*/
|
||||
private String aesKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonUtils.toJson(this);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package vip.carpool.api.gateway.common.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import static org.springframework.http.HttpStatus.BAD_REQUEST;
|
||||
|
||||
/**
|
||||
* @ClassName 自定义异常
|
||||
* @author 刘荣华
|
||||
* @Date 2019/6/27
|
||||
**/
|
||||
@Getter
|
||||
public class BadRequestException extends RuntimeException {
|
||||
|
||||
private Integer status = BAD_REQUEST.value();
|
||||
|
||||
public BadRequestException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public BadRequestException(HttpStatus status, String msg) {
|
||||
super(msg);
|
||||
this.status = status.value();
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package vip.carpool.api.gateway.common.exception;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import vip.carpool.api.gateway.common.api.ApiCode;
|
||||
import vip.carpool.api.gateway.common.api.ApiResult;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
/**
|
||||
* @ClassName 全局异常处理
|
||||
* @author 刘荣华
|
||||
* @Date 2019/6/27
|
||||
**/
|
||||
@Slf4j
|
||||
@ControllerAdvice
|
||||
public class GatewayExceptionHandler {
|
||||
|
||||
@ExceptionHandler(value = {Exception.class})
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ResponseBody
|
||||
public ApiResult allError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
return ApiResult.fail(ApiCode.FAIL, exception.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理所有接口数据验证异常
|
||||
*
|
||||
* @param e
|
||||
* @returns
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
@ResponseBody
|
||||
public ApiResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
|
||||
e.printStackTrace();
|
||||
String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
|
||||
StringBuffer msg = new StringBuffer(str[1] + ":");
|
||||
msg.append(e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
|
||||
return ApiResult.fail(msg.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理自定义异常
|
||||
*
|
||||
* @param e
|
||||
* @return
|
||||
*/
|
||||
@ExceptionHandler(value = BadRequestException.class)
|
||||
@ResponseBody
|
||||
public ApiResult badRequestException(BadRequestException e) {
|
||||
// 打印堆栈信息
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
return ApiResult.fail(e.getMessage());
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
public abstract class AbstractHandler implements WxMpMessageHandler {
|
||||
protected Logger logger = LoggerFactory.getLogger(getClass());
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Component
|
||||
public class KfSessionHandler extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
//TODO 对会话做处理
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
import vip.carpool.api.gateway.common.builder.TextBuilder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Component
|
||||
public class LocationHandler extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
if (wxMessage.getMsgType().equals(XmlMsgType.LOCATION)) {
|
||||
//TODO 接收处理用户发送的地理位置消息
|
||||
try {
|
||||
String content = "感谢反馈,您的的地理位置已收到!";
|
||||
return new TextBuilder().build(content, wxMessage, null);
|
||||
} catch (Exception e) {
|
||||
this.logger.error("位置消息接收处理失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//上报地理位置事件
|
||||
this.logger.info("上报地理位置,纬度 : {},经度 : {},精度 : {}",
|
||||
wxMessage.getLatitude(), wxMessage.getLongitude(), String.valueOf(wxMessage.getPrecision()));
|
||||
|
||||
//TODO 可以将用户地理位置信息保存到本地数据库,以便以后使用
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
import vip.carpool.api.gateway.common.utils.JsonUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Component
|
||||
public class LogHandler extends AbstractHandler {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
this.logger.info("\n接收到请求消息,内容:{}", JsonUtils.toJson(wxMessage));
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static me.chanjar.weixin.common.api.WxConsts.EventType;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Component
|
||||
public class MenuHandler extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context, WxMpService weixinService,
|
||||
WxSessionManager sessionManager) {
|
||||
String msg = String.format("type:%s, event:%s, key:%s",
|
||||
wxMessage.getMsgType(), wxMessage.getEvent(),
|
||||
wxMessage.getEventKey());
|
||||
if (EventType.VIEW.equals(wxMessage.getEvent())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return WxMpXmlOutMessage.TEXT().content(msg)
|
||||
.fromUser(wxMessage.getToUser()).toUser(wxMessage.getFromUser())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import vip.carpool.api.gateway.common.builder.TextBuilder;
|
||||
import vip.carpool.api.gateway.common.utils.JsonUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static me.chanjar.weixin.common.api.WxConsts.XmlMsgType;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Component
|
||||
public class MsgHandler extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context, WxMpService weixinService,
|
||||
WxSessionManager sessionManager) {
|
||||
|
||||
if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) {
|
||||
//TODO 可以选择将消息保存到本地
|
||||
}
|
||||
|
||||
//当用户输入关键词如“你好”,“客服”等,并且有客服在线时,把消息转发给在线客服
|
||||
try {
|
||||
if (StringUtils.startsWithAny(wxMessage.getContent(), "你好", "客服")
|
||||
&& weixinService.getKefuService().kfOnlineList()
|
||||
.getKfOnlineList().size() > 0) {
|
||||
return WxMpXmlOutMessage.TRANSFER_CUSTOMER_SERVICE()
|
||||
.fromUser(wxMessage.getToUser())
|
||||
.toUser(wxMessage.getFromUser()).build();
|
||||
}
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
//TODO 组装回复消息
|
||||
String content = "收到信息内容:" + JsonUtils.toJson(wxMessage);
|
||||
|
||||
return new TextBuilder().build(content, wxMessage, weixinService);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Component
|
||||
public class NullHandler extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Component
|
||||
public class ScanHandler extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMpXmlMessage, Map<String, Object> map,
|
||||
WxMpService wxMpService, WxSessionManager wxSessionManager) throws WxErrorException {
|
||||
// 扫码事件处理
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 门店审核事件处理
|
||||
*
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Component
|
||||
public class StoreCheckNotifyHandler extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
// TODO 处理门店审核事件
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
||||
import org.springframework.stereotype.Component;
|
||||
import vip.carpool.api.gateway.common.builder.TextBuilder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Component
|
||||
public class SubscribeHandler extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context, WxMpService weixinService,
|
||||
WxSessionManager sessionManager) throws WxErrorException {
|
||||
|
||||
this.logger.info("新关注用户 OPENID: " + wxMessage.getFromUser());
|
||||
|
||||
// 获取微信用户基本信息
|
||||
try {
|
||||
WxMpUser userWxInfo = weixinService.getUserService()
|
||||
.userInfo(wxMessage.getFromUser(), null);
|
||||
if (userWxInfo != null) {
|
||||
// TODO 可以添加关注用户到本地数据库
|
||||
}
|
||||
} catch (WxErrorException e) {
|
||||
if (e.getError().getErrorCode() == 48001) {
|
||||
this.logger.info("该公众号没有获取用户信息权限!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WxMpXmlOutMessage responseResult = null;
|
||||
try {
|
||||
responseResult = this.handleSpecial(wxMessage);
|
||||
} catch (Exception e) {
|
||||
this.logger.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
if (responseResult != null) {
|
||||
return responseResult;
|
||||
}
|
||||
|
||||
try {
|
||||
return new TextBuilder().build("感谢关注", wxMessage, weixinService);
|
||||
} catch (Exception e) {
|
||||
this.logger.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理特殊请求,比如如果是扫码进来的,可以做相应处理
|
||||
*/
|
||||
private WxMpXmlOutMessage handleSpecial(WxMpXmlMessage wxMessage)
|
||||
throws Exception {
|
||||
//TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package vip.carpool.api.gateway.common.handler;
|
||||
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Component
|
||||
public class UnsubscribeHandler extends AbstractHandler {
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
String openId = wxMessage.getFromUser();
|
||||
this.logger.info("取消关注用户 OPENID: " + openId);
|
||||
// TODO 可以更新本地数据库为取消关注状态
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package vip.carpool.api.gateway.common.utils;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
/**
|
||||
* @author
|
||||
*/
|
||||
public class JsonUtils {
|
||||
private static final ObjectMapper JSON = new ObjectMapper();
|
||||
|
||||
static {
|
||||
JSON.setSerializationInclusion(Include.NON_NULL);
|
||||
JSON.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE);
|
||||
}
|
||||
|
||||
public static String toJson(Object obj) {
|
||||
try {
|
||||
return JSON.writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package vip.carpool.api.gateway.common.utils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
|
||||
/**
|
||||
* @ClassName 异常工具
|
||||
* @author 刘荣华
|
||||
* @Date 2019/6/27
|
||||
**/
|
||||
public class ThrowableUtil {
|
||||
|
||||
/**
|
||||
* 获取堆栈信息
|
||||
*
|
||||
* @param throwable
|
||||
* @return
|
||||
*/
|
||||
public static String getStackTrace(Throwable throwable) {
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
try {
|
||||
throwable.printStackTrace(pw);
|
||||
return sw.toString();
|
||||
} finally {
|
||||
pw.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package vip.carpool.api.gateway.common.utils;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
/**
|
||||
* 2018/7/3
|
||||
*/
|
||||
public final class WXXmlUtil {
|
||||
public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
|
||||
documentBuilderFactory.setXIncludeAware(false);
|
||||
documentBuilderFactory.setExpandEntityReferences(false);
|
||||
|
||||
return documentBuilderFactory.newDocumentBuilder();
|
||||
}
|
||||
|
||||
public static Document newDocument() throws ParserConfigurationException {
|
||||
return newDocumentBuilder().newDocument();
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
package vip.carpool.api.gateway.common.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
@Slf4j
|
||||
public class XmlMapUtil {
|
||||
|
||||
private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
private static final Random RANDOM = new SecureRandom();
|
||||
|
||||
/**
|
||||
* XML格式字符串转换为Map
|
||||
*
|
||||
* @param strXML XML字符串
|
||||
* @return XML数据转换后的Map
|
||||
* @throws Exception
|
||||
*/
|
||||
public static Map<String, String> xmlToMap(String strXML) throws Exception {
|
||||
try {
|
||||
Map<String, String> data = new HashMap<String, String>();
|
||||
DocumentBuilder documentBuilder = WXXmlUtil.newDocumentBuilder();
|
||||
InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
|
||||
Document doc = documentBuilder.parse(stream);
|
||||
doc.getDocumentElement().normalize();
|
||||
NodeList nodeList = doc.getDocumentElement().getChildNodes();
|
||||
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
|
||||
Node node = nodeList.item(idx);
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||
Element element = (Element) node;
|
||||
data.put(element.getNodeName(), element.getTextContent());
|
||||
}
|
||||
}
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception ex) {
|
||||
// do nothing
|
||||
}
|
||||
return data;
|
||||
} catch (Exception ex) {
|
||||
log.warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Map转换为XML格式的字符串
|
||||
*
|
||||
* @param data Map类型数据
|
||||
* @return XML格式的字符串
|
||||
* @throws Exception
|
||||
*/
|
||||
public static String mapToXml(Map<String, String> data) throws Exception {
|
||||
Document document = WXXmlUtil.newDocument();
|
||||
Element root = document.createElement("xml");
|
||||
document.appendChild(root);
|
||||
for (String key : data.keySet()) {
|
||||
String value = data.get(key);
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
value = value.trim();
|
||||
Element filed = document.createElement(key);
|
||||
filed.appendChild(document.createTextNode(value));
|
||||
root.appendChild(filed);
|
||||
}
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
Transformer transformer = tf.newTransformer();
|
||||
DOMSource source = new DOMSource(document);
|
||||
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
StringWriter writer = new StringWriter();
|
||||
StreamResult result = new StreamResult(writer);
|
||||
transformer.transform(source, result);
|
||||
String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
|
||||
try {
|
||||
writer.close();
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
package vip.carpool.api.gateway.common.web.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/docs")
|
||||
@ApiIgnore
|
||||
public class ApiDocController extends BaseController {
|
||||
|
||||
/**
|
||||
* swaggerUI
|
||||
*/
|
||||
@GetMapping("")
|
||||
public String swaggerUI(){
|
||||
return "redirect:/swagger-ui.html";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
|
||||
package vip.carpool.api.gateway.common.web.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import vip.carpool.api.gateway.common.api.ApiController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
@Slf4j
|
||||
public abstract class BaseController extends ApiController {
|
||||
|
||||
/**
|
||||
* 获取当前请求
|
||||
*
|
||||
* @return request
|
||||
*/
|
||||
public HttpServletRequest getRequest() {
|
||||
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
}
|
||||
/**
|
||||
* 获取当前请求
|
||||
*
|
||||
* @return response
|
||||
*/
|
||||
public HttpServletResponse getResponse() {
|
||||
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
|
||||
|
||||
package vip.carpool.api.gateway.common.web.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
|
||||
@ApiModel("ID-NAME-VO")
|
||||
public class CommonIdName {
|
||||
|
||||
@ApiModelProperty("id")
|
||||
private String id;
|
||||
|
||||
@ApiModelProperty("名称")
|
||||
private String name;
|
||||
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
public CommonIdName(String id, String name) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public CommonIdName() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CommonIdName [id=" + id + ", name=" + name + "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package vip.carpool.api.gateway.controller.wechat;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.bean.WxJsapiSignature;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
|
||||
import me.chanjar.weixin.mp.bean.result.WxMpUser;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import vip.carpool.api.gateway.common.api.ApiResult;
|
||||
import vip.carpool.api.gateway.common.exception.BadRequestException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/wechat")
|
||||
@Api(value = "微信公众号模块", tags = "微信公众号模块", description = "微信公众号模块")
|
||||
public class WeChatController {
|
||||
|
||||
@Resource
|
||||
private WxMpService wxMpService;
|
||||
|
||||
/**
|
||||
* 小程序,颁发token,暂时模拟openid
|
||||
*
|
||||
* @return token字符串
|
||||
*/
|
||||
@PostMapping("/oauth/accessToken")
|
||||
@ApiOperation(value = "获取公众号accessToken", notes = "获取公众号accessToken")
|
||||
public ApiResult login(@ApiParam(name = "code必传", required = true) @RequestParam("code") String code) {
|
||||
log.info("客户绑定颁发token入参:{}", code);
|
||||
try {
|
||||
log.info("正在获取公众号受权……");
|
||||
// 获取accessToken
|
||||
WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code);
|
||||
// 获取用户信息
|
||||
WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(accessToken, null);
|
||||
log.info("正在获取公众号受权结束:unionId为:{}", wxMpUser.getUnionId());
|
||||
return ApiResult.ok(wxMpUser);
|
||||
} catch (WxErrorException e) {
|
||||
log.error("获取公众号受权失败 accessToken: code={}, error={}", code, e.getMessage());
|
||||
throw new BadRequestException("获取公众号受权失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序,颁发token,暂时模拟openid
|
||||
*
|
||||
* @return token字符串
|
||||
*/
|
||||
@PostMapping("/oauth/getWxMpUser")
|
||||
@ApiOperation(value = "获取公众号用户信息", notes = "获取公众号用户信息")
|
||||
public ApiResult getWxMpUser(@ApiParam(name = "accessToken必传", required = true) @RequestParam("accessToken") String accessToken,
|
||||
@ApiParam(name = "openId必传", required = true) @RequestParam("openId") String openId) {
|
||||
log.info("客户绑定颁发token入参:{}", accessToken);
|
||||
try {
|
||||
log.info("正在获取公众号用户信息……");
|
||||
// 获取accessToken
|
||||
WxMpOAuth2AccessToken oAuth2AccessToken = new WxMpOAuth2AccessToken();
|
||||
oAuth2AccessToken.setAccessToken(accessToken);
|
||||
oAuth2AccessToken.setOpenId(openId);
|
||||
// 获取用户信息
|
||||
WxMpUser wxMpUser = wxMpService.oauth2getUserInfo(oAuth2AccessToken, null);
|
||||
log.info("正在获取公众号受权结束:unionId为:{}", wxMpUser.getUnionId());
|
||||
return ApiResult.ok(wxMpUser);
|
||||
} catch (WxErrorException e) {
|
||||
log.error("获取公众号受权失败 accessToken: {}, openId={}, error={}", accessToken, openId, e.getMessage());
|
||||
throw new BadRequestException("获取公众号受权失败");
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/getShareInfo")
|
||||
@ApiOperation(value = "公众号分享", notes = "公众号分享功能")
|
||||
public ApiResult share(@ApiParam(name = "需要分享的url,必传", required = true) @RequestParam("url") String url) {
|
||||
try {
|
||||
WxJsapiSignature wxJsapiSignature = wxMpService.createJsapiSignature(url);
|
||||
return ApiResult.ok(wxJsapiSignature);
|
||||
} catch (WxErrorException e) {
|
||||
log.error("公众号分享: url={}, error={}", url, e.getMessage());
|
||||
throw new BadRequestException("公众号分享失败");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package vip.carpool.api.gateway.controller.wechat;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
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.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import vip.carpool.api.gateway.common.api.ApiCode;
|
||||
import vip.carpool.api.gateway.common.api.ApiResult;
|
||||
import vip.carpool.api.gateway.common.exception.BadRequestException;
|
||||
import vip.carpool.api.gateway.common.utils.ThrowableUtil;
|
||||
import vip.carpool.api.gateway.dto.SubscribeMessageDTO;
|
||||
import vip.carpool.api.gateway.vo.TemplateData;
|
||||
import vip.carpool.api.gateway.vo.TemplateMsgVO;
|
||||
import vip.carpool.api.gateway.vo.WxMsg;
|
||||
import vip.carpool.api.gateway.vo.WxMssVo;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping
|
||||
@Api(value = "微信小程序回复用户消息模块", tags = "微信小程序回复用户消息模块", description = "微信小程序回复用户消息模块")
|
||||
public class WeChatMessageController {
|
||||
|
||||
|
||||
@Resource
|
||||
private WxMaService wxMiniService;
|
||||
|
||||
|
||||
@PostMapping("/sendMessage")
|
||||
public void sendMessage(String openId, String message) throws WxErrorException {
|
||||
WxMaKefuMessage wxMaKefuMessage = new WxMaKefuMessage();
|
||||
wxMaKefuMessage.setMsgType("text");
|
||||
wxMaKefuMessage.setToUser(openId);
|
||||
WxMaKefuMessage.KfText text = new WxMaKefuMessage.KfText(message);
|
||||
wxMaKefuMessage.setText(text);
|
||||
wxMiniService.getMsgService().sendKefuMsg(wxMaKefuMessage);
|
||||
log.info("成功回复消息:" + message);
|
||||
}
|
||||
|
||||
/*public static void main(String[] args) {
|
||||
List<WxMsg> list = new ArrayList<>();
|
||||
WxMsg wxMsg = new WxMsg();
|
||||
wxMsg.setName("keyword1");
|
||||
wxMsg.setValue("易鑫车贷");
|
||||
list.add(wxMsg);
|
||||
wxMsg = new WxMsg();
|
||||
wxMsg.setName("keyword2");
|
||||
wxMsg.setValue("尊敬的客户:您在农业银行的贷款申请已受理,具体贷款结果请咨询合作机构!");
|
||||
list.add(wxMsg);
|
||||
String msg = JSON.toJSONString(list);
|
||||
JSONObject object = new JSONObject();
|
||||
object.put("msgs", msg);
|
||||
System.out.println(object.toJSONString());
|
||||
|
||||
}*/
|
||||
|
||||
@PostMapping("/sendSubscribeMessage")
|
||||
public ApiResult sendSubscribeMessage(@Validated @RequestBody TemplateMsgVO templateMsgVO) {
|
||||
try {
|
||||
WxMssVo subscribeMessage = new WxMssVo();
|
||||
//跳转小程序页面路径
|
||||
subscribeMessage.setPage(templateMsgVO.getUrl());
|
||||
//模板消息id
|
||||
subscribeMessage.setTemplate_id(templateMsgVO.getTemplateId());
|
||||
//给谁推送 用户的openid (可以调用根据code换openid接口)
|
||||
subscribeMessage.setTouser(templateMsgVO.getOpenId());
|
||||
//==========================================创建一个参数集合========================================================
|
||||
Gson gson = new Gson();
|
||||
String msgs = templateMsgVO.getMsgs();
|
||||
Map<String, TemplateData> wxMaTemplateDataMap = new HashMap<>();
|
||||
List<WxMsg> msgList = gson.fromJson(msgs, new TypeToken<List<WxMsg>>() {
|
||||
}.getType());
|
||||
if (msgs != null && msgList.size() > 0) {
|
||||
for (WxMsg wxMsg : msgList) {
|
||||
wxMaTemplateDataMap.put(wxMsg.getName(), new TemplateData(wxMsg.getValue()));
|
||||
}
|
||||
}
|
||||
subscribeMessage.setData(wxMaTemplateDataMap);
|
||||
String str = JSON.toJSONString(subscribeMessage);
|
||||
log.info("给客户推送消息:{}", str);
|
||||
//这里简单起见我们每次都获取最新的access_token(时间开发中,应该在access_token快过期时再重新获取)
|
||||
String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + wxMiniService.getAccessToken();
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, subscribeMessage, String.class);
|
||||
SubscribeMessageDTO subscribeMessageDTO = JSON.parseObject(responseEntity.getBody(), SubscribeMessageDTO.class);
|
||||
if(null != subscribeMessageDTO.getErrcode() && subscribeMessageDTO.getErrcode().equals(0)){
|
||||
return ApiResult.ok(responseEntity.getBody());
|
||||
}
|
||||
return ApiResult.fail(ApiCode.FAIL, responseEntity.getBody());
|
||||
} catch (WxErrorException e) {
|
||||
log.error("消息推送失败:{}", ThrowableUtil.getStackTrace(e));
|
||||
throw new BadRequestException("消息推送失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package vip.carpool.api.gateway.controller.wechat;
|
||||
|
||||
import cn.binarywang.wx.miniapp.api.WxMaService;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
|
||||
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import vip.carpool.api.gateway.common.api.ApiResult;
|
||||
import vip.carpool.api.gateway.common.exception.BadRequestException;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/wxmini")
|
||||
@Api(value = "微信小程序模块", tags = "微信小程序模块", description = "微信小程序模块")
|
||||
public class WeChatMiniController {
|
||||
|
||||
@Resource
|
||||
private WxMaService wxMiniService;
|
||||
|
||||
/**
|
||||
* 小程序,颁发token,暂时模拟openid
|
||||
*
|
||||
* @return token字符串
|
||||
*/
|
||||
@PostMapping("/oauth/accessToken")
|
||||
@ApiOperation(value = "获取小程序accessToken", notes = "获取小程序accessToken")
|
||||
public ApiResult login(@ApiParam(name = "code必传", required = true) @RequestParam("code") String code,
|
||||
@ApiParam(name = "encryptedData必传", required = true) @RequestParam("encryptedData") String encryptedData,
|
||||
@ApiParam(name = "iv必传", required = true) @RequestParam("iv") String iv) {
|
||||
try {
|
||||
log.info("正在获取小程序受权……");
|
||||
WxMaJscode2SessionResult session = wxMiniService.getUserService().getSessionInfo(code);
|
||||
log.info("正在获取小程序受权:session为:{}", session.toString());
|
||||
// 先获取微信token
|
||||
String sessionKey = session.getSessionKey();
|
||||
String unionId = session.getUnionid();
|
||||
// 解密用户信息
|
||||
WxMaUserInfo userInfo = wxMiniService.getUserService().getUserInfo(sessionKey, encryptedData, iv);
|
||||
if (StringUtils.isBlank(unionId)) {
|
||||
unionId = userInfo.getUnionId();
|
||||
} else {
|
||||
userInfo.setUnionId(unionId);
|
||||
}
|
||||
log.info("正在获取小程序受权结束:unionId为:{},userInfo:{}", unionId, userInfo.toString());
|
||||
return ApiResult.ok(userInfo);
|
||||
} catch (WxErrorException e) {
|
||||
log.error("获取小程序受权失败 accessToken: code={}, error={}", code, e.getMessage());
|
||||
throw new BadRequestException("获取小程序受权失败");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
package vip.carpool.api.gateway.controller.wechat;
|
||||
|
||||
import cn.hutool.core.util.XmlUtil;
|
||||
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
|
||||
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
|
||||
import io.swagger.annotations.Api;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.ssl.SSLContexts;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.w3c.dom.Document;
|
||||
import vip.carpool.api.gateway.common.api.ApiCode;
|
||||
import vip.carpool.api.gateway.common.api.ApiResult;
|
||||
import vip.carpool.api.gateway.common.exception.BadRequestException;
|
||||
import vip.carpool.api.gateway.common.utils.XmlMapUtil;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.security.*;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/wechat")
|
||||
@Api(value = "企业付款到用户零钱", tags = "企业付款到用户零钱", description = "企业付款到用户零钱")
|
||||
public class WeChatPayUserController {
|
||||
|
||||
private final static String ACTIVE_TEST = "test";
|
||||
private final static String ACTIVE_PROD = "prod";
|
||||
private static final String CONFIG_FILENAME_DEV = "client_cert_dev.p12";
|
||||
private static final String CONFIG_FILENAME_TEST = "client_cert_test.p12";
|
||||
private static final String CONFIG_FILENAME_PROD = "client_cert_prod.p12";
|
||||
|
||||
@Value("${spring.profiles.active}")
|
||||
private String env;
|
||||
@Value("${wx.client.cert.path:}")
|
||||
private String clientCertPath;
|
||||
@Value("${mmpaymkttransfers}")
|
||||
private String mmpaymkttransfers;
|
||||
|
||||
@PostMapping("/payUser")
|
||||
public ApiResult payUser(String xmlData, String certificateKey) {
|
||||
if (StringUtils.isBlank(xmlData) || StringUtils.isBlank(certificateKey)) {
|
||||
throw new BadRequestException("付款入参为空,请检查:xml, mchId");
|
||||
}
|
||||
String path;
|
||||
if (env.equals(ACTIVE_TEST)) {
|
||||
path = clientCertPath + CONFIG_FILENAME_TEST;
|
||||
} else if (env.equals(ACTIVE_PROD)) {
|
||||
path = clientCertPath + CONFIG_FILENAME_PROD;
|
||||
} else {
|
||||
path = CONFIG_FILENAME_DEV;
|
||||
}
|
||||
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(path);
|
||||
try {
|
||||
//指定读取证书格式为PKCS12
|
||||
KeyStore keyStore = KeyStore.getInstance("PKCS12");
|
||||
;
|
||||
//指定PKCS12的密码(商户ID)
|
||||
keyStore.load(inputStream, certificateKey.toCharArray());
|
||||
// Trust own CA and all self-signed certs
|
||||
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, certificateKey.toCharArray()).build();
|
||||
//指定TLS版本, Allow TLSv1 protocol only
|
||||
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
|
||||
sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
//设置httpclient的SSLSocketFactory
|
||||
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
|
||||
HttpPost httppost = new HttpPost(mmpaymkttransfers);
|
||||
//这里要设置编码,不然xml中有中文的话会提示签名失败或者展示乱码
|
||||
httppost.addHeader("Content-Type", "text/xml");
|
||||
StringEntity se = new StringEntity(xmlData, "UTF-8");
|
||||
httppost.setEntity(se);
|
||||
CloseableHttpResponse responseEntry = httpclient.execute(httppost);
|
||||
Document document = XmlUtil.readXML(responseEntry.getEntity().getContent());
|
||||
String result = doc2FormatString(document);
|
||||
Map<String, String> resultMap = XmlMapUtil.xmlToMap(result);
|
||||
String returnCode = resultMap.get("return_code");
|
||||
String resultCode = resultMap.get("result_code");
|
||||
if ("FAIL".equals(returnCode) || "FAIL".equals(resultCode)) {
|
||||
return ApiResult.fail(ApiCode.FAIL, resultMap);
|
||||
}
|
||||
resultMap.remove("mch_appid");
|
||||
resultMap.remove("mchid");
|
||||
return ApiResult.ok(resultMap);
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
throw new BadRequestException("提取证书失败,请检查密钥是否正确:" + e.getMessage());
|
||||
} catch (CertificateException e) {
|
||||
e.printStackTrace();
|
||||
throw new BadRequestException("提取证书异常,请检查证书是否正确:" + e.getMessage());
|
||||
} catch (KeyManagementException e) {
|
||||
e.printStackTrace();
|
||||
throw new BadRequestException("提取证书失败:" + e.getMessage());
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
throw new BadRequestException("提取证书失败,证书已损坏:" + e.getMessage());
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
throw new BadRequestException("提取证书异常,请检查证书是否为PKCS12格式:" + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new BadRequestException("读取证书异常:" + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new BadRequestException("xml转map异常:" + e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
if (null != inputStream) {
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String doc2FormatString(Document doc) {
|
||||
String docString = "";
|
||||
if (doc != null) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
try {
|
||||
OutputFormat format = new OutputFormat(doc, "UTF-8", true);
|
||||
//format.setIndenting(true);//设置是否缩进,默认为true
|
||||
//format.setIndent(4);//设置缩进字符数
|
||||
//format.setPreserveSpace(false);//设置是否保持原来的格式,默认为 false
|
||||
//format.setLineWidth(500);//设置行宽度
|
||||
XMLSerializer serializer = new XMLSerializer(stringWriter, format);
|
||||
serializer.asDOMSerializer();
|
||||
serializer.serialize(doc);
|
||||
docString = stringWriter.toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (stringWriter != null) {
|
||||
try {
|
||||
stringWriter.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("XML内容:" + docString);
|
||||
return docString;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package vip.carpool.api.gateway.controller.wechat;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
|
||||
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
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.RestController;
|
||||
import vip.carpool.api.gateway.common.api.ApiResult;
|
||||
import vip.carpool.api.gateway.common.exception.BadRequestException;
|
||||
import vip.carpool.api.gateway.common.utils.ThrowableUtil;
|
||||
import vip.carpool.api.gateway.vo.TemplateMsgVO;
|
||||
import vip.carpool.api.gateway.vo.WxMsg;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: huangguojie
|
||||
* @Date: 2020/7/19 14:54
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* Description:
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/wechat")
|
||||
@Api(value = "推送模版消息", tags = "推送模版消息", description = "推送模版消息")
|
||||
public class WeChatTemplateMessageController {
|
||||
|
||||
@Resource
|
||||
private WxMpService wxService;
|
||||
|
||||
/**
|
||||
* 推送模版消息
|
||||
*
|
||||
* @param templateMsgVO TemplateMsgVO
|
||||
* @return ApiResult
|
||||
*/
|
||||
@PostMapping(value = "/sendTemplateMsg")
|
||||
@ApiOperation(value = "推送模版消息", notes = "推送模版消息")
|
||||
public ApiResult sendTemplateMsg(@Validated @RequestBody TemplateMsgVO templateMsgVO) {
|
||||
WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
|
||||
.toUser(templateMsgVO.getOpenId())
|
||||
.templateId(templateMsgVO.getTemplateId())
|
||||
.url(templateMsgVO.getUrl())
|
||||
.build();
|
||||
try {
|
||||
Gson gson = new Gson();
|
||||
String msgs = templateMsgVO.getMsgs();
|
||||
List<WxMsg> msgList = gson.fromJson(msgs, new TypeToken<List<WxMsg>>(){}.getType());
|
||||
if(msgs != null && msgList.size() > 0) {
|
||||
for(WxMsg wxMsg: msgList) {
|
||||
WxMpTemplateData templateData = new WxMpTemplateData(wxMsg.getName(), wxMsg.getValue(), wxMsg.getColor());
|
||||
templateMessage.addData(templateData);
|
||||
}
|
||||
}
|
||||
log.info("给客户推送消息:{}", templateMessage.toJson());
|
||||
String msgId = this.wxService.getTemplateMsgService().sendTemplateMsg(templateMessage);
|
||||
log.info("给客户推送消息结果:{}", msgId);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("msgId", msgId);
|
||||
return ApiResult.ok(jsonObject);
|
||||
} catch (WxErrorException e) {
|
||||
log.error("消息推送失败:{}", ThrowableUtil.getStackTrace(e));
|
||||
throw new BadRequestException("消息推送失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package vip.carpool.api.gateway.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: huangguojie
|
||||
* @Date: 2020/12/13 15:13
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class SubscribeMessageDTO {
|
||||
|
||||
/**
|
||||
* errcode : 0
|
||||
* errmsg : ok
|
||||
*/
|
||||
private Integer errcode;
|
||||
private String errmsg;
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package vip.carpool.api.gateway.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: huangguojie
|
||||
* @Date: 2020/9/19 20:25
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class UserOfflineTaskFinishCallDTO {
|
||||
private Integer retCode;
|
||||
private String retMsg;
|
||||
private String content;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package vip.carpool.api.gateway.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: huangguojie
|
||||
* @Date: 2020/9/25 21:24
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class CustomerVO {
|
||||
private String openId;
|
||||
private String secretId;
|
||||
private String secretKey;
|
||||
private String projectId;
|
||||
private String subProjectId;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package vip.carpool.api.gateway.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: huangguojie
|
||||
* @Date: 2020/12/13 11:49
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class TemplateData {
|
||||
private String value;
|
||||
|
||||
public TemplateData(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package vip.carpool.api.gateway.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author 刘荣华
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "推送模版消息入参")
|
||||
public class TemplateMsgVO {
|
||||
|
||||
@NotBlank(message = "必传")
|
||||
@ApiModelProperty(value = "openId")
|
||||
private String openId;
|
||||
|
||||
@NotBlank(message = "模板id必传")
|
||||
@ApiModelProperty(value = "模板id")
|
||||
private String templateId;
|
||||
|
||||
@ApiModelProperty(value = "需要跳转的url")
|
||||
private String url;
|
||||
|
||||
@NotBlank(message = "消息体必传")
|
||||
@ApiModelProperty(value = "消息体")
|
||||
private String msgs;
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package vip.carpool.api.gateway.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: huangguojie
|
||||
* @Date: 2020/9/19 20:25
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class UserOfflineTaskFinishVO {
|
||||
private String url;
|
||||
private String data;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package vip.carpool.api.gateway.vo;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
public class WxMsg {
|
||||
|
||||
@NotBlank(message = "消息参数必填")
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "消息参数值必填")
|
||||
private String value;
|
||||
|
||||
@NotBlank(message = "参数值颜色必填")
|
||||
private String color;
|
||||
|
||||
public WxMsg() {
|
||||
|
||||
}
|
||||
|
||||
public WxMsg(String name , String value, String color) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(String color) {
|
||||
this.color = color;
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package vip.carpool.api.gateway.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author: huangguojie
|
||||
* @Date: 2020/12/13 11:49
|
||||
* To change this template use File | Settings | File Templates.
|
||||
* Description:
|
||||
*/
|
||||
@Data
|
||||
public class WxMssVo {
|
||||
private String touser;//用户openid
|
||||
private String template_id;//订阅消息模版id
|
||||
private String page = "pages/index/index";//默认跳到小程序首页
|
||||
private Map<String, TemplateData> data;//推送文字
|
||||
}
|
30
carpool-wx-api/src/main/resources/application-dev.yml
Normal file
30
carpool-wx-api/src/main/resources/application-dev.yml
Normal file
@ -0,0 +1,30 @@
|
||||
wx:
|
||||
client:
|
||||
cert:
|
||||
path: config/
|
||||
# 是否开启微信真实环境
|
||||
is-product: true
|
||||
wbank:
|
||||
clientId:
|
||||
apikey:
|
||||
pay:
|
||||
appId:
|
||||
mchId:
|
||||
mchKey:
|
||||
subAppId:
|
||||
subMchId:
|
||||
keyPath:
|
||||
miniapp:
|
||||
appid: wxad50a166ce47e667
|
||||
secret: c3f96e82e681e4f1ac8416a662a169e7
|
||||
token:
|
||||
aesKey:
|
||||
msgDataFormat: JSON
|
||||
mp:
|
||||
configs:
|
||||
#(一个公众号的appid)
|
||||
- appId:
|
||||
#(公众号的appsecret)
|
||||
secret:
|
||||
token: #(接口配置里的Token值)
|
||||
aesKey: #(接口配置里的EncodingAESKey值)
|
30
carpool-wx-api/src/main/resources/application-prod.yml
Normal file
30
carpool-wx-api/src/main/resources/application-prod.yml
Normal file
@ -0,0 +1,30 @@
|
||||
wx:
|
||||
client:
|
||||
cert:
|
||||
path: config/
|
||||
# 是否开启微信真实环境
|
||||
is-product: true
|
||||
wbank:
|
||||
clientId:
|
||||
apikey:
|
||||
pay:
|
||||
appId:
|
||||
mchId:
|
||||
mchKey:
|
||||
subAppId:
|
||||
subMchId:
|
||||
keyPath:
|
||||
miniapp:
|
||||
appid: wxad50a166ce47e667
|
||||
secret: c3f96e82e681e4f1ac8416a662a169e7
|
||||
token:
|
||||
aesKey:
|
||||
msgDataFormat: JSON
|
||||
mp:
|
||||
configs:
|
||||
#(一个公众号的appid)
|
||||
- appId:
|
||||
#(公众号的appsecret)
|
||||
secret:
|
||||
token: #(接口配置里的Token值)
|
||||
aesKey: #(接口配置里的EncodingAESKey值)
|
30
carpool-wx-api/src/main/resources/application-test.yml
Normal file
30
carpool-wx-api/src/main/resources/application-test.yml
Normal file
@ -0,0 +1,30 @@
|
||||
wx:
|
||||
client:
|
||||
cert:
|
||||
path: config/
|
||||
# 是否开启微信真实环境
|
||||
is-product: true
|
||||
wbank:
|
||||
clientId:
|
||||
apikey:
|
||||
pay:
|
||||
appId:
|
||||
mchId:
|
||||
mchKey:
|
||||
subAppId:
|
||||
subMchId:
|
||||
keyPath:
|
||||
miniapp:
|
||||
appid:
|
||||
secret:
|
||||
token:
|
||||
aesKey:
|
||||
msgDataFormat: JSON
|
||||
mp:
|
||||
configs:
|
||||
#(一个公众号的appid)
|
||||
- appId:
|
||||
#(公众号的appsecret)
|
||||
secret:
|
||||
token: #(接口配置里的Token值)
|
||||
aesKey: #(接口配置里的EncodingAESKey值)
|
31
carpool-wx-api/src/main/resources/application.yml
Normal file
31
carpool-wx-api/src/main/resources/application.yml
Normal file
@ -0,0 +1,31 @@
|
||||
server:
|
||||
port: 7085
|
||||
spring:
|
||||
#启用环境(开发、测试、生产)
|
||||
profiles:
|
||||
active: prod
|
||||
swagger:
|
||||
enabled: true
|
||||
title: 标题
|
||||
description: 描述信息
|
||||
version: 1.0
|
||||
contact:
|
||||
name: 维护者信息
|
||||
|
||||
logging:
|
||||
level:
|
||||
com.abchina.api.gateway: DEBUG
|
||||
org.springframework.web: INFO
|
||||
com.github.binarywang.demo.wx.mp: DEBUG
|
||||
me.chanjar.weixin: DEBUG
|
||||
|
||||
# 农行api地址
|
||||
abchina:
|
||||
# 名称
|
||||
name: abchina-api-gateway
|
||||
# 版本
|
||||
version: 1.0.0
|
||||
# 版权年份
|
||||
copyrightYear: 2020
|
||||
|
||||
mmpaymkttransfers: https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
|
76
carpool-wx-api/src/main/resources/logback.xml
Normal file
76
carpool-wx-api/src/main/resources/logback.xml
Normal file
@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<!-- 日志存放路径 -->
|
||||
<!-- <property name="log.path" value="/home/abchina-api-gateway/logs" />-->
|
||||
<property name="log.path" value="/accd/wbank/logs/carpool-ex-api/logs" />
|
||||
<!-- 日志输出格式 -->
|
||||
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 系统日志输出 -->
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/abchina-api-gateway.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/abchina-api-gateway.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/abchina-api-gateway-error.log</file>
|
||||
<!-- 循环政策:基于时间创建日志文件 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/abchina-api-gateway-error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大的历史 60天 -->
|
||||
<maxHistory>60</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>ERROR</level>
|
||||
<!-- 匹配时的操作:接收(记录) -->
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 系统模块日志级别控制 -->
|
||||
<logger name="com.abchina" level="info" />
|
||||
<!-- Spring日志级别控制 -->
|
||||
<logger name="org.springframework" level="warn" />
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
<!--系统操作日志-->
|
||||
<root level="info">
|
||||
<appender-ref ref="file_info" />
|
||||
<appender-ref ref="file_error" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
35
pom.xml
35
pom.xml
@ -33,6 +33,7 @@
|
||||
<poi.version>4.1.2</poi.version>
|
||||
<velocity.version>1.7</velocity.version>
|
||||
<jwt.version>0.9.1</jwt.version>
|
||||
<hutool.version>5.2.0</hutool.version>
|
||||
</properties>
|
||||
|
||||
<!-- 依赖声明 -->
|
||||
@ -205,6 +206,37 @@
|
||||
<version>${ruoyi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--hutool 工具包-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-models</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- swagger2-UI-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>${swagger.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 拼车小程序模块 -->
|
||||
<dependency>
|
||||
<groupId>com.ruoyi</groupId>
|
||||
@ -213,6 +245,8 @@
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@ -224,6 +258,7 @@
|
||||
<module>ruoyi-generator</module>
|
||||
<module>ruoyi-common</module>
|
||||
<module>ruiyi-carpool</module>
|
||||
<module>carpool-wx-api</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user