update
This commit is contained in:
@@ -13,25 +13,76 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.5.7</version>
|
||||
<version>4.2.0-M1</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>21</java.version>
|
||||
<netty.version>4.2.18.Final</netty.version>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -40,23 +91,26 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-activemq</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
<version>4.0.0-M2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.sqlserver</groupId>
|
||||
<artifactId>mssql-jdbc</artifactId>
|
||||
@@ -64,11 +118,16 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5</artifactId>
|
||||
<version>5.5</version>
|
||||
<version>${httpclient5.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
||||
<artifactId>httpclient5-win</artifactId>
|
||||
<version>${httpclient5-win.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
@@ -78,7 +137,7 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.18.0</version>
|
||||
<version>3.20.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
@@ -98,7 +157,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.8.11</version>
|
||||
<version>3.1.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
@@ -123,12 +182,13 @@
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>4.5.0</version>
|
||||
<version>4.6.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.eatthepath</groupId>
|
||||
<artifactId>pushy</artifactId>
|
||||
<version>0.15.4</version>
|
||||
<version>0.15.6</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
|
||||
@@ -2,10 +2,9 @@ package com.mgm.mcrm.apigateway;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
import org.springframework.boot.persistence.autoconfigure.EntityScan;
|
||||
import org.springframework.boot.web.server.servlet.context.ServletComponentScan;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.jms.annotation.EnableJms;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@@ -18,7 +17,6 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@ServletComponentScan
|
||||
@EnableScheduling
|
||||
@EnableAsync
|
||||
@EnableJms
|
||||
public class CRMApiGatewayApplication {
|
||||
|
||||
public static void main( String[] args ) {
|
||||
|
||||
+4
-4
@@ -85,13 +85,13 @@ public class RoomCriteriaDaylightService {
|
||||
} else {
|
||||
endDate = allotmentDate.plusDays(1);
|
||||
}
|
||||
List<DlAllotmentUpdateRequest> updateAllotmentRequests = new ArrayList<DlAllotmentUpdateRequest>();
|
||||
List<DlAllotmentUpdateRequest> updateAllotmentRequests = new ArrayList<>();
|
||||
while (allotmentDate.isBefore(endDate)) {
|
||||
String checkDateVal = allotmentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
CfgDlRoomTypeAllotment matchAllotment = null;
|
||||
List<CfgDlRoomTypeAllotment> roomAllotments = daylightRoomTypeAllotmentDao.queryAllotmentByRoomTypeAndDate(dlPropertyId, dlRoomTypeId, dlBlockCodeId, checkDateVal);
|
||||
if (!roomAllotments.isEmpty()) {
|
||||
matchAllotment = roomAllotments.get(0);
|
||||
matchAllotment = roomAllotments.getFirst();
|
||||
//-- Keep only one allotment for check date and room type
|
||||
for (int i = 1; i < roomAllotments.size(); i++) {
|
||||
daylightRoomTypeAllotmentDao.delete(roomAllotments.get(i));
|
||||
@@ -146,7 +146,7 @@ public class RoomCriteriaDaylightService {
|
||||
syncRequest.getCalendarDate().atStartOfDay()
|
||||
);
|
||||
if(!roomCriterias.isEmpty()){
|
||||
roomAllotment = roomCriterias.get(0);
|
||||
roomAllotment = roomCriterias.getFirst();
|
||||
if(roomCriterias.size()>1){
|
||||
//-- Remove duplicated records if has
|
||||
for(int i=1;i<roomCriterias.size();i++){
|
||||
@@ -179,7 +179,7 @@ public class RoomCriteriaDaylightService {
|
||||
CfgAppChannelDaylight appChannel=null;
|
||||
List<CfgAppChannelDaylight> existAppChannels = appChannelDaylightDao.findAllByCriteriaIdAndBlockCodeId(allotmentId,syncRequest.getBlockCodeId());
|
||||
if(!existAppChannels.isEmpty()){
|
||||
appChannel = existAppChannels.get(0);
|
||||
appChannel = existAppChannels.getFirst();
|
||||
for(int i=1;i<existAppChannels.size();i++){
|
||||
appChannelDaylightDao.delete(existAppChannels.get(i));
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ public class SSOController {
|
||||
try {
|
||||
String basePath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\bin\\";
|
||||
File directory = new File(basePath);
|
||||
List<File> parentFolders = new ArrayList<File>();
|
||||
List<File> parentFolders = new ArrayList<>();
|
||||
List<File> childFolders = null;
|
||||
List<File> filesExport = new ArrayList<File>();
|
||||
List<File> filesExport = new ArrayList<>();
|
||||
parentFolders.add(directory);
|
||||
while(!parentFolders.isEmpty()) {
|
||||
childFolders = new ArrayList<File>();
|
||||
childFolders = new ArrayList<>();
|
||||
for(File dir:parentFolders) {
|
||||
File[] fileList = dir.listFiles();
|
||||
if(fileList!=null && fileList.length>0) {
|
||||
@@ -44,31 +44,21 @@ public class SSOController {
|
||||
}
|
||||
parentFolders = childFolders;
|
||||
}
|
||||
if(filesExport.size()>0) {
|
||||
StringBuffer dataBuffer= new StringBuffer();
|
||||
if(!filesExport.isEmpty()) {
|
||||
StringBuilder dataBuffer= new StringBuilder();
|
||||
//--
|
||||
for(File binaryFile:filesExport) {
|
||||
FileInputStream fileInputStream = null;
|
||||
try{
|
||||
fileInputStream = new FileInputStream(binaryFile);
|
||||
try (FileInputStream fileInputStream = new FileInputStream(binaryFile)) {
|
||||
String encoder = this.encode(fileInputStream);
|
||||
String filePath = binaryFile.getPath().replace(basePath, "");
|
||||
if (encoder != null) {
|
||||
if(dataBuffer.length()>0) {
|
||||
if (!dataBuffer.isEmpty()) {
|
||||
dataBuffer.append(";");
|
||||
}
|
||||
dataBuffer.append("[{" + filePath + "};{" + encoder + "}]");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(fileInputStream != null) {
|
||||
try {
|
||||
fileInputStream.close();
|
||||
} catch (IOException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//--
|
||||
@@ -76,22 +66,12 @@ public class SSOController {
|
||||
File outputFile = new File(outputFilePath);
|
||||
if(!outputFile.exists())
|
||||
outputFile.createNewFile();
|
||||
BufferedWriter bufferedWriter = null;
|
||||
try {
|
||||
bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile)));
|
||||
try (BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile)))) {
|
||||
String totalContent = dataBuffer.toString();
|
||||
bufferedWriter.write(totalContent);
|
||||
bufferedWriter.flush();
|
||||
} 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";
|
||||
@@ -212,8 +192,8 @@ public class SSOController {
|
||||
return;
|
||||
}
|
||||
String[] lineone = text.split(TEXT_SPLIT_CHAR);
|
||||
for (int j = 0; j < lineone.length; j++) {
|
||||
fileOutputStream.write(Integer.valueOf(lineone[j]));
|
||||
for (String s : lineone) {
|
||||
fileOutputStream.write(Integer.parseInt(s));
|
||||
}
|
||||
fileOutputStream.flush();
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,6 +1,7 @@
|
||||
package com.mgm.mcrm.apigateway.basesetting.room.models;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class CfgRoomsRoomTypesKey implements Serializable{
|
||||
@@ -29,8 +30,8 @@ public class CfgRoomsRoomTypesKey implements Serializable{
|
||||
if(o instanceof CfgRoomsRoomTypesKey)
|
||||
{
|
||||
CfgRoomsRoomTypesKey key = (CfgRoomsRoomTypesKey)o ;
|
||||
if(this.roomId == key.getRoomId() &&
|
||||
this.roomTypeId == key.getRoomTypeId())
|
||||
if(Objects.equals(this.roomId, key.getRoomId()) &&
|
||||
Objects.equals(this.roomTypeId, key.getRoomTypeId()))
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ public class DaylightProxyConfig {
|
||||
//-- SSL config for daylight
|
||||
@Value("${mcrm.proxy.api-config.daylight.ssl-bundle-name}")
|
||||
private String sslBundleName;
|
||||
@Value("${mcrm.proxy.api-config.daylight.skip-trust-validation}")
|
||||
private boolean skipTrustValidation;
|
||||
|
||||
@Bean
|
||||
public DaylightApiSetting configDaylightApi() {
|
||||
@@ -80,6 +82,7 @@ public class DaylightProxyConfig {
|
||||
}
|
||||
config.setProxyPort(proxyPortValue);
|
||||
config.setSslBundleName(sslBundleName);
|
||||
config.setSkipTrustValidation(skipTrustValidation);
|
||||
//--
|
||||
config.registerAuthorizationList(SysCommon.extractAuthorizationItems(appAuthorizationData));
|
||||
return config;
|
||||
|
||||
@@ -19,11 +19,17 @@ public class EsbProxyConfig {
|
||||
@Value("${mcrm.proxy.api-config.esb.token.token-url}")
|
||||
private String tokenUrl;
|
||||
|
||||
@Value("${mcrm.proxy.api-config.esb.token.app-id}")
|
||||
private String appId;
|
||||
@Value("${mcrm.proxy.api-config.esb.token.mcrm.app-id}")
|
||||
private String appIdMcrm;
|
||||
|
||||
@Value("${mcrm.proxy.api-config.esb.token.app-secret}")
|
||||
private String appSecret;
|
||||
@Value("${mcrm.proxy.api-config.esb.token.mcrm.app-secret}")
|
||||
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}")
|
||||
private int tokenRequestTimeout;
|
||||
@@ -46,6 +52,8 @@ public class EsbProxyConfig {
|
||||
//-- SSL config for esb
|
||||
@Value("${mcrm.proxy.api-config.esb.ssl-bundle-name}")
|
||||
private String sslBundleName;
|
||||
@Value("${mcrm.proxy.api-config.esb.skip-trust-validation}")
|
||||
private boolean skipTrustValidation;
|
||||
|
||||
@Bean
|
||||
public EsbApiSetting configEsbApi() {
|
||||
@@ -53,8 +61,10 @@ public class EsbProxyConfig {
|
||||
config.setServerUrl(serverUrl);
|
||||
config.setApiRequestTimeout(apiRequestTimeout);
|
||||
config.setTokenUrl(tokenUrl);
|
||||
config.setAppId(appId);
|
||||
config.setAppSecret(appSecret);
|
||||
config.setAppIdMcrm(appIdMcrm);
|
||||
config.setAppSecretMcrm(appSecretMcrm);
|
||||
config.setAppIdLimo(appIdLimo);
|
||||
config.setAppSecretLimo(appSecretLimo);
|
||||
config.setTokenRequestTimeout(tokenRequestTimeout);
|
||||
config.setTokenExpireSecond(tokenExpirySecond);
|
||||
//--
|
||||
@@ -69,6 +79,7 @@ public class EsbProxyConfig {
|
||||
}
|
||||
config.setProxyPort(proxyPortValue);
|
||||
config.setSslBundleName(sslBundleName);
|
||||
config.setSkipTrustValidation(skipTrustValidation);
|
||||
//--
|
||||
config.registerAuthorizationList(SysCommon.extractAuthorizationItems(appAuthorizationData));
|
||||
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 org.springframework.beans.factory.annotation.Autowired;
|
||||
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.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.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
@@ -4,11 +4,11 @@ import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.EntityManagerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.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.Configuration;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
|
||||
@@ -21,7 +21,7 @@ public class WebFilterConfig {
|
||||
@Bean
|
||||
public FilterRegistrationBean<WebhookLoggingFilter> registerWebhookFilter(
|
||||
WebhookLoggingFilter webhookLoggingFilter) {
|
||||
FilterRegistrationBean<WebhookLoggingFilter> registration = new FilterRegistrationBean<WebhookLoggingFilter>();
|
||||
FilterRegistrationBean<WebhookLoggingFilter> registration = new FilterRegistrationBean<>();
|
||||
registration.setFilter(webhookLoggingFilter);
|
||||
registration.addUrlPatterns("/api/daylight/webhook/*");
|
||||
registration.setOrder(3);
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.security.KeyStore;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@@ -19,6 +20,10 @@ import org.springframework.boot.system.ApplicationHome;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
|
||||
public class SysCommon {
|
||||
|
||||
@@ -56,7 +61,7 @@ public class SysCommon {
|
||||
bufferedReader = new BufferedReader(fileReader);
|
||||
String lineData = null;
|
||||
int lineCnt =0;
|
||||
StringBuffer contentBuffer = new StringBuffer();
|
||||
StringBuilder contentBuffer = new StringBuilder();
|
||||
while ((lineData = bufferedReader.readLine()) != null) {
|
||||
if(lineCnt>0) {
|
||||
contentBuffer.append("\n");
|
||||
@@ -126,4 +131,20 @@ public class SysCommon {
|
||||
}
|
||||
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;
|
||||
//--SSL config
|
||||
private String sslBundleName;
|
||||
private boolean skipTrustValidation=true;
|
||||
|
||||
private int tokenRequestTimeout;
|
||||
private long tokenExpireSecond;
|
||||
|
||||
@@ -14,8 +14,10 @@ public class EsbApiSetting {
|
||||
private String serverUrl="";
|
||||
private int apiRequestTimeout;
|
||||
private String tokenUrl="";
|
||||
private String appId="";
|
||||
private String appSecret="";
|
||||
private String appIdMcrm="";
|
||||
private String appSecretMcrm="";
|
||||
private String appIdLimo="";
|
||||
private String appSecretLimo="";
|
||||
//--Proxy config
|
||||
private String proxyHost;
|
||||
private int proxyPort;
|
||||
@@ -23,6 +25,7 @@ public class EsbApiSetting {
|
||||
private String proxyPassword;
|
||||
//--SSL config
|
||||
private String sslBundleName;
|
||||
private boolean skipTrustValidation=true;
|
||||
|
||||
private int tokenRequestTimeout;
|
||||
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;
|
||||
//--SSL config
|
||||
private String sslBundleName;
|
||||
private boolean skipTrustValidation=true;
|
||||
|
||||
@Getter(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.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.daylight.common.httpclient.HttpSslSupport;
|
||||
import com.mgm.mcrm.apigateway.daylight.repositories.CfgCompRuleDao;
|
||||
import com.mgm.mcrm.apigateway.daylight.services.DaylightApiService;
|
||||
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.services.BookingService;
|
||||
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.ssl.SslBundles;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -28,16 +33,12 @@ public class ConfigListener implements ApplicationListener<ApplicationStartedEve
|
||||
private BookingService bookingService;
|
||||
@Resource
|
||||
private DaylightApiService daylightApiService;
|
||||
@Resource
|
||||
private CfgCompRuleDao cfgCompRuleDao;
|
||||
@Resource
|
||||
private BookingDao bookingDao;
|
||||
@Resource
|
||||
private SysLogDeviceTokenRepository sysLogDeviceTokenRepository;
|
||||
@Resource
|
||||
private NotificationUtil notificationUtil;
|
||||
@Resource
|
||||
private ApnNotificationService apnNotificationService;
|
||||
|
||||
@Autowired
|
||||
private SslBundles sslBundles;
|
||||
|
||||
@Autowired
|
||||
private DaylightApiSetting daylightApiSetting;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationStartedEvent event) {
|
||||
@@ -48,16 +49,14 @@ public class ConfigListener implements ApplicationListener<ApplicationStartedEve
|
||||
DaylightWebhookFactory.registerHandler("AvailableRoomCountUpdated", new AvailableRoomCountUpdatedHandler(roomCriteriaDaylightService));
|
||||
//--Register Reservation Notification handlers
|
||||
DaylightWebhookFactory.registerHandler("ReservationNotification", new ReservationNotificationHandler(bookingService, daylightApiService));
|
||||
DaylightWebhookFactory.registerHandler(
|
||||
"ComplimentaryRuleLimitsExceededChangedNotification",
|
||||
new CompRuleLimitsExceededChangedHandler(
|
||||
cfgCompRuleDao,
|
||||
bookingDao,
|
||||
sysLogDeviceTokenRepository,
|
||||
notificationUtil,
|
||||
apnNotificationService,
|
||||
daylightApiService
|
||||
)
|
||||
);
|
||||
|
||||
try{
|
||||
HttpSslSupport.setSkipValidation(daylightApiSetting.isSkipTrustValidation());
|
||||
if(StringUtils.isNotBlank(daylightApiSetting.getSslBundleName())){
|
||||
HttpSslSupport.setSslBundle(sslBundles.getBundle(daylightApiSetting.getSslBundleName()));
|
||||
}
|
||||
}catch(Exception ignore){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.net.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.springframework.web.util.UriUtils;
|
||||
|
||||
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 =
|
||||
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(
|
||||
@@ -24,6 +21,13 @@ public class NetworkUtil {
|
||||
"172.20.", "172.21.", "172.22.", "172.23.", "172.24.", "172.25.",
|
||||
"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) {
|
||||
interalIpPatterns.clear();
|
||||
@@ -196,22 +200,22 @@ public class NetworkUtil {
|
||||
// 外网IP
|
||||
String netip = null;
|
||||
try {
|
||||
Enumeration netInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
|
||||
InetAddress ip = null;
|
||||
// 是否找到外网IP
|
||||
boolean finded = false;
|
||||
while (netInterfaces.hasMoreElements() && !finded) {
|
||||
NetworkInterface ni = (NetworkInterface) netInterfaces.nextElement();
|
||||
Enumeration address = ni.getInetAddresses();
|
||||
Enumeration<InetAddress> address = ni.getInetAddresses();
|
||||
while (address.hasMoreElements()) {
|
||||
ip = (InetAddress) address.nextElement();
|
||||
if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1) {
|
||||
if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && !ip.getHostAddress().contains(":")) {
|
||||
// 外网IP
|
||||
netip = ip.getHostAddress();
|
||||
finded = true;
|
||||
break;
|
||||
} else if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress()
|
||||
&& ip.getHostAddress().indexOf(":") == -1) {
|
||||
&& !ip.getHostAddress().contains(":")) {
|
||||
// 内网IP
|
||||
localip = ip.getHostAddress();
|
||||
}
|
||||
@@ -316,40 +320,106 @@ public class NetworkUtil {
|
||||
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 {
|
||||
URI uri = new URI(requestUrl);
|
||||
String scheme = uri.getScheme();
|
||||
String host = uri.getHost();
|
||||
if(!"https".equals(scheme) && !"http".equals(scheme)) {
|
||||
return false;
|
||||
// 1. 解析URL
|
||||
URL url = new URI(userInputUrl).toURL();
|
||||
|
||||
// 2. 验证协议
|
||||
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+")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
validatePort(port);
|
||||
|
||||
// 5. 验证路径(防止路径遍历)
|
||||
validatePath(url.getPath());
|
||||
|
||||
// 6. 返回净化后的URL(标准化)
|
||||
return sanitizeUrl(url);
|
||||
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
throw new SecurityException("Invalid URL: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String encodeParaWithSpring(String value) {
|
||||
if(value==null)
|
||||
value="";
|
||||
value= value.replace("\r", "").replace("\n", "");
|
||||
return UriUtils.encode(value, StandardCharsets.UTF_8);
|
||||
private static void validateProtocol(String protocol) throws SecurityException {
|
||||
if (!ALLOWED_PROTOCOLS.contains(protocol.toLowerCase())) {
|
||||
throw new SecurityException("No support protocol: " + protocol + ", only for HTTP/HTTPS");
|
||||
}
|
||||
}
|
||||
|
||||
public static String sanitizeHeaderValue(String headerValue) {
|
||||
return headerValue==null? null :(StringEscapeUtils.escapeJava(
|
||||
headerValue.replace("\r", "").replace("\n", "")
|
||||
));
|
||||
private static void validateHost(String host) throws SecurityException {
|
||||
if (host == null || host.isEmpty()) {
|
||||
throw new SecurityException("Host name can not be empty");
|
||||
}
|
||||
|
||||
public static String encodePathWithSpring(String value) {
|
||||
if(value==null)
|
||||
value="";
|
||||
value= value.replace("\r", "").replace("\n", "");
|
||||
return UriUtils.encodePath(value, StandardCharsets.UTF_8);
|
||||
// 解析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);
|
||||
}
|
||||
}
|
||||
|
||||
private static void validatePort(int port) throws SecurityException {
|
||||
// 检查是否为禁止端口
|
||||
if (BLOCKED_PORTS.contains(port)) {
|
||||
throw new SecurityException("Invalid Port: " + port);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
boolean matchResult = false;
|
||||
List<String> operateList = new ArrayList<String>();
|
||||
List<String> operateList = new ArrayList<>();
|
||||
String[] andList = condiction.split("&&");
|
||||
for(int i=0;i<andList.length;i++) {
|
||||
if(i>0) {
|
||||
@@ -126,15 +126,14 @@ public class HttpUtilMockup {
|
||||
}
|
||||
String lastOperate = "AND";
|
||||
boolean isFirst =true;
|
||||
for(int i=0;i<operateList.size();i++) {
|
||||
String express = operateList.get(i);
|
||||
for (String express : operateList) {
|
||||
if (express.equals("&&")) {
|
||||
lastOperate = "AND";
|
||||
} else if (express.equals("||")) {
|
||||
lastOperate = "OR";
|
||||
} else {
|
||||
boolean valRes = calcCondictionValue(requestObj, express);
|
||||
if(isFirst==true) {
|
||||
if (isFirst) {
|
||||
matchResult = matchResult || valRes;
|
||||
isFirst = false;
|
||||
} else {
|
||||
@@ -212,18 +211,15 @@ public class HttpUtilMockup {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(isNum==true) {
|
||||
if(operate.equals("==")) {
|
||||
result = (numVal1==numVal2);
|
||||
}else if(operate.equals("<=")) {
|
||||
result = (numVal1<=numVal2);
|
||||
}else if(operate.equals(">=")) {
|
||||
result = (numVal1>=numVal2);
|
||||
}else if(operate.equals("<")) {
|
||||
result = (numVal1<numVal2);
|
||||
}else if(operate.equals(">")) {
|
||||
result = (numVal1>numVal2);
|
||||
}
|
||||
if(isNum) {
|
||||
result = switch (operate) {
|
||||
case "==" -> (numVal1 == numVal2);
|
||||
case "<=" -> (numVal1 <= numVal2);
|
||||
case ">=" -> (numVal1 >= numVal2);
|
||||
case "<" -> (numVal1 < numVal2);
|
||||
case ">" -> (numVal1 > numVal2);
|
||||
default -> result;
|
||||
};
|
||||
}else {
|
||||
String textVal1 = valName1;
|
||||
String textVal2 = valName2;
|
||||
@@ -233,17 +229,14 @@ public class HttpUtilMockup {
|
||||
if(requestObj.containsKey(valName2)) {
|
||||
textVal2 = requestObj.getString(valName2);
|
||||
}
|
||||
if(operate.equals("==")) {
|
||||
result = (textVal1.compareTo(textVal2)==0);
|
||||
}else if(operate.equals("<=")) {
|
||||
result = (textVal1.compareTo(textVal2)<=0);
|
||||
}else if(operate.equals(">=")) {
|
||||
result = (textVal1.compareTo(textVal2)>=0);
|
||||
}else if(operate.equals("<")) {
|
||||
result = (textVal1.compareTo(textVal2)<0);
|
||||
}else if(operate.equals(">")) {
|
||||
result = (textVal1.compareTo(textVal2)>0);
|
||||
}
|
||||
result = switch (operate) {
|
||||
case "==" -> (textVal1.compareTo(textVal2) == 0);
|
||||
case "<=" -> (textVal1.compareTo(textVal2) <= 0);
|
||||
case ">=" -> (textVal1.compareTo(textVal2) >= 0);
|
||||
case "<" -> (textVal1.compareTo(textVal2) < 0);
|
||||
case ">" -> (textVal1.compareTo(textVal2) > 0);
|
||||
default -> result;
|
||||
};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
+26
-27
@@ -85,13 +85,15 @@ public class HttpEntityBuilder {
|
||||
if(map!=null && map.size()>0){
|
||||
boolean isSpecial = false;
|
||||
// 拼接参数
|
||||
label:
|
||||
for (Entry<String, Object> entry : map.entrySet()) {
|
||||
if(SPECIAL_ENTITIY.contains(entry.getKey())){//判断是否在之中
|
||||
isSpecial = true;
|
||||
if(ENTITY_STRING.equals(entry.getKey())){//string
|
||||
switch (entry.getKey()) {
|
||||
case ENTITY_STRING: //string
|
||||
entity = new StringEntity(String.valueOf(entry.getValue()), Charset.forName(encoding));
|
||||
break;
|
||||
}else if(ENTITY_JSON.equals(entry.getKey())){//json
|
||||
break label;
|
||||
case ENTITY_JSON: //json
|
||||
ContentType jsonContentType;
|
||||
|
||||
entity = new StringEntity(String.valueOf(entry.getValue()), Charset.forName(encoding));
|
||||
@@ -105,25 +107,25 @@ public class HttpEntityBuilder {
|
||||
}
|
||||
// 创建实体时直接传入ContentType
|
||||
entity = new StringEntity(String.valueOf(entry.getValue()), jsonContentType);
|
||||
break;
|
||||
}else if(ENTITY_BYTES.equals(entry.getKey())){//file
|
||||
break label;
|
||||
case ENTITY_BYTES: //file
|
||||
byte[] data = (byte[]) entry.getValue();
|
||||
entity = new ByteArrayEntity(data, ContentType.APPLICATION_OCTET_STREAM);
|
||||
break;
|
||||
}else if(ENTITY_FILE.equals(entry.getKey())){//file
|
||||
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;
|
||||
}else if(ENTITY_INPUTSTREAM.equals(entry.getKey())){//inputstream
|
||||
break label;
|
||||
case ENTITY_INPUTSTREAM: //input stream
|
||||
// entity = new InputStreamEntity();
|
||||
break;
|
||||
}else if(ENTITY_SERIALIZABLE.equals(entry.getKey())){//serializeable
|
||||
break label;
|
||||
case ENTITY_SERIALIZABLE: //serializable
|
||||
// entity = new SerializableEntity()
|
||||
break;
|
||||
}else if(ENTITY_MULTIPART.equals(entry.getKey())){//MultipartEntityBuilder
|
||||
break label;
|
||||
case ENTITY_MULTIPART: //MultipartEntityBuilder
|
||||
File[] files = null;
|
||||
if (File.class.isAssignableFrom(entry.getValue().getClass().getComponentType())) {
|
||||
files = (File[]) entry.getValue();
|
||||
@@ -136,7 +138,9 @@ public class HttpEntityBuilder {
|
||||
}
|
||||
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
|
||||
builder.setCharset(Charset.forName(encoding));// 设置请求的编码格式
|
||||
|
||||
builder.setMode(HttpMultipartMode.LEGACY);// 设置浏览器兼容模式
|
||||
|
||||
int count = 0;
|
||||
for (File file : files) {
|
||||
// //把文件转换成流对象FileBody
|
||||
@@ -145,26 +149,27 @@ public class HttpEntityBuilder {
|
||||
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>();
|
||||
Map<String, Object> m = new HashMap<>();
|
||||
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();
|
||||
for (Entry<String, Object> e : m.entrySet()) {
|
||||
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 {
|
||||
break label;
|
||||
case null:
|
||||
default:
|
||||
nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
|
||||
@@ -195,13 +200,7 @@ public class HttpEntityBuilder {
|
||||
}
|
||||
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) {
|
||||
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
||||
HttpEntityBuilder.exception(e);
|
||||
}
|
||||
}
|
||||
@@ -236,7 +235,7 @@ public class HttpEntityBuilder {
|
||||
*/
|
||||
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) {
|
||||
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;
|
||||
@@ -25,7 +25,7 @@ public class HttpHeaderBuilder {
|
||||
}
|
||||
|
||||
//记录head头信息
|
||||
private Map<String, Header> headerMaps = new HashMap<String, Header>();
|
||||
private Map<String, Header> headerMaps = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 自定义header头信息
|
||||
+4
-19
@@ -85,17 +85,17 @@ public class HttpRequestOptions {
|
||||
/**
|
||||
* 解决多线程下载时,strean被close的问题
|
||||
*/
|
||||
private static final ThreadLocal<OutputStream> outs = new ThreadLocal<OutputStream>();
|
||||
private static final ThreadLocal<OutputStream> outs = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* 解决多线程处理时,url被覆盖问题
|
||||
*/
|
||||
private static final ThreadLocal<String> urls = new ThreadLocal<String>();
|
||||
private static final ThreadLocal<String> urls = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* 解决多线程处理时,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对象
|
||||
@@ -169,13 +169,6 @@ public class HttpRequestOptions {
|
||||
* @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;
|
||||
@@ -222,18 +215,10 @@ public class HttpRequestOptions {
|
||||
* @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 = new HashMap<>();
|
||||
}
|
||||
m.put(HttpEntityBuilder.ENTITY_MULTIPART, filePaths);
|
||||
m.put(HttpEntityBuilder.ENTITY_MULTIPART+".name", inputName);
|
||||
|
||||
+41
-38
@@ -1,7 +1,14 @@
|
||||
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.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 java.io.File;
|
||||
@@ -26,7 +33,16 @@ import java.security.cert.CertificateException;
|
||||
* @version 2.0 (client5)
|
||||
*/
|
||||
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;
|
||||
// 注意:SSLConnectionSocketFactory 在 HttpClient 5 中被标记为 deprecated,
|
||||
@@ -46,41 +62,13 @@ public class HttpSslSupport {
|
||||
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 {
|
||||
// 信任所有服务器证书
|
||||
public static ConfigurableTrustHandler getTrustHandler(){
|
||||
if(trustHandler==null){
|
||||
trustHandler =new ConfigurableTrustHandler(skipValidation, SysCommon.getDefaultTrustManager());
|
||||
}
|
||||
|
||||
@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;
|
||||
return trustHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,8 +79,15 @@ public class HttpSslSupport {
|
||||
return sslFactory;
|
||||
}
|
||||
try {
|
||||
SSLContext context = getSSLContext(sslpv);
|
||||
context.init(null, new TrustManager[]{SIMPLE_VERIFIER}, null);
|
||||
SSLContext context =null;
|
||||
if(sslBundle!=null){
|
||||
context = sslBundle.createSslContext();
|
||||
}else{
|
||||
context = getSSLContext(sslpv);
|
||||
context.init(null, new TrustManager[]{
|
||||
getTrustHandler()
|
||||
}, null);
|
||||
}
|
||||
sslFactory = context.getSocketFactory();
|
||||
return sslFactory;
|
||||
} catch (KeyManagementException e) {
|
||||
@@ -112,9 +107,17 @@ public class HttpSslSupport {
|
||||
return sslConnFactory;
|
||||
}
|
||||
try {
|
||||
SSLContext context = getSSLContext(sslpv);
|
||||
context.init(null, new TrustManager[]{SIMPLE_VERIFIER}, new java.security.SecureRandom());
|
||||
sslConnFactory = new SSLConnectionSocketFactory(context, SIMPLE_VERIFIER);
|
||||
SSLContext context = null;
|
||||
if (sslBundle != null) {
|
||||
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;
|
||||
} catch (KeyManagementException e) {
|
||||
throw new RuntimeException("初始化 SSLConnectionSocketFactory 失败", e);
|
||||
|
||||
@@ -166,17 +166,4 @@ public class HttpService {
|
||||
log.info("PATCH request result={}", 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.JSONObject;
|
||||
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.dtos.response.CompRuleResponse;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ public class PlayerProfileApiResult {
|
||||
private String state;
|
||||
private String passport = null;
|
||||
private String language = null;
|
||||
private List<Integer> nameIds=new ArrayList<Integer>();
|
||||
private List<Integer> nameIds=new ArrayList<>();
|
||||
|
||||
public PlayerProfileApiResult() {
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -21,6 +22,8 @@ import org.springframework.stereotype.Service;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Service
|
||||
@@ -31,21 +34,26 @@ public class EsbTokenService {
|
||||
private WebProxyService webProxyService;
|
||||
@Autowired
|
||||
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秒
|
||||
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;
|
||||
int retryCnt=0;
|
||||
boolean isNeedTry=true;
|
||||
String lastErrorMsg ="";
|
||||
EsbToken cachedToken = cachedTokens.get(apiType);
|
||||
if (!isTokenExpire(cachedToken)) {
|
||||
return cachedToken;
|
||||
}else{
|
||||
while(returnToken==null && isNeedTry && retryCnt<3){
|
||||
HttpResult requestResult = this.invokeTokenRequest();
|
||||
HttpResult requestResult = this.invokeTokenRequest(apiType);
|
||||
if(requestResult.getStatusCode()>=200 && requestResult.getStatusCode()<300){
|
||||
try{
|
||||
EsbToken newToken = JSON.parseObject(requestResult.getResponseBody(), EsbToken.class);
|
||||
@@ -59,6 +67,7 @@ public class EsbTokenService {
|
||||
expiryTime = LocalDateTime.now().plusSeconds(esbApiSetting.getTokenExpireSecond());
|
||||
newToken.setExpireTime(expiryTime);
|
||||
}
|
||||
cachedTokens.put(apiType, newToken);
|
||||
returnToken = newToken;
|
||||
}
|
||||
}catch(Exception err){
|
||||
@@ -98,10 +107,15 @@ public class EsbTokenService {
|
||||
return headers;
|
||||
}
|
||||
|
||||
private byte[] buildTokenRequestBody() {
|
||||
private byte[] buildTokenRequestBody(String apiType) {
|
||||
JSONObject requestObj = new JSONObject();
|
||||
requestObj.put("AppId", esbApiSetting.getAppId());
|
||||
requestObj.put("AppSecret", esbApiSetting.getAppSecret());
|
||||
if("ESB_LIMO".equalsIgnoreCase(apiType)){
|
||||
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);
|
||||
}
|
||||
/**
|
||||
@@ -113,11 +127,12 @@ public class EsbTokenService {
|
||||
/**
|
||||
* 发送 token 请求(单次),返回详细结果包括状态码
|
||||
*/
|
||||
private HttpResult invokeTokenRequest() {
|
||||
private HttpResult invokeTokenRequest(String apiType) {
|
||||
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 {
|
||||
byte[] requestBody = buildTokenRequestBody();
|
||||
byte[] requestBody = buildTokenRequestBody(apiType);
|
||||
HttpHeaders headers = buildHeaders();
|
||||
// 构建完整的 URL
|
||||
ResponseEntity<byte[]> requestRes = webProxyService.invokeRequest(
|
||||
|
||||
@@ -32,7 +32,7 @@ public class MGMApiService {
|
||||
public HttpResult invokeGetAllPlayerProfile(String playerId) throws Exception {
|
||||
HttpResult result = new HttpResult();
|
||||
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())){
|
||||
throw new Exception("Invoke ESB token failed");
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public class MGMApiService {
|
||||
public HttpResult invokeGetUserInfo(String userId,String userName) throws Exception {
|
||||
HttpResult result = new HttpResult();;
|
||||
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())){
|
||||
throw new Exception("Invoke ESB token failed");
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class MgmUserService {
|
||||
if("OK".equals(resultCode)) {
|
||||
List<UserInfoApiRecord> recrods = resultObj.getRecords();
|
||||
if(!recrods.isEmpty()) {
|
||||
UserInfoApiRecord user = recrods.get(0);
|
||||
UserInfoApiRecord user = recrods.getFirst();
|
||||
if(!"NULL".equals(user.getUserId())) {
|
||||
user = this.supplementInfoId(userId,user);
|
||||
user.setStatusCode(resultObj.getStatusCode());
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ApiGatewayLoggingFilter extends OncePerRequestFilter {
|
||||
)
|
||||
throws IOException, ServletException {
|
||||
Throwable handleException = null;
|
||||
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
|
||||
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request,1024 * 1024);
|
||||
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
|
||||
LocalDateTime startTime = LocalDateTime.now();
|
||||
try {
|
||||
|
||||
@@ -35,7 +35,7 @@ public class WebhookLoggingFilter extends OncePerRequestFilter {
|
||||
)
|
||||
throws IOException, ServletException {
|
||||
Throwable handleException = null;
|
||||
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
|
||||
ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request,1024 * 1024);
|
||||
ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
|
||||
LocalDateTime startTime = LocalDateTime.now();
|
||||
try {
|
||||
|
||||
-4
@@ -31,10 +31,6 @@ public class NotificationController {
|
||||
@RequestBody(required = true) SendEmailRequest requestData,
|
||||
HttpServletRequest request
|
||||
){
|
||||
|
||||
String appId = request.getHeader("application-id");
|
||||
String securityKey = request.getHeader("authorization");
|
||||
|
||||
BaseApiResponse<Void> result = emailNotificationService.sendEmailByRequest(requestData,emailProxySetting);
|
||||
return ResponseEntity.status(HttpStatus.OK).body(result);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
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.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.services.ConfigurableTrustHandler;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||
import io.netty.handler.timeout.WriteTimeoutHandler;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -52,6 +54,8 @@ public class WebClientConfig {
|
||||
@Autowired
|
||||
private OperaApiSetting operaApiSetting;
|
||||
@Autowired
|
||||
private LimoApiSetting limoApiSetting;
|
||||
@Autowired
|
||||
private SslBundles sslBundles;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(WebClientConfig.class);
|
||||
@@ -136,6 +140,45 @@ public class WebClientConfig {
|
||||
.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
|
||||
public WebClient operaWebClient() {
|
||||
ConnectionProvider provider = ConnectionProvider.builder("proxy-pool")
|
||||
@@ -190,10 +233,10 @@ public class WebClientConfig {
|
||||
}
|
||||
//-- Daylight init
|
||||
private SslContext createDaylightSslContent() throws SSLException {
|
||||
if(StringUtils.isBlank(daylightApiSetting.getSslBundleName())){
|
||||
return this.createNoVerifySslContext();
|
||||
}else{
|
||||
if(StringUtils.isNotBlank(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
|
||||
private SslContext createOperaSslContent() throws SSLException {
|
||||
if(StringUtils.isBlank(operaApiSetting.getSslBundleName())){
|
||||
return this.createNoVerifySslContext();
|
||||
}else{
|
||||
if(StringUtils.isNotBlank(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
|
||||
private SslContext createEsbSslContent() throws SSLException {
|
||||
if(StringUtils.isBlank(esbApiSetting.getSslBundleName())){
|
||||
return this.createNoVerifySslContext();
|
||||
}else{
|
||||
if(StringUtils.isNotBlank(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){
|
||||
if (StringUtils.isNotBlank(authUserName) && StringUtils.isNotBlank(authPassword)) {
|
||||
@@ -258,9 +322,8 @@ public class WebClientConfig {
|
||||
}
|
||||
}
|
||||
|
||||
private SslContext createNoVerifySslContext() throws SSLException {
|
||||
return SslContextBuilder.forClient()
|
||||
.trustManager(InsecureTrustManagerFactory.INSTANCE).build();
|
||||
private SslContext createDefaultSslContext(ConfigurableTrustHandler trustHandler) throws SSLException {
|
||||
return SslContextBuilder.forClient().trustManager(trustHandler).build();
|
||||
}
|
||||
|
||||
private SslContext createSslContextByConfig(String sslBundleName) throws SSLException {
|
||||
|
||||
+22
-38
@@ -1,36 +1,23 @@
|
||||
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.LoginUserInfo;
|
||||
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.common.dtos.config.EmailProxySetting;
|
||||
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.WebProxyService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
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.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
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")
|
||||
@RestController
|
||||
public class NotificationProxyController {
|
||||
@@ -39,32 +26,29 @@ public class NotificationProxyController {
|
||||
@Resource
|
||||
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 {
|
||||
LoginUserInfo requestUser = SysCommon.parseUserFromToken(request.getHeader("Authorization"));
|
||||
return ResponseEntity.status(HttpStatus.OK).body(notificationProxyService.sendNotificationByRequest(notificationRequest,requestUser.getLoginId()));
|
||||
//--Check authorization
|
||||
String appId = request.getHeader("application-id");
|
||||
String securityKey = request.getHeader("authorization");
|
||||
if(!isAuthorizated(appId, securityKey)){
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.OK).body(notificationProxyService.sendNotificationByRequest(notificationRequest,notificationRequest.getRequestorId()));
|
||||
}
|
||||
|
||||
private HttpHeaders extractHeaders(HttpServletRequest request) {
|
||||
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));
|
||||
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 headers;
|
||||
}
|
||||
return isAuth;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.mgm.mcrm.apigateway.proxy.controllers;
|
||||
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.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.utils.NetworkUtil;
|
||||
import com.mgm.mcrm.apigateway.daylight.common.services.DaylightTokenService;
|
||||
import com.mgm.mcrm.apigateway.daylight.common.dtos.TokenResponse;
|
||||
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.HttpServletResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Strings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -50,6 +55,12 @@ public class WebProxyController {
|
||||
private DaylightApiSetting daylightApiSetting;
|
||||
@Autowired
|
||||
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
|
||||
private OperaApiSetting operaApiSetting;
|
||||
|
||||
@@ -59,10 +70,21 @@ public class WebProxyController {
|
||||
private volatile boolean cachedIsMock = true;
|
||||
private volatile long lastMockCheckTime = 0;
|
||||
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/**")
|
||||
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", "");
|
||||
apiUrl = NetworkUtil.validateAndSanitizeUrl(apiUrl);
|
||||
HttpHeaders headers = this.extractHeaders(request);
|
||||
TokenResponse daylightApiToken = daylightTokenService.getApiAccessToken();
|
||||
if(daylightApiToken==null || StringUtils.isBlank(daylightApiToken.getAccessToken())){
|
||||
@@ -74,7 +96,7 @@ public class WebProxyController {
|
||||
WebProxyService.DAYLIGHT_API,
|
||||
HttpMethod.valueOf(request.getMethod()),
|
||||
apiUrl,
|
||||
request.getQueryString(),
|
||||
NetworkUtil.sanitizeCRLF(request.getQueryString()),
|
||||
headers,
|
||||
getRequestBody(request),
|
||||
Duration.ofSeconds(daylightApiSetting.getApiTimeout()),
|
||||
@@ -83,15 +105,40 @@ public class WebProxyController {
|
||||
}
|
||||
@RequestMapping("/api/esb/proxy/**")
|
||||
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());
|
||||
String apiUrl = esbApiSetting.getServerUrl() + request.getRequestURI().replace("/api/esb/proxy", "");
|
||||
String queryString = request.getQueryString();
|
||||
boolean isLimo = "ESB_LIMO".equalsIgnoreCase(apiType);
|
||||
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);
|
||||
byte[] requestBody = getRequestBody(request);
|
||||
|
||||
EsbToken esbToken = esbTokenService.getApiAccessToken();
|
||||
EsbToken esbToken = esbTokenService.getApiAccessToken(apiType);
|
||||
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");
|
||||
}
|
||||
headers.set("authorization", esbToken.getAccessToken());
|
||||
@@ -127,14 +174,62 @@ public class WebProxyController {
|
||||
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());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@RequestMapping("/api/opera/proxy/**")
|
||||
public ResponseEntity<byte[]> invokeOperaApiProxy(HttpServletRequest request) throws Exception {
|
||||
String apiUrl = operaApiSetting.getServerUrl() + request.getRequestURI().replace("/api/opera/proxy", "");
|
||||
apiUrl = NetworkUtil.validateAndSanitizeUrl(apiUrl);
|
||||
return webProxyService.invokeRequest(
|
||||
WebProxyService.OPERA_API,
|
||||
HttpMethod.valueOf(request.getMethod()),
|
||||
apiUrl,
|
||||
request.getQueryString(),
|
||||
NetworkUtil.sanitizeCRLF(request.getQueryString()),
|
||||
extractHeaders(request),
|
||||
getRequestBody(request),
|
||||
Duration.ofSeconds(operaApiSetting.getTimeout()),
|
||||
@@ -142,6 +237,24 @@ public class WebProxyController {
|
||||
).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) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
Collections.list(request.getHeaderNames()).forEach(name -> {
|
||||
@@ -150,7 +263,7 @@ public class WebProxyController {
|
||||
!name.equalsIgnoreCase("application-id") &&
|
||||
!name.equalsIgnoreCase("authorization")
|
||||
) {
|
||||
headers.add(name, request.getHeader(name));
|
||||
headers.add(NetworkUtil.sanitizeCRLF(name), NetworkUtil.sanitizeCRLF(request.getHeader(name)));
|
||||
}
|
||||
});
|
||||
return headers;
|
||||
|
||||
@@ -26,4 +26,6 @@ public class SendNotificationRequest {
|
||||
|
||||
@Schema(description = "Type of booking ")
|
||||
private String type;
|
||||
|
||||
private String requestorId;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
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.proxy.exception.HttpProxyErrorHandler;
|
||||
import com.mgm.mcrm.apigateway.proxy.exception.ProxyErrorHandler;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
@@ -23,7 +22,6 @@ import reactor.core.publisher.Mono;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
@@ -31,9 +29,11 @@ public class WebProxyService {
|
||||
public final static String DAYLIGHT_API="DAYLIGHT_API";
|
||||
public final static String ESB_API="ESB_API";
|
||||
public final static String OPERA_API="OPERA_API";
|
||||
public final static String LIMO_API="LIMO_API";
|
||||
private final WebClient daylightWebClient;
|
||||
private final WebClient esbWebClient;
|
||||
private final WebClient operaWebClient;
|
||||
private final WebClient limoWebClient;
|
||||
private final Logger logger = LoggerFactory.getLogger(WebProxyService.class);
|
||||
|
||||
public Mono<ResponseEntity<byte[]>> invokeRequest(
|
||||
@@ -54,6 +54,8 @@ public class WebProxyService {
|
||||
targetWebClient=esbWebClient;
|
||||
}else if(OPERA_API.equalsIgnoreCase(apiType)){
|
||||
targetWebClient=operaWebClient;
|
||||
}else if(LIMO_API.equalsIgnoreCase(apiType)){
|
||||
targetWebClient=limoWebClient;
|
||||
}else{
|
||||
throw new Exception("Unknown request API type of "+apiType);
|
||||
}
|
||||
|
||||
@@ -139,88 +139,88 @@ public class BookingService {
|
||||
}
|
||||
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
|
||||
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());
|
||||
//设置Notification 内容
|
||||
String notificationTitle = "#EN# Room status updated#EN#" +
|
||||
"#CN#房間狀態已更改#CN#";
|
||||
String notificationContent = "#EN#Player {playerId}, {propertyName}, {roomCode},room status changed to reserved.#EN#" +
|
||||
"#CN#Player {playerId}, {propertyName}, {roomCode}, 房間狀態已預訂。#CN#";
|
||||
String[] placeholders = {
|
||||
"{playerId}", "{propertyName}", "{roomCode}"
|
||||
};
|
||||
LogUtil.info(BookingService.class,"Set notification info");
|
||||
String[] values = {
|
||||
StringUtils.defaultString(dbBooking.getPlayerId()),
|
||||
StringUtils.defaultString(property == null ? null : property.getName()),
|
||||
StringUtils.defaultString(dbBooking.getRoomTypeCode())
|
||||
};
|
||||
LogUtil.info(BookingService.class,"Replace each");
|
||||
notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
||||
String transactionId = "DLBKSC"+dbBooking.getId();
|
||||
LogUtil.info(BookingService.class,"Get device token from DB Start");
|
||||
LogUtil.info(BookingService.class,"dbBooking.getCreatedBy()=" + dbBooking.getCreatedBy());
|
||||
SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(StringUtils.trim(dbBooking.getCreatedBy()));
|
||||
LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
||||
String deviceTokenValue =null;
|
||||
String finalTitle = null;
|
||||
String finalContent = null;
|
||||
if(deviceToken!=null){
|
||||
deviceTokenValue = deviceToken.getDeviceToken();
|
||||
finalTitle = notificationUtil.distinguishLanguage(notificationTitle,deviceToken.getUseLanguageType());
|
||||
notificationContent = notificationUtil.distinguishLanguage(notificationContent,deviceToken.getUseLanguageType());
|
||||
|
||||
}
|
||||
// NOTIFICATION
|
||||
apnNotificationService.pushApnMessage(transactionId,deviceTokenValue,finalTitle,notificationContent,true);
|
||||
}
|
||||
|
||||
LogUtil.info(BookingService.class,"Daylight webhook updated, prepare send notification");
|
||||
log.info("dbBooking checkin={}, checkout={}", checkInDate, checkOutDate);
|
||||
log.info("dlBooking checkin={}, checkout={}", daylightBooking.getCheckinDate(), daylightBooking.getCheckoutDate());
|
||||
LogUtil.info(BookingService.class,"Db booking status=" + dbBookingStatus);
|
||||
//Send notification to Booker when Booking C/I | C/O date changed
|
||||
if ((checkInDate != null && !checkInDate.equals(daylightBooking.getCheckinDate()))||
|
||||
(checkOutDate != null && !checkOutDate.equals(daylightBooking.getCheckoutDate()))) {
|
||||
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());
|
||||
|
||||
|
||||
//设置Notification 内容
|
||||
String notificationTitle = "#EN# Room status updated#EN#" +
|
||||
"#CN#房間狀態已更改#CN#";
|
||||
String notificationContent = "#EN#Player {playerId}, {propertyName}, {roomCode},Stay date changed.#EN#" +
|
||||
"#CN#Player {playerId}, {propertyName}, {roomCode}, 住宿日期已變更。#CN#";
|
||||
String[] placeholders = {
|
||||
"{playerId}", "{propertyName}", "{roomCode}"
|
||||
};
|
||||
String[] values = {
|
||||
StringUtils.defaultString(dbBooking.getPlayerId()),
|
||||
StringUtils.defaultString(property == null ? null : property.getName()),
|
||||
StringUtils.defaultString(dbBooking.getRoomTypeCode())
|
||||
};
|
||||
|
||||
notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
||||
String transactionId = "DLBKDC" + dbBooking.getId();
|
||||
|
||||
SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(StringUtils.trim(dbBooking.getCreatedBy()));
|
||||
LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
||||
String deviceTokenValue = null;
|
||||
String finalTitle = null;
|
||||
String finalContent = null;
|
||||
if (deviceToken != null) {
|
||||
LogUtil.info(BookingService.class,"Get device Token success");
|
||||
deviceTokenValue = deviceToken.getDeviceToken();
|
||||
finalTitle = notificationUtil.distinguishLanguage(notificationTitle, deviceToken.getUseLanguageType());
|
||||
notificationContent = notificationUtil.distinguishLanguage(notificationContent, deviceToken.getUseLanguageType());
|
||||
}
|
||||
// NOTIFICATION
|
||||
apnNotificationService.pushApnMessage(transactionId, deviceTokenValue, finalTitle, notificationContent, true);
|
||||
}
|
||||
LogUtil.info(BookingService.class,"End send notification function");
|
||||
// //Send Notification to Booker when booking lastOpera status Changed
|
||||
// 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());
|
||||
// //设置Notification 内容
|
||||
// String notificationTitle = "#EN# Room status updated#EN#" +
|
||||
// "#CN#房間狀態已更改#CN#";
|
||||
// String notificationContent = "#EN#Player {playerId}, {propertyName}, {roomCode},room status changed to reserved.#EN#" +
|
||||
// "#CN#Player {playerId}, {propertyName}, {roomCode}, 房間狀態已預訂。#CN#";
|
||||
// String[] placeholders = {
|
||||
// "{playerId}", "{propertyName}", "{roomCode}"
|
||||
// };
|
||||
// LogUtil.info(BookingService.class,"Set notification info");
|
||||
// String[] values = {
|
||||
// StringUtils.defaultString(dbBooking.getPlayerId()),
|
||||
// StringUtils.defaultString(property == null ? null : property.getName()),
|
||||
// StringUtils.defaultString(dbBooking.getRoomTypeCode())
|
||||
// };
|
||||
// LogUtil.info(BookingService.class,"Replace each");
|
||||
// notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
||||
// String transactionId = "DLBKSC"+dbBooking.getId();
|
||||
// LogUtil.info(BookingService.class,"Get device token from DB Start");
|
||||
// LogUtil.info(BookingService.class,"dbBooking.getCreatedBy()=" + dbBooking.getCreatedBy());
|
||||
// SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(StringUtils.trim(dbBooking.getCreatedBy()));
|
||||
// LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
||||
// String deviceTokenValue =null;
|
||||
// String finalTitle = null;
|
||||
// String finalContent = null;
|
||||
// if(deviceToken!=null){
|
||||
// deviceTokenValue = deviceToken.getDeviceToken();
|
||||
// finalTitle = notificationUtil.distinguishLanguage(notificationTitle,deviceToken.getUseLanguageType());
|
||||
// notificationContent = notificationUtil.distinguishLanguage(notificationContent,deviceToken.getUseLanguageType());
|
||||
//
|
||||
// }
|
||||
//// NOTIFICATION
|
||||
// apnNotificationService.pushApnMessage(transactionId,deviceTokenValue,finalTitle,notificationContent,true);
|
||||
// }
|
||||
//
|
||||
// LogUtil.info(BookingService.class,"Daylight webhook updated, prepare send notification");
|
||||
// log.info("dbBooking checkin={}, checkout={}", checkInDate, checkOutDate);
|
||||
// log.info("dlBooking checkin={}, checkout={}", daylightBooking.getCheckinDate(), daylightBooking.getCheckoutDate());
|
||||
// LogUtil.info(BookingService.class,"Db booking status=" + dbBookingStatus);
|
||||
// //Send notification to Booker when Booking C/I | C/O date changed
|
||||
// if ((checkInDate != null && !checkInDate.equals(daylightBooking.getCheckinDate()))||
|
||||
// (checkOutDate != null && !checkOutDate.equals(daylightBooking.getCheckoutDate()))) {
|
||||
// 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());
|
||||
//
|
||||
//
|
||||
// //设置Notification 内容
|
||||
// String notificationTitle = "#EN# Room status updated#EN#" +
|
||||
// "#CN#房間狀態已更改#CN#";
|
||||
// String notificationContent = "#EN#Player {playerId}, {propertyName}, {roomCode},Stay date changed.#EN#" +
|
||||
// "#CN#Player {playerId}, {propertyName}, {roomCode}, 住宿日期已變更。#CN#";
|
||||
// String[] placeholders = {
|
||||
// "{playerId}", "{propertyName}", "{roomCode}"
|
||||
// };
|
||||
// String[] values = {
|
||||
// StringUtils.defaultString(dbBooking.getPlayerId()),
|
||||
// StringUtils.defaultString(property == null ? null : property.getName()),
|
||||
// StringUtils.defaultString(dbBooking.getRoomTypeCode())
|
||||
// };
|
||||
//
|
||||
// notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
||||
// String transactionId = "DLBKDC" + dbBooking.getId();
|
||||
//
|
||||
// SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(StringUtils.trim(dbBooking.getCreatedBy()));
|
||||
// LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
||||
// String deviceTokenValue = null;
|
||||
// String finalTitle = null;
|
||||
// String finalContent = null;
|
||||
// if (deviceToken != null) {
|
||||
// LogUtil.info(BookingService.class,"Get device Token success");
|
||||
// deviceTokenValue = deviceToken.getDeviceToken();
|
||||
// finalTitle = notificationUtil.distinguishLanguage(notificationTitle, deviceToken.getUseLanguageType());
|
||||
// notificationContent = notificationUtil.distinguishLanguage(notificationContent, deviceToken.getUseLanguageType());
|
||||
// }
|
||||
//// NOTIFICATION
|
||||
// apnNotificationService.pushApnMessage(transactionId, deviceTokenValue, finalTitle, notificationContent, true);
|
||||
// }
|
||||
// LogUtil.info(BookingService.class,"End send notification function");
|
||||
}
|
||||
|
||||
public Bookings findOneByDlProfileId(String dlProfileId) {
|
||||
|
||||
@@ -64,6 +64,7 @@ mcrm:
|
||||
username:
|
||||
password:
|
||||
ssl-bundle-name:
|
||||
skip-trust-validation: true
|
||||
server-url: https://eu1.api.uat.development.abovecloud.io
|
||||
request-timeout: 30
|
||||
token:
|
||||
@@ -85,7 +86,8 @@ mcrm:
|
||||
username:
|
||||
password:
|
||||
ssl-bundle-name:
|
||||
server-url:
|
||||
skip-trust-validation: true
|
||||
server-url: https://mgpmsdevows45.dev.mgmmacao.org
|
||||
request-timeout: 30
|
||||
security:
|
||||
authorization-data: "[MCRM_APP/securItykeyOfCrmapp87895312],[MCRM_CMS/seCuritykeyOfCrmCms8wetw432]"
|
||||
@@ -97,16 +99,37 @@ mcrm:
|
||||
username:
|
||||
password:
|
||||
ssl-bundle-name:
|
||||
server-url: https://hca.mcmsapoc.com
|
||||
skip-trust-validation: true
|
||||
server-url: https://mmesbdevapp14.dev.mgmmacao.org
|
||||
request-timeout: 30
|
||||
api-path:
|
||||
mcrm: /api/crmapp/v1.0
|
||||
limo: /api/limo/v1.0
|
||||
token:
|
||||
token-url: /RequestAccessToken
|
||||
mcrm:
|
||||
app-id: mgmtestuser001
|
||||
app-secret: MGM@!666
|
||||
limo:
|
||||
app-id: crmappid
|
||||
app-secret: crmsecuritykey
|
||||
request-timeout: 30
|
||||
default-expiry-second: 700
|
||||
security:
|
||||
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:
|
||||
email-sender:
|
||||
smtp-server: smtp.qq.com
|
||||
@@ -125,7 +148,7 @@ server:
|
||||
uri-encoding: UTF-8
|
||||
|
||||
logging:
|
||||
config: classpath:logback.xml
|
||||
config: classpath:log4j2-spring.xml
|
||||
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
@@ -156,3 +179,4 @@ apns:
|
||||
|
||||
daylight:
|
||||
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