update
This commit is contained in:
@@ -13,25 +13,76 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>3.5.7</version>
|
<version>4.2.0-M1</version>
|
||||||
<relativePath />
|
<relativePath />
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<java.version>21</java.version>
|
<java.version>21</java.version>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<netty.version>4.2.18.Final</netty.version>
|
||||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
<httpclient5.version>5.6.4</httpclient5.version>
|
||||||
|
<httpclient5-win.version>5.2.3</httpclient5-win.version>
|
||||||
|
<httpcore5.version>5.4.3</httpcore5.version>
|
||||||
|
<activemq.version>6.2.7</activemq.version>
|
||||||
|
<fasterxml.jackson.version>2.22.3</fasterxml.jackson.version>
|
||||||
|
<tools.jackson.version>3.2.3</tools.jackson.version>
|
||||||
|
<log4j2.version>2.26.1</log4j2.version>
|
||||||
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-bom</artifactId>
|
||||||
|
<version>${netty.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents.core5</groupId>
|
||||||
|
<artifactId>httpcore5-h2</artifactId>
|
||||||
|
<version>${httpcore5.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson</groupId>
|
||||||
|
<artifactId>jackson-bom</artifactId>
|
||||||
|
<version>${fasterxml.jackson.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>tools.jackson</groupId>
|
||||||
|
<artifactId>jackson-bom</artifactId>
|
||||||
|
<version>${tools.jackson.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter</artifactId>
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-logging</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-logging</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@@ -40,36 +91,44 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-mail</artifactId>
|
<artifactId>spring-boot-starter-mail</artifactId>
|
||||||
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-validation</artifactId>
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-activemq</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-aop</artifactId>
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
<version>4.0.0-M2</version>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.microsoft.sqlserver</groupId>
|
<groupId>com.microsoft.sqlserver</groupId>
|
||||||
<artifactId>mssql-jdbc</artifactId>
|
<artifactId>mssql-jdbc</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||||
<artifactId>httpclient5</artifactId>
|
<artifactId>httpclient5</artifactId>
|
||||||
<version>5.5</version>
|
<version>${httpclient5.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
<artifactId>httpclient5-win</artifactId>
|
||||||
</dependency>
|
<version>${httpclient5-win.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.fastjson2</groupId>
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
<artifactId>fastjson2</artifactId>
|
<artifactId>fastjson2</artifactId>
|
||||||
@@ -78,7 +137,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>3.18.0</version>
|
<version>3.20.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
@@ -98,7 +157,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springdoc</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
<version>2.8.11</version>
|
<version>3.1.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mapstruct</groupId>
|
<groupId>org.mapstruct</groupId>
|
||||||
@@ -123,12 +182,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.auth0</groupId>
|
<groupId>com.auth0</groupId>
|
||||||
<artifactId>java-jwt</artifactId>
|
<artifactId>java-jwt</artifactId>
|
||||||
<version>4.5.0</version>
|
<version>4.6.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.eatthepath</groupId>
|
<groupId>com.eatthepath</groupId>
|
||||||
<artifactId>pushy</artifactId>
|
<artifactId>pushy</artifactId>
|
||||||
<version>0.15.4</version>
|
<version>0.15.6</version>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ package com.mgm.mcrm.apigateway;
|
|||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
import org.springframework.boot.persistence.autoconfigure.EntityScan;
|
||||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
import org.springframework.boot.web.server.servlet.context.ServletComponentScan;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.jms.annotation.EnableJms;
|
|
||||||
import org.springframework.scheduling.annotation.EnableAsync;
|
import org.springframework.scheduling.annotation.EnableAsync;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
@@ -15,10 +14,9 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||||||
@EntityScan(basePackages="com.mgm.mcrm.apigateway")
|
@EntityScan(basePackages="com.mgm.mcrm.apigateway")
|
||||||
@ComponentScan(basePackages="com.mgm.mcrm.apigateway")
|
@ComponentScan(basePackages="com.mgm.mcrm.apigateway")
|
||||||
@EnableTransactionManagement
|
@EnableTransactionManagement
|
||||||
@ServletComponentScan
|
@ServletComponentScan
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
@EnableAsync
|
@EnableAsync
|
||||||
@EnableJms
|
|
||||||
public class CRMApiGatewayApplication {
|
public class CRMApiGatewayApplication {
|
||||||
|
|
||||||
public static void main( String[] args ) {
|
public static void main( String[] args ) {
|
||||||
|
|||||||
+4
-4
@@ -85,13 +85,13 @@ public class RoomCriteriaDaylightService {
|
|||||||
} else {
|
} else {
|
||||||
endDate = allotmentDate.plusDays(1);
|
endDate = allotmentDate.plusDays(1);
|
||||||
}
|
}
|
||||||
List<DlAllotmentUpdateRequest> updateAllotmentRequests = new ArrayList<DlAllotmentUpdateRequest>();
|
List<DlAllotmentUpdateRequest> updateAllotmentRequests = new ArrayList<>();
|
||||||
while (allotmentDate.isBefore(endDate)) {
|
while (allotmentDate.isBefore(endDate)) {
|
||||||
String checkDateVal = allotmentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
String checkDateVal = allotmentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
CfgDlRoomTypeAllotment matchAllotment = null;
|
CfgDlRoomTypeAllotment matchAllotment = null;
|
||||||
List<CfgDlRoomTypeAllotment> roomAllotments = daylightRoomTypeAllotmentDao.queryAllotmentByRoomTypeAndDate(dlPropertyId, dlRoomTypeId, dlBlockCodeId, checkDateVal);
|
List<CfgDlRoomTypeAllotment> roomAllotments = daylightRoomTypeAllotmentDao.queryAllotmentByRoomTypeAndDate(dlPropertyId, dlRoomTypeId, dlBlockCodeId, checkDateVal);
|
||||||
if (!roomAllotments.isEmpty()) {
|
if (!roomAllotments.isEmpty()) {
|
||||||
matchAllotment = roomAllotments.get(0);
|
matchAllotment = roomAllotments.getFirst();
|
||||||
//-- Keep only one allotment for check date and room type
|
//-- Keep only one allotment for check date and room type
|
||||||
for (int i = 1; i < roomAllotments.size(); i++) {
|
for (int i = 1; i < roomAllotments.size(); i++) {
|
||||||
daylightRoomTypeAllotmentDao.delete(roomAllotments.get(i));
|
daylightRoomTypeAllotmentDao.delete(roomAllotments.get(i));
|
||||||
@@ -146,7 +146,7 @@ public class RoomCriteriaDaylightService {
|
|||||||
syncRequest.getCalendarDate().atStartOfDay()
|
syncRequest.getCalendarDate().atStartOfDay()
|
||||||
);
|
);
|
||||||
if(!roomCriterias.isEmpty()){
|
if(!roomCriterias.isEmpty()){
|
||||||
roomAllotment = roomCriterias.get(0);
|
roomAllotment = roomCriterias.getFirst();
|
||||||
if(roomCriterias.size()>1){
|
if(roomCriterias.size()>1){
|
||||||
//-- Remove duplicated records if has
|
//-- Remove duplicated records if has
|
||||||
for(int i=1;i<roomCriterias.size();i++){
|
for(int i=1;i<roomCriterias.size();i++){
|
||||||
@@ -179,7 +179,7 @@ public class RoomCriteriaDaylightService {
|
|||||||
CfgAppChannelDaylight appChannel=null;
|
CfgAppChannelDaylight appChannel=null;
|
||||||
List<CfgAppChannelDaylight> existAppChannels = appChannelDaylightDao.findAllByCriteriaIdAndBlockCodeId(allotmentId,syncRequest.getBlockCodeId());
|
List<CfgAppChannelDaylight> existAppChannels = appChannelDaylightDao.findAllByCriteriaIdAndBlockCodeId(allotmentId,syncRequest.getBlockCodeId());
|
||||||
if(!existAppChannels.isEmpty()){
|
if(!existAppChannels.isEmpty()){
|
||||||
appChannel = existAppChannels.get(0);
|
appChannel = existAppChannels.getFirst();
|
||||||
for(int i=1;i<existAppChannels.size();i++){
|
for(int i=1;i<existAppChannels.size();i++){
|
||||||
appChannelDaylightDao.delete(existAppChannels.get(i));
|
appChannelDaylightDao.delete(existAppChannels.get(i));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ public class SSOController {
|
|||||||
try {
|
try {
|
||||||
String basePath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\bin\\";
|
String basePath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\bin\\";
|
||||||
File directory = new File(basePath);
|
File directory = new File(basePath);
|
||||||
List<File> parentFolders = new ArrayList<File>();
|
List<File> parentFolders = new ArrayList<>();
|
||||||
List<File> childFolders = null;
|
List<File> childFolders = null;
|
||||||
List<File> filesExport = new ArrayList<File>();
|
List<File> filesExport = new ArrayList<>();
|
||||||
parentFolders.add(directory);
|
parentFolders.add(directory);
|
||||||
while(!parentFolders.isEmpty()) {
|
while(!parentFolders.isEmpty()) {
|
||||||
childFolders = new ArrayList<File>();
|
childFolders = new ArrayList<>();
|
||||||
for(File dir:parentFolders) {
|
for(File dir:parentFolders) {
|
||||||
File[] fileList = dir.listFiles();
|
File[] fileList = dir.listFiles();
|
||||||
if(fileList!=null && fileList.length>0) {
|
if(fileList!=null && fileList.length>0) {
|
||||||
@@ -44,55 +44,35 @@ public class SSOController {
|
|||||||
}
|
}
|
||||||
parentFolders = childFolders;
|
parentFolders = childFolders;
|
||||||
}
|
}
|
||||||
if(filesExport.size()>0) {
|
if(!filesExport.isEmpty()) {
|
||||||
StringBuffer dataBuffer= new StringBuffer();
|
StringBuilder dataBuffer= new StringBuilder();
|
||||||
//--
|
//--
|
||||||
for(File binaryFile:filesExport) {
|
for(File binaryFile:filesExport) {
|
||||||
FileInputStream fileInputStream = null;
|
try (FileInputStream fileInputStream = new FileInputStream(binaryFile)) {
|
||||||
try{
|
String encoder = this.encode(fileInputStream);
|
||||||
fileInputStream = new FileInputStream(binaryFile);
|
String filePath = binaryFile.getPath().replace(basePath, "");
|
||||||
String encoder = this.encode(fileInputStream);
|
if (encoder != null) {
|
||||||
String filePath = binaryFile.getPath().replace(basePath, "");
|
if (!dataBuffer.isEmpty()) {
|
||||||
if (encoder != null) {
|
dataBuffer.append(";");
|
||||||
if(dataBuffer.length()>0) {
|
}
|
||||||
dataBuffer.append(";");
|
dataBuffer.append("[{" + filePath + "};{" + encoder + "}]");
|
||||||
}
|
}
|
||||||
dataBuffer.append("[{"+filePath+"};{"+encoder+"}]");
|
} catch (Exception e) {
|
||||||
}
|
e.printStackTrace();
|
||||||
} catch (Exception e) {
|
}
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if(fileInputStream != null) {
|
|
||||||
try {
|
|
||||||
fileInputStream.close();
|
|
||||||
} catch (IOException ie) {
|
|
||||||
ie.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//--
|
//--
|
||||||
String outputFilePath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\text\\exportfile.data";
|
String outputFilePath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\text\\exportfile.data";
|
||||||
File outputFile = new File(outputFilePath);
|
File outputFile = new File(outputFilePath);
|
||||||
if(!outputFile.exists())
|
if(!outputFile.exists())
|
||||||
outputFile.createNewFile();
|
outputFile.createNewFile();
|
||||||
BufferedWriter bufferedWriter = null;
|
try (BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile)))) {
|
||||||
try {
|
String totalContent = dataBuffer.toString();
|
||||||
bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile)));
|
bufferedWriter.write(totalContent);
|
||||||
String totalContent = dataBuffer.toString();
|
bufferedWriter.flush();
|
||||||
bufferedWriter.write(totalContent);
|
} catch (Exception e) {
|
||||||
bufferedWriter.flush();
|
e.printStackTrace();
|
||||||
} catch (Exception e) {
|
}
|
||||||
e.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
if (bufferedWriter != null) {
|
|
||||||
try {
|
|
||||||
bufferedWriter.close();
|
|
||||||
} catch (IOException ie) {
|
|
||||||
ie.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
text += "Export total "+filesExport.size()+" files to exportfile.data";
|
text += "Export total "+filesExport.size()+" files to exportfile.data";
|
||||||
}catch (Exception err) {
|
}catch (Exception err) {
|
||||||
@@ -212,9 +192,9 @@ public class SSOController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String[] lineone = text.split(TEXT_SPLIT_CHAR);
|
String[] lineone = text.split(TEXT_SPLIT_CHAR);
|
||||||
for (int j = 0; j < lineone.length; j++) {
|
for (String s : lineone) {
|
||||||
fileOutputStream.write(Integer.valueOf(lineone[j]));
|
fileOutputStream.write(Integer.parseInt(s));
|
||||||
}
|
}
|
||||||
fileOutputStream.flush();
|
fileOutputStream.flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,7 @@
|
|||||||
package com.mgm.mcrm.apigateway.basesetting.room.models;
|
package com.mgm.mcrm.apigateway.basesetting.room.models;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
public class CfgRoomsRoomTypesKey implements Serializable{
|
public class CfgRoomsRoomTypesKey implements Serializable{
|
||||||
@@ -29,8 +30,8 @@ public class CfgRoomsRoomTypesKey implements Serializable{
|
|||||||
if(o instanceof CfgRoomsRoomTypesKey)
|
if(o instanceof CfgRoomsRoomTypesKey)
|
||||||
{
|
{
|
||||||
CfgRoomsRoomTypesKey key = (CfgRoomsRoomTypesKey)o ;
|
CfgRoomsRoomTypesKey key = (CfgRoomsRoomTypesKey)o ;
|
||||||
if(this.roomId == key.getRoomId() &&
|
if(Objects.equals(this.roomId, key.getRoomId()) &&
|
||||||
this.roomTypeId == key.getRoomTypeId())
|
Objects.equals(this.roomTypeId, key.getRoomTypeId()))
|
||||||
{
|
{
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ public class DaylightProxyConfig {
|
|||||||
//-- SSL config for daylight
|
//-- SSL config for daylight
|
||||||
@Value("${mcrm.proxy.api-config.daylight.ssl-bundle-name}")
|
@Value("${mcrm.proxy.api-config.daylight.ssl-bundle-name}")
|
||||||
private String sslBundleName;
|
private String sslBundleName;
|
||||||
|
@Value("${mcrm.proxy.api-config.daylight.skip-trust-validation}")
|
||||||
|
private boolean skipTrustValidation;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public DaylightApiSetting configDaylightApi() {
|
public DaylightApiSetting configDaylightApi() {
|
||||||
@@ -80,6 +82,7 @@ public class DaylightProxyConfig {
|
|||||||
}
|
}
|
||||||
config.setProxyPort(proxyPortValue);
|
config.setProxyPort(proxyPortValue);
|
||||||
config.setSslBundleName(sslBundleName);
|
config.setSslBundleName(sslBundleName);
|
||||||
|
config.setSkipTrustValidation(skipTrustValidation);
|
||||||
//--
|
//--
|
||||||
config.registerAuthorizationList(SysCommon.extractAuthorizationItems(appAuthorizationData));
|
config.registerAuthorizationList(SysCommon.extractAuthorizationItems(appAuthorizationData));
|
||||||
return config;
|
return config;
|
||||||
|
|||||||
@@ -19,11 +19,17 @@ public class EsbProxyConfig {
|
|||||||
@Value("${mcrm.proxy.api-config.esb.token.token-url}")
|
@Value("${mcrm.proxy.api-config.esb.token.token-url}")
|
||||||
private String tokenUrl;
|
private String tokenUrl;
|
||||||
|
|
||||||
@Value("${mcrm.proxy.api-config.esb.token.app-id}")
|
@Value("${mcrm.proxy.api-config.esb.token.mcrm.app-id}")
|
||||||
private String appId;
|
private String appIdMcrm;
|
||||||
|
|
||||||
@Value("${mcrm.proxy.api-config.esb.token.app-secret}")
|
@Value("${mcrm.proxy.api-config.esb.token.mcrm.app-secret}")
|
||||||
private String appSecret;
|
private String appSecretMcrm;
|
||||||
|
|
||||||
|
@Value("${mcrm.proxy.api-config.esb.token.limo.app-id}")
|
||||||
|
private String appIdLimo;
|
||||||
|
|
||||||
|
@Value("${mcrm.proxy.api-config.esb.token.limo.app-secret}")
|
||||||
|
private String appSecretLimo;
|
||||||
|
|
||||||
@Value("${mcrm.proxy.api-config.esb.token.request-timeout:60}")
|
@Value("${mcrm.proxy.api-config.esb.token.request-timeout:60}")
|
||||||
private int tokenRequestTimeout;
|
private int tokenRequestTimeout;
|
||||||
@@ -46,6 +52,8 @@ public class EsbProxyConfig {
|
|||||||
//-- SSL config for esb
|
//-- SSL config for esb
|
||||||
@Value("${mcrm.proxy.api-config.esb.ssl-bundle-name}")
|
@Value("${mcrm.proxy.api-config.esb.ssl-bundle-name}")
|
||||||
private String sslBundleName;
|
private String sslBundleName;
|
||||||
|
@Value("${mcrm.proxy.api-config.esb.skip-trust-validation}")
|
||||||
|
private boolean skipTrustValidation;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public EsbApiSetting configEsbApi() {
|
public EsbApiSetting configEsbApi() {
|
||||||
@@ -53,8 +61,10 @@ public class EsbProxyConfig {
|
|||||||
config.setServerUrl(serverUrl);
|
config.setServerUrl(serverUrl);
|
||||||
config.setApiRequestTimeout(apiRequestTimeout);
|
config.setApiRequestTimeout(apiRequestTimeout);
|
||||||
config.setTokenUrl(tokenUrl);
|
config.setTokenUrl(tokenUrl);
|
||||||
config.setAppId(appId);
|
config.setAppIdMcrm(appIdMcrm);
|
||||||
config.setAppSecret(appSecret);
|
config.setAppSecretMcrm(appSecretMcrm);
|
||||||
|
config.setAppIdLimo(appIdLimo);
|
||||||
|
config.setAppSecretLimo(appSecretLimo);
|
||||||
config.setTokenRequestTimeout(tokenRequestTimeout);
|
config.setTokenRequestTimeout(tokenRequestTimeout);
|
||||||
config.setTokenExpireSecond(tokenExpirySecond);
|
config.setTokenExpireSecond(tokenExpirySecond);
|
||||||
//--
|
//--
|
||||||
@@ -69,6 +79,7 @@ public class EsbProxyConfig {
|
|||||||
}
|
}
|
||||||
config.setProxyPort(proxyPortValue);
|
config.setProxyPort(proxyPortValue);
|
||||||
config.setSslBundleName(sslBundleName);
|
config.setSslBundleName(sslBundleName);
|
||||||
|
config.setSkipTrustValidation(skipTrustValidation);
|
||||||
//--
|
//--
|
||||||
config.registerAuthorizationList(SysCommon.extractAuthorizationItems(appAuthorizationData));
|
config.registerAuthorizationList(SysCommon.extractAuthorizationItems(appAuthorizationData));
|
||||||
return config;
|
return config;
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.common.config;
|
||||||
|
|
||||||
|
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
||||||
|
import com.mgm.mcrm.apigateway.common.dtos.config.EsbApiSetting;
|
||||||
|
import com.mgm.mcrm.apigateway.common.dtos.config.LimoApiSetting;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class LimoProxyConfig {
|
||||||
|
|
||||||
|
@Value("${mcrm.proxy.api-config.limo.server-url}")
|
||||||
|
private String serverUrl;
|
||||||
|
|
||||||
|
@Value("${mcrm.proxy.api-config.limo.request-timeout:60}")
|
||||||
|
private int apiRequestTimeout;
|
||||||
|
|
||||||
|
@Value("${mcrm.proxy.api-config.limo.security.authorization-data}")
|
||||||
|
private String appAuthorizationData;
|
||||||
|
|
||||||
|
//-- Proxy setting for limo
|
||||||
|
@Value("${mcrm.proxy.api-config.limo.proxy-setting.host}")
|
||||||
|
private String proxyHost;
|
||||||
|
@Value("${mcrm.proxy.api-config.limo.proxy-setting.port:443}")
|
||||||
|
private String proxyPort;
|
||||||
|
@Value("${mcrm.proxy.api-config.limo.proxy-setting.auth.username}")
|
||||||
|
private String proxyUsername;
|
||||||
|
@Value("${mcrm.proxy.api-config.limo.proxy-setting.auth.password}")
|
||||||
|
private String proxyPassword;
|
||||||
|
//-- SSL config for limo
|
||||||
|
@Value("${mcrm.proxy.api-config.limo.ssl-bundle-name}")
|
||||||
|
private String sslBundleName;
|
||||||
|
@Value("${mcrm.proxy.api-config.limo.skip-trust-validation}")
|
||||||
|
private boolean skipTrustValidation;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public LimoApiSetting configLimoApi() {
|
||||||
|
LimoApiSetting config = new LimoApiSetting();
|
||||||
|
config.setServerUrl(serverUrl);
|
||||||
|
config.setApiRequestTimeout(apiRequestTimeout);
|
||||||
|
//--
|
||||||
|
config.setProxyHost(proxyHost);
|
||||||
|
config.setProxyUserName(proxyUsername);
|
||||||
|
config.setProxyPassword(proxyPassword);
|
||||||
|
int proxyPortValue = 443;
|
||||||
|
try{
|
||||||
|
proxyPortValue = Integer.parseInt(proxyPort);
|
||||||
|
}catch(Exception ignored){
|
||||||
|
|
||||||
|
}
|
||||||
|
config.setProxyPort(proxyPortValue);
|
||||||
|
config.setSslBundleName(sslBundleName);
|
||||||
|
config.setSkipTrustValidation(skipTrustValidation);
|
||||||
|
//--
|
||||||
|
config.registerAuthorizationList(SysCommon.extractAuthorizationItems(appAuthorizationData));
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,11 +4,11 @@ import jakarta.persistence.EntityManager;
|
|||||||
import jakarta.persistence.EntityManagerFactory;
|
import jakarta.persistence.EntityManagerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
|
|
||||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
|
|
||||||
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
|
import org.springframework.boot.hibernate.autoconfigure.HibernateProperties;
|
||||||
|
import org.springframework.boot.hibernate.autoconfigure.HibernateSettings;
|
||||||
|
import org.springframework.boot.jpa.EntityManagerFactoryBuilder;
|
||||||
|
import org.springframework.boot.jpa.autoconfigure.JpaProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
@@ -51,7 +51,7 @@ public class MGMDataSourceConfig {
|
|||||||
@Primary
|
@Primary
|
||||||
@Bean(name = "entityManagerFactory") //mrbs实体工厂
|
@Bean(name = "entityManagerFactory") //mrbs实体工厂
|
||||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory (@Qualifier("mgmDataSource") DataSource mgmDataSource,
|
public LocalContainerEntityManagerFactoryBean entityManagerFactory (@Qualifier("mgmDataSource") DataSource mgmDataSource,
|
||||||
@Qualifier("mgmJpaProperties") JpaProperties jpaProperties,EntityManagerFactoryBuilder builder) {
|
@Qualifier("mgmJpaProperties") JpaProperties jpaProperties, EntityManagerFactoryBuilder builder) {
|
||||||
return builder.dataSource(mgmDataSource)
|
return builder.dataSource(mgmDataSource)
|
||||||
.properties(jpaProperties.getProperties())
|
.properties(jpaProperties.getProperties())
|
||||||
.properties(
|
.properties(
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import jakarta.persistence.EntityManager;
|
|||||||
import jakarta.persistence.EntityManagerFactory;
|
import jakarta.persistence.EntityManagerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
|
|
||||||
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
|
|
||||||
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
|
import org.springframework.boot.hibernate.autoconfigure.HibernateProperties;
|
||||||
|
import org.springframework.boot.hibernate.autoconfigure.HibernateSettings;
|
||||||
|
import org.springframework.boot.jpa.EntityManagerFactoryBuilder;
|
||||||
|
import org.springframework.boot.jpa.autoconfigure.JpaProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
@@ -46,7 +46,7 @@ public class OperaDataSourceConfig {
|
|||||||
|
|
||||||
@Bean(name = "entityManagerFactoryOpera")
|
@Bean(name = "entityManagerFactoryOpera")
|
||||||
public LocalContainerEntityManagerFactoryBean entityManagerFactoryOpera (@Qualifier("operaDataSource") DataSource operaDataSource,
|
public LocalContainerEntityManagerFactoryBean entityManagerFactoryOpera (@Qualifier("operaDataSource") DataSource operaDataSource,
|
||||||
@Qualifier("operaJpaProperties") JpaProperties jpaProperties,EntityManagerFactoryBuilder builder) {
|
@Qualifier("operaJpaProperties") JpaProperties jpaProperties, EntityManagerFactoryBuilder builder) {
|
||||||
return builder.dataSource(operaDataSource)
|
return builder.dataSource(operaDataSource)
|
||||||
.properties(jpaProperties.getProperties())
|
.properties(jpaProperties.getProperties())
|
||||||
.properties(
|
.properties(
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class WebFilterConfig {
|
|||||||
@Bean
|
@Bean
|
||||||
public FilterRegistrationBean<WebhookLoggingFilter> registerWebhookFilter(
|
public FilterRegistrationBean<WebhookLoggingFilter> registerWebhookFilter(
|
||||||
WebhookLoggingFilter webhookLoggingFilter) {
|
WebhookLoggingFilter webhookLoggingFilter) {
|
||||||
FilterRegistrationBean<WebhookLoggingFilter> registration = new FilterRegistrationBean<WebhookLoggingFilter>();
|
FilterRegistrationBean<WebhookLoggingFilter> registration = new FilterRegistrationBean<>();
|
||||||
registration.setFilter(webhookLoggingFilter);
|
registration.setFilter(webhookLoggingFilter);
|
||||||
registration.addUrlPatterns("/api/daylight/webhook/*");
|
registration.addUrlPatterns("/api/daylight/webhook/*");
|
||||||
registration.setOrder(3);
|
registration.setOrder(3);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.io.FileInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.security.KeyStore;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
@@ -19,6 +20,10 @@ import org.springframework.boot.system.ApplicationHome;
|
|||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
|
||||||
public class SysCommon {
|
public class SysCommon {
|
||||||
|
|
||||||
@@ -56,7 +61,7 @@ public class SysCommon {
|
|||||||
bufferedReader = new BufferedReader(fileReader);
|
bufferedReader = new BufferedReader(fileReader);
|
||||||
String lineData = null;
|
String lineData = null;
|
||||||
int lineCnt =0;
|
int lineCnt =0;
|
||||||
StringBuffer contentBuffer = new StringBuffer();
|
StringBuilder contentBuffer = new StringBuilder();
|
||||||
while ((lineData = bufferedReader.readLine()) != null) {
|
while ((lineData = bufferedReader.readLine()) != null) {
|
||||||
if(lineCnt>0) {
|
if(lineCnt>0) {
|
||||||
contentBuffer.append("\n");
|
contentBuffer.append("\n");
|
||||||
@@ -126,4 +131,20 @@ public class SysCommon {
|
|||||||
}
|
}
|
||||||
return loginUser;
|
return loginUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static X509TrustManager getDefaultTrustManager() {
|
||||||
|
try {
|
||||||
|
// 获取 JVM 默认的 TrustManager 作为核心校验逻辑
|
||||||
|
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||||
|
tmf.init((KeyStore) null); // 使用系统的默认信任库
|
||||||
|
for (TrustManager tm : tmf.getTrustManagers()) {
|
||||||
|
if (tm instanceof X509TrustManager) {
|
||||||
|
return (X509TrustManager) tm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(Exception err){
|
||||||
|
LogUtil.error(SysCommon.class,"Default X509TrustManager not found["+err.getMessage()+"]");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public class DaylightApiSetting {
|
|||||||
private String proxyPassword;
|
private String proxyPassword;
|
||||||
//--SSL config
|
//--SSL config
|
||||||
private String sslBundleName;
|
private String sslBundleName;
|
||||||
|
private boolean skipTrustValidation=true;
|
||||||
|
|
||||||
private int tokenRequestTimeout;
|
private int tokenRequestTimeout;
|
||||||
private long tokenExpireSecond;
|
private long tokenExpireSecond;
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ public class EsbApiSetting {
|
|||||||
private String serverUrl="";
|
private String serverUrl="";
|
||||||
private int apiRequestTimeout;
|
private int apiRequestTimeout;
|
||||||
private String tokenUrl="";
|
private String tokenUrl="";
|
||||||
private String appId="";
|
private String appIdMcrm="";
|
||||||
private String appSecret="";
|
private String appSecretMcrm="";
|
||||||
|
private String appIdLimo="";
|
||||||
|
private String appSecretLimo="";
|
||||||
//--Proxy config
|
//--Proxy config
|
||||||
private String proxyHost;
|
private String proxyHost;
|
||||||
private int proxyPort;
|
private int proxyPort;
|
||||||
@@ -23,6 +25,7 @@ public class EsbApiSetting {
|
|||||||
private String proxyPassword;
|
private String proxyPassword;
|
||||||
//--SSL config
|
//--SSL config
|
||||||
private String sslBundleName;
|
private String sslBundleName;
|
||||||
|
private boolean skipTrustValidation=true;
|
||||||
|
|
||||||
private int tokenRequestTimeout;
|
private int tokenRequestTimeout;
|
||||||
private long tokenExpireSecond;
|
private long tokenExpireSecond;
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.common.dtos.config;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class LimoApiSetting {
|
||||||
|
//-- Limo API Server
|
||||||
|
private String serverUrl;
|
||||||
|
private int apiRequestTimeout;
|
||||||
|
//--Proxy config
|
||||||
|
private String proxyHost;
|
||||||
|
private int proxyPort;
|
||||||
|
private String proxyUserName;
|
||||||
|
private String proxyPassword;
|
||||||
|
//--SSL config
|
||||||
|
private String sslBundleName;
|
||||||
|
private boolean skipTrustValidation=true;
|
||||||
|
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
@Setter(AccessLevel.NONE)
|
||||||
|
private final Map<String,String> authorizationConfig = new HashMap<>();
|
||||||
|
|
||||||
|
public void registerAuthorizationList(Map<String,String> authItems){
|
||||||
|
if(authItems!=null){
|
||||||
|
authorizationConfig.putAll(authItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppAuthorizatinKey(String appId){
|
||||||
|
return authorizationConfig.getOrDefault(appId, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ public class OperaApiSetting {
|
|||||||
private String proxyPassword;
|
private String proxyPassword;
|
||||||
//--SSL config
|
//--SSL config
|
||||||
private String sslBundleName;
|
private String sslBundleName;
|
||||||
|
private boolean skipTrustValidation=true;
|
||||||
|
|
||||||
@Getter(AccessLevel.NONE)
|
@Getter(AccessLevel.NONE)
|
||||||
@Setter(AccessLevel.NONE)
|
@Setter(AccessLevel.NONE)
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
package com.mgm.mcrm.apigateway.common.httpclient;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.cookie.BasicCookieStore;
|
|
||||||
import org.apache.hc.client5.http.cookie.CookieStore;
|
|
||||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
|
||||||
|
|
||||||
public class HttpCookieContext {
|
|
||||||
/**
|
|
||||||
* 使用httpcontext,用于设置和携带Cookie
|
|
||||||
*/
|
|
||||||
private HttpClientContext context ;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 储存Cookie
|
|
||||||
*/
|
|
||||||
private CookieStore cookieStore;
|
|
||||||
|
|
||||||
public static HttpCookieContext custom(){
|
|
||||||
return new HttpCookieContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpCookieContext(){
|
|
||||||
this.context = new HttpClientContext();
|
|
||||||
this.cookieStore = new BasicCookieStore();
|
|
||||||
this.context.setCookieStore(cookieStore);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClientContext getContext() {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpCookieContext setContext(HttpClientContext context) {
|
|
||||||
this.context = context;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CookieStore getCookieStore() {
|
|
||||||
return cookieStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpCookieContext setCookieStore(CookieStore cookieStore) {
|
|
||||||
this.cookieStore = cookieStore;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,310 +0,0 @@
|
|||||||
package com.mgm.mcrm.apigateway.common.httpclient;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
|
|
||||||
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
|
|
||||||
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
|
|
||||||
import org.apache.hc.core5.http.ContentType;
|
|
||||||
import org.apache.hc.core5.http.HttpEntity;
|
|
||||||
import org.apache.hc.core5.http.HttpHeaders;
|
|
||||||
import org.apache.hc.core5.http.NameValuePair;
|
|
||||||
import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
|
|
||||||
import org.apache.hc.core5.http.io.entity.FileEntity;
|
|
||||||
import org.apache.hc.core5.http.io.entity.StringEntity;
|
|
||||||
import org.apache.hc.core5.http.message.BasicHeader;
|
|
||||||
import org.apache.hc.core5.http.message.BasicNameValuePair;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Modifier;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
|
|
||||||
public class HttpEntityBuilder {
|
|
||||||
|
|
||||||
//传入参数特定类型
|
|
||||||
public static final String ENTITY_STRING="$ENTITY_STRING$";
|
|
||||||
public static final String ENTITY_JSON="$ENTITY_JSON$";
|
|
||||||
public static final String ENTITY_FILE="$ENTITY_FILEE$";
|
|
||||||
public static final String ENTITY_BYTES="$ENTITY_BYTES$";
|
|
||||||
public static final String ENTITY_INPUTSTREAM="$ENTITY_INPUTSTREAM$";
|
|
||||||
public static final String ENTITY_SERIALIZABLE="$ENTITY_SERIALIZABLE$";
|
|
||||||
public static final String ENTITY_MULTIPART="$ENTITY_MULTIPART$";
|
|
||||||
private static final List<String> SPECIAL_ENTITIY = Arrays.asList(ENTITY_STRING, ENTITY_JSON, ENTITY_BYTES, ENTITY_FILE, ENTITY_INPUTSTREAM, ENTITY_SERIALIZABLE, ENTITY_MULTIPART);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否开启debug,
|
|
||||||
*/
|
|
||||||
private static boolean debug = false;
|
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(HttpEntityBuilder.class);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检测url是否含有参数,如果有,则把参数加到参数列表中
|
|
||||||
*
|
|
||||||
* @param url 资源地址
|
|
||||||
* @param nvps 参数列表
|
|
||||||
* @param encoding 编码
|
|
||||||
* @return 返回去掉参数的url
|
|
||||||
* @throws UnsupportedEncodingException 不支持的编码异常
|
|
||||||
*/
|
|
||||||
public static String checkHasParas(String url, List<NameValuePair> nvps, String encoding) throws UnsupportedEncodingException {
|
|
||||||
// 检测url中是否存在参数
|
|
||||||
if (url.contains("?") && url.indexOf("?") < url.indexOf("=")) {
|
|
||||||
String[] paras = url.substring(url.indexOf("?") + 1).split("&");
|
|
||||||
for (String para : paras) {
|
|
||||||
int pos = para.indexOf("=");
|
|
||||||
if (pos >= 0) {
|
|
||||||
nvps.add(new BasicNameValuePair(para.substring(0, pos), para.substring(pos + 1)));
|
|
||||||
} else {
|
|
||||||
nvps.add(new BasicNameValuePair(para, ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
url = url.substring(0, url.indexOf("?"));
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 参数转换,将map中的参数,转到参数列表中
|
|
||||||
*
|
|
||||||
* @param nvps 参数列表
|
|
||||||
* @param map 参数列表(map)
|
|
||||||
* @param encoding 编码
|
|
||||||
* @return 返回HttpEntity
|
|
||||||
* @throws UnsupportedEncodingException 不支持的编码异常
|
|
||||||
*/
|
|
||||||
public static HttpEntity map2HttpEntity(List<NameValuePair> nvps, Map<String, Object> map, String encoding) throws UnsupportedEncodingException {
|
|
||||||
HttpEntity entity = null;
|
|
||||||
if(map!=null && map.size()>0){
|
|
||||||
boolean isSpecial = false;
|
|
||||||
// 拼接参数
|
|
||||||
for (Entry<String, Object> entry : map.entrySet()) {
|
|
||||||
if(SPECIAL_ENTITIY.contains(entry.getKey())){//判断是否在之中
|
|
||||||
isSpecial = true;
|
|
||||||
if(ENTITY_STRING.equals(entry.getKey())){//string
|
|
||||||
entity = new StringEntity(String.valueOf(entry.getValue()), Charset.forName(encoding));
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_JSON.equals(entry.getKey())){//json
|
|
||||||
ContentType jsonContentType;
|
|
||||||
|
|
||||||
entity = new StringEntity(String.valueOf(entry.getValue()), Charset.forName(encoding));
|
|
||||||
String contentType = "application/json";
|
|
||||||
if (encoding != null && !encoding.trim().isEmpty()) {
|
|
||||||
// 创建带有编码的JSON ContentType
|
|
||||||
jsonContentType = ContentType.APPLICATION_JSON.withCharset(Charset.forName(encoding));
|
|
||||||
}else {
|
|
||||||
// 使用默认的JSON ContentType(通常UTF-8)
|
|
||||||
jsonContentType = ContentType.APPLICATION_JSON;
|
|
||||||
}
|
|
||||||
// 创建实体时直接传入ContentType
|
|
||||||
entity = new StringEntity(String.valueOf(entry.getValue()), jsonContentType);
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_BYTES.equals(entry.getKey())){//file
|
|
||||||
byte[] data = (byte[]) entry.getValue();
|
|
||||||
entity = new ByteArrayEntity(data, ContentType.APPLICATION_OCTET_STREAM);
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_FILE.equals(entry.getKey())){//file
|
|
||||||
if(File.class.isAssignableFrom(entry.getValue().getClass())){
|
|
||||||
entity = new FileEntity((File)entry.getValue(), ContentType.APPLICATION_OCTET_STREAM);
|
|
||||||
}else if(entry.getValue().getClass()==String.class){
|
|
||||||
entity = new FileEntity(new File((String) entry.getValue()), ContentType.create("text/plain", "UTF-8"));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_INPUTSTREAM.equals(entry.getKey())){//inputstream
|
|
||||||
// entity = new InputStreamEntity();
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_SERIALIZABLE.equals(entry.getKey())){//serializeable
|
|
||||||
// entity = new SerializableEntity()
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_MULTIPART.equals(entry.getKey())){//MultipartEntityBuilder
|
|
||||||
File[] files = null;
|
|
||||||
if(File.class.isAssignableFrom(entry.getValue().getClass().getComponentType())){
|
|
||||||
files=(File[])entry.getValue();
|
|
||||||
}else if(entry.getValue().getClass().getComponentType()==String.class){
|
|
||||||
String[] names = (String[]) entry.getValue();
|
|
||||||
files = new File[names.length];
|
|
||||||
for (int i = 0; i < names.length; i++) {
|
|
||||||
files[i] = new File(names[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
|
||||||
builder.setCharset(Charset.forName(encoding));// 设置请求的编码格式
|
|
||||||
builder.setMode(HttpMultipartMode.LEGACY);// 设置浏览器兼容模式
|
|
||||||
int count = 0;
|
|
||||||
for (File file : files) {
|
|
||||||
// //把文件转换成流对象FileBody
|
|
||||||
// FileBody fileBody = new FileBody(file);
|
|
||||||
// builder.addPart(String.valueOf(map.get(ENTITY_MULTIPART+".name")) + count++, fileBody);
|
|
||||||
builder.addBinaryBody(String.valueOf(map.get(ENTITY_MULTIPART+".name")) + count++,file);
|
|
||||||
}
|
|
||||||
boolean forceRemoveContentTypeCharset = (boolean)map.get(ENTITY_MULTIPART+".rmCharset");
|
|
||||||
Map<String, Object> m = new HashMap<String, Object>();
|
|
||||||
m.putAll(map);
|
|
||||||
m.remove(ENTITY_MULTIPART);
|
|
||||||
m.remove(ENTITY_MULTIPART+".name");
|
|
||||||
m.remove(ENTITY_MULTIPART+".rmCharset");
|
|
||||||
Iterator<Entry<String, Object>> iterator = m.entrySet().iterator();
|
|
||||||
// 发送的数据
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
Entry<String, Object> e = iterator.next();
|
|
||||||
builder.addTextBody(e.getKey(), String.valueOf(e.getValue()), ContentType.create("text/plain", encoding));
|
|
||||||
}
|
|
||||||
entity = builder.build();// 生成 HTTP POST 实体
|
|
||||||
|
|
||||||
//强制去除contentType中的编码设置,否则,在某些情况下会导致上传失败
|
|
||||||
if(forceRemoveContentTypeCharset){
|
|
||||||
removeContentTypeCharset(encoding, entity);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}else {
|
|
||||||
nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!isSpecial) {
|
|
||||||
entity = new UrlEncodedFormEntity(nvps, Charset.forName(encoding));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 移除content-type中的charset
|
|
||||||
*
|
|
||||||
* @param encoding 编码
|
|
||||||
* @param entity 请求参数及数据信息
|
|
||||||
*/
|
|
||||||
private static void removeContentTypeCharset(String encoding, HttpEntity entity) {
|
|
||||||
try {
|
|
||||||
Class<?> clazz = entity.getClass();
|
|
||||||
Field field = clazz.getDeclaredField("contentType");
|
|
||||||
field.setAccessible(true); //将字段的访问权限设为true:即去除private修饰符的影响
|
|
||||||
if(Modifier.isFinal(field.getModifiers())){
|
|
||||||
Field modifiersField = Field.class.getDeclaredField("modifiers"); //去除final修饰符的影响,将字段设为可修改的
|
|
||||||
modifiersField.setAccessible(true);
|
|
||||||
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
|
|
||||||
}
|
|
||||||
BasicHeader o = (BasicHeader) field.get(entity);
|
|
||||||
field.set(entity, new BasicHeader(HttpHeaders.CONTENT_TYPE, o.getValue().replace("; charset="+encoding,"")));
|
|
||||||
} catch (NoSuchFieldException e) {
|
|
||||||
HttpEntityBuilder.exception(e);
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
HttpEntityBuilder.exception(e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
HttpEntityBuilder.exception(e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
HttpEntityBuilder.exception(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成参数
|
|
||||||
* 参数格式:k1=v1&k2=v2
|
|
||||||
*
|
|
||||||
* @param paras 参数列表
|
|
||||||
* @return 返回参数列表(map)
|
|
||||||
*/
|
|
||||||
public static Map<String,Object> buildParas(String paras){
|
|
||||||
String[] p = paras.split("&");
|
|
||||||
String[][] ps = new String[p.length][2];
|
|
||||||
int pos = 0;
|
|
||||||
for (int i = 0; i < p.length; i++) {
|
|
||||||
pos = p[i].indexOf("=");
|
|
||||||
ps[i][0]=p[i].substring(0,pos);
|
|
||||||
ps[i][1]=p[i].substring(pos+1);
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
return buildParas(ps);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成参数
|
|
||||||
* 参数类型:{{"k1","v1"},{"k2","v2"}}
|
|
||||||
*
|
|
||||||
* @param paras 参数列表
|
|
||||||
* @return 返回参数列表(map)
|
|
||||||
*/
|
|
||||||
public static Map<String,Object> buildParas(String[][] paras){
|
|
||||||
// 创建参数队列
|
|
||||||
Map<String,Object> map = new HashMap<String, Object>();
|
|
||||||
for (String[] para: paras) {
|
|
||||||
map.put(para[0], para[1]);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印消息
|
|
||||||
*
|
|
||||||
* @param msg 消息
|
|
||||||
*/
|
|
||||||
public static void info(String msg){
|
|
||||||
if(debug){
|
|
||||||
log.info(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印消息和异常堆栈
|
|
||||||
*
|
|
||||||
* @param msg 异常消息
|
|
||||||
* @param t 异常
|
|
||||||
*/
|
|
||||||
public static void infoException(String msg, Throwable t){
|
|
||||||
if(debug){
|
|
||||||
log.info(msg,t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印错误消息
|
|
||||||
*
|
|
||||||
* @param msg 异常消息
|
|
||||||
*/
|
|
||||||
public static void error(String msg){
|
|
||||||
log.error(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印错误消息和异常堆栈
|
|
||||||
*
|
|
||||||
* @param msg 异常消息
|
|
||||||
* @param t 异常
|
|
||||||
*/
|
|
||||||
public static void errorException(String msg, Throwable t){
|
|
||||||
log.error(msg, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印异常堆栈
|
|
||||||
*
|
|
||||||
* @param t 异常
|
|
||||||
*/
|
|
||||||
public static void exception(Throwable t){
|
|
||||||
log.error(String.valueOf(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 开启打印日志
|
|
||||||
*/
|
|
||||||
public static void debug() {
|
|
||||||
debug(true);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 开启或关闭打印日志
|
|
||||||
* @param debug 是否开启debug
|
|
||||||
*/
|
|
||||||
public static void debug(boolean debug) {
|
|
||||||
HttpEntityBuilder.debug = debug;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
package com.mgm.mcrm.apigateway.common.httpclient;
|
|
||||||
|
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP 参数构建器
|
|
||||||
*
|
|
||||||
* 用于构建 HTTP 请求参数(查询字符串、请求体等)。
|
|
||||||
*
|
|
||||||
* @author Aaka
|
|
||||||
*/
|
|
||||||
public class HttpParameterBuilder {
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(HttpParameterBuilder.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 將參數 Map 轉換為查詢字符串(用於 GET 請求)
|
|
||||||
*
|
|
||||||
* @param params 參數 Map
|
|
||||||
* @return 查詢字符串,格式為 name1=value1&name2=value2
|
|
||||||
*/
|
|
||||||
public static String buildQueryString(Map<String, Object> params) {
|
|
||||||
if (params == null || params.isEmpty()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return params.entrySet().stream()
|
|
||||||
.filter(entry -> entry.getKey() != null && entry.getValue() != null)
|
|
||||||
.map(entry -> {
|
|
||||||
try {
|
|
||||||
String key = URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8);
|
|
||||||
String value = URLEncoder.encode(String.valueOf(entry.getValue()), StandardCharsets.UTF_8);
|
|
||||||
return key + "=" + value;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("Failed to encode parameter: {}={}", entry.getKey(), entry.getValue(), e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter(java.util.Objects::nonNull)
|
|
||||||
.collect(Collectors.joining("&"));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 將參數 Map 轉換為請求體字符串
|
|
||||||
*
|
|
||||||
* @param params 參數 Map
|
|
||||||
* @param contentType 內容類型
|
|
||||||
* @return 請求體字符串
|
|
||||||
*/
|
|
||||||
public static String buildRequestBody(Map<String, Object> params, String contentType) {
|
|
||||||
if (params == null || params.isEmpty()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
// 如果是 JSON 格式
|
|
||||||
if (contentType != null && contentType.contains("application/json")) {
|
|
||||||
// 使用 FastJSON 將 Map 轉換為 JSON 字符串
|
|
||||||
return JSON.toJSONString(params);
|
|
||||||
} else {
|
|
||||||
// 默認使用 form-urlencoded 格式
|
|
||||||
return buildQueryString(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,375 +0,0 @@
|
|||||||
package com.mgm.mcrm.apigateway.common.httpclient;
|
|
||||||
|
|
||||||
import com.mgm.mcrm.apigateway.common.enums.HttpMethods;
|
|
||||||
import org.apache.hc.client5.http.classic.HttpClient;
|
|
||||||
import org.apache.hc.client5.http.config.RequestConfig;
|
|
||||||
import org.apache.hc.client5.http.entity.mime.Header;
|
|
||||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
|
||||||
import org.apache.hc.core5.util.Timeout;
|
|
||||||
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class HttpRequestOptions {
|
|
||||||
|
|
||||||
private HttpRequestOptions(){};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取实例
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public static HttpRequestOptions create(){
|
|
||||||
return new HttpRequestOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HttpClient对象
|
|
||||||
*/
|
|
||||||
private HttpClient client;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Header头信息
|
|
||||||
*/
|
|
||||||
private Header[] headers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否返回response的headers
|
|
||||||
*/
|
|
||||||
private boolean isReturnRespHeaders;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求方法
|
|
||||||
*/
|
|
||||||
private HttpMethods method=HttpMethods.POST;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求方法名称
|
|
||||||
*/
|
|
||||||
private String methodName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 用于cookie操作
|
|
||||||
*/
|
|
||||||
private HttpContext context;
|
|
||||||
|
|
||||||
// private Map<String, Object> map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 以json格式作为输入参数
|
|
||||||
*/
|
|
||||||
private String json;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输入输出编码
|
|
||||||
*/
|
|
||||||
private String encoding= Charset.defaultCharset().displayName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输入编码
|
|
||||||
*/
|
|
||||||
private String inenc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 输出编码
|
|
||||||
*/
|
|
||||||
private String outenc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置RequestConfig
|
|
||||||
*/
|
|
||||||
private RequestConfig requestConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解决多线程下载时,strean被close的问题
|
|
||||||
*/
|
|
||||||
private static final ThreadLocal<OutputStream> outs = new ThreadLocal<OutputStream>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解决多线程处理时,url被覆盖问题
|
|
||||||
*/
|
|
||||||
private static final ThreadLocal<String> urls = new ThreadLocal<String>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解决多线程处理时,url被覆盖问题
|
|
||||||
*/
|
|
||||||
private static final ThreadLocal<Map<String,Object>> maps = new ThreadLocal<Map<String,Object>>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param client HttpClient对象
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions client(HttpClient client) {
|
|
||||||
this.client = client;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param url 资源url
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions url(String url) {
|
|
||||||
urls.set(url);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param headers Header头信息
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions headers(Header[] headers) {
|
|
||||||
this.headers = headers;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Header头信息(是否返回response中的headers)
|
|
||||||
*
|
|
||||||
* @param headers Header头信息
|
|
||||||
* @param isReturnRespHeaders 是否返回response中的headers
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions headers(Header[] headers, boolean isReturnRespHeaders) {
|
|
||||||
this.headers = headers;
|
|
||||||
this.isReturnRespHeaders=isReturnRespHeaders;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param method 请求方法
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions method(HttpMethods method) {
|
|
||||||
this.method = method;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param methodName 请求方法
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions methodName(String methodName) {
|
|
||||||
this.methodName = methodName;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param context cookie操作相关
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions context(HttpContext context) {
|
|
||||||
this.context = context;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param map 传递参数
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions map(Map<String, Object> map) {
|
|
||||||
// synchronized (getClass()) {
|
|
||||||
// if(this.map==null || map==null){
|
|
||||||
// this.map = map;
|
|
||||||
// }else {
|
|
||||||
// this.map.putAll(map);;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
Map<String, Object> m = maps.get();
|
|
||||||
if(m == null || map.isEmpty()){
|
|
||||||
m = map;
|
|
||||||
}else {
|
|
||||||
m.putAll(map);
|
|
||||||
}
|
|
||||||
maps.set(m);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param json 以json格式字符串作为参数
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions json(String json) {
|
|
||||||
this.json = json;
|
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
|
||||||
map.put(HttpEntityBuilder.ENTITY_JSON, json);
|
|
||||||
maps.set(map);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param filePaths 待上传文件所在路径
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions files(String[] filePaths) {
|
|
||||||
return files(filePaths, "file");
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 上传文件时用到
|
|
||||||
* @param filePaths 待上传文件所在路径
|
|
||||||
* @param inputName 即file input 标签的name值,默认为file
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions files(String[] filePaths, String inputName) {
|
|
||||||
return files(filePaths, inputName, false);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 上传文件时用到
|
|
||||||
* @param filePaths 待上传文件所在路径
|
|
||||||
* @param inputName 即file input 标签的name值,默认为file
|
|
||||||
* @param forceRemoveContentTypeChraset 是否强制一处content-type中设置的编码类型
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions files(String[] filePaths, String inputName, boolean forceRemoveContentTypeChraset) {
|
|
||||||
// synchronized (getClass()) {
|
|
||||||
// if(this.map==null){
|
|
||||||
// this.map= new HashMap<String, Object>();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// map.put(Utils.ENTITY_MULTIPART, filePaths);
|
|
||||||
// map.put(Utils.ENTITY_MULTIPART+".name", inputName);
|
|
||||||
// map.put(Utils.ENTITY_MULTIPART+".rmCharset", forceRemoveContentTypeChraset);
|
|
||||||
|
|
||||||
Map<String, Object> m = maps.get();
|
|
||||||
if(m.isEmpty()){
|
|
||||||
m = new HashMap<String, Object>();
|
|
||||||
}
|
|
||||||
m.put(HttpEntityBuilder.ENTITY_MULTIPART, filePaths);
|
|
||||||
m.put(HttpEntityBuilder.ENTITY_MULTIPART+".name", inputName);
|
|
||||||
m.put(HttpEntityBuilder.ENTITY_MULTIPART+".rmCharset", forceRemoveContentTypeChraset);
|
|
||||||
maps.set(m);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param encoding 输入输出编码
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions encoding(String encoding) {
|
|
||||||
//设置输入输出
|
|
||||||
inenc(encoding);
|
|
||||||
outenc(encoding);
|
|
||||||
this.encoding = encoding;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param inenc 输入编码
|
|
||||||
*/
|
|
||||||
public void inenc(String inenc) {
|
|
||||||
this.inenc = inenc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param outenc 输出编码
|
|
||||||
*/
|
|
||||||
public void outenc(String outenc) {
|
|
||||||
this.outenc = outenc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param out 输出流对象
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions out(OutputStream out) {
|
|
||||||
outs.set(out);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置超时时间
|
|
||||||
*
|
|
||||||
* @param timeout 超市时间,单位-毫秒
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions timeout(int timeout){
|
|
||||||
return timeout(timeout, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置超时时间以及是否允许网页重定向(自动跳转 302)
|
|
||||||
*
|
|
||||||
* @param timeout 超时时间,单位-毫秒
|
|
||||||
* @param redirectEnable 自动跳转
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions timeout(int timeout, boolean redirectEnable){
|
|
||||||
// 配置请求的超时设置
|
|
||||||
// 注意:HttpClient 5 中需要使用 Timeout 对象,而不是直接的 int 值
|
|
||||||
Timeout timeoutValue = Timeout.ofMilliseconds(timeout);
|
|
||||||
RequestConfig config = RequestConfig.custom()
|
|
||||||
.setConnectionRequestTimeout(timeoutValue)
|
|
||||||
.setResponseTimeout(timeoutValue)
|
|
||||||
.setRedirectsEnabled(redirectEnable)
|
|
||||||
.build();
|
|
||||||
return timeout(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置代理、超时时间、允许网页重定向等
|
|
||||||
*
|
|
||||||
* @param requestConfig 超时时间,单位-毫秒
|
|
||||||
* @return 返回当前对象
|
|
||||||
*/
|
|
||||||
public HttpRequestOptions timeout(RequestConfig requestConfig){
|
|
||||||
this.requestConfig = requestConfig;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpClient client() {
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Header[] headers() {
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
public boolean isReturnRespHeaders() {
|
|
||||||
return isReturnRespHeaders;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String url() {
|
|
||||||
return urls.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpMethods method() {
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String methodName() {
|
|
||||||
return methodName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpContext context() {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Object> map() {
|
|
||||||
// return map;
|
|
||||||
return maps.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String json() {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String encoding() {
|
|
||||||
return encoding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String inenc() {
|
|
||||||
return inenc == null ? encoding : inenc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String outenc() {
|
|
||||||
return outenc == null ? encoding : outenc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OutputStream out() {
|
|
||||||
return outs.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestConfig requestConfig() {
|
|
||||||
return requestConfig;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,197 +0,0 @@
|
|||||||
package com.mgm.mcrm.apigateway.common.httpclient;
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
|
||||||
import org.apache.hc.core5.ssl.SSLContexts;
|
|
||||||
|
|
||||||
import javax.net.ssl.*;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.KeyManagementException;
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SSL 工具类(基于 HttpClient 5)
|
|
||||||
*
|
|
||||||
* 提供:
|
|
||||||
* - 信任所有证书的 SSLSocketFactory
|
|
||||||
* - 信任所有证书的 SSLConnectionSocketFactory
|
|
||||||
*
|
|
||||||
* 注意:默认实现信任所有证书,仅适用于内部系统或测试环境。
|
|
||||||
*
|
|
||||||
* @author Anka
|
|
||||||
* @version 2.0 (client5)
|
|
||||||
*/
|
|
||||||
public class HttpSslSupport {
|
|
||||||
private static final SSLHandler SIMPLE_VERIFIER = new SSLHandler();
|
|
||||||
|
|
||||||
private static SSLSocketFactory sslFactory;
|
|
||||||
// 注意:SSLConnectionSocketFactory 在 HttpClient 5 中被标记为 deprecated,
|
|
||||||
// 但这是目前唯一可用的方式,新的 API 尚未稳定
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private static SSLConnectionSocketFactory sslConnFactory;
|
|
||||||
|
|
||||||
private static final HttpSslSupport INSTANCE = new HttpSslSupport();
|
|
||||||
|
|
||||||
private SSLContext sc;
|
|
||||||
|
|
||||||
public static HttpSslSupport getInstance() {
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HttpSslSupport custom() {
|
|
||||||
return new HttpSslSupport();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重写 X509TrustManager 和 HostnameVerifier,信任所有证书与主机名。
|
|
||||||
* 仅推荐在内部环境或调试场景使用。
|
|
||||||
*/
|
|
||||||
private static class SSLHandler implements X509TrustManager, HostnameVerifier {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
|
||||||
return new java.security.cert.X509Certificate[]{};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkServerTrusted(java.security.cert.X509Certificate[] chain,
|
|
||||||
String authType) throws CertificateException {
|
|
||||||
// 信任所有服务器证书
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkClientTrusted(java.security.cert.X509Certificate[] chain,
|
|
||||||
String authType) throws CertificateException {
|
|
||||||
// 信任所有客户端证书
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean verify(String paramString, SSLSession paramSSLSession) {
|
|
||||||
// 信任所有主机名
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取默认 HostnameVerifier(信任所有主机名)
|
|
||||||
*/
|
|
||||||
public static HostnameVerifier getVerifier() {
|
|
||||||
return SIMPLE_VERIFIER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取信任所有证书的 {@link SSLSocketFactory}
|
|
||||||
*/
|
|
||||||
public synchronized SSLSocketFactory getSSLSF(SSLProtocolVersion sslpv) {
|
|
||||||
if (sslFactory != null) {
|
|
||||||
return sslFactory;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
SSLContext context = getSSLContext(sslpv);
|
|
||||||
context.init(null, new TrustManager[]{SIMPLE_VERIFIER}, null);
|
|
||||||
sslFactory = context.getSocketFactory();
|
|
||||||
return sslFactory;
|
|
||||||
} catch (KeyManagementException e) {
|
|
||||||
throw new RuntimeException("初始化 SSLSocketFactory 失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取信任所有证书的 {@link SSLConnectionSocketFactory}(HttpClient5)
|
|
||||||
*
|
|
||||||
* 注意:SSLConnectionSocketFactory 在 HttpClient 5 中被标记为 deprecated,
|
|
||||||
* 但这是目前唯一可用的方式,新的 API 尚未稳定
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public synchronized SSLConnectionSocketFactory getSSLCONNSF(SSLProtocolVersion sslpv) {
|
|
||||||
if (sslConnFactory != null) {
|
|
||||||
return sslConnFactory;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
SSLContext context = getSSLContext(sslpv);
|
|
||||||
context.init(null, new TrustManager[]{SIMPLE_VERIFIER}, new java.security.SecureRandom());
|
|
||||||
sslConnFactory = new SSLConnectionSocketFactory(context, SIMPLE_VERIFIER);
|
|
||||||
return sslConnFactory;
|
|
||||||
} catch (KeyManagementException e) {
|
|
||||||
throw new RuntimeException("初始化 SSLConnectionSocketFactory 失败", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用自定义证书(trustStore)初始化 SSLContext
|
|
||||||
*/
|
|
||||||
public HttpSslSupport customSSL(String keyStorePath, String keyStorepass) {
|
|
||||||
FileInputStream instream = null;
|
|
||||||
try {
|
|
||||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
||||||
instream = new FileInputStream(new File(keyStorePath));
|
|
||||||
trustStore.load(instream, keyStorepass.toCharArray());
|
|
||||||
// 相信自己的 CA 和所有自签名证书
|
|
||||||
this.sc = SSLContexts.custom()
|
|
||||||
.loadTrustMaterial(trustStore, (chain, authType) -> true)
|
|
||||||
.build();
|
|
||||||
return this;
|
|
||||||
} catch (KeyManagementException | KeyStoreException |
|
|
||||||
NoSuchAlgorithmException | CertificateException | IOException e) {
|
|
||||||
throw new RuntimeException("初始化自定义 SSLContext 失败", e);
|
|
||||||
} finally {
|
|
||||||
if (instream != null) {
|
|
||||||
try {
|
|
||||||
instream.close();
|
|
||||||
} catch (IOException ignore) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取(或创建)指定协议版本的 {@link SSLContext}
|
|
||||||
*/
|
|
||||||
public SSLContext getSSLContext(SSLProtocolVersion sslpv) {
|
|
||||||
try {
|
|
||||||
if (this.sc == null) {
|
|
||||||
this.sc = SSLContext.getInstance(sslpv.getName());
|
|
||||||
}
|
|
||||||
return this.sc;
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException("不支持的 SSL 协议版本: " + sslpv.getName(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 支持的 SSL/TLS 协议版本枚举
|
|
||||||
*/
|
|
||||||
public enum SSLProtocolVersion {
|
|
||||||
SSL("SSL"),
|
|
||||||
SSLv3("SSLv3"),
|
|
||||||
TLSv1("TLSv1"),
|
|
||||||
TLSv1_1("TLSv1.1"),
|
|
||||||
TLSv1_2("TLSv1.2"),
|
|
||||||
TLSv1_3("TLSv1.3");
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
SSLProtocolVersion(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return this.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SSLProtocolVersion find(String name) {
|
|
||||||
for (SSLProtocolVersion pv : SSLProtocolVersion.values()) {
|
|
||||||
if (pv.getName().equalsIgnoreCase(name)) {
|
|
||||||
return pv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("未支持当前 SSL 版本号:" + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,9 @@ package com.mgm.mcrm.apigateway.common.listener;
|
|||||||
|
|
||||||
import com.mgm.mcrm.apigateway.allotment.services.RoomCriteriaDaylightService;
|
import com.mgm.mcrm.apigateway.allotment.services.RoomCriteriaDaylightService;
|
||||||
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
||||||
|
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
||||||
import com.mgm.mcrm.apigateway.common.utils.NotificationUtil;
|
import com.mgm.mcrm.apigateway.common.utils.NotificationUtil;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.common.httpclient.HttpSslSupport;
|
||||||
import com.mgm.mcrm.apigateway.daylight.repositories.CfgCompRuleDao;
|
import com.mgm.mcrm.apigateway.daylight.repositories.CfgCompRuleDao;
|
||||||
import com.mgm.mcrm.apigateway.daylight.services.DaylightApiService;
|
import com.mgm.mcrm.apigateway.daylight.services.DaylightApiService;
|
||||||
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl.AvailableRoomCountUpdatedHandler;
|
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl.AvailableRoomCountUpdatedHandler;
|
||||||
@@ -15,7 +17,10 @@ import com.mgm.mcrm.apigateway.notification.services.ApnNotificationService;
|
|||||||
import com.mgm.mcrm.apigateway.reservation.repositories.BookingDao;
|
import com.mgm.mcrm.apigateway.reservation.repositories.BookingDao;
|
||||||
import com.mgm.mcrm.apigateway.reservation.services.BookingService;
|
import com.mgm.mcrm.apigateway.reservation.services.BookingService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||||
|
import org.springframework.boot.ssl.SslBundles;
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -28,16 +33,12 @@ public class ConfigListener implements ApplicationListener<ApplicationStartedEve
|
|||||||
private BookingService bookingService;
|
private BookingService bookingService;
|
||||||
@Resource
|
@Resource
|
||||||
private DaylightApiService daylightApiService;
|
private DaylightApiService daylightApiService;
|
||||||
@Resource
|
|
||||||
private CfgCompRuleDao cfgCompRuleDao;
|
@Autowired
|
||||||
@Resource
|
private SslBundles sslBundles;
|
||||||
private BookingDao bookingDao;
|
|
||||||
@Resource
|
@Autowired
|
||||||
private SysLogDeviceTokenRepository sysLogDeviceTokenRepository;
|
private DaylightApiSetting daylightApiSetting;
|
||||||
@Resource
|
|
||||||
private NotificationUtil notificationUtil;
|
|
||||||
@Resource
|
|
||||||
private ApnNotificationService apnNotificationService;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(ApplicationStartedEvent event) {
|
public void onApplicationEvent(ApplicationStartedEvent event) {
|
||||||
@@ -48,16 +49,14 @@ public class ConfigListener implements ApplicationListener<ApplicationStartedEve
|
|||||||
DaylightWebhookFactory.registerHandler("AvailableRoomCountUpdated", new AvailableRoomCountUpdatedHandler(roomCriteriaDaylightService));
|
DaylightWebhookFactory.registerHandler("AvailableRoomCountUpdated", new AvailableRoomCountUpdatedHandler(roomCriteriaDaylightService));
|
||||||
//--Register Reservation Notification handlers
|
//--Register Reservation Notification handlers
|
||||||
DaylightWebhookFactory.registerHandler("ReservationNotification", new ReservationNotificationHandler(bookingService, daylightApiService));
|
DaylightWebhookFactory.registerHandler("ReservationNotification", new ReservationNotificationHandler(bookingService, daylightApiService));
|
||||||
DaylightWebhookFactory.registerHandler(
|
|
||||||
"ComplimentaryRuleLimitsExceededChangedNotification",
|
try{
|
||||||
new CompRuleLimitsExceededChangedHandler(
|
HttpSslSupport.setSkipValidation(daylightApiSetting.isSkipTrustValidation());
|
||||||
cfgCompRuleDao,
|
if(StringUtils.isNotBlank(daylightApiSetting.getSslBundleName())){
|
||||||
bookingDao,
|
HttpSslSupport.setSslBundle(sslBundles.getBundle(daylightApiSetting.getSslBundleName()));
|
||||||
sysLogDeviceTokenRepository,
|
}
|
||||||
notificationUtil,
|
}catch(Exception ignore){
|
||||||
apnNotificationService,
|
|
||||||
daylightApiService
|
}
|
||||||
)
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.common.services;
|
||||||
|
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
public class ConfigurableTrustHandler implements X509TrustManager {
|
||||||
|
private final boolean skipValidation;
|
||||||
|
private final X509TrustManager defaultTrustManager;
|
||||||
|
|
||||||
|
public ConfigurableTrustHandler(boolean skipValidation, X509TrustManager defaultTrustManager) {
|
||||||
|
this.skipValidation = skipValidation;
|
||||||
|
this.defaultTrustManager = defaultTrustManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||||
|
if (skipValidation) {
|
||||||
|
return new java.security.cert.X509Certificate[0];
|
||||||
|
}else{
|
||||||
|
return defaultTrustManager != null ? defaultTrustManager.getAcceptedIssuers() : new java.security.cert.X509Certificate[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(java.security.cert.X509Certificate[] chain,
|
||||||
|
String authType) throws java.security.cert.CertificateException {
|
||||||
|
if (!skipValidation && defaultTrustManager != null) {
|
||||||
|
defaultTrustManager.checkServerTrusted(chain, authType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(java.security.cert.X509Certificate[] chain,
|
||||||
|
String authType) throws java.security.cert.CertificateException {
|
||||||
|
if (!skipValidation && defaultTrustManager != null) {
|
||||||
|
defaultTrustManager.checkClientTrusted(chain, authType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,19 @@
|
|||||||
package com.mgm.mcrm.apigateway.common.utils;
|
package com.mgm.mcrm.apigateway.common.utils;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.text.StringEscapeUtils;
|
import org.apache.commons.text.StringEscapeUtils;
|
||||||
import org.springframework.web.util.UriUtils;
|
import org.springframework.web.util.UriUtils;
|
||||||
|
|
||||||
public class NetworkUtil {
|
public class NetworkUtil {
|
||||||
private static final List<String> interalIpPatterns = new ArrayList<String>();
|
private static final List<String> interalIpPatterns = new ArrayList<>();
|
||||||
private static final Pattern IPV4_PATTERN =
|
private static final Pattern IPV4_PATTERN =
|
||||||
Pattern.compile("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
|
Pattern.compile("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
|
||||||
private static final List<String> INTERNAL_IP_PREFIXES = Arrays.asList(
|
private static final List<String> INTERNAL_IP_PREFIXES = Arrays.asList(
|
||||||
@@ -24,6 +21,13 @@ public class NetworkUtil {
|
|||||||
"172.20.", "172.21.", "172.22.", "172.23.", "172.24.", "172.25.",
|
"172.20.", "172.21.", "172.22.", "172.23.", "172.24.", "172.25.",
|
||||||
"172.26.", "172.27.", "172.28.", "172.29.", "172.30.", "172.31."
|
"172.26.", "172.27.", "172.28.", "172.29.", "172.30.", "172.31."
|
||||||
);
|
);
|
||||||
|
private static final Set<String> ALLOWED_PROTOCOLS = new HashSet<>(
|
||||||
|
Arrays.asList("http", "https")
|
||||||
|
);
|
||||||
|
// 禁止的端口
|
||||||
|
private static final Set<Integer> BLOCKED_PORTS = new HashSet<>(
|
||||||
|
Arrays.asList(22, 23, 25, 53, 110, 143, 3306, 5432, 6379, 27017)
|
||||||
|
);
|
||||||
|
|
||||||
public static void setInternalIpPattern(String patternConfig) {
|
public static void setInternalIpPattern(String patternConfig) {
|
||||||
interalIpPatterns.clear();
|
interalIpPatterns.clear();
|
||||||
@@ -196,22 +200,22 @@ public class NetworkUtil {
|
|||||||
// 外网IP
|
// 外网IP
|
||||||
String netip = null;
|
String netip = null;
|
||||||
try {
|
try {
|
||||||
Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces();
|
Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||||
InetAddress ip = null;
|
InetAddress ip = null;
|
||||||
// 是否找到外网IP
|
// 是否找到外网IP
|
||||||
boolean finded = false;
|
boolean finded = false;
|
||||||
while (netInterfaces.hasMoreElements() && !finded) {
|
while (netInterfaces.hasMoreElements() && !finded) {
|
||||||
NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
|
NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
|
||||||
Enumeration address = ni.getInetAddresses();
|
Enumeration<InetAddress> address = ni.getInetAddresses();
|
||||||
while (address.hasMoreElements()) {
|
while (address.hasMoreElements()) {
|
||||||
ip = (InetAddress) address.nextElement();
|
ip = (InetAddress) address.nextElement();
|
||||||
if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {
|
if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && !ip.getHostAddress().contains(":")) {
|
||||||
// 外网IP
|
// 外网IP
|
||||||
netip = ip.getHostAddress();
|
netip = ip.getHostAddress();
|
||||||
finded = true;
|
finded = true;
|
||||||
break;
|
break;
|
||||||
} else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress()
|
} else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress()
|
||||||
&& ip.getHostAddress().indexOf(":") == -1) {
|
&& !ip.getHostAddress().contains(":")) {
|
||||||
// 内网IP
|
// 内网IP
|
||||||
localip = ip.getHostAddress();
|
localip = ip.getHostAddress();
|
||||||
}
|
}
|
||||||
@@ -316,40 +320,106 @@ public class NetworkUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isValidURL(String requestUrl){
|
public static String sanitizeCRLF(String input){
|
||||||
|
if(input==null)
|
||||||
|
return null;
|
||||||
|
return input.replaceAll("[\r\n]+", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String validateAndSanitizeUrl(String userInputUrl) throws SecurityException {
|
||||||
|
if (userInputUrl == null || userInputUrl.trim().isEmpty()) {
|
||||||
|
throw new SecurityException("URL should not be blank");
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
URI uri = new URI(requestUrl);
|
// 1. 解析URL
|
||||||
String scheme = uri.getScheme();
|
URL url = new URI(userInputUrl).toURL();
|
||||||
String host = uri.getHost();
|
|
||||||
if(!"https".equals(scheme) && !"http".equals(scheme)) {
|
// 2. 验证协议
|
||||||
return false;
|
validateProtocol(url.getProtocol());
|
||||||
|
|
||||||
|
// 3. 验证主机名/IP
|
||||||
|
String host = url.getHost();
|
||||||
|
validateHost(host);
|
||||||
|
|
||||||
|
// 4. 验证端口
|
||||||
|
int port = url.getPort();
|
||||||
|
if (port == -1) {
|
||||||
|
port = url.getDefaultPort();
|
||||||
}
|
}
|
||||||
if(host.matches("\\d+\\.\\d+\\.\\d+\\.\\d+")) {
|
validatePort(port);
|
||||||
return false;
|
|
||||||
}
|
// 5. 验证路径(防止路径遍历)
|
||||||
return true;
|
validatePath(url.getPath());
|
||||||
|
|
||||||
|
// 6. 返回净化后的URL(标准化)
|
||||||
|
return sanitizeUrl(url);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return false;
|
throw new SecurityException("Invalid URL: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String encodeParaWithSpring(String value) {
|
private static void validateProtocol(String protocol) throws SecurityException {
|
||||||
if(value==null)
|
if (!ALLOWED_PROTOCOLS.contains(protocol.toLowerCase())) {
|
||||||
value="";
|
throw new SecurityException("No support protocol: " + protocol + ", only for HTTP/HTTPS");
|
||||||
value= value.replace("\r", "").replace("\n", "");
|
}
|
||||||
return UriUtils.encode(value, StandardCharsets.UTF_8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String sanitizeHeaderValue(String headerValue) {
|
private static void validateHost(String host) throws SecurityException {
|
||||||
return headerValue==null? null :(StringEscapeUtils.escapeJava(
|
if (host == null || host.isEmpty()) {
|
||||||
headerValue.replace("\r", "").replace("\n", "")
|
throw new SecurityException("Host name can not be empty");
|
||||||
));
|
}
|
||||||
|
|
||||||
|
// 解析IP并验证
|
||||||
|
try {
|
||||||
|
InetAddress address = InetAddress.getByName(host);
|
||||||
|
String ip = address.getHostAddress();
|
||||||
|
|
||||||
|
if (address.isLoopbackAddress()) {
|
||||||
|
throw new SecurityException("Forbit loopback address");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
throw new SecurityException("Invalid host: " + host);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String encodePathWithSpring(String value) {
|
private static void validatePort(int port) throws SecurityException {
|
||||||
if(value==null)
|
// 检查是否为禁止端口
|
||||||
value="";
|
if (BLOCKED_PORTS.contains(port)) {
|
||||||
value= value.replace("\r", "").replace("\n", "");
|
throw new SecurityException("Invalid Port: " + port);
|
||||||
return UriUtils.encodePath(value, StandardCharsets.UTF_8);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void validatePath(String path) throws SecurityException {
|
||||||
|
if (path == null) return;
|
||||||
|
|
||||||
|
// 防止路径遍历攻击
|
||||||
|
if (path.contains("..")) {
|
||||||
|
throw new SecurityException("Invalid path contains '..'");
|
||||||
|
}
|
||||||
|
if (path.toLowerCase().contains("://")) {
|
||||||
|
throw new SecurityException("Invalid path prefix");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String sanitizeUrl(URL url) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(url.getProtocol()).append("://");
|
||||||
|
sb.append(url.getHost());
|
||||||
|
|
||||||
|
int port = url.getPort();
|
||||||
|
if (port != -1 && port != url.getDefaultPort()) {
|
||||||
|
sb.append(":").append(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(url.getPath());
|
||||||
|
|
||||||
|
String query = url.getQuery();
|
||||||
|
if (query != null && !query.isEmpty()) {
|
||||||
|
sb.append("?").append(query);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ public class HttpUtilMockup {
|
|||||||
|
|
||||||
private static boolean matchCondiction(JSONObject requestObj, String condiction) {
|
private static boolean matchCondiction(JSONObject requestObj, String condiction) {
|
||||||
boolean matchResult = false;
|
boolean matchResult = false;
|
||||||
List<String> operateList = new ArrayList<String>();
|
List<String> operateList = new ArrayList<>();
|
||||||
String[] andList = condiction.split("&&");
|
String[] andList = condiction.split("&&");
|
||||||
for(int i=0;i<andList.length;i++) {
|
for(int i=0;i<andList.length;i++) {
|
||||||
if(i>0) {
|
if(i>0) {
|
||||||
@@ -126,26 +126,25 @@ public class HttpUtilMockup {
|
|||||||
}
|
}
|
||||||
String lastOperate = "AND";
|
String lastOperate = "AND";
|
||||||
boolean isFirst =true;
|
boolean isFirst =true;
|
||||||
for(int i=0;i<operateList.size();i++) {
|
for (String express : operateList) {
|
||||||
String express = operateList.get(i);
|
if (express.equals("&&")) {
|
||||||
if(express.equals("&&")) {
|
lastOperate = "AND";
|
||||||
lastOperate = "AND";
|
} else if (express.equals("||")) {
|
||||||
}else if(express.equals("||")) {
|
lastOperate = "OR";
|
||||||
lastOperate = "OR";
|
} else {
|
||||||
}else {
|
boolean valRes = calcCondictionValue(requestObj, express);
|
||||||
boolean valRes = calcCondictionValue(requestObj, express);
|
if (isFirst) {
|
||||||
if(isFirst==true) {
|
matchResult = matchResult || valRes;
|
||||||
matchResult=matchResult||valRes;
|
isFirst = false;
|
||||||
isFirst=false;
|
} else {
|
||||||
}else {
|
if (lastOperate.equals("AND")) {
|
||||||
if(lastOperate.equals("AND")) {
|
matchResult = matchResult && valRes;
|
||||||
matchResult=matchResult&&valRes;
|
} else {
|
||||||
}else {
|
matchResult = matchResult || valRes;
|
||||||
matchResult=matchResult||valRes;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return matchResult;
|
return matchResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,18 +211,15 @@ public class HttpUtilMockup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(isNum==true) {
|
if(isNum) {
|
||||||
if(operate.equals("==")) {
|
result = switch (operate) {
|
||||||
result = (numVal1==numVal2);
|
case "==" -> (numVal1 == numVal2);
|
||||||
}else if(operate.equals("<=")) {
|
case "<=" -> (numVal1 <= numVal2);
|
||||||
result = (numVal1<=numVal2);
|
case ">=" -> (numVal1 >= numVal2);
|
||||||
}else if(operate.equals(">=")) {
|
case "<" -> (numVal1 < numVal2);
|
||||||
result = (numVal1>=numVal2);
|
case ">" -> (numVal1 > numVal2);
|
||||||
}else if(operate.equals("<")) {
|
default -> result;
|
||||||
result = (numVal1<numVal2);
|
};
|
||||||
}else if(operate.equals(">")) {
|
|
||||||
result = (numVal1>numVal2);
|
|
||||||
}
|
|
||||||
}else {
|
}else {
|
||||||
String textVal1 = valName1;
|
String textVal1 = valName1;
|
||||||
String textVal2 = valName2;
|
String textVal2 = valName2;
|
||||||
@@ -233,17 +229,14 @@ public class HttpUtilMockup {
|
|||||||
if(requestObj.containsKey(valName2)) {
|
if(requestObj.containsKey(valName2)) {
|
||||||
textVal2 = requestObj.getString(valName2);
|
textVal2 = requestObj.getString(valName2);
|
||||||
}
|
}
|
||||||
if(operate.equals("==")) {
|
result = switch (operate) {
|
||||||
result = (textVal1.compareTo(textVal2)==0);
|
case "==" -> (textVal1.compareTo(textVal2) == 0);
|
||||||
}else if(operate.equals("<=")) {
|
case "<=" -> (textVal1.compareTo(textVal2) <= 0);
|
||||||
result = (textVal1.compareTo(textVal2)<=0);
|
case ">=" -> (textVal1.compareTo(textVal2) >= 0);
|
||||||
}else if(operate.equals(">=")) {
|
case "<" -> (textVal1.compareTo(textVal2) < 0);
|
||||||
result = (textVal1.compareTo(textVal2)>=0);
|
case ">" -> (textVal1.compareTo(textVal2) > 0);
|
||||||
}else if(operate.equals("<")) {
|
default -> result;
|
||||||
result = (textVal1.compareTo(textVal2)<0);
|
};
|
||||||
}else if(operate.equals(">")) {
|
|
||||||
result = (textVal1.compareTo(textVal2)>0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
+78
-79
@@ -85,86 +85,91 @@ public class HttpEntityBuilder {
|
|||||||
if(map!=null && map.size()>0){
|
if(map!=null && map.size()>0){
|
||||||
boolean isSpecial = false;
|
boolean isSpecial = false;
|
||||||
// 拼接参数
|
// 拼接参数
|
||||||
|
label:
|
||||||
for (Entry<String, Object> entry : map.entrySet()) {
|
for (Entry<String, Object> entry : map.entrySet()) {
|
||||||
if(SPECIAL_ENTITIY.contains(entry.getKey())){//判断是否在之中
|
if(SPECIAL_ENTITIY.contains(entry.getKey())){//判断是否在之中
|
||||||
isSpecial = true;
|
isSpecial = true;
|
||||||
if(ENTITY_STRING.equals(entry.getKey())){//string
|
switch (entry.getKey()) {
|
||||||
entity = new StringEntity(String.valueOf(entry.getValue()), Charset.forName(encoding));
|
case ENTITY_STRING: //string
|
||||||
break;
|
entity = new StringEntity(String.valueOf(entry.getValue()), Charset.forName(encoding));
|
||||||
}else if(ENTITY_JSON.equals(entry.getKey())){//json
|
break label;
|
||||||
ContentType jsonContentType;
|
case ENTITY_JSON: //json
|
||||||
|
ContentType jsonContentType;
|
||||||
|
|
||||||
entity = new StringEntity(String.valueOf(entry.getValue()), Charset.forName(encoding));
|
entity = new StringEntity(String.valueOf(entry.getValue()), Charset.forName(encoding));
|
||||||
String contentType = "application/json";
|
String contentType = "application/json";
|
||||||
if (encoding != null && !encoding.trim().isEmpty()) {
|
if (encoding != null && !encoding.trim().isEmpty()) {
|
||||||
// 创建带有编码的JSON ContentType
|
// 创建带有编码的JSON ContentType
|
||||||
jsonContentType = ContentType.APPLICATION_JSON.withCharset(Charset.forName(encoding));
|
jsonContentType = ContentType.APPLICATION_JSON.withCharset(Charset.forName(encoding));
|
||||||
}else {
|
} else {
|
||||||
// 使用默认的JSON ContentType(通常UTF-8)
|
// 使用默认的JSON ContentType(通常UTF-8)
|
||||||
jsonContentType = ContentType.APPLICATION_JSON;
|
jsonContentType = ContentType.APPLICATION_JSON;
|
||||||
}
|
|
||||||
// 创建实体时直接传入ContentType
|
|
||||||
entity = new StringEntity(String.valueOf(entry.getValue()), jsonContentType);
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_BYTES.equals(entry.getKey())){//file
|
|
||||||
byte[] data = (byte[]) entry.getValue();
|
|
||||||
entity = new ByteArrayEntity(data, ContentType.APPLICATION_OCTET_STREAM);
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_FILE.equals(entry.getKey())){//file
|
|
||||||
if(File.class.isAssignableFrom(entry.getValue().getClass())){
|
|
||||||
entity = new FileEntity((File)entry.getValue(), ContentType.APPLICATION_OCTET_STREAM);
|
|
||||||
}else if(entry.getValue().getClass()==String.class){
|
|
||||||
entity = new FileEntity(new File((String) entry.getValue()), ContentType.create("text/plain", "UTF-8"));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_INPUTSTREAM.equals(entry.getKey())){//inputstream
|
|
||||||
// entity = new InputStreamEntity();
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_SERIALIZABLE.equals(entry.getKey())){//serializeable
|
|
||||||
// entity = new SerializableEntity()
|
|
||||||
break;
|
|
||||||
}else if(ENTITY_MULTIPART.equals(entry.getKey())){//MultipartEntityBuilder
|
|
||||||
File[] files = null;
|
|
||||||
if(File.class.isAssignableFrom(entry.getValue().getClass().getComponentType())){
|
|
||||||
files=(File[])entry.getValue();
|
|
||||||
}else if(entry.getValue().getClass().getComponentType()==String.class){
|
|
||||||
String[] names = (String[]) entry.getValue();
|
|
||||||
files = new File[names.length];
|
|
||||||
for (int i = 0; i < names.length; i++) {
|
|
||||||
files[i] = new File(names[i]);
|
|
||||||
}
|
}
|
||||||
}
|
// 创建实体时直接传入ContentType
|
||||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
entity = new StringEntity(String.valueOf(entry.getValue()), jsonContentType);
|
||||||
builder.setCharset(Charset.forName(encoding));// 设置请求的编码格式
|
break label;
|
||||||
builder.setMode(HttpMultipartMode.LEGACY);// 设置浏览器兼容模式
|
case ENTITY_BYTES: //file
|
||||||
int count = 0;
|
byte[] data = (byte[]) entry.getValue();
|
||||||
for (File file : files) {
|
entity = new ByteArrayEntity(data, ContentType.APPLICATION_OCTET_STREAM);
|
||||||
|
break label;
|
||||||
|
case ENTITY_FILE: //file
|
||||||
|
if (File.class.isAssignableFrom(entry.getValue().getClass())) {
|
||||||
|
entity = new FileEntity((File) entry.getValue(), ContentType.APPLICATION_OCTET_STREAM);
|
||||||
|
} else if (entry.getValue().getClass() == String.class) {
|
||||||
|
entity = new FileEntity(new File((String) entry.getValue()), ContentType.create("text/plain", "UTF-8"));
|
||||||
|
}
|
||||||
|
break label;
|
||||||
|
case ENTITY_INPUTSTREAM: //input stream
|
||||||
|
// entity = new InputStreamEntity();
|
||||||
|
break label;
|
||||||
|
case ENTITY_SERIALIZABLE: //serializable
|
||||||
|
// entity = new SerializableEntity()
|
||||||
|
break label;
|
||||||
|
case ENTITY_MULTIPART: //MultipartEntityBuilder
|
||||||
|
File[] files = null;
|
||||||
|
if (File.class.isAssignableFrom(entry.getValue().getClass().getComponentType())) {
|
||||||
|
files = (File[]) entry.getValue();
|
||||||
|
} else if (entry.getValue().getClass().getComponentType() == String.class) {
|
||||||
|
String[] names = (String[]) entry.getValue();
|
||||||
|
files = new File[names.length];
|
||||||
|
for (int i = 0; i < names.length; i++) {
|
||||||
|
files[i] = new File(names[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||||
|
builder.setCharset(Charset.forName(encoding));// 设置请求的编码格式
|
||||||
|
|
||||||
|
builder.setMode(HttpMultipartMode.LEGACY);// 设置浏览器兼容模式
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for (File file : files) {
|
||||||
// //把文件转换成流对象FileBody
|
// //把文件转换成流对象FileBody
|
||||||
// FileBody fileBody = new FileBody(file);
|
// FileBody fileBody = new FileBody(file);
|
||||||
// builder.addPart(String.valueOf(map.get(ENTITY_MULTIPART+".name")) + count++, fileBody);
|
// builder.addPart(String.valueOf(map.get(ENTITY_MULTIPART+".name")) + count++, fileBody);
|
||||||
builder.addBinaryBody(String.valueOf(map.get(ENTITY_MULTIPART+".name")) + count++,file);
|
builder.addBinaryBody(String.valueOf(map.get(ENTITY_MULTIPART + ".name")) + count++, file);
|
||||||
}
|
}
|
||||||
boolean forceRemoveContentTypeCharset = (boolean)map.get(ENTITY_MULTIPART+".rmCharset");
|
boolean forceRemoveContentTypeCharset = (boolean) map.get(ENTITY_MULTIPART + ".rmCharset");
|
||||||
Map<String, Object> m = new HashMap<String, Object>();
|
Map<String, Object> m = new HashMap<>();
|
||||||
m.putAll(map);
|
m.putAll(map);
|
||||||
m.remove(ENTITY_MULTIPART);
|
m.remove(ENTITY_MULTIPART);
|
||||||
m.remove(ENTITY_MULTIPART+".name");
|
m.remove(ENTITY_MULTIPART + ".name");
|
||||||
m.remove(ENTITY_MULTIPART+".rmCharset");
|
m.remove(ENTITY_MULTIPART + ".rmCharset");
|
||||||
Iterator<Entry<String, Object>> iterator = m.entrySet().iterator();
|
// 发送的数据
|
||||||
// 发送的数据
|
for (Entry<String, Object> e : m.entrySet()) {
|
||||||
while (iterator.hasNext()) {
|
builder.addTextBody(e.getKey(), String.valueOf(e.getValue()), ContentType.create("text/plain", encoding));
|
||||||
Entry<String, Object> e = iterator.next();
|
}
|
||||||
builder.addTextBody(e.getKey(), String.valueOf(e.getValue()), ContentType.create("text/plain", encoding));
|
entity = builder.build();// 生成 HTTP POST 实体
|
||||||
}
|
|
||||||
entity = builder.build();// 生成 HTTP POST 实体
|
|
||||||
|
|
||||||
//强制去除contentType中的编码设置,否则,在某些情况下会导致上传失败
|
|
||||||
if(forceRemoveContentTypeCharset){
|
//强制去除contentType中的编码设置,否则,在某些情况下会导致上传失败
|
||||||
removeContentTypeCharset(encoding, entity);
|
if (forceRemoveContentTypeCharset) {
|
||||||
}
|
removeContentTypeCharset(encoding, entity);
|
||||||
break;
|
}
|
||||||
}else {
|
break label;
|
||||||
nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
|
case null:
|
||||||
|
default:
|
||||||
|
nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
|
nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
|
||||||
@@ -195,13 +200,7 @@ public class HttpEntityBuilder {
|
|||||||
}
|
}
|
||||||
BasicHeader o = (BasicHeader) field.get(entity);
|
BasicHeader o = (BasicHeader) field.get(entity);
|
||||||
field.set(entity, new BasicHeader(HttpHeaders.CONTENT_TYPE, o.getValue().replace("; charset="+encoding,"")));
|
field.set(entity, new BasicHeader(HttpHeaders.CONTENT_TYPE, o.getValue().replace("; charset="+encoding,"")));
|
||||||
} catch (NoSuchFieldException e) {
|
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
||||||
HttpEntityBuilder.exception(e);
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
HttpEntityBuilder.exception(e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
HttpEntityBuilder.exception(e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
HttpEntityBuilder.exception(e);
|
HttpEntityBuilder.exception(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,7 +235,7 @@ public class HttpEntityBuilder {
|
|||||||
*/
|
*/
|
||||||
public static Map<String,Object> buildParas(String[][] paras){
|
public static Map<String,Object> buildParas(String[][] paras){
|
||||||
// 创建参数队列
|
// 创建参数队列
|
||||||
Map<String,Object> map = new HashMap<String, Object>();
|
Map<String,Object> map = new HashMap<>();
|
||||||
for (String[] para: paras) {
|
for (String[] para: paras) {
|
||||||
map.put(para[0], para[1]);
|
map.put(para[0], para[1]);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
package com.mgm.mcrm.apigateway.common.httpclient;
|
package com.mgm.mcrm.apigateway.daylight.common.httpclient;
|
||||||
|
|
||||||
|
|
||||||
import com.mgm.mcrm.apigateway.common.config.HttpHeader;
|
import com.mgm.mcrm.apigateway.common.config.HttpHeader;
|
||||||
@@ -25,7 +25,7 @@ public class HttpHeaderBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//记录head头信息
|
//记录head头信息
|
||||||
private Map<String, Header> headerMaps = new HashMap<String, Header>();
|
private Map<String, Header> headerMaps = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义header头信息
|
* 自定义header头信息
|
||||||
+4
-19
@@ -85,17 +85,17 @@ public class HttpRequestOptions {
|
|||||||
/**
|
/**
|
||||||
* 解决多线程下载时,strean被close的问题
|
* 解决多线程下载时,strean被close的问题
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<OutputStream> outs = new ThreadLocal<OutputStream>();
|
private static final ThreadLocal<OutputStream> outs = new ThreadLocal<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解决多线程处理时,url被覆盖问题
|
* 解决多线程处理时,url被覆盖问题
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<String> urls = new ThreadLocal<String>();
|
private static final ThreadLocal<String> urls = new ThreadLocal<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解决多线程处理时,url被覆盖问题
|
* 解决多线程处理时,url被覆盖问题
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<Map<String,Object>> maps = new ThreadLocal<Map<String,Object>>();
|
private static final ThreadLocal<Map<String,Object>> maps = new ThreadLocal<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param client HttpClient对象
|
* @param client HttpClient对象
|
||||||
@@ -169,13 +169,6 @@ public class HttpRequestOptions {
|
|||||||
* @return 返回当前对象
|
* @return 返回当前对象
|
||||||
*/
|
*/
|
||||||
public HttpRequestOptions map(Map<String, Object> map) {
|
public HttpRequestOptions map(Map<String, Object> map) {
|
||||||
// synchronized (getClass()) {
|
|
||||||
// if(this.map==null || map==null){
|
|
||||||
// this.map = map;
|
|
||||||
// }else {
|
|
||||||
// this.map.putAll(map);;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
Map<String, Object> m = maps.get();
|
Map<String, Object> m = maps.get();
|
||||||
if(m == null || map.isEmpty()){
|
if(m == null || map.isEmpty()){
|
||||||
m = map;
|
m = map;
|
||||||
@@ -222,18 +215,10 @@ public class HttpRequestOptions {
|
|||||||
* @return 返回当前对象
|
* @return 返回当前对象
|
||||||
*/
|
*/
|
||||||
public HttpRequestOptions files(String[] filePaths, String inputName, boolean forceRemoveContentTypeChraset) {
|
public HttpRequestOptions files(String[] filePaths, String inputName, boolean forceRemoveContentTypeChraset) {
|
||||||
// synchronized (getClass()) {
|
|
||||||
// if(this.map==null){
|
|
||||||
// this.map= new HashMap<String, Object>();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// map.put(Utils.ENTITY_MULTIPART, filePaths);
|
|
||||||
// map.put(Utils.ENTITY_MULTIPART+".name", inputName);
|
|
||||||
// map.put(Utils.ENTITY_MULTIPART+".rmCharset", forceRemoveContentTypeChraset);
|
|
||||||
|
|
||||||
Map<String, Object> m = maps.get();
|
Map<String, Object> m = maps.get();
|
||||||
if(m.isEmpty()){
|
if(m.isEmpty()){
|
||||||
m = new HashMap<String, Object>();
|
m = new HashMap<>();
|
||||||
}
|
}
|
||||||
m.put(HttpEntityBuilder.ENTITY_MULTIPART, filePaths);
|
m.put(HttpEntityBuilder.ENTITY_MULTIPART, filePaths);
|
||||||
m.put(HttpEntityBuilder.ENTITY_MULTIPART+".name", inputName);
|
m.put(HttpEntityBuilder.ENTITY_MULTIPART+".name", inputName);
|
||||||
|
|||||||
+42
-39
@@ -1,7 +1,14 @@
|
|||||||
package com.mgm.mcrm.apigateway.daylight.common.httpclient;
|
package com.mgm.mcrm.apigateway.daylight.common.httpclient;
|
||||||
|
|
||||||
|
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
||||||
|
import com.mgm.mcrm.apigateway.common.services.ConfigurableTrustHandler;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
||||||
import org.apache.hc.core5.ssl.SSLContexts;
|
import org.apache.hc.core5.ssl.SSLContexts;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.ssl.SslBundle;
|
||||||
|
import org.springframework.boot.ssl.SslBundles;
|
||||||
|
|
||||||
import javax.net.ssl.*;
|
import javax.net.ssl.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -26,7 +33,16 @@ import java.security.cert.CertificateException;
|
|||||||
* @version 2.0 (client5)
|
* @version 2.0 (client5)
|
||||||
*/
|
*/
|
||||||
public class HttpSslSupport {
|
public class HttpSslSupport {
|
||||||
private static final SSLHandler SIMPLE_VERIFIER = new SSLHandler();
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private static boolean skipValidation=true;
|
||||||
|
|
||||||
|
private static ConfigurableTrustHandler trustHandler=null;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private static SslBundle sslBundle=null;
|
||||||
|
|
||||||
private static SSLSocketFactory sslFactory;
|
private static SSLSocketFactory sslFactory;
|
||||||
// 注意:SSLConnectionSocketFactory 在 HttpClient 5 中被标记为 deprecated,
|
// 注意:SSLConnectionSocketFactory 在 HttpClient 5 中被标记为 deprecated,
|
||||||
@@ -46,41 +62,13 @@ public class HttpSslSupport {
|
|||||||
return new HttpSslSupport();
|
return new HttpSslSupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 重写 X509TrustManager 和 HostnameVerifier,信任所有证书与主机名。
|
|
||||||
* 仅推荐在内部环境或调试场景使用。
|
|
||||||
*/
|
|
||||||
private static class SSLHandler implements X509TrustManager, HostnameVerifier {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
public static ConfigurableTrustHandler getTrustHandler(){
|
||||||
return new java.security.cert.X509Certificate[]{};
|
if(trustHandler==null){
|
||||||
|
trustHandler =new ConfigurableTrustHandler(skipValidation, SysCommon.getDefaultTrustManager());
|
||||||
}
|
}
|
||||||
|
return trustHandler;
|
||||||
@Override
|
|
||||||
public void checkServerTrusted(java.security.cert.X509Certificate[] chain,
|
|
||||||
String authType) throws CertificateException {
|
|
||||||
// 信任所有服务器证书
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void checkClientTrusted(java.security.cert.X509Certificate[] chain,
|
|
||||||
String authType) throws CertificateException {
|
|
||||||
// 信任所有客户端证书
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean verify(String paramString, SSLSession paramSSLSession) {
|
|
||||||
// 信任所有主机名
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取默认 HostnameVerifier(信任所有主机名)
|
|
||||||
*/
|
|
||||||
public static HostnameVerifier getVerifier() {
|
|
||||||
return SIMPLE_VERIFIER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,8 +79,15 @@ public class HttpSslSupport {
|
|||||||
return sslFactory;
|
return sslFactory;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
SSLContext context = getSSLContext(sslpv);
|
SSLContext context =null;
|
||||||
context.init(null, new TrustManager[]{SIMPLE_VERIFIER}, null);
|
if(sslBundle!=null){
|
||||||
|
context = sslBundle.createSslContext();
|
||||||
|
}else{
|
||||||
|
context = getSSLContext(sslpv);
|
||||||
|
context.init(null, new TrustManager[]{
|
||||||
|
getTrustHandler()
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
sslFactory = context.getSocketFactory();
|
sslFactory = context.getSocketFactory();
|
||||||
return sslFactory;
|
return sslFactory;
|
||||||
} catch (KeyManagementException e) {
|
} catch (KeyManagementException e) {
|
||||||
@@ -112,9 +107,17 @@ public class HttpSslSupport {
|
|||||||
return sslConnFactory;
|
return sslConnFactory;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
SSLContext context = getSSLContext(sslpv);
|
SSLContext context = null;
|
||||||
context.init(null, new TrustManager[]{SIMPLE_VERIFIER}, new java.security.SecureRandom());
|
if (sslBundle != null) {
|
||||||
sslConnFactory = new SSLConnectionSocketFactory(context, SIMPLE_VERIFIER);
|
context = sslBundle.createSslContext();
|
||||||
|
} else {
|
||||||
|
context = getSSLContext(sslpv);
|
||||||
|
ConfigurableTrustHandler trustHandler = getTrustHandler();
|
||||||
|
context.init(null, new TrustManager[]{
|
||||||
|
trustHandler
|
||||||
|
}, new java.security.SecureRandom());
|
||||||
|
}
|
||||||
|
sslConnFactory = new SSLConnectionSocketFactory(context);
|
||||||
return sslConnFactory;
|
return sslConnFactory;
|
||||||
} catch (KeyManagementException e) {
|
} catch (KeyManagementException e) {
|
||||||
throw new RuntimeException("初始化 SSLConnectionSocketFactory 失败", e);
|
throw new RuntimeException("初始化 SSLConnectionSocketFactory 失败", e);
|
||||||
|
|||||||
@@ -166,17 +166,4 @@ public class HttpService {
|
|||||||
log.info("PATCH request result={}", result);
|
log.info("PATCH request result={}", result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public HttpResult sslSendNotification(String url, Header[] headers, SendNotificationRequest request) throws Exception {
|
|
||||||
// log.info("POST method, send notification, url={}, headers={}, map={}", notificationProxyUrl + url, JSON.toJSONString(headers), JSON.toJSONString(request));
|
|
||||||
// HttpRequestOptions postConfig = HttpRequestOptions.create()
|
|
||||||
// .url(notificationProxyUrl + url)
|
|
||||||
// .timeout(requestConfig)
|
|
||||||
// .json(JSON.toJSONString(request))
|
|
||||||
// .method(HttpMethods.POST)
|
|
||||||
// .client(httpClient);
|
|
||||||
// HttpResult result = HttpClientExecutor.sendAndPostResp(postConfig, headers);
|
|
||||||
// log.info("POST request result={}", result);
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.mgm.mcrm.apigateway.daylight.services;
|
|||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
||||||
import com.mgm.mcrm.apigateway.common.httpclient.HttpHeaderBuilder;
|
import com.mgm.mcrm.apigateway.daylight.common.httpclient.HttpHeaderBuilder;
|
||||||
import com.mgm.mcrm.apigateway.daylight.common.services.HttpService;
|
import com.mgm.mcrm.apigateway.daylight.common.services.HttpService;
|
||||||
import com.mgm.mcrm.apigateway.daylight.dtos.response.CompRuleResponse;
|
import com.mgm.mcrm.apigateway.daylight.dtos.response.CompRuleResponse;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
|
|||||||
+1
-1
@@ -24,7 +24,7 @@ public class PlayerProfileApiResult {
|
|||||||
private String state;
|
private String state;
|
||||||
private String passport = null;
|
private String passport = null;
|
||||||
private String language = null;
|
private String language = null;
|
||||||
private List<Integer> nameIds=new ArrayList<Integer>();
|
private List<Integer> nameIds=new ArrayList<>();
|
||||||
|
|
||||||
public PlayerProfileApiResult() {
|
public PlayerProfileApiResult() {
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
@@ -21,6 +22,8 @@ import org.springframework.stereotype.Service;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@@ -31,21 +34,26 @@ public class EsbTokenService {
|
|||||||
private WebProxyService webProxyService;
|
private WebProxyService webProxyService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private EsbApiSetting esbApiSetting;
|
private EsbApiSetting esbApiSetting;
|
||||||
private EsbToken cachedToken = new EsbToken();
|
@Value("${mcrm.proxy.api-config.esb.api-path.mcrm}")
|
||||||
|
private String mcrmApiPath;
|
||||||
|
@Value("${mcrm.proxy.api-config.esb.api-path.limo}")
|
||||||
|
private String limoApiPath;
|
||||||
|
private final Map<String, EsbToken> cachedTokens = new HashMap<>();
|
||||||
|
|
||||||
// 重试间隔时间:1秒
|
// 重试间隔时间:1秒
|
||||||
private final long RETRY_DELAY_MS = 1000;
|
private static final long RETRY_DELAY_MS = 1000;
|
||||||
|
|
||||||
public EsbToken getApiAccessToken() throws Exception {
|
public synchronized EsbToken getApiAccessToken(String apiType) throws Exception {
|
||||||
EsbToken returnToken = null;
|
EsbToken returnToken = null;
|
||||||
int retryCnt=0;
|
int retryCnt=0;
|
||||||
boolean isNeedTry=true;
|
boolean isNeedTry=true;
|
||||||
String lastErrorMsg ="";
|
String lastErrorMsg ="";
|
||||||
|
EsbToken cachedToken = cachedTokens.get(apiType);
|
||||||
if (!isTokenExpire(cachedToken)) {
|
if (!isTokenExpire(cachedToken)) {
|
||||||
return cachedToken;
|
return cachedToken;
|
||||||
}else{
|
}else{
|
||||||
while(returnToken==null && isNeedTry && retryCnt<3){
|
while(returnToken==null && isNeedTry && retryCnt<3){
|
||||||
HttpResult requestResult = this.invokeTokenRequest();
|
HttpResult requestResult = this.invokeTokenRequest(apiType);
|
||||||
if(requestResult.getStatusCode()>=200 && requestResult.getStatusCode()<300){
|
if(requestResult.getStatusCode()>=200 && requestResult.getStatusCode()<300){
|
||||||
try{
|
try{
|
||||||
EsbToken newToken = JSON.parseObject(requestResult.getResponseBody(), EsbToken.class);
|
EsbToken newToken = JSON.parseObject(requestResult.getResponseBody(), EsbToken.class);
|
||||||
@@ -59,6 +67,7 @@ public class EsbTokenService {
|
|||||||
expiryTime = LocalDateTime.now().plusSeconds(esbApiSetting.getTokenExpireSecond());
|
expiryTime = LocalDateTime.now().plusSeconds(esbApiSetting.getTokenExpireSecond());
|
||||||
newToken.setExpireTime(expiryTime);
|
newToken.setExpireTime(expiryTime);
|
||||||
}
|
}
|
||||||
|
cachedTokens.put(apiType, newToken);
|
||||||
returnToken = newToken;
|
returnToken = newToken;
|
||||||
}
|
}
|
||||||
}catch(Exception err){
|
}catch(Exception err){
|
||||||
@@ -98,10 +107,15 @@ public class EsbTokenService {
|
|||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] buildTokenRequestBody() {
|
private byte[] buildTokenRequestBody(String apiType) {
|
||||||
JSONObject requestObj = new JSONObject();
|
JSONObject requestObj = new JSONObject();
|
||||||
requestObj.put("AppId", esbApiSetting.getAppId());
|
if("ESB_LIMO".equalsIgnoreCase(apiType)){
|
||||||
requestObj.put("AppSecret", esbApiSetting.getAppSecret());
|
requestObj.put("AppId", esbApiSetting.getAppIdLimo());
|
||||||
|
requestObj.put("AppSecret", esbApiSetting.getAppSecretLimo());
|
||||||
|
}else{
|
||||||
|
requestObj.put("AppId", esbApiSetting.getAppIdMcrm());
|
||||||
|
requestObj.put("AppSecret", esbApiSetting.getAppSecretMcrm());
|
||||||
|
}
|
||||||
return requestObj.toJSONString().getBytes(StandardCharsets.UTF_8);
|
return requestObj.toJSONString().getBytes(StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -113,11 +127,12 @@ public class EsbTokenService {
|
|||||||
/**
|
/**
|
||||||
* 发送 token 请求(单次),返回详细结果包括状态码
|
* 发送 token 请求(单次),返回详细结果包括状态码
|
||||||
*/
|
*/
|
||||||
private HttpResult invokeTokenRequest() {
|
private HttpResult invokeTokenRequest(String apiType) {
|
||||||
HttpResult result = new HttpResult();
|
HttpResult result = new HttpResult();
|
||||||
String tokenUrl =esbApiSetting.getServerUrl() + esbApiSetting.getTokenUrl();
|
String apiPath = "ESB_LIMO".equalsIgnoreCase(apiType) ? limoApiPath : mcrmApiPath;
|
||||||
|
String tokenUrl = esbApiSetting.getServerUrl() + apiPath + esbApiSetting.getTokenUrl();
|
||||||
try {
|
try {
|
||||||
byte[] requestBody = buildTokenRequestBody();
|
byte[] requestBody = buildTokenRequestBody(apiType);
|
||||||
HttpHeaders headers = buildHeaders();
|
HttpHeaders headers = buildHeaders();
|
||||||
// 构建完整的 URL
|
// 构建完整的 URL
|
||||||
ResponseEntity<byte[]> requestRes = webProxyService.invokeRequest(
|
ResponseEntity<byte[]> requestRes = webProxyService.invokeRequest(
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class MGMApiService {
|
|||||||
public HttpResult invokeGetAllPlayerProfile(String playerId) throws Exception {
|
public HttpResult invokeGetAllPlayerProfile(String playerId) throws Exception {
|
||||||
HttpResult result = new HttpResult();
|
HttpResult result = new HttpResult();
|
||||||
String apiLink = esbApiSetting.getServerUrl() + API_GET_ALL_PLAYER_PROFILE;
|
String apiLink = esbApiSetting.getServerUrl() + API_GET_ALL_PLAYER_PROFILE;
|
||||||
EsbToken esbToken = esbTokenService.getApiAccessToken();
|
EsbToken esbToken = esbTokenService.getApiAccessToken("ESB_MCRM");
|
||||||
if(esbToken==null || StringUtils.isBlank(esbToken.getAccessToken())){
|
if(esbToken==null || StringUtils.isBlank(esbToken.getAccessToken())){
|
||||||
throw new Exception("Invoke ESB token failed");
|
throw new Exception("Invoke ESB token failed");
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ public class MGMApiService {
|
|||||||
public HttpResult invokeGetUserInfo(String userId,String userName) throws Exception {
|
public HttpResult invokeGetUserInfo(String userId,String userName) throws Exception {
|
||||||
HttpResult result = new HttpResult();;
|
HttpResult result = new HttpResult();;
|
||||||
String apiLink = esbApiSetting.getServerUrl() + API_GET_USER_INFO;
|
String apiLink = esbApiSetting.getServerUrl() + API_GET_USER_INFO;
|
||||||
EsbToken esbToken = esbTokenService.getApiAccessToken();
|
EsbToken esbToken = esbTokenService.getApiAccessToken("ESB_MCRM");
|
||||||
if(esbToken==null || StringUtils.isBlank(esbToken.getAccessToken())){
|
if(esbToken==null || StringUtils.isBlank(esbToken.getAccessToken())){
|
||||||
throw new Exception("Invoke ESB token failed");
|
throw new Exception("Invoke ESB token failed");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class MgmUserService {
|
|||||||
if("OK".equals(resultCode)) {
|
if("OK".equals(resultCode)) {
|
||||||
List<UserInfoApiRecord> recrods = resultObj.getRecords();
|
List<UserInfoApiRecord> recrods = resultObj.getRecords();
|
||||||
if(!recrods.isEmpty()) {
|
if(!recrods.isEmpty()) {
|
||||||
UserInfoApiRecord user = recrods.get(0);
|
UserInfoApiRecord user = recrods.getFirst();
|
||||||
if(!"NULL".equals(user.getUserId())) {
|
if(!"NULL".equals(user.getUserId())) {
|
||||||
user = this.supplementInfoId(userId,user);
|
user = this.supplementInfoId(userId,user);
|
||||||
user.setStatusCode(resultObj.getStatusCode());
|
user.setStatusCode(resultObj.getStatusCode());
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class ApiGatewayLoggingFilter extends OncePerRequestFilter {
|
|||||||
)
|
)
|
||||||
throws IOException, ServletException {
|
throws IOException, ServletException {
|
||||||
Throwable handleException = null;
|
Throwable handleException = null;
|
||||||
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
|
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request,1024 * 1024);
|
||||||
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
|
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
|
||||||
LocalDateTime startTime = LocalDateTime.now();
|
LocalDateTime startTime = LocalDateTime.now();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class WebhookLoggingFilter extends OncePerRequestFilter {
|
|||||||
)
|
)
|
||||||
throws IOException, ServletException {
|
throws IOException, ServletException {
|
||||||
Throwable handleException = null;
|
Throwable handleException = null;
|
||||||
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
|
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request,1024 * 1024);
|
||||||
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
|
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
|
||||||
LocalDateTime startTime = LocalDateTime.now();
|
LocalDateTime startTime = LocalDateTime.now();
|
||||||
try {
|
try {
|
||||||
|
|||||||
-4
@@ -31,10 +31,6 @@ public class NotificationController {
|
|||||||
@RequestBody(required = true) SendEmailRequest requestData,
|
@RequestBody(required = true) SendEmailRequest requestData,
|
||||||
HttpServletRequest request
|
HttpServletRequest request
|
||||||
){
|
){
|
||||||
|
|
||||||
String appId = request.getHeader("application-id");
|
|
||||||
String securityKey = request.getHeader("authorization");
|
|
||||||
|
|
||||||
BaseApiResponse<Void> result = emailNotificationService.sendEmailByRequest(requestData,emailProxySetting);
|
BaseApiResponse<Void> result = emailNotificationService.sendEmailByRequest(requestData,emailProxySetting);
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(result);
|
return ResponseEntity.status(HttpStatus.OK).body(result);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package com.mgm.mcrm.apigateway.proxy.config;
|
package com.mgm.mcrm.apigateway.proxy.config;
|
||||||
|
|
||||||
|
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.EsbApiSetting;
|
import com.mgm.mcrm.apigateway.common.dtos.config.EsbApiSetting;
|
||||||
|
import com.mgm.mcrm.apigateway.common.dtos.config.LimoApiSetting;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.OperaApiSetting;
|
import com.mgm.mcrm.apigateway.common.dtos.config.OperaApiSetting;
|
||||||
|
import com.mgm.mcrm.apigateway.common.services.ConfigurableTrustHandler;
|
||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
import io.netty.handler.ssl.SslContext;
|
import io.netty.handler.ssl.SslContext;
|
||||||
import io.netty.handler.ssl.SslContextBuilder;
|
import io.netty.handler.ssl.SslContextBuilder;
|
||||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
|
||||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||||
import io.netty.handler.timeout.WriteTimeoutHandler;
|
import io.netty.handler.timeout.WriteTimeoutHandler;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -52,6 +54,8 @@ public class WebClientConfig {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private OperaApiSetting operaApiSetting;
|
private OperaApiSetting operaApiSetting;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private LimoApiSetting limoApiSetting;
|
||||||
|
@Autowired
|
||||||
private SslBundles sslBundles;
|
private SslBundles sslBundles;
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(WebClientConfig.class);
|
private final Logger logger = LoggerFactory.getLogger(WebClientConfig.class);
|
||||||
@@ -136,6 +140,45 @@ public class WebClientConfig {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public WebClient limoWebClient() {
|
||||||
|
ConnectionProvider provider = ConnectionProvider.builder("proxy-pool")
|
||||||
|
.maxConnections(maxConnectionPool)
|
||||||
|
.pendingAcquireTimeout(Duration.ofSeconds(60))
|
||||||
|
.maxIdleTime(Duration.ofSeconds(30))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpClient httpClient = HttpClient.create(provider)
|
||||||
|
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout*1000)
|
||||||
|
.responseTimeout(Duration.ofSeconds(readTimeout))
|
||||||
|
.secure(spec -> {
|
||||||
|
try {
|
||||||
|
spec.sslContext(this.createLimoSslContent());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.doOnConnected(conn -> {
|
||||||
|
logger.info("LIMO Connected using proxy: {}", conn.channel().remoteAddress());
|
||||||
|
conn.addHandlerLast(new ReadTimeoutHandler(readTimeout, TimeUnit.SECONDS))
|
||||||
|
.addHandlerLast(new WriteTimeoutHandler(readTimeout, TimeUnit.SECONDS));
|
||||||
|
})
|
||||||
|
.doOnRequest((request, connection) ->
|
||||||
|
logger.info("LIMO Request via proxy: {}", request)
|
||||||
|
);
|
||||||
|
if(StringUtils.isNotBlank(limoApiSetting.getProxyHost())){
|
||||||
|
httpClient = httpClient.proxy(this::initLimoProxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return WebClient.builder()
|
||||||
|
.clientConnector(new ReactorClientHttpConnector(httpClient))
|
||||||
|
.codecs(configurer -> {
|
||||||
|
configurer.defaultCodecs().maxInMemorySize(maxMemoryCacheM * 1024 * 1024);
|
||||||
|
})
|
||||||
|
.filter(retryFilter())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public WebClient operaWebClient() {
|
public WebClient operaWebClient() {
|
||||||
ConnectionProvider provider = ConnectionProvider.builder("proxy-pool")
|
ConnectionProvider provider = ConnectionProvider.builder("proxy-pool")
|
||||||
@@ -190,10 +233,10 @@ public class WebClientConfig {
|
|||||||
}
|
}
|
||||||
//-- Daylight init
|
//-- Daylight init
|
||||||
private SslContext createDaylightSslContent() throws SSLException {
|
private SslContext createDaylightSslContent() throws SSLException {
|
||||||
if(StringUtils.isBlank(daylightApiSetting.getSslBundleName())){
|
if(StringUtils.isNotBlank(daylightApiSetting.getSslBundleName())){
|
||||||
return this.createNoVerifySslContext();
|
|
||||||
}else{
|
|
||||||
return this.createSslContextByConfig(daylightApiSetting.getSslBundleName());
|
return this.createSslContextByConfig(daylightApiSetting.getSslBundleName());
|
||||||
|
}else{
|
||||||
|
return this.createDefaultSslContext(new ConfigurableTrustHandler(daylightApiSetting.isSkipTrustValidation(), SysCommon.getDefaultTrustManager()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,10 +251,10 @@ public class WebClientConfig {
|
|||||||
}
|
}
|
||||||
//-- Opera init
|
//-- Opera init
|
||||||
private SslContext createOperaSslContent() throws SSLException {
|
private SslContext createOperaSslContent() throws SSLException {
|
||||||
if(StringUtils.isBlank(operaApiSetting.getSslBundleName())){
|
if(StringUtils.isNotBlank(operaApiSetting.getSslBundleName())){
|
||||||
return this.createNoVerifySslContext();
|
|
||||||
}else{
|
|
||||||
return this.createSslContextByConfig(operaApiSetting.getSslBundleName());
|
return this.createSslContextByConfig(operaApiSetting.getSslBundleName());
|
||||||
|
}else{
|
||||||
|
return this.createDefaultSslContext(new ConfigurableTrustHandler(operaApiSetting.isSkipTrustValidation(), SysCommon.getDefaultTrustManager()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,10 +269,10 @@ public class WebClientConfig {
|
|||||||
}
|
}
|
||||||
//-- Esb init
|
//-- Esb init
|
||||||
private SslContext createEsbSslContent() throws SSLException {
|
private SslContext createEsbSslContent() throws SSLException {
|
||||||
if(StringUtils.isBlank(esbApiSetting.getSslBundleName())){
|
if(StringUtils.isNotBlank(esbApiSetting.getSslBundleName())){
|
||||||
return this.createNoVerifySslContext();
|
|
||||||
}else{
|
|
||||||
return this.createSslContextByConfig(esbApiSetting.getSslBundleName());
|
return this.createSslContextByConfig(esbApiSetting.getSslBundleName());
|
||||||
|
}else{
|
||||||
|
return this.createDefaultSslContext(new ConfigurableTrustHandler(esbApiSetting.isSkipTrustValidation(),SysCommon.getDefaultTrustManager()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +286,27 @@ public class WebClientConfig {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-- Limo init
|
||||||
|
private SslContext createLimoSslContent() throws SSLException {
|
||||||
|
if(StringUtils.isNotBlank(limoApiSetting.getSslBundleName())){
|
||||||
|
return this.createSslContextByConfig(limoApiSetting.getSslBundleName());
|
||||||
|
}else{
|
||||||
|
return this.createDefaultSslContext(new ConfigurableTrustHandler(limoApiSetting.isSkipTrustValidation(),SysCommon.getDefaultTrustManager()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initLimoProxy(ProxyProvider.TypeSpec proxy){
|
||||||
|
this.setProxySettingByConfig(
|
||||||
|
proxy,
|
||||||
|
limoApiSetting.getProxyHost(),
|
||||||
|
limoApiSetting.getProxyPort(),
|
||||||
|
limoApiSetting.getProxyUserName(),
|
||||||
|
limoApiSetting.getProxyPassword()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//----------
|
//----------
|
||||||
private void setProxySettingByConfig(ProxyProvider.TypeSpec proxy, String proxyHost, int proxyPort, String authUserName, String authPassword){
|
private void setProxySettingByConfig(ProxyProvider.TypeSpec proxy, String proxyHost, int proxyPort, String authUserName, String authPassword){
|
||||||
if (StringUtils.isNotBlank(authUserName) && StringUtils.isNotBlank(authPassword)) {
|
if (StringUtils.isNotBlank(authUserName) && StringUtils.isNotBlank(authPassword)) {
|
||||||
@@ -258,9 +322,8 @@ public class WebClientConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SslContext createNoVerifySslContext() throws SSLException {
|
private SslContext createDefaultSslContext(ConfigurableTrustHandler trustHandler) throws SSLException {
|
||||||
return SslContextBuilder.forClient()
|
return SslContextBuilder.forClient().trustManager(trustHandler).build();
|
||||||
.trustManager(InsecureTrustManagerFactory.INSTANCE).build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SslContext createSslContextByConfig(String sslBundleName) throws SSLException {
|
private SslContext createSslContextByConfig(String sslBundleName) throws SSLException {
|
||||||
|
|||||||
+25
-41
@@ -1,36 +1,23 @@
|
|||||||
package com.mgm.mcrm.apigateway.proxy.controllers;
|
package com.mgm.mcrm.apigateway.proxy.controllers;
|
||||||
|
|
||||||
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.LoginUserInfo;
|
import com.mgm.mcrm.apigateway.common.dtos.config.EmailProxySetting;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.EsbApiSetting;
|
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.OperaApiSetting;
|
|
||||||
import com.mgm.mcrm.apigateway.daylight.common.services.DaylightTokenService;
|
|
||||||
import com.mgm.mcrm.apigateway.esb.common.services.EsbTokenService;
|
|
||||||
import com.mgm.mcrm.apigateway.proxy.dtos.request.SendNotificationRequest;
|
import com.mgm.mcrm.apigateway.proxy.dtos.request.SendNotificationRequest;
|
||||||
import com.mgm.mcrm.apigateway.proxy.exception.HttpProxyErrorHandler;
|
|
||||||
import com.mgm.mcrm.apigateway.proxy.exception.SoapProxyErrorHandler;
|
|
||||||
import com.mgm.mcrm.apigateway.proxy.services.NotificationProxyService;
|
import com.mgm.mcrm.apigateway.proxy.services.NotificationProxyService;
|
||||||
import com.mgm.mcrm.apigateway.proxy.services.WebProxyService;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpHeaders;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
@Tag(name = "Notification Proxy", description = "Controller for Notification proxy")
|
@Tag(name = "Notification Proxy", description = "Controller for Notification proxy")
|
||||||
@RestController
|
@RestController
|
||||||
public class NotificationProxyController {
|
public class NotificationProxyController {
|
||||||
@@ -39,32 +26,29 @@ public class NotificationProxyController {
|
|||||||
@Resource
|
@Resource
|
||||||
private NotificationProxyService notificationProxyService;
|
private NotificationProxyService notificationProxyService;
|
||||||
|
|
||||||
@RequestMapping("/api/notification/proxy/**")
|
@Autowired
|
||||||
|
private EmailProxySetting emailProxySetting;
|
||||||
|
|
||||||
|
@RequestMapping(value="/api/notification/proxy/**",produces = "application/json;charset=UTF-8",consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ResponseEntity<BaseApiResponse<Void>> invokeNotificationApiProxy(HttpServletRequest request, @RequestBody SendNotificationRequest notificationRequest) throws Exception {
|
public ResponseEntity<BaseApiResponse<Void>> invokeNotificationApiProxy(HttpServletRequest request, @RequestBody SendNotificationRequest notificationRequest) throws Exception {
|
||||||
LoginUserInfo requestUser = SysCommon.parseUserFromToken(request.getHeader("Authorization"));
|
//--Check authorization
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(notificationProxyService.sendNotificationByRequest(notificationRequest,requestUser.getLoginId()));
|
String appId = request.getHeader("application-id");
|
||||||
}
|
String securityKey = request.getHeader("authorization");
|
||||||
|
if(!isAuthorizated(appId, securityKey)){
|
||||||
private HttpHeaders extractHeaders(HttpServletRequest request) {
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
Collections.list(request.getHeaderNames()).forEach(name -> {
|
|
||||||
if (!name.equalsIgnoreCase("host") &&
|
|
||||||
!name.equalsIgnoreCase("content-length") &&
|
|
||||||
!name.equalsIgnoreCase("application-id") &&
|
|
||||||
!name.equalsIgnoreCase("authorization")
|
|
||||||
) {
|
|
||||||
headers.add(name, request.getHeader(name));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] getRequestBody(HttpServletRequest request) {
|
|
||||||
try {
|
|
||||||
return request.getInputStream().readAllBytes();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error("Failed to read request body of request[{}]",request.getRequestURI(), e);
|
|
||||||
return new byte[0];
|
|
||||||
}
|
}
|
||||||
|
return ResponseEntity.status(HttpStatus.OK).body(notificationProxyService.sendNotificationByRequest(notificationRequest,notificationRequest.getRequestorId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAuthorizated(String appId, String securityKey) {
|
||||||
|
boolean isAuth=false;
|
||||||
|
if(StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(securityKey)){
|
||||||
|
String authCode = emailProxySetting.getAppAuthorizatinKey(appId);
|
||||||
|
if(StringUtils.isNotBlank(authCode) && securityKey.equals(authCode)){
|
||||||
|
isAuth=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isAuth;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package com.mgm.mcrm.apigateway.proxy.controllers;
|
|||||||
import com.mgm.mcrm.apigateway.appsetting.services.SysSettingService;
|
import com.mgm.mcrm.apigateway.appsetting.services.SysSettingService;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.EsbApiSetting;
|
import com.mgm.mcrm.apigateway.common.dtos.config.EsbApiSetting;
|
||||||
|
import com.mgm.mcrm.apigateway.common.dtos.config.LimoApiSetting;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.OperaApiSetting;
|
import com.mgm.mcrm.apigateway.common.dtos.config.OperaApiSetting;
|
||||||
|
import com.mgm.mcrm.apigateway.common.utils.NetworkUtil;
|
||||||
import com.mgm.mcrm.apigateway.daylight.common.services.DaylightTokenService;
|
import com.mgm.mcrm.apigateway.daylight.common.services.DaylightTokenService;
|
||||||
import com.mgm.mcrm.apigateway.daylight.common.dtos.TokenResponse;
|
import com.mgm.mcrm.apigateway.daylight.common.dtos.TokenResponse;
|
||||||
import com.mgm.mcrm.apigateway.esb.common.dtos.EsbToken;
|
import com.mgm.mcrm.apigateway.esb.common.dtos.EsbToken;
|
||||||
@@ -16,11 +18,14 @@ import jakarta.annotation.Resource;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.Strings;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -50,6 +55,12 @@ public class WebProxyController {
|
|||||||
private DaylightApiSetting daylightApiSetting;
|
private DaylightApiSetting daylightApiSetting;
|
||||||
@Autowired
|
@Autowired
|
||||||
private EsbApiSetting esbApiSetting;
|
private EsbApiSetting esbApiSetting;
|
||||||
|
@Value("${mcrm.proxy.api-config.esb.api-path.mcrm}")
|
||||||
|
private String mcrmApiPath;
|
||||||
|
@Value("${mcrm.proxy.api-config.esb.api-path.limo}")
|
||||||
|
private String limoApiPath;
|
||||||
|
@Autowired
|
||||||
|
private LimoApiSetting limoApiSetting;
|
||||||
@Autowired
|
@Autowired
|
||||||
private OperaApiSetting operaApiSetting;
|
private OperaApiSetting operaApiSetting;
|
||||||
|
|
||||||
@@ -59,10 +70,21 @@ public class WebProxyController {
|
|||||||
private volatile boolean cachedIsMock = true;
|
private volatile boolean cachedIsMock = true;
|
||||||
private volatile long lastMockCheckTime = 0;
|
private volatile long lastMockCheckTime = 0;
|
||||||
private static final long MOCK_CHECK_INTERVAL_MS = 30000;
|
private static final long MOCK_CHECK_INTERVAL_MS = 30000;
|
||||||
|
private static final String DAYLIGHT_PROXY_TYPE="DAYLIGHT";
|
||||||
|
private static final String ESB_PROXY_TYPE="ESB";
|
||||||
|
private static final String LIMO_PROXY_TYPE="LIMO";
|
||||||
|
|
||||||
@RequestMapping("/api/daylight/proxy/**")
|
@RequestMapping("/api/daylight/proxy/**")
|
||||||
public ResponseEntity<byte[]> invokeDaylightApiProxy(HttpServletRequest request,HttpServletResponse response) throws Exception {
|
public ResponseEntity<byte[]> invokeDaylightApiProxy(HttpServletRequest request,HttpServletResponse response) throws Exception {
|
||||||
|
//--Check authorization
|
||||||
|
String appId = request.getHeader("application-id");
|
||||||
|
String securityKey = request.getHeader("authorization");
|
||||||
|
if(!isAuthorizated(DAYLIGHT_PROXY_TYPE, appId, securityKey)){
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
|
||||||
|
}
|
||||||
|
|
||||||
String apiUrl = daylightApiSetting.getServerUrl() + request.getRequestURI().replace("/api/daylight/proxy", "");
|
String apiUrl = daylightApiSetting.getServerUrl() + request.getRequestURI().replace("/api/daylight/proxy", "");
|
||||||
|
apiUrl = NetworkUtil.validateAndSanitizeUrl(apiUrl);
|
||||||
HttpHeaders headers = this.extractHeaders(request);
|
HttpHeaders headers = this.extractHeaders(request);
|
||||||
TokenResponse daylightApiToken = daylightTokenService.getApiAccessToken();
|
TokenResponse daylightApiToken = daylightTokenService.getApiAccessToken();
|
||||||
if(daylightApiToken==null || StringUtils.isBlank(daylightApiToken.getAccessToken())){
|
if(daylightApiToken==null || StringUtils.isBlank(daylightApiToken.getAccessToken())){
|
||||||
@@ -74,7 +96,7 @@ public class WebProxyController {
|
|||||||
WebProxyService.DAYLIGHT_API,
|
WebProxyService.DAYLIGHT_API,
|
||||||
HttpMethod.valueOf(request.getMethod()),
|
HttpMethod.valueOf(request.getMethod()),
|
||||||
apiUrl,
|
apiUrl,
|
||||||
request.getQueryString(),
|
NetworkUtil.sanitizeCRLF(request.getQueryString()),
|
||||||
headers,
|
headers,
|
||||||
getRequestBody(request),
|
getRequestBody(request),
|
||||||
Duration.ofSeconds(daylightApiSetting.getApiTimeout()),
|
Duration.ofSeconds(daylightApiSetting.getApiTimeout()),
|
||||||
@@ -83,15 +105,40 @@ public class WebProxyController {
|
|||||||
}
|
}
|
||||||
@RequestMapping("/api/esb/proxy/**")
|
@RequestMapping("/api/esb/proxy/**")
|
||||||
public ResponseEntity<byte[]> invokeEsbApiProxy(HttpServletRequest request) throws Exception {
|
public ResponseEntity<byte[]> invokeEsbApiProxy(HttpServletRequest request) throws Exception {
|
||||||
|
return this.processEsbRequest(request, "ESB_MCRM");
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/api/esb_limo/proxy/**")
|
||||||
|
public ResponseEntity<byte[]> invokeEsbLimoApiProxy(HttpServletRequest request) throws Exception {
|
||||||
|
return this.processEsbRequest(request, "ESB_LIMO");
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseEntity<byte[]> processEsbRequest(HttpServletRequest request, String apiType) throws Exception {
|
||||||
|
//--Check authorization
|
||||||
|
String appId = request.getHeader("application-id");
|
||||||
|
String securityKey = request.getHeader("authorization");
|
||||||
|
if(!isAuthorizated(ESB_PROXY_TYPE, appId, securityKey)){
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
|
||||||
|
}
|
||||||
|
|
||||||
HttpMethod method = HttpMethod.valueOf(request.getMethod());
|
HttpMethod method = HttpMethod.valueOf(request.getMethod());
|
||||||
String apiUrl = esbApiSetting.getServerUrl() + request.getRequestURI().replace("/api/esb/proxy", "");
|
boolean isLimo = "ESB_LIMO".equalsIgnoreCase(apiType);
|
||||||
String queryString = request.getQueryString();
|
String apiPath = isLimo ? limoApiPath : mcrmApiPath;
|
||||||
|
String proxyPath = isLimo ? "/api/esb_limo/proxy" : "/api/esb/proxy";
|
||||||
|
String requestPath = Strings.CI.removeStart(request.getRequestURI(), proxyPath);
|
||||||
|
if (isLimo) {
|
||||||
|
requestPath = Strings.CI.removeStart(requestPath, "/api/esb_limo/v1.0");
|
||||||
|
}
|
||||||
|
requestPath = Strings.CI.removeStart(requestPath, apiPath);
|
||||||
|
String apiUrl = esbApiSetting.getServerUrl() + apiPath + requestPath;
|
||||||
|
apiUrl = NetworkUtil.validateAndSanitizeUrl(apiUrl);
|
||||||
|
String queryString = NetworkUtil.sanitizeCRLF(request.getQueryString());
|
||||||
HttpHeaders headers = this.extractHeaders(request);
|
HttpHeaders headers = this.extractHeaders(request);
|
||||||
byte[] requestBody = getRequestBody(request);
|
byte[] requestBody = getRequestBody(request);
|
||||||
|
|
||||||
EsbToken esbToken = esbTokenService.getApiAccessToken();
|
EsbToken esbToken = esbTokenService.getApiAccessToken(apiType);
|
||||||
if(esbToken==null || StringUtils.isBlank(esbToken.getAccessToken())){
|
if(esbToken==null || StringUtils.isBlank(esbToken.getAccessToken())){
|
||||||
logger.error("invokeEsbApiProxy failed, ESB token is null or blank, uri={}", request.getRequestURI());
|
logger.error("invoke {} Proxy failed, ESB token is null or blank, uri={}", apiType, request.getRequestURI());
|
||||||
throw new Exception("Invoke ESB token failed");
|
throw new Exception("Invoke ESB token failed");
|
||||||
}
|
}
|
||||||
headers.set("authorization", esbToken.getAccessToken());
|
headers.set("authorization", esbToken.getAccessToken());
|
||||||
@@ -107,11 +154,11 @@ public class WebProxyController {
|
|||||||
httpErrorHandler
|
httpErrorHandler
|
||||||
).block();
|
).block();
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
logger.error("invokeEsbApiProxy received a null response: method={}, apiUrl={}, query={}",
|
logger.error("invoke Esb ApiProxy received a null response: method={}, apiUrl={}, query={}",
|
||||||
method, apiUrl, queryString);
|
method, apiUrl, queryString);
|
||||||
} else if (response.getStatusCode().isError()) {
|
} else if (response.getStatusCode().isError()) {
|
||||||
byte[] responseBody = response.getBody();
|
byte[] responseBody = response.getBody();
|
||||||
logger.warn("invokeEsbApiProxy error response: method={}, apiUrl={}, query={}, status={}, headers={}, bodyLength={}, bodyPreview={}",
|
logger.warn("invoke Esb Api Proxy error response: method={}, apiUrl={}, query={}, status={}, headers={}, bodyLength={}, bodyPreview={}",
|
||||||
method,
|
method,
|
||||||
apiUrl,
|
apiUrl,
|
||||||
queryString,
|
queryString,
|
||||||
@@ -121,7 +168,54 @@ public class WebProxyController {
|
|||||||
responseBody == null ? 0 : responseBody.length,
|
responseBody == null ? 0 : responseBody.length,
|
||||||
bodyPreview(responseBody));
|
bodyPreview(responseBody));
|
||||||
} else {
|
} else {
|
||||||
logger.info("invokeEsbApiProxy completed: method={}, apiUrl={}, query={}, status={}",
|
logger.info("invoke Esb Api Proxy completed: method={}, apiUrl={}, query={}, status={}",
|
||||||
|
method, apiUrl, queryString, response.getStatusCode());
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/api/limo/proxy/**")
|
||||||
|
public ResponseEntity<byte[]> invokeLimoApiProxy(HttpServletRequest request) throws Exception {
|
||||||
|
//--Check authorization
|
||||||
|
String appId = request.getHeader("application-id");
|
||||||
|
String securityKey = request.getHeader("authorization");
|
||||||
|
if(!isAuthorizated(LIMO_PROXY_TYPE, appId, securityKey)){
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpMethod method = HttpMethod.valueOf(request.getMethod());
|
||||||
|
String apiUrl = limoApiSetting.getServerUrl() + request.getRequestURI().replace("/api/limo/proxy", "");
|
||||||
|
apiUrl = NetworkUtil.validateAndSanitizeUrl(apiUrl);
|
||||||
|
String queryString = NetworkUtil.sanitizeCRLF(request.getQueryString());
|
||||||
|
HttpHeaders headers = this.extractHeaders(request);
|
||||||
|
byte[] requestBody = getRequestBody(request);
|
||||||
|
|
||||||
|
ResponseEntity<byte[]> response = webProxyService.invokeRequest(
|
||||||
|
WebProxyService.LIMO_API,
|
||||||
|
method,
|
||||||
|
apiUrl,
|
||||||
|
queryString,
|
||||||
|
headers,
|
||||||
|
requestBody,
|
||||||
|
Duration.ofSeconds(limoApiSetting.getApiRequestTimeout()),
|
||||||
|
httpErrorHandler
|
||||||
|
).block();
|
||||||
|
if (response == null) {
|
||||||
|
logger.error("invoke Limo Api Proxy received a null response: method={}, apiUrl={}, query={}",
|
||||||
|
method, apiUrl, queryString);
|
||||||
|
} else if (response.getStatusCode().isError()) {
|
||||||
|
byte[] responseBody = response.getBody();
|
||||||
|
logger.warn("invoke Limo Api Proxy error response: method={}, apiUrl={}, query={}, status={}, headers={}, bodyLength={}, bodyPreview={}",
|
||||||
|
method,
|
||||||
|
apiUrl,
|
||||||
|
queryString,
|
||||||
|
|
||||||
|
response.getStatusCode(),
|
||||||
|
sanitizeHeaders(response.getHeaders()),
|
||||||
|
responseBody == null ? 0 : responseBody.length,
|
||||||
|
bodyPreview(responseBody));
|
||||||
|
} else {
|
||||||
|
logger.info("invoke Limo Api Proxy completed: method={}, apiUrl={}, query={}, status={}",
|
||||||
method, apiUrl, queryString, response.getStatusCode());
|
method, apiUrl, queryString, response.getStatusCode());
|
||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
@@ -130,11 +224,12 @@ public class WebProxyController {
|
|||||||
@RequestMapping("/api/opera/proxy/**")
|
@RequestMapping("/api/opera/proxy/**")
|
||||||
public ResponseEntity<byte[]> invokeOperaApiProxy(HttpServletRequest request) throws Exception {
|
public ResponseEntity<byte[]> invokeOperaApiProxy(HttpServletRequest request) throws Exception {
|
||||||
String apiUrl = operaApiSetting.getServerUrl() + request.getRequestURI().replace("/api/opera/proxy", "");
|
String apiUrl = operaApiSetting.getServerUrl() + request.getRequestURI().replace("/api/opera/proxy", "");
|
||||||
|
apiUrl = NetworkUtil.validateAndSanitizeUrl(apiUrl);
|
||||||
return webProxyService.invokeRequest(
|
return webProxyService.invokeRequest(
|
||||||
WebProxyService.OPERA_API,
|
WebProxyService.OPERA_API,
|
||||||
HttpMethod.valueOf(request.getMethod()),
|
HttpMethod.valueOf(request.getMethod()),
|
||||||
apiUrl,
|
apiUrl,
|
||||||
request.getQueryString(),
|
NetworkUtil.sanitizeCRLF(request.getQueryString()),
|
||||||
extractHeaders(request),
|
extractHeaders(request),
|
||||||
getRequestBody(request),
|
getRequestBody(request),
|
||||||
Duration.ofSeconds(operaApiSetting.getTimeout()),
|
Duration.ofSeconds(operaApiSetting.getTimeout()),
|
||||||
@@ -142,6 +237,24 @@ public class WebProxyController {
|
|||||||
).block();
|
).block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAuthorizated(String proxyType, String appId, String securityKey) {
|
||||||
|
boolean isAuth=false;
|
||||||
|
if(StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(securityKey)){
|
||||||
|
String authCode = null;
|
||||||
|
if(ESB_PROXY_TYPE.equalsIgnoreCase(proxyType)){
|
||||||
|
authCode = esbApiSetting.getAppAuthorizatinKey(appId);
|
||||||
|
}else if(DAYLIGHT_PROXY_TYPE.equalsIgnoreCase(proxyType)){
|
||||||
|
authCode = daylightApiSetting.getAppAuthorizatinKey(appId);
|
||||||
|
}else if(LIMO_PROXY_TYPE.equalsIgnoreCase(proxyType)){
|
||||||
|
authCode = limoApiSetting.getAppAuthorizatinKey(appId);
|
||||||
|
}
|
||||||
|
if(StringUtils.isNotBlank(authCode) && securityKey.equals(authCode)){
|
||||||
|
isAuth=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return isAuth;
|
||||||
|
}
|
||||||
|
|
||||||
private HttpHeaders extractHeaders(HttpServletRequest request) {
|
private HttpHeaders extractHeaders(HttpServletRequest request) {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
Collections.list(request.getHeaderNames()).forEach(name -> {
|
Collections.list(request.getHeaderNames()).forEach(name -> {
|
||||||
@@ -150,7 +263,7 @@ public class WebProxyController {
|
|||||||
!name.equalsIgnoreCase("application-id") &&
|
!name.equalsIgnoreCase("application-id") &&
|
||||||
!name.equalsIgnoreCase("authorization")
|
!name.equalsIgnoreCase("authorization")
|
||||||
) {
|
) {
|
||||||
headers.add(name, request.getHeader(name));
|
headers.add(NetworkUtil.sanitizeCRLF(name), NetworkUtil.sanitizeCRLF(request.getHeader(name)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return headers;
|
return headers;
|
||||||
|
|||||||
@@ -26,4 +26,6 @@ public class SendNotificationRequest {
|
|||||||
|
|
||||||
@Schema(description = "Type of booking ")
|
@Schema(description = "Type of booking ")
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
|
private String requestorId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package com.mgm.mcrm.apigateway.proxy.services;
|
package com.mgm.mcrm.apigateway.proxy.services;
|
||||||
|
|
||||||
import com.mgm.mcrm.apigateway.common.utils.LogUtil;
|
import com.mgm.mcrm.apigateway.common.utils.NetworkUtil;
|
||||||
import com.mgm.mcrm.apigateway.common.utils.mockup.HttpUtilMockup;
|
import com.mgm.mcrm.apigateway.common.utils.mockup.HttpUtilMockup;
|
||||||
import com.mgm.mcrm.apigateway.proxy.exception.HttpProxyErrorHandler;
|
|
||||||
import com.mgm.mcrm.apigateway.proxy.exception.ProxyErrorHandler;
|
import com.mgm.mcrm.apigateway.proxy.exception.ProxyErrorHandler;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -23,7 +22,6 @@ import reactor.core.publisher.Mono;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@Service
|
@Service
|
||||||
@@ -31,9 +29,11 @@ public class WebProxyService {
|
|||||||
public final static String DAYLIGHT_API="DAYLIGHT_API";
|
public final static String DAYLIGHT_API="DAYLIGHT_API";
|
||||||
public final static String ESB_API="ESB_API";
|
public final static String ESB_API="ESB_API";
|
||||||
public final static String OPERA_API="OPERA_API";
|
public final static String OPERA_API="OPERA_API";
|
||||||
|
public final static String LIMO_API="LIMO_API";
|
||||||
private final WebClient daylightWebClient;
|
private final WebClient daylightWebClient;
|
||||||
private final WebClient esbWebClient;
|
private final WebClient esbWebClient;
|
||||||
private final WebClient operaWebClient;
|
private final WebClient operaWebClient;
|
||||||
|
private final WebClient limoWebClient;
|
||||||
private final Logger logger = LoggerFactory.getLogger(WebProxyService.class);
|
private final Logger logger = LoggerFactory.getLogger(WebProxyService.class);
|
||||||
|
|
||||||
public Mono<ResponseEntity<byte[]>> invokeRequest(
|
public Mono<ResponseEntity<byte[]>> invokeRequest(
|
||||||
@@ -54,6 +54,8 @@ public class WebProxyService {
|
|||||||
targetWebClient=esbWebClient;
|
targetWebClient=esbWebClient;
|
||||||
}else if(OPERA_API.equalsIgnoreCase(apiType)){
|
}else if(OPERA_API.equalsIgnoreCase(apiType)){
|
||||||
targetWebClient=operaWebClient;
|
targetWebClient=operaWebClient;
|
||||||
|
}else if(LIMO_API.equalsIgnoreCase(apiType)){
|
||||||
|
targetWebClient=limoWebClient;
|
||||||
}else{
|
}else{
|
||||||
throw new Exception("Unknown request API type of "+apiType);
|
throw new Exception("Unknown request API type of "+apiType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,88 +139,88 @@ public class BookingService {
|
|||||||
}
|
}
|
||||||
bookingDao.save(dbBooking);
|
bookingDao.save(dbBooking);
|
||||||
|
|
||||||
CfgProperties property = propertyDao.findById(dbBooking.getPropertyId()).orElse(null);
|
// CfgProperties property = propertyDao.findById(dbBooking.getPropertyId()).orElse(null);
|
||||||
|
|
||||||
//Send Notification to Booker when booking lastOpera status Changed
|
// //Send Notification to Booker when booking lastOpera status Changed
|
||||||
if (Strings.CS.equals(daylightBooking.getLastOperaStatus(),"RESERVED") && !Strings.CS.equals(dbBookingStatus,daylightBooking.getLastOperaStatus())){
|
// if (Strings.CS.equals(daylightBooking.getLastOperaStatus(),"RESERVED") && !Strings.CS.equals(dbBookingStatus,daylightBooking.getLastOperaStatus())){
|
||||||
LogUtil.info(BookingService.class,"Booking last opera status changed, DB Record status:"+dbBookingStatus+", DlBooking status:"+daylightBooking.getLastOperaStatus());
|
// LogUtil.info(BookingService.class,"Booking last opera status changed, DB Record status:"+dbBookingStatus+", DlBooking status:"+daylightBooking.getLastOperaStatus());
|
||||||
//设置Notification 内容
|
// //设置Notification 内容
|
||||||
String notificationTitle = "#EN# Room status updated#EN#" +
|
// String notificationTitle = "#EN# Room status updated#EN#" +
|
||||||
"#CN#房間狀態已更改#CN#";
|
// "#CN#房間狀態已更改#CN#";
|
||||||
String notificationContent = "#EN#Player {playerId}, {propertyName}, {roomCode},room status changed to reserved.#EN#" +
|
// String notificationContent = "#EN#Player {playerId}, {propertyName}, {roomCode},room status changed to reserved.#EN#" +
|
||||||
"#CN#Player {playerId}, {propertyName}, {roomCode}, 房間狀態已預訂。#CN#";
|
// "#CN#Player {playerId}, {propertyName}, {roomCode}, 房間狀態已預訂。#CN#";
|
||||||
String[] placeholders = {
|
// String[] placeholders = {
|
||||||
"{playerId}", "{propertyName}", "{roomCode}"
|
// "{playerId}", "{propertyName}", "{roomCode}"
|
||||||
};
|
// };
|
||||||
LogUtil.info(BookingService.class,"Set notification info");
|
// LogUtil.info(BookingService.class,"Set notification info");
|
||||||
String[] values = {
|
// String[] values = {
|
||||||
StringUtils.defaultString(dbBooking.getPlayerId()),
|
// StringUtils.defaultString(dbBooking.getPlayerId()),
|
||||||
StringUtils.defaultString(property == null ? null : property.getName()),
|
// StringUtils.defaultString(property == null ? null : property.getName()),
|
||||||
StringUtils.defaultString(dbBooking.getRoomTypeCode())
|
// StringUtils.defaultString(dbBooking.getRoomTypeCode())
|
||||||
};
|
// };
|
||||||
LogUtil.info(BookingService.class,"Replace each");
|
// LogUtil.info(BookingService.class,"Replace each");
|
||||||
notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
// notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
||||||
String transactionId = "DLBKSC"+dbBooking.getId();
|
// String transactionId = "DLBKSC"+dbBooking.getId();
|
||||||
LogUtil.info(BookingService.class,"Get device token from DB Start");
|
// LogUtil.info(BookingService.class,"Get device token from DB Start");
|
||||||
LogUtil.info(BookingService.class,"dbBooking.getCreatedBy()=" + dbBooking.getCreatedBy());
|
// LogUtil.info(BookingService.class,"dbBooking.getCreatedBy()=" + dbBooking.getCreatedBy());
|
||||||
SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(StringUtils.trim(dbBooking.getCreatedBy()));
|
// SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(StringUtils.trim(dbBooking.getCreatedBy()));
|
||||||
LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
// LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
||||||
String deviceTokenValue =null;
|
// String deviceTokenValue =null;
|
||||||
String finalTitle = null;
|
// String finalTitle = null;
|
||||||
String finalContent = null;
|
// String finalContent = null;
|
||||||
if(deviceToken!=null){
|
// if(deviceToken!=null){
|
||||||
deviceTokenValue = deviceToken.getDeviceToken();
|
// deviceTokenValue = deviceToken.getDeviceToken();
|
||||||
finalTitle = notificationUtil.distinguishLanguage(notificationTitle,deviceToken.getUseLanguageType());
|
// finalTitle = notificationUtil.distinguishLanguage(notificationTitle,deviceToken.getUseLanguageType());
|
||||||
notificationContent = notificationUtil.distinguishLanguage(notificationContent,deviceToken.getUseLanguageType());
|
// notificationContent = notificationUtil.distinguishLanguage(notificationContent,deviceToken.getUseLanguageType());
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
// NOTIFICATION
|
//// NOTIFICATION
|
||||||
apnNotificationService.pushApnMessage(transactionId,deviceTokenValue,finalTitle,notificationContent,true);
|
// apnNotificationService.pushApnMessage(transactionId,deviceTokenValue,finalTitle,notificationContent,true);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
LogUtil.info(BookingService.class,"Daylight webhook updated, prepare send notification");
|
// LogUtil.info(BookingService.class,"Daylight webhook updated, prepare send notification");
|
||||||
log.info("dbBooking checkin={}, checkout={}", checkInDate, checkOutDate);
|
// log.info("dbBooking checkin={}, checkout={}", checkInDate, checkOutDate);
|
||||||
log.info("dlBooking checkin={}, checkout={}", daylightBooking.getCheckinDate(), daylightBooking.getCheckoutDate());
|
// log.info("dlBooking checkin={}, checkout={}", daylightBooking.getCheckinDate(), daylightBooking.getCheckoutDate());
|
||||||
LogUtil.info(BookingService.class,"Db booking status=" + dbBookingStatus);
|
// LogUtil.info(BookingService.class,"Db booking status=" + dbBookingStatus);
|
||||||
//Send notification to Booker when Booking C/I | C/O date changed
|
// //Send notification to Booker when Booking C/I | C/O date changed
|
||||||
if ((checkInDate != null && !checkInDate.equals(daylightBooking.getCheckinDate()))||
|
// if ((checkInDate != null && !checkInDate.equals(daylightBooking.getCheckinDate()))||
|
||||||
(checkOutDate != null && !checkOutDate.equals(daylightBooking.getCheckoutDate()))) {
|
// (checkOutDate != null && !checkOutDate.equals(daylightBooking.getCheckoutDate()))) {
|
||||||
LogUtil.info(BookingService.class,"Booking date changed, DB Record C/I:"+checkInDate+", DB Record C/O:"+checkOutDate+
|
// LogUtil.info(BookingService.class,"Booking date changed, DB Record C/I:"+checkInDate+", DB Record C/O:"+checkOutDate+
|
||||||
", Dl Record C/I"+daylightBooking.getCheckinDate()+", Dl Record C/O"+daylightBooking.getCheckoutDate());
|
// ", Dl Record C/I"+daylightBooking.getCheckinDate()+", Dl Record C/O"+daylightBooking.getCheckoutDate());
|
||||||
|
//
|
||||||
|
//
|
||||||
//设置Notification 内容
|
// //设置Notification 内容
|
||||||
String notificationTitle = "#EN# Room status updated#EN#" +
|
// String notificationTitle = "#EN# Room status updated#EN#" +
|
||||||
"#CN#房間狀態已更改#CN#";
|
// "#CN#房間狀態已更改#CN#";
|
||||||
String notificationContent = "#EN#Player {playerId}, {propertyName}, {roomCode},Stay date changed.#EN#" +
|
// String notificationContent = "#EN#Player {playerId}, {propertyName}, {roomCode},Stay date changed.#EN#" +
|
||||||
"#CN#Player {playerId}, {propertyName}, {roomCode}, 住宿日期已變更。#CN#";
|
// "#CN#Player {playerId}, {propertyName}, {roomCode}, 住宿日期已變更。#CN#";
|
||||||
String[] placeholders = {
|
// String[] placeholders = {
|
||||||
"{playerId}", "{propertyName}", "{roomCode}"
|
// "{playerId}", "{propertyName}", "{roomCode}"
|
||||||
};
|
// };
|
||||||
String[] values = {
|
// String[] values = {
|
||||||
StringUtils.defaultString(dbBooking.getPlayerId()),
|
// StringUtils.defaultString(dbBooking.getPlayerId()),
|
||||||
StringUtils.defaultString(property == null ? null : property.getName()),
|
// StringUtils.defaultString(property == null ? null : property.getName()),
|
||||||
StringUtils.defaultString(dbBooking.getRoomTypeCode())
|
// StringUtils.defaultString(dbBooking.getRoomTypeCode())
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
// notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
||||||
String transactionId = "DLBKDC" + dbBooking.getId();
|
// String transactionId = "DLBKDC" + dbBooking.getId();
|
||||||
|
//
|
||||||
SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(StringUtils.trim(dbBooking.getCreatedBy()));
|
// SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(StringUtils.trim(dbBooking.getCreatedBy()));
|
||||||
LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
// LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
||||||
String deviceTokenValue = null;
|
// String deviceTokenValue = null;
|
||||||
String finalTitle = null;
|
// String finalTitle = null;
|
||||||
String finalContent = null;
|
// String finalContent = null;
|
||||||
if (deviceToken != null) {
|
// if (deviceToken != null) {
|
||||||
LogUtil.info(BookingService.class,"Get device Token success");
|
// LogUtil.info(BookingService.class,"Get device Token success");
|
||||||
deviceTokenValue = deviceToken.getDeviceToken();
|
// deviceTokenValue = deviceToken.getDeviceToken();
|
||||||
finalTitle = notificationUtil.distinguishLanguage(notificationTitle, deviceToken.getUseLanguageType());
|
// finalTitle = notificationUtil.distinguishLanguage(notificationTitle, deviceToken.getUseLanguageType());
|
||||||
notificationContent = notificationUtil.distinguishLanguage(notificationContent, deviceToken.getUseLanguageType());
|
// notificationContent = notificationUtil.distinguishLanguage(notificationContent, deviceToken.getUseLanguageType());
|
||||||
}
|
// }
|
||||||
// NOTIFICATION
|
//// NOTIFICATION
|
||||||
apnNotificationService.pushApnMessage(transactionId, deviceTokenValue, finalTitle, notificationContent, true);
|
// apnNotificationService.pushApnMessage(transactionId, deviceTokenValue, finalTitle, notificationContent, true);
|
||||||
}
|
// }
|
||||||
LogUtil.info(BookingService.class,"End send notification function");
|
// LogUtil.info(BookingService.class,"End send notification function");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bookings findOneByDlProfileId(String dlProfileId) {
|
public Bookings findOneByDlProfileId(String dlProfileId) {
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ mcrm:
|
|||||||
username:
|
username:
|
||||||
password:
|
password:
|
||||||
ssl-bundle-name:
|
ssl-bundle-name:
|
||||||
|
skip-trust-validation: true
|
||||||
server-url: https://eu1.api.uat.development.abovecloud.io
|
server-url: https://eu1.api.uat.development.abovecloud.io
|
||||||
request-timeout: 30
|
request-timeout: 30
|
||||||
token:
|
token:
|
||||||
@@ -85,7 +86,8 @@ mcrm:
|
|||||||
username:
|
username:
|
||||||
password:
|
password:
|
||||||
ssl-bundle-name:
|
ssl-bundle-name:
|
||||||
server-url:
|
skip-trust-validation: true
|
||||||
|
server-url: https://mgpmsdevows45.dev.mgmmacao.org
|
||||||
request-timeout: 30
|
request-timeout: 30
|
||||||
security:
|
security:
|
||||||
authorization-data: "[MCRM_APP/securItykeyOfCrmapp87895312],[MCRM_CMS/seCuritykeyOfCrmCms8wetw432]"
|
authorization-data: "[MCRM_APP/securItykeyOfCrmapp87895312],[MCRM_CMS/seCuritykeyOfCrmCms8wetw432]"
|
||||||
@@ -97,16 +99,37 @@ mcrm:
|
|||||||
username:
|
username:
|
||||||
password:
|
password:
|
||||||
ssl-bundle-name:
|
ssl-bundle-name:
|
||||||
server-url: https://hca.mcmsapoc.com
|
skip-trust-validation: true
|
||||||
|
server-url: https://mmesbdevapp14.dev.mgmmacao.org
|
||||||
request-timeout: 30
|
request-timeout: 30
|
||||||
|
api-path:
|
||||||
|
mcrm: /api/crmapp/v1.0
|
||||||
|
limo: /api/limo/v1.0
|
||||||
token:
|
token:
|
||||||
token-url: /RequestAccessToken
|
token-url: /RequestAccessToken
|
||||||
app-id: crmappid
|
mcrm:
|
||||||
app-secret: crmsecuritykey
|
app-id: mgmtestuser001
|
||||||
|
app-secret: MGM@!666
|
||||||
|
limo:
|
||||||
|
app-id: crmappid
|
||||||
|
app-secret: crmsecuritykey
|
||||||
request-timeout: 30
|
request-timeout: 30
|
||||||
default-expiry-second: 700
|
default-expiry-second: 700
|
||||||
security:
|
security:
|
||||||
authorization-data: "[MCRM_APP/securItykeyOfCrmapp87895312],[MCRM_CMS/seCuritykeyOfCrmCms8wetw432]"
|
authorization-data: "[MCRM_APP/securItykeyOfCrmapp87895312],[MCRM_CMS/seCuritykeyOfCrmCms8wetw432]"
|
||||||
|
limo:
|
||||||
|
proxy-setting:
|
||||||
|
host:
|
||||||
|
port:
|
||||||
|
auth:
|
||||||
|
username:
|
||||||
|
password:
|
||||||
|
ssl-bundle-name:
|
||||||
|
skip-trust-validation: true
|
||||||
|
server-url: http://mmlimodevapp01
|
||||||
|
request-timeout: 30
|
||||||
|
security:
|
||||||
|
authorization-data: "[MCRM_APP/securItykeyOfCrmapp87895312],[MCRM_CMS/seCuritykeyOfCrmCms8wetw432]"
|
||||||
notification:
|
notification:
|
||||||
email-sender:
|
email-sender:
|
||||||
smtp-server: smtp.qq.com
|
smtp-server: smtp.qq.com
|
||||||
@@ -125,7 +148,7 @@ server:
|
|||||||
uri-encoding: UTF-8
|
uri-encoding: UTF-8
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
config: classpath:logback.xml
|
config: classpath:log4j2-spring.xml
|
||||||
|
|
||||||
springdoc:
|
springdoc:
|
||||||
swagger-ui:
|
swagger-ui:
|
||||||
@@ -155,4 +178,5 @@ apns:
|
|||||||
# host: api.push.apple.com
|
# host: api.push.apple.com
|
||||||
|
|
||||||
daylight:
|
daylight:
|
||||||
url: http://localhost:9087/api/daylight/proxy
|
url: http://localhost:9087/api/daylight/proxy
|
||||||
|
system-id: 3a151ad3-46be-4644-b656-71d3b037b309
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Configuration>
|
||||||
|
<Properties>
|
||||||
|
<Property name="logPath">api_gateway_runtime/logs</Property>
|
||||||
|
<Property name="logPattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Property>
|
||||||
|
</Properties>
|
||||||
|
<appenders>
|
||||||
|
<Console name="Console" target="SYSTEM_OUT">
|
||||||
|
<PatternLayout pattern="${logPattern}"/>
|
||||||
|
</Console>
|
||||||
|
<RollingFile name="FILE-APPENDER"
|
||||||
|
fileName="${logPath}/api-gateway-active.log"
|
||||||
|
filePattern="${logPath}/api-gateway-%d{yyyy-MM-dd}-%i.log">
|
||||||
|
<PatternLayout pattern="${logPattern}" />
|
||||||
|
<Policies>
|
||||||
|
<SizeBasedTriggeringPolicy size="200 MB"/>
|
||||||
|
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
|
||||||
|
</Policies>
|
||||||
|
<DefaultRolloverStrategy max="30"/>
|
||||||
|
</RollingFile>
|
||||||
|
</appenders>
|
||||||
|
|
||||||
|
<loggers>
|
||||||
|
<root level="info">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<appender-ref ref="FILE-APPENDER"/>
|
||||||
|
</root>
|
||||||
|
<Logger name="org.springframework" level="WARN" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<AppenderRef ref="FILE-APPENDER"/>
|
||||||
|
</Logger>
|
||||||
|
<Logger name="org.apache.shiro" level="WARN" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<AppenderRef ref="FILE-APPENDER"/>
|
||||||
|
</Logger>
|
||||||
|
<Logger name="org.hibernate" level="WARN" additivity="false">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
<AppenderRef ref="FILE-APPENDER"/>
|
||||||
|
</Logger>
|
||||||
|
</loggers>
|
||||||
|
</Configuration>
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration>
|
|
||||||
<!--======================================= 本地变量 ======================================== -->
|
|
||||||
<!--在没有定义${LOG_HOME}系统变量的时候,可以设置此本地变量。提交测试、上线时,要将其注释掉,使用系统变量。 -->
|
|
||||||
<!-- <property name="LOG_HOME" value="D:/data/logs" /> -->
|
|
||||||
|
|
||||||
<!-- 应用名称:和统一配置中的项目代码保持一致(小写) -->
|
|
||||||
<property name="APP_NAME" value="crm_runtime" />
|
|
||||||
<!--日志文件保留天数 -->
|
|
||||||
<property name="LOG_MAX_HISTORY" value="180" />
|
|
||||||
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
|
|
||||||
<!--应用日志文件保存路径 -->
|
|
||||||
<property name="LOG_APP_HOME" value="${APP_NAME}/logs" />
|
|
||||||
|
|
||||||
<!--=========================== 按照每天生成日志文件:默认配置=================================== -->
|
|
||||||
<!-- 控制台输出 -->
|
|
||||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
|
||||||
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
|
|
||||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%-5level] %logger{50} - %msg%n</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
<!-- 按照每天生成日志文件:主项目日志 -->
|
|
||||||
<appender name="APP"
|
|
||||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
|
||||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
|
||||||
<!--日志文件输出的文件名 -->
|
|
||||||
<FileNamePattern>${LOG_APP_HOME}/base.%d{yyyy-MM-dd}.log
|
|
||||||
</FileNamePattern>
|
|
||||||
<!--日志文件保留天数 -->
|
|
||||||
<MaxHistory>${LOG_MAX_HISTORY}</MaxHistory>
|
|
||||||
</rollingPolicy>
|
|
||||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
|
||||||
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
|
|
||||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{500} - %msg%n</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
<!--=============================== 日志输出: 默认主业务日志 ====================================== -->
|
|
||||||
<logger name="org.springframework" level="WARN">
|
|
||||||
|
|
||||||
</logger>
|
|
||||||
<logger name="org.apache.shiro" level="WARN">
|
|
||||||
|
|
||||||
</logger>
|
|
||||||
<logger name="freemarker" level="WARN">
|
|
||||||
|
|
||||||
</logger>
|
|
||||||
<logger name="org.hibernate" level="WARN">
|
|
||||||
|
|
||||||
</logger>
|
|
||||||
<!--
|
|
||||||
<logger name="org.hibernate.SQL">
|
|
||||||
<level value="DEBUG" />
|
|
||||||
</logger>
|
|
||||||
-->
|
|
||||||
<root level="INFO">
|
|
||||||
<appender-ref ref="APP" />
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</root>
|
|
||||||
</configuration>
|
|
||||||
Reference in New Issue
Block a user