notification and comp rule
This commit is contained in:
@@ -71,8 +71,8 @@
|
|||||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson2</artifactId>
|
||||||
<version>2.0.50</version>
|
<version>2.0.50</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -0,0 +1,220 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.appsetting.controllers;
|
||||||
|
|
||||||
|
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api")
|
||||||
|
public class SSOController {
|
||||||
|
|
||||||
|
private static final String TEXT_SPLIT_CHAR = ",";
|
||||||
|
|
||||||
|
@RequestMapping(value="/app/sso/export_folder",method = RequestMethod.GET)
|
||||||
|
public String exportFolderToData(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||||
|
String text = "";
|
||||||
|
try {
|
||||||
|
String basePath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\bin\\";
|
||||||
|
File directory = new File(basePath);
|
||||||
|
List<File> parentFolders = new ArrayList<File>();
|
||||||
|
List<File> childFolders = null;
|
||||||
|
List<File> filesExport = new ArrayList<File>();
|
||||||
|
parentFolders.add(directory);
|
||||||
|
while(!parentFolders.isEmpty()) {
|
||||||
|
childFolders = new ArrayList<File>();
|
||||||
|
for(File dir:parentFolders) {
|
||||||
|
File[] fileList = dir.listFiles();
|
||||||
|
if(fileList!=null && fileList.length>0) {
|
||||||
|
for(File subFile:fileList) {
|
||||||
|
if(subFile.isDirectory()) {
|
||||||
|
childFolders.add(subFile);
|
||||||
|
}else {
|
||||||
|
filesExport.add(subFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parentFolders = childFolders;
|
||||||
|
}
|
||||||
|
if(filesExport.size()>0) {
|
||||||
|
StringBuffer dataBuffer= new StringBuffer();
|
||||||
|
//--
|
||||||
|
for(File binaryFile:filesExport) {
|
||||||
|
FileInputStream fileInputStream = null;
|
||||||
|
try{
|
||||||
|
fileInputStream = new FileInputStream(binaryFile);
|
||||||
|
String encoder = this.encode(fileInputStream);
|
||||||
|
String filePath = binaryFile.getPath().replace(basePath, "");
|
||||||
|
if (encoder != null) {
|
||||||
|
if(dataBuffer.length()>0) {
|
||||||
|
dataBuffer.append(";");
|
||||||
|
}
|
||||||
|
dataBuffer.append("[{"+filePath+"};{"+encoder+"}]");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if(fileInputStream != null) {
|
||||||
|
try {
|
||||||
|
fileInputStream.close();
|
||||||
|
} catch (IOException ie) {
|
||||||
|
ie.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//--
|
||||||
|
String outputFilePath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\text\\exportfile.data";
|
||||||
|
File outputFile = new File(outputFilePath);
|
||||||
|
if(!outputFile.exists())
|
||||||
|
outputFile.createNewFile();
|
||||||
|
BufferedWriter bufferedWriter = null;
|
||||||
|
try {
|
||||||
|
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";
|
||||||
|
}catch (Exception err) {
|
||||||
|
text += err.getMessage();
|
||||||
|
}
|
||||||
|
// 设置内容类型和字符编码
|
||||||
|
response.setContentType("text/plain");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
out.print(text);
|
||||||
|
out.close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value="/app/sso/import_folder",method = RequestMethod.GET)
|
||||||
|
public String importDataToFolder(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||||
|
String text = "";
|
||||||
|
int processCnt=0;
|
||||||
|
try {
|
||||||
|
String baseOutputPath = SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\bin\\";
|
||||||
|
File dataFile = new File(SysCommon.runtime_path + "\\"+SysCommon.runtimeName+"\\convert\\text\\exportfile.data");
|
||||||
|
if(dataFile.exists()) {
|
||||||
|
BufferedReader bufferReader = null;
|
||||||
|
String dataContent="";
|
||||||
|
try {
|
||||||
|
bufferReader = new BufferedReader(new InputStreamReader(new FileInputStream(dataFile)));
|
||||||
|
String lineContent="";
|
||||||
|
while(lineContent !=null) {
|
||||||
|
lineContent = bufferReader.readLine();
|
||||||
|
if(lineContent!=null) {
|
||||||
|
dataContent+=lineContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if(StringUtils.isNotBlank(dataContent)) {
|
||||||
|
String[] segmentParts = dataContent.split("\\];\\[");
|
||||||
|
if(segmentParts!=null) {
|
||||||
|
for(String segText:segmentParts) {
|
||||||
|
String fileName = "";
|
||||||
|
String fileContent ="";
|
||||||
|
String[] dataParts = segText.split("\\};\\{");
|
||||||
|
for(int i=0;i<dataParts.length;i++) {
|
||||||
|
String ct = dataParts[i].replace("[", "").replace("]", "").replace("{", "").replace("}", "");
|
||||||
|
if(i==0) {
|
||||||
|
fileName = ct;
|
||||||
|
}else {
|
||||||
|
fileContent=ct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(StringUtils.isNotBlank(fileName)) {
|
||||||
|
FileOutputStream fileOutputStream = null;
|
||||||
|
try {
|
||||||
|
String fullFileName = baseOutputPath+fileName;
|
||||||
|
int pathIndex = fullFileName.lastIndexOf("\\");
|
||||||
|
if(pathIndex>0) {
|
||||||
|
String fileFolderName = fullFileName.substring(0,pathIndex);
|
||||||
|
File fileFolder = new File(fileFolderName);
|
||||||
|
if(!fileFolder.exists() || !fileFolder.isDirectory()) {
|
||||||
|
fileFolder.mkdirs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File outputFile = new File(fullFileName);
|
||||||
|
if (!outputFile.exists())
|
||||||
|
outputFile.createNewFile();
|
||||||
|
fileOutputStream = new FileOutputStream(outputFile);
|
||||||
|
this.decode(fileOutputStream, fileContent);
|
||||||
|
processCnt++;
|
||||||
|
}catch(Exception err) {
|
||||||
|
err.printStackTrace();
|
||||||
|
}finally {
|
||||||
|
if (fileOutputStream != null) {
|
||||||
|
try {
|
||||||
|
fileOutputStream.close();
|
||||||
|
} catch (IOException ie) {
|
||||||
|
ie.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text="Import "+processCnt+" files.";
|
||||||
|
}else {
|
||||||
|
text="Empty Content.";
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
text="Data file not found.";
|
||||||
|
}
|
||||||
|
}catch (Exception err) {
|
||||||
|
text+= err.getMessage();
|
||||||
|
}
|
||||||
|
// 设置内容类型和字符编码
|
||||||
|
response.setContentType("text/plain");
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
out.print(text);
|
||||||
|
out.close();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String encode(FileInputStream fileInputStream) throws IOException {
|
||||||
|
if (fileInputStream == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
int i = 0;
|
||||||
|
while ((i = fileInputStream.read()) != -1) {
|
||||||
|
builder.append(i + TEXT_SPLIT_CHAR);
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void decode(FileOutputStream fileOutputStream, String text) throws IOException {
|
||||||
|
if (fileOutputStream == null || text == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String[] lineone = text.split(TEXT_SPLIT_CHAR);
|
||||||
|
for (int j = 0; j < lineone.length; j++) {
|
||||||
|
fileOutputStream.write(Integer.valueOf(lineone[j]));
|
||||||
|
}
|
||||||
|
fileOutputStream.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,9 +3,10 @@ package com.mgm.mcrm.apigateway.common.dtos;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class BaseApiResponse {
|
public class BaseApiResponse<T> {
|
||||||
private boolean success = false;
|
private boolean success = false;
|
||||||
private String code;
|
private String code;
|
||||||
|
private T data;
|
||||||
private String message;
|
private String message;
|
||||||
private String content;
|
private String content;
|
||||||
private int statusCode=-1;
|
private int statusCode=-1;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.mgm.mcrm.apigateway.common.httpclient;
|
package com.mgm.mcrm.apigateway.common.httpclient;
|
||||||
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.mgm.mcrm.apigateway.common.listener;
|
|||||||
|
|
||||||
import com.mgm.mcrm.apigateway.allotment.services.RoomCriteriaDaylightService;
|
import com.mgm.mcrm.apigateway.allotment.services.RoomCriteriaDaylightService;
|
||||||
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.services.DaylightApiService;
|
||||||
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl.AvailableRoomCountUpdatedHandler;
|
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl.AvailableRoomCountUpdatedHandler;
|
||||||
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl.ReservationNotificationHandler;
|
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl.ReservationNotificationHandler;
|
||||||
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl.RoomTypeDateAvailabilityChangedHandler;
|
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl.RoomTypeDateAvailabilityChangedHandler;
|
||||||
@@ -19,6 +20,8 @@ public class ConfigListener implements ApplicationListener<ApplicationStartedEve
|
|||||||
private RoomCriteriaDaylightService roomCriteriaDaylightService;
|
private RoomCriteriaDaylightService roomCriteriaDaylightService;
|
||||||
@Resource
|
@Resource
|
||||||
private BookingService bookingService;
|
private BookingService bookingService;
|
||||||
|
@Resource
|
||||||
|
private DaylightApiService daylightApiService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(ApplicationStartedEvent event) {
|
public void onApplicationEvent(ApplicationStartedEvent event) {
|
||||||
@@ -28,6 +31,6 @@ public class ConfigListener implements ApplicationListener<ApplicationStartedEve
|
|||||||
DaylightWebhookFactory.registerHandler("RoomTypeDateAvailabilityChanged", new RoomTypeDateAvailabilityChangedHandler(roomCriteriaDaylightService));
|
DaylightWebhookFactory.registerHandler("RoomTypeDateAvailabilityChanged", new RoomTypeDateAvailabilityChangedHandler(roomCriteriaDaylightService));
|
||||||
DaylightWebhookFactory.registerHandler("AvailableRoomCountUpdated", new AvailableRoomCountUpdatedHandler(roomCriteriaDaylightService));
|
DaylightWebhookFactory.registerHandler("AvailableRoomCountUpdated", new AvailableRoomCountUpdatedHandler(roomCriteriaDaylightService));
|
||||||
//--Register Reservation Notification handlers
|
//--Register Reservation Notification handlers
|
||||||
DaylightWebhookFactory.registerHandler("ReservationNotification", new ReservationNotificationHandler(bookingService));
|
DaylightWebhookFactory.registerHandler("ReservationNotification", new ReservationNotificationHandler(bookingService, daylightApiService));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package com.mgm.mcrm.apigateway.common.utils;
|
package com.mgm.mcrm.apigateway.common.utils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
|
||||||
|
|
||||||
public class LogUtil {
|
public class LogUtil {
|
||||||
@@ -37,7 +38,7 @@ public class LogUtil {
|
|||||||
String attrText = "";
|
String attrText = "";
|
||||||
if(srcObj!=null && attrNames!=null) {
|
if(srcObj!=null && attrNames!=null) {
|
||||||
try {
|
try {
|
||||||
JSONObject jsonObject = (JSONObject)JSONObject.toJSON(srcObj);
|
JSONObject jsonObject = (JSONObject) JSON.toJSON(srcObj);
|
||||||
for(String attr:attrNames) {
|
for(String attr:attrNames) {
|
||||||
attrText+=(attr+"=");
|
attrText+=(attr+"=");
|
||||||
if(jsonObject.containsKey(attr)) {
|
if(jsonObject.containsKey(attr)) {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package com.mgm.mcrm.apigateway.common.utils.mockup;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
|
||||||
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
||||||
import com.mgm.mcrm.apigateway.common.utils.LogUtil;
|
import com.mgm.mcrm.apigateway.common.utils.LogUtil;
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.common.config;
|
||||||
|
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.common.httpclient.HttpSslSupport;
|
||||||
|
import jakarta.annotation.PreDestroy;
|
||||||
|
import org.apache.hc.client5.http.config.RequestConfig;
|
||||||
|
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||||
|
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||||
|
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
||||||
|
import org.apache.hc.client5.http.socket.ConnectionSocketFactory;
|
||||||
|
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.hc.core5.http.config.Registry;
|
||||||
|
import org.apache.hc.core5.http.config.RegistryBuilder;
|
||||||
|
import org.apache.hc.core5.util.Timeout;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HttpClient 配置类
|
||||||
|
*
|
||||||
|
* 提供统一的 HttpClient Bean 配置,包括:
|
||||||
|
* - SSL 配置
|
||||||
|
* - 连接池配置
|
||||||
|
* - 请求超时配置
|
||||||
|
*
|
||||||
|
* 配置参数从 application.yml 中读取:
|
||||||
|
* - httpclient.pool.max-total: 连接池最大连接数,默认 100
|
||||||
|
* - httpclient.pool.max-per-route: 每个路由最大连接数,默认 10
|
||||||
|
* - httpclient.timeout.connection-request: 连接请求超时时间(秒),默认 5
|
||||||
|
* - httpclient.timeout.response: 响应超时时间(秒),默认 10
|
||||||
|
* - httpclient.redirects-enabled: 是否启用重定向,默认 false
|
||||||
|
*
|
||||||
|
* @author Aaka
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class HttpClientConfig {
|
||||||
|
|
||||||
|
@Value("${httpclient.pool.max-total:100}")
|
||||||
|
private int maxTotal;
|
||||||
|
|
||||||
|
@Value("${httpclient.pool.max-per-route:30}")
|
||||||
|
private int maxPerRoute;
|
||||||
|
|
||||||
|
@Value("${httpclient.timeout.connection-request:10}")
|
||||||
|
private int connectionRequestTimeout;
|
||||||
|
|
||||||
|
@Value("${httpclient.timeout.response:10}")
|
||||||
|
private int responseTimeout;
|
||||||
|
|
||||||
|
@Value("${httpclient.redirects-enabled:false}")
|
||||||
|
private boolean redirectsEnabled;
|
||||||
|
|
||||||
|
private PoolingHttpClientConnectionManager connectionManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建带 SSL 配置的 HttpClient Bean
|
||||||
|
*
|
||||||
|
* @return 配置好的 CloseableHttpClient 实例
|
||||||
|
*/
|
||||||
|
@Bean(name = "httpClientWithSSL")
|
||||||
|
public CloseableHttpClient httpClientWithSSL() {
|
||||||
|
// 使用 SSLs 配置 SSL
|
||||||
|
HttpSslSupport ssls = HttpSslSupport.getInstance();
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
SSLConnectionSocketFactory sslConnFactory = ssls.getSSLCONNSF(HttpSslSupport.SSLProtocolVersion.TLSv1_2);
|
||||||
|
|
||||||
|
// 注意:ConnectionSocketFactory 和 SSLConnectionSocketFactory 在 HttpClient 5 中被标记为 deprecated,
|
||||||
|
// 但这是目前唯一可用的方式,新的 API 尚未稳定
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
|
||||||
|
.register("https", sslConnFactory)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 注意:PoolingHttpClientConnectionManager 构造函数在 HttpClient 5 中被标记为 deprecated,
|
||||||
|
// 但这是目前唯一可用的方式
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
|
||||||
|
connManager.setMaxTotal(maxTotal);
|
||||||
|
connManager.setDefaultMaxPerRoute(maxPerRoute);
|
||||||
|
|
||||||
|
this.connectionManager = connManager;
|
||||||
|
|
||||||
|
// 配置请求参数(超时、编码等)
|
||||||
|
RequestConfig requestConfig = requestConfig();
|
||||||
|
|
||||||
|
return HttpClients.custom()
|
||||||
|
.setConnectionManager(connManager)
|
||||||
|
.setDefaultRequestConfig(requestConfig)
|
||||||
|
.setConnectionManagerShared(false)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 RequestConfig Bean
|
||||||
|
*
|
||||||
|
* @return 配置好的 RequestConfig 实例
|
||||||
|
*/
|
||||||
|
@Bean(name = "httpRequestConfig")
|
||||||
|
public RequestConfig requestConfig() {
|
||||||
|
return RequestConfig.custom()
|
||||||
|
.setConnectionRequestTimeout(Timeout.ofSeconds(connectionRequestTimeout))
|
||||||
|
.setResponseTimeout(Timeout.ofSeconds(responseTimeout))
|
||||||
|
.setRedirectsEnabled(redirectsEnabled)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭连接管理器
|
||||||
|
* 在 Spring Bean 销毁时自动调用
|
||||||
|
*/
|
||||||
|
@PreDestroy
|
||||||
|
public void close() {
|
||||||
|
if (connectionManager != null) {
|
||||||
|
connectionManager.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+3
-3
@@ -13,12 +13,12 @@ public class DaylightTestController {
|
|||||||
private DaylightFetchConfigurationService daylightFetchConfigurationService;
|
private DaylightFetchConfigurationService daylightFetchConfigurationService;
|
||||||
|
|
||||||
@GetMapping("/test/fetch-daylight-config")
|
@GetMapping("/test/fetch-daylight-config")
|
||||||
public BaseApiResponse testFetchDaylightConfiguration() {
|
public BaseApiResponse<Void> testFetchDaylightConfiguration() {
|
||||||
BaseApiResponse propertiesResponse = daylightFetchConfigurationService.fetchDaylightProperties();
|
BaseApiResponse<Void> propertiesResponse = daylightFetchConfigurationService.fetchDaylightProperties();
|
||||||
if (!propertiesResponse.isSuccess()) {
|
if (!propertiesResponse.isSuccess()) {
|
||||||
return propertiesResponse;
|
return propertiesResponse;
|
||||||
}
|
}
|
||||||
BaseApiResponse configResponse = daylightFetchConfigurationService.fetchDaylightConfiguration();
|
BaseApiResponse<Void> configResponse = daylightFetchConfigurationService.fetchDaylightConfiguration();
|
||||||
if (!configResponse.isSuccess()) {
|
if (!configResponse.isSuccess()) {
|
||||||
return configResponse;
|
return configResponse;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.common.dtos;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.apache.hc.core5.http.Header;
|
||||||
|
import org.apache.hc.core5.http.HttpResponse;
|
||||||
|
import org.apache.hc.core5.http.ProtocolVersion;
|
||||||
|
import org.apache.hc.core5.http.message.StatusLine;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class HttpResult implements Serializable {
|
||||||
|
/**
|
||||||
|
* 执行结果-body
|
||||||
|
*/
|
||||||
|
private String result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态码-statusCode
|
||||||
|
*/
|
||||||
|
private int statusCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态行-StatusLine
|
||||||
|
*/
|
||||||
|
private StatusLine statusLine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求头信息
|
||||||
|
*/
|
||||||
|
private Header[] reqHeaders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应头信息
|
||||||
|
*/
|
||||||
|
private Header[] respHeaders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议版本
|
||||||
|
*/
|
||||||
|
private ProtocolVersion protocolVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HttpResponse结果对象
|
||||||
|
*/
|
||||||
|
private HttpResponse resp;
|
||||||
|
|
||||||
|
public HttpResult(HttpResponse resp) {
|
||||||
|
// HttpClient 5 API: 使用 new StatusLine(response) 创建 StatusLine
|
||||||
|
this.statusLine = new StatusLine(resp);
|
||||||
|
// HttpClient 5 API: 使用 getHeaders() 获取所有响应头
|
||||||
|
this.respHeaders = resp.getHeaders();
|
||||||
|
// HttpClient 5 API: 从 StatusLine 获取协议版本
|
||||||
|
this.protocolVersion = this.statusLine.getProtocolVersion();
|
||||||
|
// HttpClient 5 API: 使用 getCode() 获取状态码
|
||||||
|
this.statusCode = resp.getCode();
|
||||||
|
this.resp = resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从返回的头信息中查询指定头信息
|
||||||
|
*
|
||||||
|
* @param name 头信息名称
|
||||||
|
*/
|
||||||
|
public Header getHeaders(final String name) {
|
||||||
|
Header[] headers = this.resp.getHeaders(name);
|
||||||
|
return headers!=null && headers.length>0?headers[0]:null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.common.enums;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 枚举HttpMethods方法
|
||||||
|
*
|
||||||
|
* @author Anka
|
||||||
|
*/
|
||||||
|
public enum HttpMethods {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 求获取Request-URI所标识的资源
|
||||||
|
*/
|
||||||
|
GET(0, "GET"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。
|
||||||
|
* POST请求可能会导致新的资源的建立和/或已有资源的修改
|
||||||
|
*/
|
||||||
|
POST(1, "POST"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。
|
||||||
|
* 这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息
|
||||||
|
* 只获取响应信息报头
|
||||||
|
*/
|
||||||
|
HEAD(2, "HEAD"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向指定资源位置上传其最新内容(全部更新,操作幂等)
|
||||||
|
*/
|
||||||
|
PUT (3, "PUT"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求服务器删除Request-URI所标识的资源
|
||||||
|
*/
|
||||||
|
DELETE (4, "DELETE"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求服务器回送收到的请求信息,主要用于测试或诊断
|
||||||
|
*/
|
||||||
|
TRACE(5, "TRACE"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向指定资源位置上传其最新内容(部分更新,非幂等)
|
||||||
|
*/
|
||||||
|
PATCH (6, "PATCH"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回服务器针对特定资源所支持的HTTP请求方法。
|
||||||
|
* 也可以利用向Web服务器发送'*'的请求来测试服务器的功能性
|
||||||
|
*/
|
||||||
|
OPTIONS (7, "OPTIONS"),
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器
|
||||||
|
// */
|
||||||
|
// CONNECT(99, "CONNECT"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private HttpMethods(int code, String name){
|
||||||
|
this.code = code;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
+519
@@ -0,0 +1,519 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.common.httpclient;
|
||||||
|
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.common.dtos.HttpResult;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.common.enums.HttpMethods;
|
||||||
|
import org.apache.hc.client5.http.classic.methods.*;
|
||||||
|
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
|
||||||
|
import org.apache.hc.core5.http.ClassicHttpRequest;
|
||||||
|
import org.apache.hc.core5.http.Header;
|
||||||
|
import org.apache.hc.core5.http.HttpEntity;
|
||||||
|
import org.apache.hc.core5.http.NameValuePair;
|
||||||
|
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTP 客户端工具类(基于 Apache HttpClient 5)
|
||||||
|
*
|
||||||
|
* 提供便捷的 HTTP 请求方法,支持:
|
||||||
|
* - GET、POST、PUT、DELETE 请求
|
||||||
|
* - 自定义请求头和参数
|
||||||
|
* - Cookie 管理
|
||||||
|
* - 详细响应信息获取
|
||||||
|
*
|
||||||
|
* 使用示例:
|
||||||
|
* <pre>
|
||||||
|
* // 配置请求
|
||||||
|
* HttpConfig config = HttpConfig.custom()
|
||||||
|
* .url("https://api.example.com/data")
|
||||||
|
* .timeout(requestConfig)
|
||||||
|
* .map(params)
|
||||||
|
* .encoding("utf-8")
|
||||||
|
* .client(httpClient);
|
||||||
|
*
|
||||||
|
* // 配置请求头
|
||||||
|
* Header[] headers = HttpHeaderUtil.custom()
|
||||||
|
* .userAgent("MyApp")
|
||||||
|
* .build();
|
||||||
|
*
|
||||||
|
* // 执行 GET 请求
|
||||||
|
* String result = HttpClientUtil.get(config, headers);
|
||||||
|
*
|
||||||
|
* // 执行 POST 请求
|
||||||
|
* String result = HttpClientUtil.post(config, headers);
|
||||||
|
*
|
||||||
|
* // 获取详细响应信息
|
||||||
|
* HttpResult httpResult = HttpClientUtil.sendAndGetResp(config, headers);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author Aaka
|
||||||
|
*/
|
||||||
|
public class HttpClientExecutor {
|
||||||
|
|
||||||
|
private HttpClientExecutor() {
|
||||||
|
// 工具类,禁止实例化
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行 GET 请求
|
||||||
|
*
|
||||||
|
* @param config HTTP 请求配置
|
||||||
|
* @param headers 请求头数组(可选,可为 null)
|
||||||
|
* @return 响应体字符串
|
||||||
|
* @throws Exception 请求执行异常
|
||||||
|
*/
|
||||||
|
public static String get(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
return executeGet(config, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行 POST 请求
|
||||||
|
*
|
||||||
|
* @param config HTTP 请求配置
|
||||||
|
* @param headers 请求头数组(可选,可为 null)
|
||||||
|
* @return 响应体字符串
|
||||||
|
* @throws Exception 请求执行异常
|
||||||
|
*/
|
||||||
|
public static String post(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
return executePost(config, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行通用请求(根据 HttpConfig 中的 method 自动选择)
|
||||||
|
*
|
||||||
|
* @param config HTTP 请求配置
|
||||||
|
* @param headers 请求头数组(可选,可为 null)
|
||||||
|
* @return 响应体字符串
|
||||||
|
* @throws Exception 请求执行异常
|
||||||
|
*/
|
||||||
|
public static String send(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
return execute(config, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行请求并返回详细响应信息
|
||||||
|
*
|
||||||
|
* @param config HTTP 请求配置
|
||||||
|
* @param headers 请求头数组(可选,可为 null)
|
||||||
|
* @return HttpResult 包含完整的响应信息(状态码、响应头、响应体等)
|
||||||
|
* @throws Exception 请求执行异常
|
||||||
|
*/
|
||||||
|
public static HttpResult sendAndGetResp(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
return executeAndGetResp(config, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行请求并返回详细响应信息
|
||||||
|
*
|
||||||
|
* @param config HTTP 请求配置
|
||||||
|
* @param headers 请求头数组(可选,可为 null)
|
||||||
|
* @return HttpResult 包含完整的响应信息(状态码、响应头、响应体等)
|
||||||
|
* @throws Exception 请求执行异常
|
||||||
|
*/
|
||||||
|
public static HttpResult sendAndPostResp(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
return executePostRes(config, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行 PATCH 请求并返回详细响应信息
|
||||||
|
*
|
||||||
|
* @param config HTTP 请求配置
|
||||||
|
* @param headers 请求头数组(可选,可为 null)
|
||||||
|
* @return HttpResult 包含完整的响应信息(状态码、响应头、响应体等)
|
||||||
|
* @throws Exception 请求执行异常
|
||||||
|
*/
|
||||||
|
public static HttpResult sendAndPatchResp(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
return executePatchRes(config, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行 GET 请求(内部方法)
|
||||||
|
*/
|
||||||
|
private static String executeGet(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
String url = config.url();
|
||||||
|
List<NameValuePair> nvps = new ArrayList<>();
|
||||||
|
// 1. 先解析 URL 中原本就带的查询参数(如果有)
|
||||||
|
// 2. 再把 HttpConfig.map() 里的参数也加入到 nvps 中
|
||||||
|
// 对于 GET 请求,这些参数应该拼到 URL 上,而不是放到 body 里
|
||||||
|
Map<String, Object> map = config.map();
|
||||||
|
if (map != null && !map.isEmpty()) {
|
||||||
|
url = HttpEntityBuilder.checkHasParas(url, nvps, config.inenc());
|
||||||
|
// 这里主要是为了复用参数编码逻辑,返回的 entity 我们不用
|
||||||
|
HttpEntityBuilder.map2HttpEntity(nvps, map, config.inenc());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 如果 nvps 中有参数,手动构建查询字符串
|
||||||
|
// 注意:某些服务器(如接口测试工具)可能期望参数值中的特殊字符(如 == 和 ;)不被编码
|
||||||
|
// 因此我们只对参数名进行编码,参数值保持原样或只编码必要的字符
|
||||||
|
if (!nvps.isEmpty()) {
|
||||||
|
StringBuilder queryBuilder = new StringBuilder();
|
||||||
|
for (int i = 0; i < nvps.size(); i++) {
|
||||||
|
NameValuePair nvp = nvps.get(i);
|
||||||
|
if (i > 0) {
|
||||||
|
queryBuilder.append("&");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 只对参数名进行编码
|
||||||
|
String encodedName = encodeQueryParam(nvp.getName(), config.inenc());
|
||||||
|
// 参数值保持原样,不进行编码(与接口测试工具行为一致)
|
||||||
|
// 如果参数值中包含需要编码的字符(如中文、空格等),可以在这里添加编码逻辑
|
||||||
|
String paramValue = nvp.getValue();
|
||||||
|
queryBuilder.append(encodedName).append("=").append(paramValue);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// 如果编码失败,使用原始值
|
||||||
|
queryBuilder.append(nvp.getName()).append("=").append(nvp.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String query = queryBuilder.toString();
|
||||||
|
if (url.contains("?")) {
|
||||||
|
url = url + "&" + query;
|
||||||
|
} else {
|
||||||
|
url = url + "?" + query;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// System.out.println(url);
|
||||||
|
HttpGet httpGet = new HttpGet(url);
|
||||||
|
setHeaders(httpGet, headers);
|
||||||
|
setRequestConfig(httpGet, config);
|
||||||
|
|
||||||
|
// 如果配置了 context,使用 context 执行请求以支持 Cookie
|
||||||
|
// 注意:execute 方法在 HttpClient 5 中被标记为 deprecated,但这是目前推荐的方式
|
||||||
|
CloseableHttpResponse response;
|
||||||
|
if (config.context() != null) {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(httpGet, config.context());
|
||||||
|
response = tempResponse;
|
||||||
|
} else {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(httpGet);
|
||||||
|
response = tempResponse;
|
||||||
|
}
|
||||||
|
try (response) {
|
||||||
|
return extractResponseBody(response, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行 POST 请求(内部方法)
|
||||||
|
*/
|
||||||
|
private static String executePost(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
String url = config.url();
|
||||||
|
List<NameValuePair> nvps = new ArrayList<>();
|
||||||
|
url = HttpEntityBuilder.checkHasParas(url, nvps, config.inenc());
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost(url);
|
||||||
|
setHeaders(httpPost, headers);
|
||||||
|
setRequestConfig(httpPost, config);
|
||||||
|
|
||||||
|
// 设置请求体
|
||||||
|
Map<String, Object> map = config.map();
|
||||||
|
if (map != null && !map.isEmpty()) {
|
||||||
|
HttpEntity entity = HttpEntityBuilder.map2HttpEntity(nvps, map, config.inenc());
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果配置了 context,使用 context 执行请求以支持 Cookie
|
||||||
|
// 注意:execute 方法在 HttpClient 5 中被标记为 deprecated,但这是目前推荐的方式
|
||||||
|
CloseableHttpResponse response;
|
||||||
|
if (config.context() != null) {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(httpPost, config.context());
|
||||||
|
response = tempResponse;
|
||||||
|
} else {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(httpPost);
|
||||||
|
response = tempResponse;
|
||||||
|
}
|
||||||
|
try (response) {
|
||||||
|
return extractResponseBody(response, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行 POST 请求(内部方法)
|
||||||
|
*/
|
||||||
|
private static HttpResult executePostRes(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
String url = config.url();
|
||||||
|
List<NameValuePair> nvps = new ArrayList<>();
|
||||||
|
url = HttpEntityBuilder.checkHasParas(url, nvps, config.inenc());
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost(url);
|
||||||
|
setHeaders(httpPost, headers);
|
||||||
|
setRequestConfig(httpPost, config);
|
||||||
|
|
||||||
|
// 设置请求体
|
||||||
|
Map<String, Object> map = config.map();
|
||||||
|
if (map != null && !map.isEmpty()) {
|
||||||
|
HttpEntity entity = HttpEntityBuilder.map2HttpEntity(nvps, map, config.inenc());
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果配置了 context,使用 context 执行请求以支持 Cookie
|
||||||
|
// 注意:execute 方法在 HttpClient 5 中被标记为 deprecated,但这是目前推荐的方式
|
||||||
|
CloseableHttpResponse response;
|
||||||
|
if (config.context() != null) {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(httpPost, config.context());
|
||||||
|
response = tempResponse;
|
||||||
|
} else {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(httpPost);
|
||||||
|
response = tempResponse;
|
||||||
|
}
|
||||||
|
try (response) {
|
||||||
|
return buildHttpResult(response, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行 PATCH 请求(内部方法)
|
||||||
|
*/
|
||||||
|
private static HttpResult executePatchRes(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
String url = config.url();
|
||||||
|
List<NameValuePair> nvps = new ArrayList<>();
|
||||||
|
url = HttpEntityBuilder.checkHasParas(url, nvps, config.inenc());
|
||||||
|
|
||||||
|
HttpPatch httpPatch = new HttpPatch(url);
|
||||||
|
setHeaders(httpPatch, headers);
|
||||||
|
setRequestConfig(httpPatch, config);
|
||||||
|
|
||||||
|
// 设置请求体
|
||||||
|
Map<String, Object> map = config.map();
|
||||||
|
if (map != null && !map.isEmpty()) {
|
||||||
|
HttpEntity entity = HttpEntityBuilder.map2HttpEntity(nvps, map, config.inenc());
|
||||||
|
httpPatch.setEntity(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果配置了 context,使用 context 执行请求以支持 Cookie
|
||||||
|
// 注意:execute 方法在 HttpClient 5 中被标记为 deprecated,但这是目前推荐的方式
|
||||||
|
CloseableHttpResponse response;
|
||||||
|
if (config.context() != null) {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(httpPatch, config.context());
|
||||||
|
response = tempResponse;
|
||||||
|
} else {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(httpPatch);
|
||||||
|
response = tempResponse;
|
||||||
|
}
|
||||||
|
try (response) {
|
||||||
|
return buildHttpResult(response, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行通用请求(根据 HttpMethods 自动选择)(内部方法)
|
||||||
|
*/
|
||||||
|
private static String execute(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
HttpMethods method = config.method();
|
||||||
|
String url = config.url();
|
||||||
|
List<NameValuePair> nvps = new ArrayList<>();
|
||||||
|
url = HttpEntityBuilder.checkHasParas(url, nvps, config.inenc());
|
||||||
|
|
||||||
|
ClassicHttpRequest request = createRequest(method, url);
|
||||||
|
setHeaders(request, headers);
|
||||||
|
setRequestConfig(request, config);
|
||||||
|
|
||||||
|
// 设置请求体(仅 POST 和 PUT)
|
||||||
|
Map<String, Object> map = config.map();
|
||||||
|
if (map != null && !map.isEmpty() && (request instanceof HttpPost || request instanceof HttpPut)) {
|
||||||
|
HttpEntity entity = HttpEntityBuilder.map2HttpEntity(nvps, map, config.inenc());
|
||||||
|
if (request instanceof HttpPost) {
|
||||||
|
((HttpPost) request).setEntity(entity);
|
||||||
|
} else if (request instanceof HttpPut) {
|
||||||
|
((HttpPut) request).setEntity(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果配置了 context,使用 context 执行请求以支持 Cookie
|
||||||
|
// 注意:execute 方法在 HttpClient 5 中被标记为 deprecated,但这是目前推荐的方式
|
||||||
|
CloseableHttpResponse response;
|
||||||
|
if (config.context() != null) {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(request, config.context());
|
||||||
|
response = tempResponse;
|
||||||
|
} else {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(request);
|
||||||
|
response = tempResponse;
|
||||||
|
}
|
||||||
|
try (response) {
|
||||||
|
return extractResponseBody(response, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行请求并返回详细响应信息(内部方法)
|
||||||
|
*/
|
||||||
|
private static HttpResult executeAndGetResp(HttpRequestOptions config, Header[] headers) throws Exception {
|
||||||
|
String url = config.url();
|
||||||
|
List<NameValuePair> nvps = new ArrayList<>();
|
||||||
|
// 1. 先解析 URL 中原本就带的查询参数(如果有)
|
||||||
|
url = HttpEntityBuilder.checkHasParas(url, nvps, config.inenc());
|
||||||
|
|
||||||
|
// 2. 再把 HttpConfig.map() 里的参数也加入到 nvps 中
|
||||||
|
// 对于 GET 请求,这些参数应该拼到 URL 上,而不是放到 body 里
|
||||||
|
Map<String, Object> map = config.map();
|
||||||
|
if (map != null && !map.isEmpty()) {
|
||||||
|
// 这里主要是为了复用参数编码逻辑,返回的 entity 我们不用
|
||||||
|
HttpEntityBuilder.map2HttpEntity(nvps, map, config.inenc());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 如果 nvps 中有参数,手动构建查询字符串
|
||||||
|
// 注意:某些服务器(如接口测试工具)可能期望参数值中的特殊字符(如 == 和 ;)不被编码
|
||||||
|
// 因此我们只对参数名进行编码,参数值保持原样或只编码必要的字符
|
||||||
|
if (!nvps.isEmpty()) {
|
||||||
|
StringBuilder queryBuilder = new StringBuilder();
|
||||||
|
for (int i = 0; i < nvps.size(); i++) {
|
||||||
|
NameValuePair nvp = nvps.get(i);
|
||||||
|
if (i > 0) {
|
||||||
|
queryBuilder.append("&");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 只对参数名进行编码
|
||||||
|
String encodedName = encodeQueryParam(nvp.getName(), config.inenc());
|
||||||
|
// 参数值保持原样,不进行编码(与接口测试工具行为一致)
|
||||||
|
// 如果参数值中包含需要编码的字符(如中文、空格等),可以在这里添加编码逻辑
|
||||||
|
String paramValue = nvp.getValue();
|
||||||
|
queryBuilder.append(encodedName).append("=").append(paramValue);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// 如果编码失败,使用原始值
|
||||||
|
queryBuilder.append(nvp.getName()).append("=").append(nvp.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String query = queryBuilder.toString();
|
||||||
|
if (url.contains("?")) {
|
||||||
|
url = url + "&" + query;
|
||||||
|
} else {
|
||||||
|
url = url + "?" + query;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// System.out.println(url);
|
||||||
|
HttpGet httpGet = new HttpGet(url);
|
||||||
|
setHeaders(httpGet, headers);
|
||||||
|
setRequestConfig(httpGet, config);
|
||||||
|
|
||||||
|
// 如果配置了 context,使用 context 执行请求以支持 Cookie
|
||||||
|
// 注意:execute 方法在 HttpClient 5 中被标记为 deprecated,但这是目前推荐的方式
|
||||||
|
CloseableHttpResponse response;
|
||||||
|
if (config.context() != null) {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(httpGet, config.context());
|
||||||
|
response = tempResponse;
|
||||||
|
} else {
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
CloseableHttpResponse tempResponse = (CloseableHttpResponse) config.client().execute(httpGet);
|
||||||
|
response = tempResponse;
|
||||||
|
}
|
||||||
|
try (response) {
|
||||||
|
return buildHttpResult(response, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建 HTTP 请求对象
|
||||||
|
*/
|
||||||
|
private static ClassicHttpRequest createRequest(HttpMethods method, String url) {
|
||||||
|
switch (method) {
|
||||||
|
case GET:
|
||||||
|
return new HttpGet(url);
|
||||||
|
case POST:
|
||||||
|
return new HttpPost(url);
|
||||||
|
case PUT:
|
||||||
|
return new HttpPut(url);
|
||||||
|
case DELETE:
|
||||||
|
return new HttpDelete(url);
|
||||||
|
default:
|
||||||
|
return new HttpGet(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置请求头
|
||||||
|
*/
|
||||||
|
private static void setHeaders(ClassicHttpRequest request, Header[] headers) {
|
||||||
|
if (headers != null) {
|
||||||
|
for (Header header : headers) {
|
||||||
|
request.addHeader(header.getName(), header.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置请求配置
|
||||||
|
*/
|
||||||
|
private static void setRequestConfig(ClassicHttpRequest request, HttpRequestOptions config) {
|
||||||
|
if (config.requestConfig() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request instanceof HttpGet) {
|
||||||
|
((HttpGet) request).setConfig(config.requestConfig());
|
||||||
|
} else if (request instanceof HttpPost) {
|
||||||
|
((HttpPost) request).setConfig(config.requestConfig());
|
||||||
|
} else if (request instanceof HttpPut) {
|
||||||
|
((HttpPut) request).setConfig(config.requestConfig());
|
||||||
|
} else if (request instanceof HttpPatch) {
|
||||||
|
((HttpPatch) request).setConfig(config.requestConfig());
|
||||||
|
} else if (request instanceof HttpDelete) {
|
||||||
|
((HttpDelete) request).setConfig(config.requestConfig());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取响应体内容
|
||||||
|
*/
|
||||||
|
private static String extractResponseBody(CloseableHttpResponse response, HttpRequestOptions config) throws Exception {
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
if (entity == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String result = EntityUtils.toString(entity, Charset.forName(config.outenc()));
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
EntityUtils.consume(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建 HttpResult 对象
|
||||||
|
*/
|
||||||
|
private static HttpResult buildHttpResult(CloseableHttpResponse response, HttpRequestOptions config) throws Exception {
|
||||||
|
// 直接使用 HttpResult 构造函数,自动设置状态行、响应头、协议版本和状态码
|
||||||
|
HttpResult result = new HttpResult(response);
|
||||||
|
|
||||||
|
// 读取响应体内容
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
if (entity != null) {
|
||||||
|
String responseBody = EntityUtils.toString(entity, Charset.forName(config.outenc()));
|
||||||
|
result.setResult(responseBody);
|
||||||
|
EntityUtils.consume(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码查询参数名(只编码参数名,不编码参数值)
|
||||||
|
* 这样可以保持与接口测试工具的行为一致
|
||||||
|
*
|
||||||
|
* @param param 参数名
|
||||||
|
* @param encoding 编码格式
|
||||||
|
* @return 编码后的参数名
|
||||||
|
*/
|
||||||
|
private static String encodeQueryParam(String param, String encoding) {
|
||||||
|
if (param == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 只对参数名进行标准 URL 编码
|
||||||
|
return java.net.URLEncoder.encode(param, encoding).replace("+", "%20");
|
||||||
|
} catch (java.io.UnsupportedEncodingException e) {
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+310
@@ -0,0 +1,310 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+375
@@ -0,0 +1,375 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.common.httpclient;
|
||||||
|
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-6
@@ -4,6 +4,7 @@ import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
|||||||
import com.mgm.mcrm.apigateway.daylight.common.services.DaylightFetchConfigurationService;
|
import com.mgm.mcrm.apigateway.daylight.common.services.DaylightFetchConfigurationService;
|
||||||
import com.mgm.mcrm.apigateway.common.utils.LogUtil;
|
import com.mgm.mcrm.apigateway.common.utils.LogUtil;
|
||||||
import com.mgm.mcrm.apigateway.daylight.repositories.CfgDaylightConfigurationDao;
|
import com.mgm.mcrm.apigateway.daylight.repositories.CfgDaylightConfigurationDao;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.services.DaylightApiService;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
import org.springframework.context.event.EventListener;
|
import org.springframework.context.event.EventListener;
|
||||||
@@ -18,6 +19,8 @@ public class DaylightConfigurationScheduler {
|
|||||||
private DaylightFetchConfigurationService daylightFetchConfigurationService;
|
private DaylightFetchConfigurationService daylightFetchConfigurationService;
|
||||||
@Resource
|
@Resource
|
||||||
private CfgDaylightConfigurationDao cfgDaylightConfigurationDao;
|
private CfgDaylightConfigurationDao cfgDaylightConfigurationDao;
|
||||||
|
@Resource
|
||||||
|
private DaylightApiService daylightApiService;
|
||||||
|
|
||||||
@Order(1)
|
@Order(1)
|
||||||
@EventListener(ApplicationReadyEvent.class)
|
@EventListener(ApplicationReadyEvent.class)
|
||||||
@@ -30,7 +33,7 @@ public class DaylightConfigurationScheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LogUtil.warn(DaylightConfigurationScheduler.class, "No saved Daylight properties found, start startup fetch");
|
LogUtil.warn(DaylightConfigurationScheduler.class, "No saved Daylight properties found, start startup fetch");
|
||||||
BaseApiResponse propResponse = daylightFetchConfigurationService.fetchDaylightProperties();
|
BaseApiResponse<Void> propResponse = daylightFetchConfigurationService.fetchDaylightProperties();
|
||||||
if (propResponse.isSuccess()) {
|
if (propResponse.isSuccess()) {
|
||||||
LogUtil.info(DaylightConfigurationScheduler.class, "Startup properties completed: " + propResponse.getMessage());
|
LogUtil.info(DaylightConfigurationScheduler.class, "Startup properties completed: " + propResponse.getMessage());
|
||||||
} else {
|
} else {
|
||||||
@@ -52,7 +55,7 @@ public class DaylightConfigurationScheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LogUtil.warn(DaylightConfigurationScheduler.class, "No saved Daylight configurations found, start startup fetch");
|
LogUtil.warn(DaylightConfigurationScheduler.class, "No saved Daylight configurations found, start startup fetch");
|
||||||
BaseApiResponse configResponse = daylightFetchConfigurationService.fetchDaylightConfiguration();
|
BaseApiResponse<Void> configResponse = daylightFetchConfigurationService.fetchDaylightConfiguration();
|
||||||
if (configResponse.isSuccess()) {
|
if (configResponse.isSuccess()) {
|
||||||
LogUtil.info(DaylightConfigurationScheduler.class, "Startup configurations completed: " + configResponse.getMessage());
|
LogUtil.info(DaylightConfigurationScheduler.class, "Startup configurations completed: " + configResponse.getMessage());
|
||||||
} else {
|
} else {
|
||||||
@@ -79,7 +82,7 @@ public class DaylightConfigurationScheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LogUtil.warn(DaylightConfigurationScheduler.class, "No saved Daylight block codes found, start startup fetch");
|
LogUtil.warn(DaylightConfigurationScheduler.class, "No saved Daylight block codes found, start startup fetch");
|
||||||
BaseApiResponse blockResponse = daylightFetchConfigurationService.fetchDaylightBlockCodes();
|
BaseApiResponse<Void> blockResponse = daylightFetchConfigurationService.fetchDaylightBlockCodes();
|
||||||
if (blockResponse.isSuccess()) {
|
if (blockResponse.isSuccess()) {
|
||||||
LogUtil.info(DaylightConfigurationScheduler.class, "Startup block codes completed: " + blockResponse.getMessage());
|
LogUtil.info(DaylightConfigurationScheduler.class, "Startup block codes completed: " + blockResponse.getMessage());
|
||||||
} else {
|
} else {
|
||||||
@@ -99,7 +102,7 @@ public class DaylightConfigurationScheduler {
|
|||||||
try {
|
try {
|
||||||
// 1. 拉取 Properties
|
// 1. 拉取 Properties
|
||||||
LogUtil.info(DaylightConfigurationScheduler.class, "Step 1/3: Fetching properties...");
|
LogUtil.info(DaylightConfigurationScheduler.class, "Step 1/3: Fetching properties...");
|
||||||
BaseApiResponse propResponse = daylightFetchConfigurationService.fetchDaylightProperties();
|
BaseApiResponse<Void> propResponse = daylightFetchConfigurationService.fetchDaylightProperties();
|
||||||
if (propResponse.isSuccess()) {
|
if (propResponse.isSuccess()) {
|
||||||
LogUtil.info(DaylightConfigurationScheduler.class, "Properties completed: " + propResponse.getMessage());
|
LogUtil.info(DaylightConfigurationScheduler.class, "Properties completed: " + propResponse.getMessage());
|
||||||
} else {
|
} else {
|
||||||
@@ -108,7 +111,7 @@ public class DaylightConfigurationScheduler {
|
|||||||
|
|
||||||
// 2. 拉取 Configuration
|
// 2. 拉取 Configuration
|
||||||
LogUtil.info(DaylightConfigurationScheduler.class, "Step 2/3: Fetching configurations...");
|
LogUtil.info(DaylightConfigurationScheduler.class, "Step 2/3: Fetching configurations...");
|
||||||
BaseApiResponse configResponse = daylightFetchConfigurationService.fetchDaylightConfiguration();
|
BaseApiResponse<Void> configResponse = daylightFetchConfigurationService.fetchDaylightConfiguration();
|
||||||
if (configResponse.isSuccess()) {
|
if (configResponse.isSuccess()) {
|
||||||
LogUtil.info(DaylightConfigurationScheduler.class, "Configurations completed: " + configResponse.getMessage());
|
LogUtil.info(DaylightConfigurationScheduler.class, "Configurations completed: " + configResponse.getMessage());
|
||||||
} else {
|
} else {
|
||||||
@@ -117,7 +120,7 @@ public class DaylightConfigurationScheduler {
|
|||||||
|
|
||||||
// 3. 拉取 Block Codes
|
// 3. 拉取 Block Codes
|
||||||
LogUtil.info(DaylightConfigurationScheduler.class, "Step 3/3: Fetching block codes...");
|
LogUtil.info(DaylightConfigurationScheduler.class, "Step 3/3: Fetching block codes...");
|
||||||
BaseApiResponse blockResponse = daylightFetchConfigurationService.fetchDaylightBlockCodes();
|
BaseApiResponse<Void> blockResponse = daylightFetchConfigurationService.fetchDaylightBlockCodes();
|
||||||
if (blockResponse.isSuccess()) {
|
if (blockResponse.isSuccess()) {
|
||||||
LogUtil.info(DaylightConfigurationScheduler.class, "Block codes completed: " + blockResponse.getMessage());
|
LogUtil.info(DaylightConfigurationScheduler.class, "Block codes completed: " + blockResponse.getMessage());
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+34
-33
@@ -1,6 +1,7 @@
|
|||||||
package com.mgm.mcrm.apigateway.daylight.common.services;
|
package com.mgm.mcrm.apigateway.daylight.common.services;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.mgm.mcrm.apigateway.basesetting.property.models.CfgProperties;
|
import com.mgm.mcrm.apigateway.basesetting.property.models.CfgProperties;
|
||||||
import com.mgm.mcrm.apigateway.basesetting.property.repositories.PropertyDao;
|
import com.mgm.mcrm.apigateway.basesetting.property.repositories.PropertyDao;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
||||||
@@ -51,8 +52,8 @@ public class DaylightFetchConfigurationService {
|
|||||||
@Resource
|
@Resource
|
||||||
private SysLogDaylightConfigurationSyncDao syncLogDao;
|
private SysLogDaylightConfigurationSyncDao syncLogDao;
|
||||||
|
|
||||||
public BaseApiResponse fetchDaylightConfiguration() {
|
public BaseApiResponse<Void> fetchDaylightConfiguration() {
|
||||||
BaseApiResponse response = new BaseApiResponse();
|
BaseApiResponse<Void> response = new BaseApiResponse<Void>();
|
||||||
Date syncStartTime = new Date();
|
Date syncStartTime = new Date();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -185,7 +186,7 @@ public class DaylightFetchConfigurationService {
|
|||||||
.findByDlPropertyIdAndConfigName(dlPropertyId, configType);
|
.findByDlPropertyIdAndConfigName(dlPropertyId, configType);
|
||||||
if (existing != null && StringUtils.isNotBlank(existing.getConfigValue())) {
|
if (existing != null && StringUtils.isNotBlank(existing.getConfigValue())) {
|
||||||
// 解析旧数据,用 id 建索引
|
// 解析旧数据,用 id 建索引
|
||||||
List<JSONObject> oldItems = JSONObject.parseArray(existing.getConfigValue(), JSONObject.class);
|
List<JSONObject> oldItems = JSON.parseArray(existing.getConfigValue(), JSONObject.class);
|
||||||
Map<String, JSONObject> mergedMap = new HashMap<>();
|
Map<String, JSONObject> mergedMap = new HashMap<>();
|
||||||
for (JSONObject item : oldItems) {
|
for (JSONObject item : oldItems) {
|
||||||
mergedMap.put(getConfigItemKey(item), item);
|
mergedMap.put(getConfigItemKey(item), item);
|
||||||
@@ -217,7 +218,7 @@ public class DaylightFetchConfigurationService {
|
|||||||
CfgDaylightConfiguration existing = cfgDaylightConfigurationDao
|
CfgDaylightConfiguration existing = cfgDaylightConfigurationDao
|
||||||
.findByDlPropertyIdAndConfigName(dlPropertyId, configType);
|
.findByDlPropertyIdAndConfigName(dlPropertyId, configType);
|
||||||
List<JSONObject> oldItems = existing != null && StringUtils.isNotBlank(existing.getConfigValue())
|
List<JSONObject> oldItems = existing != null && StringUtils.isNotBlank(existing.getConfigValue())
|
||||||
? JSONObject.parseArray(existing.getConfigValue(), JSONObject.class)
|
? JSON.parseArray(existing.getConfigValue(), JSONObject.class)
|
||||||
: new ArrayList<>();
|
: new ArrayList<>();
|
||||||
CfgDaylightConfiguration config = existing != null ? existing : new CfgDaylightConfiguration();
|
CfgDaylightConfiguration config = existing != null ? existing : new CfgDaylightConfiguration();
|
||||||
config.setConfigName(configType);
|
config.setConfigName(configType);
|
||||||
@@ -256,8 +257,8 @@ public class DaylightFetchConfigurationService {
|
|||||||
/**
|
/**
|
||||||
* 从 Daylight API 拉取 properties 列表,存入 cfg_daylight_configuration 表
|
* 从 Daylight API 拉取 properties 列表,存入 cfg_daylight_configuration 表
|
||||||
*/
|
*/
|
||||||
public BaseApiResponse fetchDaylightProperties() {
|
public BaseApiResponse<Void> fetchDaylightProperties() {
|
||||||
BaseApiResponse response = new BaseApiResponse();
|
BaseApiResponse<Void> response = new BaseApiResponse<>();
|
||||||
Date syncStartTime = new Date();
|
Date syncStartTime = new Date();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -339,7 +340,7 @@ public class DaylightFetchConfigurationService {
|
|||||||
CfgDaylightConfiguration config = cfgDaylightConfigurationDao
|
CfgDaylightConfiguration config = cfgDaylightConfigurationDao
|
||||||
.findByDlPropertyIdAndConfigName(null, "Property");
|
.findByDlPropertyIdAndConfigName(null, "Property");
|
||||||
List<JSONObject> oldItems = config != null && StringUtils.isNotBlank(config.getConfigValue())
|
List<JSONObject> oldItems = config != null && StringUtils.isNotBlank(config.getConfigValue())
|
||||||
? JSONObject.parseArray(config.getConfigValue(), JSONObject.class)
|
? JSON.parseArray(config.getConfigValue(), JSONObject.class)
|
||||||
: new ArrayList<>();
|
: new ArrayList<>();
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
config = new CfgDaylightConfiguration();
|
config = new CfgDaylightConfiguration();
|
||||||
@@ -481,8 +482,8 @@ public class DaylightFetchConfigurationService {
|
|||||||
/**
|
/**
|
||||||
* 从 Daylight API 拉取 block codes 列表,按 property 遍历,存入 cfg_daylight_configuration 表
|
* 从 Daylight API 拉取 block codes 列表,按 property 遍历,存入 cfg_daylight_configuration 表
|
||||||
*/
|
*/
|
||||||
public BaseApiResponse fetchDaylightBlockCodes() {
|
public BaseApiResponse<Void> fetchDaylightBlockCodes() {
|
||||||
BaseApiResponse response = new BaseApiResponse();
|
BaseApiResponse<Void> response = new BaseApiResponse<>();
|
||||||
Date syncStartTime = new Date();
|
Date syncStartTime = new Date();
|
||||||
|
|
||||||
String dlPropertyId = null;
|
String dlPropertyId = null;
|
||||||
@@ -532,6 +533,7 @@ public class DaylightFetchConfigurationService {
|
|||||||
String path = "/api-gateway/data-api/v1/blocks";
|
String path = "/api-gateway/data-api/v1/blocks";
|
||||||
String apiUrl = daylightApiSetting.getServerUrl() + path;
|
String apiUrl = daylightApiSetting.getServerUrl() + path;
|
||||||
List<JSONObject> allResults = new ArrayList<>();
|
List<JSONObject> allResults = new ArrayList<>();
|
||||||
|
boolean fetchSuccess = true;
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
headers.set("authorization", "Bearer " + daylightApiToken.getAccessToken());
|
headers.set("authorization", "Bearer " + daylightApiToken.getAccessToken());
|
||||||
@@ -552,20 +554,17 @@ public class DaylightFetchConfigurationService {
|
|||||||
).block();
|
).block();
|
||||||
|
|
||||||
if (requestResponse == null) {
|
if (requestResponse == null) {
|
||||||
response.setSuccess(false);
|
log.warn("Property {} BlockCode fetch failed: Http request server can not visit", dlPropertyId);
|
||||||
response.setMessage("Http request server can not visit.");
|
fetchSuccess = false;
|
||||||
return response;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
response.setStatusCode(requestResponse.getStatusCode().value());
|
response.setStatusCode(requestResponse.getStatusCode().value());
|
||||||
|
|
||||||
if (!requestResponse.getStatusCode().is2xxSuccessful()) {
|
if (!requestResponse.getStatusCode().is2xxSuccessful()) {
|
||||||
byte[] errorBody = requestResponse.getBody();
|
byte[] errorBody = requestResponse.getBody();
|
||||||
response.setSuccess(false);
|
String errorMsg = errorBody != null ? new String(errorBody, StandardCharsets.UTF_8) : "Request failed";
|
||||||
response.setMessage(errorBody != null ? new String(errorBody, StandardCharsets.UTF_8) : "Request failed");
|
log.warn("Property {} BlockCode fetch failed: {}", dlPropertyId, errorMsg);
|
||||||
return response;
|
fetchSuccess = false;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
byte[] responseBody = requestResponse.getBody();
|
byte[] responseBody = requestResponse.getBody();
|
||||||
if (responseBody != null) {
|
if (responseBody != null) {
|
||||||
String jsonStr = new String(responseBody, StandardCharsets.UTF_8);
|
String jsonStr = new String(responseBody, StandardCharsets.UTF_8);
|
||||||
@@ -576,14 +575,16 @@ public class DaylightFetchConfigurationService {
|
|||||||
allResults.addAll(pageResults);
|
allResults.addAll(pageResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 保存为一条 CfgDaylightConfiguration,configName = "BlockCode"
|
// 保存为一条 CfgDaylightConfiguration,configName = "BlockCode"
|
||||||
if (!allResults.isEmpty()) {
|
if (fetchSuccess && !allResults.isEmpty()) {
|
||||||
boolean isIncremental = StringUtils.isNotBlank(updatedAtParam);
|
boolean isIncremental = StringUtils.isNotBlank(updatedAtParam);
|
||||||
if (isIncremental && existingConfig != null
|
if (isIncremental && existingConfig != null
|
||||||
&& StringUtils.isNotBlank(existingConfig.getConfigValue())) {
|
&& StringUtils.isNotBlank(existingConfig.getConfigValue())) {
|
||||||
// 增量同步:按 id 合并新旧数据
|
// 增量同步:按 id 合并新旧数据
|
||||||
List<JSONObject> oldItems = JSONObject.parseArray(existingConfig.getConfigValue(), JSONObject.class);
|
List<JSONObject> oldItems = JSON.parseArray(existingConfig.getConfigValue(), JSONObject.class);
|
||||||
Map<String, JSONObject> mergedMap = new HashMap<>();
|
Map<String, JSONObject> mergedMap = new HashMap<>();
|
||||||
for (JSONObject item : oldItems) {
|
for (JSONObject item : oldItems) {
|
||||||
mergedMap.put(getConfigItemKey(item), item);
|
mergedMap.put(getConfigItemKey(item), item);
|
||||||
@@ -601,7 +602,7 @@ public class DaylightFetchConfigurationService {
|
|||||||
// 全量同步:直接保存
|
// 全量同步:直接保存
|
||||||
List<JSONObject> oldItems = existingConfig != null
|
List<JSONObject> oldItems = existingConfig != null
|
||||||
&& StringUtils.isNotBlank(existingConfig.getConfigValue())
|
&& StringUtils.isNotBlank(existingConfig.getConfigValue())
|
||||||
? JSONObject.parseArray(existingConfig.getConfigValue(), JSONObject.class)
|
? JSON.parseArray(existingConfig.getConfigValue(), JSONObject.class)
|
||||||
: new ArrayList<>();
|
: new ArrayList<>();
|
||||||
CfgDaylightConfiguration config = existingConfig != null ? existingConfig : new CfgDaylightConfiguration();
|
CfgDaylightConfiguration config = existingConfig != null ? existingConfig : new CfgDaylightConfiguration();
|
||||||
if (config.getConfigName() == null) {
|
if (config.getConfigName() == null) {
|
||||||
@@ -618,20 +619,20 @@ public class DaylightFetchConfigurationService {
|
|||||||
}
|
}
|
||||||
savedCount++;
|
savedCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 按 property 记录同步日志
|
||||||
|
SysLogDaylightConfigurationSync syncLog = new SysLogDaylightConfigurationSync();
|
||||||
|
syncLog.setConfigName("BlockCode");
|
||||||
|
syncLog.setDlPropertyId(dlPropertyId);
|
||||||
|
syncLog.setLastSyncAt(syncStartTime);
|
||||||
|
syncLog.setSyncStatus(fetchSuccess ? "SUCCESS" : "FAILED");
|
||||||
|
syncLog.setRecordCount(allResults.size());
|
||||||
|
syncLog.setCreatedAt(new Date());
|
||||||
|
syncLogDao.save(syncLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
response.setSuccess(true);
|
response.setSuccess(true);
|
||||||
response.setMessage("Successfully fetched and saved " + savedCount + " block code entries.");
|
response.setMessage("Successfully fetched and saved " + savedCount + " block code entries.");
|
||||||
|
|
||||||
// 记录同步日志
|
|
||||||
SysLogDaylightConfigurationSync syncLog = new SysLogDaylightConfigurationSync();
|
|
||||||
syncLog.setConfigName("BlockCode");
|
|
||||||
syncLog.setLastSyncAt(syncStartTime);
|
|
||||||
syncLog.setSyncStatus("SUCCESS");
|
|
||||||
syncLog.setDlPropertyId(dlPropertyId);
|
|
||||||
syncLog.setRecordCount(savedCount);
|
|
||||||
syncLog.setCreatedAt(new Date());
|
|
||||||
syncLogDao.save(syncLog);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
response.setSuccess(false);
|
response.setSuccess(false);
|
||||||
response.setMessage(e.getMessage());
|
response.setMessage(e.getMessage());
|
||||||
|
|||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.common.services;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.common.dtos.TokenResponse;
|
||||||
|
import com.mgm.mcrm.apigateway.proxy.exception.HttpProxyErrorHandler;
|
||||||
|
import com.mgm.mcrm.apigateway.proxy.services.WebProxyService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
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.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class DaylightReservationService {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(DaylightReservationService.class);
|
||||||
|
private final HttpProxyErrorHandler httpProxyErrorHandler = new HttpProxyErrorHandler();
|
||||||
|
@Resource
|
||||||
|
private WebProxyService webProxyService;
|
||||||
|
@Autowired
|
||||||
|
private DaylightApiSetting daylightApiSetting;
|
||||||
|
@Resource
|
||||||
|
private DaylightTokenService daylightTokenService;
|
||||||
|
|
||||||
|
public JSONObject getDaylightReservationByDlId(
|
||||||
|
String dlReservationId,
|
||||||
|
String dlPropertyId
|
||||||
|
) {
|
||||||
|
logger.info("Entering getDaylightReservationByDlId with dlReservationId: {}, dlPropertyId: {}", dlReservationId, dlPropertyId);
|
||||||
|
try {
|
||||||
|
TokenResponse daylightApiToken = daylightTokenService.getApiAccessToken();
|
||||||
|
if (daylightApiToken == null || StringUtils.isBlank(daylightApiToken.getAccessToken())) {
|
||||||
|
logger.error("Failed to obtain Daylight API access token.");
|
||||||
|
throw new RuntimeException("Invoke daylight token failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
String apiUrl = daylightApiSetting.getServerUrl() + "/api-gateway/booking/v1/reservations/" + dlReservationId;
|
||||||
|
String queryString = "extend=PurchaseElements,CustomFields";
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.set("authorization", "Bearer " + daylightApiToken.getAccessToken());
|
||||||
|
headers.set("AC-Property-Id", dlPropertyId);
|
||||||
|
headers.set("Content-Type", "application/json");
|
||||||
|
|
||||||
|
logger.info("Invoking Daylight API: {} with query: {}", apiUrl, queryString);
|
||||||
|
ResponseEntity<byte[]> requestResponse = webProxyService.invokeRequest(
|
||||||
|
WebProxyService.DAYLIGHT_API,
|
||||||
|
HttpMethod.GET,
|
||||||
|
apiUrl,
|
||||||
|
queryString,
|
||||||
|
headers,
|
||||||
|
new byte[0],
|
||||||
|
Duration.ofSeconds(daylightApiSetting.getApiTimeout()),
|
||||||
|
httpProxyErrorHandler
|
||||||
|
).block();
|
||||||
|
|
||||||
|
if (requestResponse != null) {
|
||||||
|
logger.info("Daylight API response status: {}", requestResponse.getStatusCode());
|
||||||
|
if (requestResponse.getBody() != null) {
|
||||||
|
String responseData = new String(requestResponse.getBody(), StandardCharsets.UTF_8);
|
||||||
|
logger.info("Successfully retrieved daylight reservation data.");
|
||||||
|
JSONObject response = JSONObject.parseObject(responseData);
|
||||||
|
JSONArray reservations = response.getJSONArray("results");
|
||||||
|
JSONObject reservation = reservations.getJSONObject(0);
|
||||||
|
return reservation;
|
||||||
|
} else {
|
||||||
|
logger.warn("Daylight API returned an empty body for reservation: {}", dlReservationId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.error("Daylight API request returned null for reservation: {}", dlReservationId);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error occurred while fetching daylight reservation by ID: {}", dlReservationId, e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
package com.mgm.mcrm.apigateway.daylight.common.services;
|
package com.mgm.mcrm.apigateway.daylight.common.services;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.HttpResult;
|
import com.mgm.mcrm.apigateway.common.dtos.HttpResult;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
||||||
import com.mgm.mcrm.apigateway.daylight.common.dtos.CachedToken;
|
import com.mgm.mcrm.apigateway.daylight.common.dtos.CachedToken;
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.common.services;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.common.dtos.HttpResult;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.common.enums.HttpMethods;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.common.httpclient.HttpClientExecutor;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.common.httpclient.HttpRequestOptions;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.apache.hc.client5.http.config.RequestConfig;
|
||||||
|
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||||
|
import org.apache.hc.core5.http.Header;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 請求服務
|
||||||
|
*
|
||||||
|
* @author Aaka
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class HttpService {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HttpService.class);
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Qualifier("httpClientWithSSL")
|
||||||
|
private CloseableHttpClient httpClient;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
@Qualifier("httpRequestConfig")
|
||||||
|
private RequestConfig requestConfig;
|
||||||
|
|
||||||
|
@Value("${daylight.url}")
|
||||||
|
private String daylightUrl;
|
||||||
|
|
||||||
|
public String sslGet(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||||
|
|
||||||
|
log.info("======sslGet======url:{}===========headers:{} =============== map:{}", daylightUrl + url, JSON.toJSONString(headers), JSON.toJSONString(map));
|
||||||
|
// 使用 HttpConfig 配置 GET 请求(带参数)
|
||||||
|
HttpRequestOptions getConfig = HttpRequestOptions.create()
|
||||||
|
.url(daylightUrl + url)
|
||||||
|
.timeout(requestConfig)
|
||||||
|
.map(map)
|
||||||
|
.encoding("utf-8")
|
||||||
|
.client(httpClient);
|
||||||
|
|
||||||
|
String result = HttpClientExecutor.get(getConfig, headers);
|
||||||
|
log.info("====== GET request result size:{}", result.length());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String sslGetNoLog(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||||
|
|
||||||
|
// todo 在這裏需要把請求頭的信息插入到數據庫裏
|
||||||
|
log.info("======sslGet======url:{}===========headers:{} =============== map:{}", daylightUrl + url, JSON.toJSONString(headers), JSON.toJSONString(map));
|
||||||
|
// 使用 HttpConfig 配置 GET 请求(带参数)
|
||||||
|
HttpRequestOptions getConfig = HttpRequestOptions.create()
|
||||||
|
.url(daylightUrl + url)
|
||||||
|
.timeout(requestConfig)
|
||||||
|
.map(map)
|
||||||
|
.encoding("utf-8")
|
||||||
|
.client(httpClient);
|
||||||
|
|
||||||
|
String result = HttpClientExecutor.get(getConfig, headers);
|
||||||
|
log.info("====== GET request result size={}", result.length());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpResult sslGetHttpResult(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||||
|
|
||||||
|
// todo 在這裏需要把請求頭的信息插入到數據庫裏
|
||||||
|
log.info("======sslGet======url:{}===========headers:{} =============== map:{}", daylightUrl + url, JSON.toJSONString(headers), JSON.toJSONString(map));
|
||||||
|
// 使用 HttpConfig 配置 GET 请求(带参数)
|
||||||
|
HttpRequestOptions getConfig = HttpRequestOptions.create()
|
||||||
|
.url(daylightUrl + url)
|
||||||
|
.timeout(requestConfig)
|
||||||
|
.map(map)
|
||||||
|
.encoding("utf-8")
|
||||||
|
.client(httpClient);
|
||||||
|
|
||||||
|
HttpResult result = HttpClientExecutor.sendAndGetResp(getConfig, headers);
|
||||||
|
log.info("====== GET request result:{}", result.getResult());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 HttpConfig 配置 PUT 请求
|
||||||
|
*
|
||||||
|
* @param url 請求路徑
|
||||||
|
* @param headers 請求頭
|
||||||
|
* @param map 請求參數
|
||||||
|
* @return 接口結果的json數據
|
||||||
|
* @throws Exception 異常
|
||||||
|
*/
|
||||||
|
public String sslPut(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||||
|
log.info("======sslPut======url:{}===========headers:{} =============== map:{}", daylightUrl + url, JSON.toJSONString(headers), JSON.toJSONString(map));
|
||||||
|
HttpRequestOptions putConfig = HttpRequestOptions.create()
|
||||||
|
.url(daylightUrl + url)
|
||||||
|
.timeout(requestConfig)
|
||||||
|
.method(HttpMethods.PUT)
|
||||||
|
.json(JSON.toJSONString(map))
|
||||||
|
.encoding("utf-8")
|
||||||
|
.client(httpClient);
|
||||||
|
String result = HttpClientExecutor.send(putConfig, headers);
|
||||||
|
log.info("====== PUT request result:{}", result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 HttpConfig 配置 Delete 请求
|
||||||
|
*
|
||||||
|
* @param url 請求路徑
|
||||||
|
* @param headers 請求頭
|
||||||
|
* @param requestBody 請求參數
|
||||||
|
* @return 接口結果的json數據
|
||||||
|
* @throws Exception 異常
|
||||||
|
*/
|
||||||
|
public String sslDelete(String url, Header[] headers, Object requestBody) throws Exception {
|
||||||
|
log.info("======sslDelete======url:{}===========headers:{} =============== map:{}", daylightUrl + url, JSON.toJSONString(headers), JSON.toJSONString(requestBody));
|
||||||
|
HttpRequestOptions deleteConfig = HttpRequestOptions.create()
|
||||||
|
.url(daylightUrl + url)
|
||||||
|
.timeout(requestConfig)
|
||||||
|
.json(JSON.toJSONString(requestBody))
|
||||||
|
.method(HttpMethods.DELETE)
|
||||||
|
.client(httpClient);
|
||||||
|
String result = HttpClientExecutor.send(deleteConfig, headers);
|
||||||
|
log.info("====== DELETE request result:{}", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 HttpConfig 配置 Post 请求
|
||||||
|
*
|
||||||
|
* @param url 請求路徑
|
||||||
|
* @param headers 請求頭
|
||||||
|
* @param requestBody request 数据
|
||||||
|
* @return 接口結果的json數據
|
||||||
|
* @throws Exception 異常
|
||||||
|
*/
|
||||||
|
public HttpResult sslPost(String url, Header[] headers, Object requestBody) throws Exception {
|
||||||
|
log.info("======sslCreatePost======url:{}===========headers:{}", daylightUrl + url, JSON.toJSONString(headers));
|
||||||
|
HttpRequestOptions postConfig = HttpRequestOptions.create()
|
||||||
|
.url(daylightUrl + url)
|
||||||
|
.timeout(requestConfig)
|
||||||
|
.json(JSON.toJSONString(requestBody))
|
||||||
|
.method(HttpMethods.POST)
|
||||||
|
.client(httpClient);
|
||||||
|
HttpResult result = HttpClientExecutor.sendAndPostResp(postConfig, headers);
|
||||||
|
// System.out.println("POST 请求结果:\n" + result);
|
||||||
|
log.info("====== POST request result:{}", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 HttpConfig 配置 PATCH 请求(JSON 请求体)
|
||||||
|
*
|
||||||
|
* @param url 請求路徑
|
||||||
|
* @param headers 請求頭
|
||||||
|
* @param requestBody request 数据
|
||||||
|
* @return 接口結果的json數據
|
||||||
|
* @throws Exception 異常
|
||||||
|
*/
|
||||||
|
public HttpResult sslPatch(String url, Header[] headers, Object requestBody) throws Exception {
|
||||||
|
log.info("======sslCreatePatch======url:{}===========headers:{}", daylightUrl + url, JSON.toJSONString(headers));
|
||||||
|
HttpRequestOptions patchConfig = HttpRequestOptions.create()
|
||||||
|
.url(daylightUrl + url)
|
||||||
|
.timeout(requestConfig)
|
||||||
|
.json(JSON.toJSONString(requestBody))
|
||||||
|
.method(HttpMethods.PATCH)
|
||||||
|
.encoding("utf-8")
|
||||||
|
.client(httpClient);
|
||||||
|
HttpResult result = HttpClientExecutor.sendAndPatchResp(patchConfig, headers);
|
||||||
|
log.info("====== PATCH request result:{}", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 HttpConfig 配置 Delete 请求
|
||||||
|
*
|
||||||
|
* @param url 請求路徑
|
||||||
|
* @param headers 請求頭
|
||||||
|
* @param map Cancel数据
|
||||||
|
* @return 接口結果的json數據
|
||||||
|
* @throws Exception 異常
|
||||||
|
*/
|
||||||
|
public HttpResult sslCancelPost(String url, Header[] headers, Map<String, Object> map) throws Exception {
|
||||||
|
log.info("======sslCancelPost======url:{}===========headers:{}", daylightUrl + url, JSON.toJSONString(headers));
|
||||||
|
HttpRequestOptions postConfig = HttpRequestOptions.create()
|
||||||
|
.url(daylightUrl + url)
|
||||||
|
.timeout(requestConfig)
|
||||||
|
.json(JSON.toJSONString(map))
|
||||||
|
.method(HttpMethods.POST)
|
||||||
|
.client(httpClient);
|
||||||
|
HttpResult result = HttpClientExecutor.sendAndPostResp(postConfig, headers);
|
||||||
|
// System.out.println("POST 请求结果:\n" + result);
|
||||||
|
log.info("====== POST request result:{}", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.dtos.response;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class CompRuleResponse {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private Integer version;
|
||||||
|
private String accountId;
|
||||||
|
private String profileId;
|
||||||
|
private String folioWindowId;
|
||||||
|
private String complimentaryTypeId;
|
||||||
|
private List<String> complimentaryAccountingPresetsIds;
|
||||||
|
private String requestorId;
|
||||||
|
private String approverId;
|
||||||
|
private String paymentMethodTransactionCodeId;
|
||||||
|
private String justification;
|
||||||
|
private ComplimentaryRuleLimits complimentaryRuleLimits;
|
||||||
|
private List<String> settledFolioWindowIds;
|
||||||
|
private Boolean isExecutive;
|
||||||
|
private Boolean doNotIssueInvoice;
|
||||||
|
private Boolean isActive;
|
||||||
|
private Boolean canBeDeleted;
|
||||||
|
private Integer issuedVouchersCount;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class ComplimentaryRuleLimits {
|
||||||
|
|
||||||
|
private Amount totalAmountLimit;
|
||||||
|
private SoftTotalLimit softTotalLimit;
|
||||||
|
private List<String> limitExcludedPresetIds;
|
||||||
|
private List<String> limitExcludedTransactionCodeIds;
|
||||||
|
private TotalLimit totalLimit;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class SoftTotalLimit {
|
||||||
|
|
||||||
|
private Amount amountLimit;
|
||||||
|
private Amount remainingLimit;
|
||||||
|
private Boolean isExceeded;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class TotalLimit {
|
||||||
|
|
||||||
|
private Amount amountLimit;
|
||||||
|
private Amount remainingLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Amount {
|
||||||
|
|
||||||
|
private BigDecimal amount;
|
||||||
|
private String currency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.models;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Entity
|
||||||
|
@Table(name = "cfg_comp_rule")
|
||||||
|
public class CfgCompRule implements Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "id")
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "dl_reservation_id")
|
||||||
|
private String dlReservationId;
|
||||||
|
|
||||||
|
@Column(name = "comp_rule_id", nullable = false, unique = true)
|
||||||
|
private String compRuleId;
|
||||||
|
|
||||||
|
@Column(name = "account_id")
|
||||||
|
private String accountId;
|
||||||
|
|
||||||
|
@Column(name = "is_send_soft_limit", nullable = false)
|
||||||
|
private Integer isSendSoftLimit = 0;
|
||||||
|
|
||||||
|
@Column(name = "is_send_total_limit", nullable = false)
|
||||||
|
private Integer isSendTotalLimit = 0;
|
||||||
|
|
||||||
|
@Column(name = "created_at")
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
@Column(name = "updated_at")
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.repositories;
|
||||||
|
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.models.CfgCompRule;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface CfgCompRuleDao extends JpaRepository<CfgCompRule, Long> {
|
||||||
|
CfgCompRule findByCompRuleId(String compRuleId);
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
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.services.HttpService;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.dtos.response.CompRuleResponse;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.hc.core5.http.Header;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class DaylightApiService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private HttpService httpService;
|
||||||
|
|
||||||
|
public BaseApiResponse<List<CompRuleResponse>> daylightGetCompRulesByAccount(String dlPropertyId, String dlAccountId) {
|
||||||
|
|
||||||
|
BaseApiResponse<List<CompRuleResponse>> result = new BaseApiResponse<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
String url = "/api-gateway/cashiering/v1/accounts/" + dlAccountId + "/complimentary-rules";
|
||||||
|
// 获取对应的值
|
||||||
|
Header[] headers = HttpHeaderBuilder.custom()
|
||||||
|
.contentType("application/json")
|
||||||
|
.ac_property_id(dlPropertyId)
|
||||||
|
.build();
|
||||||
|
// 参数设置
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
|
||||||
|
String responseData = httpService.sslGet(url, headers, map);
|
||||||
|
|
||||||
|
List<CompRuleResponse> compRuleResponses = JSON.parseArray(responseData, CompRuleResponse.class);
|
||||||
|
|
||||||
|
result.setSuccess(true);
|
||||||
|
result.setData(compRuleResponses);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.setSuccess(false);
|
||||||
|
result.setData(Collections.emptyList());
|
||||||
|
result.setMessage("Failed to get dayLight comp rules for account: " + dlAccountId);
|
||||||
|
log.error("Failed to get dayLight comp rules: ", e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiResponse<JSONObject> getDaylightReservationByDlId(
|
||||||
|
String dlReservationId,
|
||||||
|
String dlPropertyId
|
||||||
|
) {
|
||||||
|
|
||||||
|
BaseApiResponse<JSONObject> result = new BaseApiResponse<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
String url = "/api-gateway/booking/v1/reservations/" + dlReservationId + "?extend=PurchaseElements,CustomFields";
|
||||||
|
// 获取对应的值
|
||||||
|
Header[] headers = HttpHeaderBuilder.custom()
|
||||||
|
.contentType("application/json")
|
||||||
|
.ac_property_id(dlPropertyId)
|
||||||
|
.build();
|
||||||
|
// 参数设置
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
|
||||||
|
String responseData = httpService.sslGet(url, headers, map);
|
||||||
|
|
||||||
|
JSONObject jsonObject = JSON.parseObject(responseData);
|
||||||
|
|
||||||
|
result.setSuccess(true);
|
||||||
|
result.setData(jsonObject);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
result.setSuccess(false);
|
||||||
|
result.setMessage("Failed to get reservation , id=" + dlReservationId);
|
||||||
|
log.error("Failed to get reservation , id={}", dlReservationId, e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -24,12 +24,12 @@ public class DaylightWebhook {
|
|||||||
private WebhookLogService webhookLogService;
|
private WebhookLogService webhookLogService;
|
||||||
|
|
||||||
@PostMapping(value = "/receive", produces = "application/json;charset=UTF-8")
|
@PostMapping(value = "/receive", produces = "application/json;charset=UTF-8")
|
||||||
public ResponseEntity<BaseApiResponse> handleRoomAvailableWebhook(
|
public ResponseEntity<BaseApiResponse<Void>> handleRoomAvailableWebhook(
|
||||||
@RequestBody(required = true) String payload,
|
@RequestBody(required = true) String payload,
|
||||||
@RequestHeader Map<String, String> headers,
|
@RequestHeader Map<String, String> headers,
|
||||||
HttpServletRequest request
|
HttpServletRequest request
|
||||||
){
|
){
|
||||||
BaseApiResponse result = new BaseApiResponse();
|
BaseApiResponse<Void> result = new BaseApiResponse<>();
|
||||||
String messageId = request.getHeader("Ac-Events-Message-Id");
|
String messageId = request.getHeader("Ac-Events-Message-Id");
|
||||||
String eventType = request.getHeader("Ac-Events-Type");
|
String eventType = request.getHeader("Ac-Events-Type");
|
||||||
|
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.webhook.dtos.reservation;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class ExceededCompRuleEvent {
|
||||||
|
private String complimentaryRuleId;
|
||||||
|
private boolean softTotalLimitIsExceeded;
|
||||||
|
private boolean softDailyLimitIsExceeded;
|
||||||
|
private boolean isExecutive;
|
||||||
|
private String trigger;
|
||||||
|
}
|
||||||
+2
-3
@@ -1,11 +1,10 @@
|
|||||||
package com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers;
|
package com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public interface DaylightWebhookHandler {
|
public interface DaylightWebhookHandler {
|
||||||
BaseApiResponse handle(String payload, Map<String, String> headers) throws Exception;
|
|
||||||
|
BaseApiResponse<Void> handle(String payload, Map<String, String> headers) throws Exception;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -20,8 +20,8 @@ import java.util.Map;
|
|||||||
public class AvailableRoomCountUpdatedHandler implements DaylightWebhookHandler {
|
public class AvailableRoomCountUpdatedHandler implements DaylightWebhookHandler {
|
||||||
private final RoomCriteriaDaylightService roomCriteriaDaylightService;
|
private final RoomCriteriaDaylightService roomCriteriaDaylightService;
|
||||||
@Override
|
@Override
|
||||||
public BaseApiResponse handle(String payload, Map<String, String> headers) {
|
public BaseApiResponse<Void> handle(String payload, Map<String, String> headers) {
|
||||||
BaseApiResponse result = new BaseApiResponse();
|
BaseApiResponse<Void> result = new BaseApiResponse<>();
|
||||||
AvailableRoomCountUpdatedEvent eventData = null;
|
AvailableRoomCountUpdatedEvent eventData = null;
|
||||||
try{
|
try{
|
||||||
eventData = JSONObject.parseObject(payload, AvailableRoomCountUpdatedEvent.class);
|
eventData = JSONObject.parseObject(payload, AvailableRoomCountUpdatedEvent.class);
|
||||||
|
|||||||
+224
@@ -0,0 +1,224 @@
|
|||||||
|
package com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
||||||
|
import com.mgm.mcrm.apigateway.common.utils.LogUtil;
|
||||||
|
import com.mgm.mcrm.apigateway.common.utils.NotificationUtil;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.dtos.response.CompRuleResponse;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.models.CfgCompRule;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.repositories.CfgCompRuleDao;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.services.DaylightApiService;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.webhook.dtos.reservation.ExceededCompRuleEvent;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.DaylightWebhookHandler;
|
||||||
|
import com.mgm.mcrm.apigateway.logging.dao.SysLogDeviceTokenRepository;
|
||||||
|
import com.mgm.mcrm.apigateway.logging.models.SysLogDeviceToken;
|
||||||
|
import com.mgm.mcrm.apigateway.notification.services.ApnNotificationService;
|
||||||
|
import com.mgm.mcrm.apigateway.reservation.models.Bookings;
|
||||||
|
import com.mgm.mcrm.apigateway.reservation.repositories.BookingDao;
|
||||||
|
import com.mgm.mcrm.apigateway.reservation.services.BookingService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.Strings;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class CompRuleLimitsExceededChangedHandler implements DaylightWebhookHandler {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CfgCompRuleDao cfgCompRuleDao;
|
||||||
|
@Resource
|
||||||
|
private BookingDao bookingDao;
|
||||||
|
@Resource
|
||||||
|
private SysLogDeviceTokenRepository sysLogDeviceTokenRepository;
|
||||||
|
@Resource
|
||||||
|
private NotificationUtil notificationUtil;
|
||||||
|
@Resource
|
||||||
|
private ApnNotificationService apnNotificationService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private DaylightApiService daylightApiService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BaseApiResponse<Void> handle(String payload, Map<String, String> headers) {
|
||||||
|
BaseApiResponse<Void> result = new BaseApiResponse<>();
|
||||||
|
ExceededCompRuleEvent eventData = null;
|
||||||
|
try{
|
||||||
|
eventData = JSONObject.parseObject(payload, ExceededCompRuleEvent.class);
|
||||||
|
}catch(Exception err){
|
||||||
|
result.setSuccess(false);
|
||||||
|
result.setMessage("Convert Payload failed:["+err.getMessage()+"]");
|
||||||
|
}
|
||||||
|
if(eventData!=null){
|
||||||
|
result = compRuleSendNotificationEvevnt(eventData);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseApiResponse<Void> compRuleSendNotificationEvevnt(ExceededCompRuleEvent event){
|
||||||
|
BaseApiResponse<Void> apiResponse = new BaseApiResponse<>();
|
||||||
|
|
||||||
|
String compRuleId = event.getComplimentaryRuleId();
|
||||||
|
boolean isExceededSoftLimit = false;
|
||||||
|
boolean isExceededTotalLimit = false;
|
||||||
|
|
||||||
|
//TO*DO Misc Charge notification by Corso 20260915 完成 / 20260916
|
||||||
|
//拿到CompRuleId 获取到对应的Booking
|
||||||
|
CfgCompRule byCompRuleId = cfgCompRuleDao.findByCompRuleId(compRuleId);
|
||||||
|
List<Bookings> bookings = bookingDao.findByDlReservationId(byCompRuleId.getDlReservationId());
|
||||||
|
Bookings originBooking = new Bookings();
|
||||||
|
|
||||||
|
//判断是否为主Booking (非WaitList 且 非ApprovalRouting)
|
||||||
|
for (Bookings booking : bookings) {
|
||||||
|
if (!Strings.CS.containsAny(booking.getApproveStatus(),"W","A") && booking.getDlReservationId() !=null){
|
||||||
|
originBooking = booking;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO 根据CompRuleId 查到对应的CompRule 是超过了SoftLimit 还是 Total Limit 需要CCJ去拿到CompRule For CCJ By Corso 2026-09-16
|
||||||
|
//查看超过SoftLimit/TotalLimit后 修改对应参数
|
||||||
|
BaseApiResponse<List<CompRuleResponse>> listBaseApiResponse =
|
||||||
|
daylightApiService.daylightGetCompRulesByAccount(originBooking.getDlPropertyId(), byCompRuleId.getAccountId());
|
||||||
|
|
||||||
|
CompRuleResponse crr = null;
|
||||||
|
|
||||||
|
for (CompRuleResponse c : listBaseApiResponse.getData()) {
|
||||||
|
if (c.getId().equals(compRuleId)) {
|
||||||
|
crr = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (crr != null) {
|
||||||
|
String miscChargeValue = originBooking.getMiscCharge();
|
||||||
|
|
||||||
|
if (miscChargeValue != null && !miscChargeValue.isBlank()
|
||||||
|
&& crr.getComplimentaryRuleLimits() != null) {
|
||||||
|
|
||||||
|
BigDecimal miscCharge = new BigDecimal(miscChargeValue);
|
||||||
|
|
||||||
|
CompRuleResponse.ComplimentaryRuleLimits limits =
|
||||||
|
crr.getComplimentaryRuleLimits();
|
||||||
|
|
||||||
|
// Soft Total Limit
|
||||||
|
if (limits.getSoftTotalLimit() != null
|
||||||
|
&& limits.getSoftTotalLimit().getAmountLimit() != null
|
||||||
|
&& limits.getSoftTotalLimit().getAmountLimit().getAmount() != null) {
|
||||||
|
|
||||||
|
BigDecimal softLimit =
|
||||||
|
limits.getSoftTotalLimit()
|
||||||
|
.getAmountLimit()
|
||||||
|
.getAmount();
|
||||||
|
|
||||||
|
if (softLimit.compareTo(miscCharge) > 0) {
|
||||||
|
isExceededSoftLimit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Total Limit
|
||||||
|
if (limits.getTotalLimit() != null
|
||||||
|
&& limits.getTotalLimit().getAmountLimit() != null
|
||||||
|
&& limits.getTotalLimit().getAmountLimit().getAmount() != null) {
|
||||||
|
|
||||||
|
BigDecimal totalLimit =
|
||||||
|
limits.getTotalLimit()
|
||||||
|
.getAmountLimit()
|
||||||
|
.getAmount();
|
||||||
|
|
||||||
|
if (totalLimit.compareTo(miscCharge) > 0) {
|
||||||
|
isExceededTotalLimit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//去DB中拿到当前CompRule对应的记录 检查是否已经发送过对应的Notification
|
||||||
|
if (byCompRuleId != null) {
|
||||||
|
boolean isSandSoftLimit = byCompRuleId.getIsSendSoftLimit() == 1;
|
||||||
|
boolean isSandTotalLimit = byCompRuleId.getIsSendTotalLimit() == 1;
|
||||||
|
if ((isSandSoftLimit && isExceededSoftLimit) || (isSandTotalLimit && isExceededTotalLimit)) {
|
||||||
|
//如果发送过 直接跳过该条记录
|
||||||
|
return apiResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//如果没有发送过 调用apns接口去发送 Notification
|
||||||
|
if (isExceededSoftLimit){
|
||||||
|
//调用APNs方法 发送超过Soft Limit Notification
|
||||||
|
LogUtil.info(BookingService.class,"Send Exceeded Soft Limit Notification Booking Dl ReservationId = "+originBooking.getDlReservationId()+
|
||||||
|
", PlayerId = "+originBooking.getPlayerId());
|
||||||
|
|
||||||
|
// //设置Notification 内容
|
||||||
|
String notificationTitle = "#EN#1 Misc-Charge Reminder#EN#" +
|
||||||
|
"#CN#1 個雜費提示#CN#";
|
||||||
|
String notificationContent = "#EN#[Misc-charge reminder] Please be informed that the Misc charge of #{playerId} ID is reach to 50%.#EN#" +
|
||||||
|
"#CN#[客人雜費提醒 ] 請注意! 閣下提供給#{playerId} 的雜費已經到達50%。#CN#";
|
||||||
|
String[] placeholders = {
|
||||||
|
"{playerId}"
|
||||||
|
};
|
||||||
|
LogUtil.info(BookingService.class,"Set notification info");
|
||||||
|
String[] values = {
|
||||||
|
StringUtils.defaultString(originBooking.getPlayerId()),
|
||||||
|
};
|
||||||
|
LogUtil.info(BookingService.class,"Replace each");
|
||||||
|
notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
||||||
|
String transactionId = "BKCRSL"+originBooking.getDlReservationId();
|
||||||
|
LogUtil.info(BookingService.class,"Get device token from DB Start");
|
||||||
|
SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(originBooking.getCreatedBy().trim());
|
||||||
|
LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
||||||
|
String deviceTokenValue =null;
|
||||||
|
String finalTitle = 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);
|
||||||
|
} else if (isExceededTotalLimit) {
|
||||||
|
//调用APNs方法 发送超过Total Limit Notificaiton
|
||||||
|
LogUtil.info(BookingService.class,"Send Exceeded Total Limit Notification Booking Dl ReservationId = "+originBooking.getDlReservationId()+
|
||||||
|
", PlayerId = "+originBooking.getPlayerId());
|
||||||
|
|
||||||
|
// //设置Notification 内容
|
||||||
|
String notificationTitle = "#EN#1 Misc-Charge Reminder#EN#" +
|
||||||
|
"#CN#1 個雜費提示#CN#";
|
||||||
|
String notificationContent = "#EN#[Mis-charge reminder] Please be informed that the misc charge of #{playerId} ID is reach to 100%, call FO to settle it ASAP. If you want to increase the limit amount, please contact related departments. \n#EN#" +
|
||||||
|
"#CN#[客人雜費提醒 ] 請注意! 閣下提供給#{playerId} 的雜費已經到達100%. 請儘快聯絡相關部門。#CN#";
|
||||||
|
String[] placeholders = {
|
||||||
|
"{playerId}"
|
||||||
|
};
|
||||||
|
LogUtil.info(BookingService.class,"Set notification info");
|
||||||
|
String[] values = {
|
||||||
|
StringUtils.defaultString(originBooking.getPlayerId()),
|
||||||
|
};
|
||||||
|
LogUtil.info(BookingService.class,"Replace each");
|
||||||
|
notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
||||||
|
String transactionId = "BKCRTL"+originBooking.getDlReservationId();
|
||||||
|
LogUtil.info(BookingService.class,"Get device token from DB Start");
|
||||||
|
SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(originBooking.getCreatedBy().trim());
|
||||||
|
LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
||||||
|
String deviceTokenValue =null;
|
||||||
|
String finalTitle = 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiResponse;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
-2
@@ -1,10 +1,12 @@
|
|||||||
package com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl;
|
package com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
||||||
import com.mgm.mcrm.apigateway.common.enums.EumnDaylightStatus;
|
import com.mgm.mcrm.apigateway.common.enums.EumnDaylightStatus;
|
||||||
import com.mgm.mcrm.apigateway.common.utils.DateTimeUtil;
|
import com.mgm.mcrm.apigateway.common.utils.DateTimeUtil;
|
||||||
|
import com.mgm.mcrm.apigateway.daylight.services.DaylightApiService;
|
||||||
import com.mgm.mcrm.apigateway.daylight.webhook.dtos.reservation.ReservationNotificationEvent;
|
import com.mgm.mcrm.apigateway.daylight.webhook.dtos.reservation.ReservationNotificationEvent;
|
||||||
import com.mgm.mcrm.apigateway.daylight.webhook.dtos.reservation.StatusCodeEntity;
|
import com.mgm.mcrm.apigateway.daylight.webhook.dtos.reservation.StatusCodeEntity;
|
||||||
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.DaylightWebhookHandler;
|
import com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.DaylightWebhookHandler;
|
||||||
@@ -14,6 +16,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
@@ -26,10 +29,11 @@ public class ReservationNotificationHandler implements DaylightWebhookHandler {
|
|||||||
|
|
||||||
private final BookingService bookingService;
|
private final BookingService bookingService;
|
||||||
|
|
||||||
|
private final DaylightApiService daylightApiService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseApiResponse handle(String payload, Map<String, String> headers) throws Exception {
|
public BaseApiResponse<Void> handle(String payload, Map<String, String> headers) throws Exception {
|
||||||
BaseApiResponse result = new BaseApiResponse();
|
BaseApiResponse<Void> result = new BaseApiResponse<>();
|
||||||
ReservationNotificationEvent eventData = null;
|
ReservationNotificationEvent eventData = null;
|
||||||
try{
|
try{
|
||||||
eventData = JSONObject.parseObject(payload, ReservationNotificationEvent.class);
|
eventData = JSONObject.parseObject(payload, ReservationNotificationEvent.class);
|
||||||
@@ -101,6 +105,36 @@ public class ReservationNotificationHandler implements DaylightWebhookHandler {
|
|||||||
String etaTime = dateTime.format(DateTimeFormatter.ofPattern("HH:mm"));
|
String etaTime = dateTime.format(DateTimeFormatter.ofPattern("HH:mm"));
|
||||||
result.setEta(etaTime);
|
result.setEta(etaTime);
|
||||||
}
|
}
|
||||||
|
BaseApiResponse<JSONObject> response =
|
||||||
|
daylightApiService.getDaylightReservationByDlId(eventData.getReservationId(), eventData.getPropertyId());
|
||||||
|
|
||||||
|
if (response.isSuccess()) {
|
||||||
|
JSONObject embedded = response.getData().getJSONObject("_embedded");
|
||||||
|
if (embedded != null) {
|
||||||
|
JSONArray customFields = embedded.getJSONArray("customFields");
|
||||||
|
|
||||||
|
if (customFields != null) {
|
||||||
|
for (int j = 0; j < customFields.size(); j++) {
|
||||||
|
JSONObject jsonObject = customFields.getJSONObject(j);
|
||||||
|
String value = jsonObject.getString("value");
|
||||||
|
JSONObject valueJson = JSONObject.parseObject(value);
|
||||||
|
String booker = valueJson.getString("Booker");
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(booker)) {
|
||||||
|
result.setCreatedBy(booker);
|
||||||
|
result.setBooker(booker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONArray jsonArray = response.getData().getJSONArray("externalIds");
|
||||||
|
if (!CollectionUtils.isEmpty(jsonArray)) {
|
||||||
|
String dlExternalNo = jsonArray.getJSONObject(0).getString("number");
|
||||||
|
result.setDlExternalNo(dlExternalNo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
package com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl;
|
package com.mgm.mcrm.apigateway.daylight.webhook.eventhandlers.impl;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.mgm.mcrm.apigateway.allotment.services.RoomCriteriaDaylightService;
|
import com.mgm.mcrm.apigateway.allotment.services.RoomCriteriaDaylightService;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
|
||||||
import com.mgm.mcrm.apigateway.daylight.webhook.dtos.room.common.RoomCounterEntity;
|
import com.mgm.mcrm.apigateway.daylight.webhook.dtos.room.common.RoomCounterEntity;
|
||||||
@@ -21,8 +21,8 @@ public class RoomTypeDateAvailabilityChangedHandler implements DaylightWebhookHa
|
|||||||
private final RoomCriteriaDaylightService roomCriteriaDaylightService;
|
private final RoomCriteriaDaylightService roomCriteriaDaylightService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseApiResponse handle(String payload, Map<String, String> headers) {
|
public BaseApiResponse<Void> handle(String payload, Map<String, String> headers) {
|
||||||
BaseApiResponse result = new BaseApiResponse();
|
BaseApiResponse<Void> result = new BaseApiResponse<>();
|
||||||
RoomTypeDateAvailabilityChangedEvent eventData = null;
|
RoomTypeDateAvailabilityChangedEvent eventData = null;
|
||||||
try{
|
try{
|
||||||
eventData = JSONObject.parseObject(payload, RoomTypeDateAvailabilityChangedEvent.class);
|
eventData = JSONObject.parseObject(payload, RoomTypeDateAvailabilityChangedEvent.class);
|
||||||
|
|||||||
+4
-4
@@ -27,7 +27,7 @@ public class NotificationController {
|
|||||||
private EmailProxySetting emailProxySetting;
|
private EmailProxySetting emailProxySetting;
|
||||||
|
|
||||||
@PostMapping(value = "/send_email", produces = "application/json;charset=UTF-8")
|
@PostMapping(value = "/send_email", produces = "application/json;charset=UTF-8")
|
||||||
public ResponseEntity<BaseApiResponse> handleSendEmailRequest(
|
public ResponseEntity<BaseApiResponse<Void>> handleSendEmailRequest(
|
||||||
@RequestBody(required = true) SendEmailRequest requestData,
|
@RequestBody(required = true) SendEmailRequest requestData,
|
||||||
HttpServletRequest request
|
HttpServletRequest request
|
||||||
){
|
){
|
||||||
@@ -35,7 +35,7 @@ public class NotificationController {
|
|||||||
String appId = request.getHeader("application-id");
|
String appId = request.getHeader("application-id");
|
||||||
String securityKey = request.getHeader("authorization");
|
String securityKey = request.getHeader("authorization");
|
||||||
|
|
||||||
BaseApiResponse result = emailNotificationService.sendEmailByRequest(requestData,emailProxySetting);
|
BaseApiResponse<Void> result = emailNotificationService.sendEmailByRequest(requestData,emailProxySetting);
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(result);
|
return ResponseEntity.status(HttpStatus.OK).body(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ public class NotificationController {
|
|||||||
* showTemp 为 HTML 正文,优先于 content;有 cc 时按群发模式发送。
|
* showTemp 为 HTML 正文,优先于 content;有 cc 时按群发模式发送。
|
||||||
*/
|
*/
|
||||||
@PostMapping(value = "/proxy/send_email", produces = "application/json;charset=UTF-8")
|
@PostMapping(value = "/proxy/send_email", produces = "application/json;charset=UTF-8")
|
||||||
public ResponseEntity<BaseApiResponse> handleSendEmailProxyRequest(
|
public ResponseEntity<BaseApiResponse<Void>> handleSendEmailProxyRequest(
|
||||||
@RequestBody(required = true) EmailProxyRequest requestData,
|
@RequestBody(required = true) EmailProxyRequest requestData,
|
||||||
HttpServletRequest request
|
HttpServletRequest request
|
||||||
) {
|
) {
|
||||||
@@ -64,7 +64,7 @@ public class NotificationController {
|
|||||||
// 有 cc 时用群发模式(false),让 to + cc 在同一封邮件里
|
// 有 cc 时用群发模式(false),让 to + cc 在同一封邮件里
|
||||||
sendEmailRequest.setSendSeparately(StringUtils.isBlank(requestData.getCc()));
|
sendEmailRequest.setSendSeparately(StringUtils.isBlank(requestData.getCc()));
|
||||||
|
|
||||||
BaseApiResponse result = emailNotificationService.sendEmailByRequest(sendEmailRequest, emailProxySetting);
|
BaseApiResponse<Void> result = emailNotificationService.sendEmailByRequest(sendEmailRequest, emailProxySetting);
|
||||||
logger.info("handleSendEmailProxyRequest end, id={}, success={}, statusCode={}, message={}",
|
logger.info("handleSendEmailProxyRequest end, id={}, success={}, statusCode={}, message={}",
|
||||||
requestData.getId(), result.isSuccess(), result.getStatusCode(), result.getMessage());
|
requestData.getId(), result.isSuccess(), result.getStatusCode(), result.getMessage());
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(result);
|
return ResponseEntity.status(HttpStatus.OK).body(result);
|
||||||
|
|||||||
+3
-3
@@ -33,12 +33,12 @@ public class ApnNotificationService {
|
|||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(ApnNotificationService.class);
|
private final Logger logger = LoggerFactory.getLogger(ApnNotificationService.class);
|
||||||
|
|
||||||
public BaseApiResponse pushApnMessage(String transactionId, String deviceToken, String title, String body, boolean isWaitResponse) {
|
public BaseApiResponse<Void> pushApnMessage(String transactionId, String deviceToken, String title, String body, boolean isWaitResponse) {
|
||||||
return pushApnMessage(transactionId, deviceToken, title, body, isWaitResponse, null);
|
return pushApnMessage(transactionId, deviceToken, title, body, isWaitResponse, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseApiResponse pushApnMessage(String transactionId, String deviceToken, String title, String body, boolean isWaitResponse, String confirmNo) {
|
public BaseApiResponse<Void> pushApnMessage(String transactionId, String deviceToken, String title, String body, boolean isWaitResponse, String confirmNo) {
|
||||||
BaseApiResponse result = new BaseApiResponse();
|
BaseApiResponse<Void> result = new BaseApiResponse<>();
|
||||||
if(StringUtils.isBlank(deviceToken)){
|
if(StringUtils.isBlank(deviceToken)){
|
||||||
result.setSuccess(false);
|
result.setSuccess(false);
|
||||||
result.setMessage("Device Token is empty");
|
result.setMessage("Device Token is empty");
|
||||||
|
|||||||
+2
-2
@@ -21,8 +21,8 @@ import java.util.Properties;
|
|||||||
public class EmailNotificationService {
|
public class EmailNotificationService {
|
||||||
private final Logger logger = LoggerFactory.getLogger(EmailNotificationService.class);
|
private final Logger logger = LoggerFactory.getLogger(EmailNotificationService.class);
|
||||||
|
|
||||||
public BaseApiResponse sendEmailByRequest(SendEmailRequest requestData, EmailProxySetting emailConfig) {
|
public BaseApiResponse<Void> sendEmailByRequest(SendEmailRequest requestData, EmailProxySetting emailConfig) {
|
||||||
BaseApiResponse result = new BaseApiResponse();
|
BaseApiResponse<Void> result = new BaseApiResponse<>();
|
||||||
try {
|
try {
|
||||||
JavaMailSenderImpl emailSender = new JavaMailSenderImpl();
|
JavaMailSenderImpl emailSender = new JavaMailSenderImpl();
|
||||||
emailSender.setHost(emailConfig.getSmtpServer());
|
emailSender.setHost(emailConfig.getSmtpServer());
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ public class NotificationProxyController {
|
|||||||
private NotificationProxyService notificationProxyService;
|
private NotificationProxyService notificationProxyService;
|
||||||
|
|
||||||
@RequestMapping("/api/notification/proxy/**")
|
@RequestMapping("/api/notification/proxy/**")
|
||||||
public ResponseEntity<BaseApiResponse> invokeNotificationApiProxy(HttpServletRequest request, @RequestBody SendNotificationRequest notificationRequest) throws Exception {
|
public ResponseEntity<BaseApiResponse<Void>> invokeNotificationApiProxy(HttpServletRequest request, @RequestBody SendNotificationRequest notificationRequest) throws Exception {
|
||||||
LoginUserInfo requestUser = SysCommon.parseUserFromToken(request.getHeader("Authorization"));
|
LoginUserInfo requestUser = SysCommon.parseUserFromToken(request.getHeader("Authorization"));
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(notificationProxyService.sendNotificationByRequest(notificationRequest,requestUser.getLoginId()));
|
return ResponseEntity.status(HttpStatus.OK).body(notificationProxyService.sendNotificationByRequest(notificationRequest,requestUser.getLoginId()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.mgm.mcrm.apigateway.proxy.controllers;
|
package com.mgm.mcrm.apigateway.proxy.controllers;
|
||||||
|
|
||||||
import com.mgm.mcrm.apigateway.appsetting.services.SysSettingService;
|
import com.mgm.mcrm.apigateway.appsetting.services.SysSettingService;
|
||||||
import com.mgm.mcrm.apigateway.common.constants.SysCommon;
|
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
import com.mgm.mcrm.apigateway.common.dtos.config.DaylightApiSetting;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.EsbApiSetting;
|
import com.mgm.mcrm.apigateway.common.dtos.config.EsbApiSetting;
|
||||||
import com.mgm.mcrm.apigateway.common.dtos.config.OperaApiSetting;
|
import com.mgm.mcrm.apigateway.common.dtos.config.OperaApiSetting;
|
||||||
@@ -64,6 +63,7 @@ public class WebProxyController {
|
|||||||
throw new Exception("Invoke daylight token failed");
|
throw new Exception("Invoke daylight token failed");
|
||||||
}
|
}
|
||||||
headers.set("authorization","Bearer "+daylightApiToken.getAccessToken());
|
headers.set("authorization","Bearer "+daylightApiToken.getAccessToken());
|
||||||
|
|
||||||
return webProxyService.invokeRequest(
|
return webProxyService.invokeRequest(
|
||||||
WebProxyService.DAYLIGHT_API,
|
WebProxyService.DAYLIGHT_API,
|
||||||
HttpMethod.valueOf(request.getMethod()),
|
HttpMethod.valueOf(request.getMethod()),
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ public class NotificationProxyService {
|
|||||||
@Resource
|
@Resource
|
||||||
private ApnNotificationService apnNotificationService;
|
private ApnNotificationService apnNotificationService;
|
||||||
|
|
||||||
public BaseApiResponse sendNotificationByRequest(SendNotificationRequest requestData, String senderId) {
|
public BaseApiResponse<Void> sendNotificationByRequest(SendNotificationRequest requestData, String senderId) {
|
||||||
BaseApiResponse result = new BaseApiResponse();
|
BaseApiResponse<Void> result = new BaseApiResponse<>();
|
||||||
String[] userIds = requestData.getEmployeeId().split("[;,]");
|
String[] userIds = requestData.getEmployeeId().split("[;,]");
|
||||||
String transactionId = requestData.getTransactionId();
|
String transactionId = requestData.getTransactionId();
|
||||||
if(StringUtils.isBlank(transactionId)){
|
if(StringUtils.isBlank(transactionId)){
|
||||||
@@ -62,7 +62,7 @@ public class NotificationProxyService {
|
|||||||
}
|
}
|
||||||
sysLogNotificationRepository.save(notificationLog);
|
sysLogNotificationRepository.save(notificationLog);
|
||||||
//-- Process APN sending
|
//-- Process APN sending
|
||||||
BaseApiResponse sendResult = apnNotificationService.pushApnMessage(
|
BaseApiResponse<Void> sendResult = apnNotificationService.pushApnMessage(
|
||||||
transactionId,
|
transactionId,
|
||||||
deviceTokenValue,
|
deviceTokenValue,
|
||||||
notificationTitle,
|
notificationTitle,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.mgm.mcrm.apigateway.reservation.models;
|
package com.mgm.mcrm.apigateway.reservation.models;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.mgm.mcrm.apigateway.reservation.repositories;
|
|||||||
|
|
||||||
import com.mgm.mcrm.apigateway.reservation.models.Bookings;
|
import com.mgm.mcrm.apigateway.reservation.models.Bookings;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -13,4 +12,6 @@ public interface BookingDao extends JpaRepository<Bookings, Long> {
|
|||||||
List<Bookings> findByDlReservationId(String dlReservationId);
|
List<Bookings> findByDlReservationId(String dlReservationId);
|
||||||
|
|
||||||
Bookings findFirstByDlProfileIdAndPlayerIdIsNotNull(String dlProfileId);
|
Bookings findFirstByDlProfileIdAndPlayerIdIsNotNull(String dlProfileId);
|
||||||
|
|
||||||
|
List<Bookings> findByDlExternalNo(String dlExternalNo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,17 +33,13 @@ import com.mgm.mcrm.apigateway.player.services.PlayerService;
|
|||||||
import com.mgm.mcrm.apigateway.reservation.models.Bookings;
|
import com.mgm.mcrm.apigateway.reservation.models.Bookings;
|
||||||
import com.mgm.mcrm.apigateway.reservation.repositories.BookingDao;
|
import com.mgm.mcrm.apigateway.reservation.repositories.BookingDao;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.java.Log;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.Strings;
|
import org.apache.commons.lang3.Strings;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
@@ -80,31 +76,33 @@ public class BookingService {
|
|||||||
private ApnNotificationService apnNotificationService;
|
private ApnNotificationService apnNotificationService;
|
||||||
|
|
||||||
public void processDaylightUpdateBooking(Bookings daylightBooking) throws Exception {
|
public void processDaylightUpdateBooking(Bookings daylightBooking) throws Exception {
|
||||||
if(daylightBooking!=null){
|
if (daylightBooking == null)
|
||||||
|
return;
|
||||||
|
|
||||||
String dlReservationId = daylightBooking.getDlReservationId();
|
String dlReservationId = daylightBooking.getDlReservationId();
|
||||||
String confirmNo = daylightBooking.getConfirmationNo();
|
String confirmNo = daylightBooking.getConfirmationNo();
|
||||||
String dbBookingStatus = null;
|
String dlExternalNo = daylightBooking.getDlExternalNo();
|
||||||
LocalDateTime checkInDate = null;
|
|
||||||
LocalDateTime checkOutDate = null;
|
List<Bookings> dbBookings = null;
|
||||||
if(StringUtils.isNotBlank(confirmNo)
|
if (StringUtils.isNotEmpty(dlExternalNo)) {
|
||||||
&& StringUtils.isNotBlank(dlReservationId)
|
dbBookings = bookingDao.findByDlExternalNo(dlExternalNo);
|
||||||
){
|
|
||||||
List<Bookings> dbBookings = bookingDao.findByDlReservationId(dlReservationId);
|
|
||||||
if (CollectionUtils.isEmpty(dbBookings)) {
|
|
||||||
dbBookings = bookingDao.findByConfirmationNo(confirmNo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(dbBookings)) {
|
if (CollectionUtils.isEmpty(dbBookings) && StringUtils.isNotEmpty(dlReservationId)) {
|
||||||
TimeUnit.SECONDS.sleep(5);
|
TimeUnit.SECONDS.sleep(2);
|
||||||
dbBookings = bookingDao.findByDlReservationId(dlReservationId);
|
dbBookings = bookingDao.findByDlReservationId(dlReservationId);
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(dbBookings)) {
|
|
||||||
dbBookings = bookingDao.findByConfirmationNo(confirmNo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(dbBookings) && StringUtils.isNotEmpty(confirmNo)) {
|
||||||
|
TimeUnit.SECONDS.sleep(2);
|
||||||
|
dbBookings = bookingDao.findByConfirmationNo(confirmNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bookings dbBooking = null;
|
Bookings dbBooking = null;
|
||||||
if(dbBookings!=null && !dbBookings.isEmpty()) {
|
LocalDateTime checkInDate = null;
|
||||||
|
LocalDateTime checkOutDate = null;
|
||||||
|
String dbBookingStatus = null;
|
||||||
|
if(!CollectionUtils.isEmpty(dbBookings)) {
|
||||||
for(Bookings booking:dbBookings){
|
for(Bookings booking:dbBookings){
|
||||||
if("N".equalsIgnoreCase(booking.getApproveStatus())) {
|
if("N".equalsIgnoreCase(booking.getApproveStatus())) {
|
||||||
dbBooking = booking;
|
dbBooking = booking;
|
||||||
@@ -116,8 +114,10 @@ public class BookingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(dbBooking!=null){
|
if(dbBooking!=null){
|
||||||
|
LogUtil.info(getClass(), "Find db Booking, id=" + dbBooking.getId());
|
||||||
this.mergeDaylightToDbBooking(daylightBooking,dbBooking);
|
this.mergeDaylightToDbBooking(daylightBooking,dbBooking);
|
||||||
}else{
|
}else{
|
||||||
|
LogUtil.info(getClass(), "Not found db Booking");
|
||||||
dbBooking = this.createBookingFromDaylight(daylightBooking);
|
dbBooking = this.createBookingFromDaylight(daylightBooking);
|
||||||
}
|
}
|
||||||
bookingDao.save(dbBooking);
|
bookingDao.save(dbBooking);
|
||||||
@@ -149,6 +149,7 @@ public class BookingService {
|
|||||||
notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
notificationContent = StringUtils.replaceEach(notificationContent, placeholders, values);
|
||||||
String transactionId = "DLBKSC"+dbBooking.getId();
|
String transactionId = "DLBKSC"+dbBooking.getId();
|
||||||
LogUtil.info(BookingService.class,"Get device token from DB Start");
|
LogUtil.info(BookingService.class,"Get device token from DB Start");
|
||||||
|
LogUtil.info(BookingService.class,"dbBooking.getCreatedBy()=" + dbBooking.getCreatedBy());
|
||||||
SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(StringUtils.trim(dbBooking.getCreatedBy()));
|
SysLogDeviceToken deviceToken = sysLogDeviceTokenRepository.findByUserId(StringUtils.trim(dbBooking.getCreatedBy()));
|
||||||
LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
LogUtil.info(BookingService.class,"Get device token from DB:" + (deviceToken == null ? "null" : deviceToken.getDeviceToken()));
|
||||||
String deviceTokenValue =null;
|
String deviceTokenValue =null;
|
||||||
@@ -204,54 +205,52 @@ public class BookingService {
|
|||||||
}
|
}
|
||||||
LogUtil.info(BookingService.class,"End send notification function");
|
LogUtil.info(BookingService.class,"End send notification function");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bookings findOneByDlProfileId(String dlProfileId) {
|
public Bookings findOneByDlProfileId(String dlProfileId) {
|
||||||
return bookingDao.findFirstByDlProfileIdAndPlayerIdIsNotNull(dlProfileId);
|
return bookingDao.findFirstByDlProfileIdAndPlayerIdIsNotNull(dlProfileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第一条是daylight返回过来的booking,第二条是本地数据库的booking
|
// 第一条是daylight返回过来的booking,第二条是本地数据库的booking
|
||||||
public void mergeDaylightToDbBooking(Bookings daylightBooking, Bookings updateBooking) throws Exception {
|
public void mergeDaylightToDbBooking(Bookings daylightBooking, Bookings dbBooking) throws Exception {
|
||||||
String nights = DateTimeUtil.getDiffDate(daylightBooking.getCheckinDate(), daylightBooking.getCheckoutDate(), "day");
|
String nights = DateTimeUtil.getDiffDate(daylightBooking.getCheckinDate(), daylightBooking.getCheckoutDate(), "day");
|
||||||
daylightBooking.setNumOfNight(Integer.valueOf(nights));
|
daylightBooking.setNumOfNight(Integer.valueOf(nights));
|
||||||
if(!"PN".equals(updateBooking.getApproveStatus())) {
|
if(!"PN".equals(dbBooking.getApproveStatus())) {
|
||||||
updateBooking.setCheckinDate(daylightBooking.getCheckinDate());
|
dbBooking.setCheckinDate(daylightBooking.getCheckinDate());
|
||||||
updateBooking.setCheckoutDate(daylightBooking.getCheckoutDate());
|
dbBooking.setCheckoutDate(daylightBooking.getCheckoutDate());
|
||||||
updateBooking.setNumOfNight(daylightBooking.getNumOfNight());
|
dbBooking.setNumOfNight(daylightBooking.getNumOfNight());
|
||||||
}
|
}
|
||||||
updateBooking.setConfirmationNo(daylightBooking.getConfirmationNo());
|
dbBooking.setConfirmationNo(daylightBooking.getConfirmationNo());
|
||||||
updateBooking.setHotelCode(daylightBooking.getHotelCode());
|
dbBooking.setHotelCode(daylightBooking.getHotelCode());
|
||||||
updateBooking.setDlProfileId(daylightBooking.getDlProfileId());
|
dbBooking.setDlProfileId(daylightBooking.getDlProfileId());
|
||||||
updateBooking.setDlSourceId(daylightBooking.getDlSourceId());
|
dbBooking.setDlSourceId(daylightBooking.getDlSourceId());
|
||||||
updateBooking.setDlGuaranteeTypeId(daylightBooking.getDlGuaranteeTypeId());
|
dbBooking.setDlGuaranteeTypeId(daylightBooking.getDlGuaranteeTypeId());
|
||||||
updateBooking.setDlChannelId(daylightBooking.getDlChannelId());
|
dbBooking.setDlChannelId(daylightBooking.getDlChannelId());
|
||||||
updateBooking.setDlAccountId(daylightBooking.getDlAccountId());
|
dbBooking.setDlAccountId(daylightBooking.getDlAccountId());
|
||||||
updateBooking.setDlBlockId(daylightBooking.getDlBlockId());
|
dbBooking.setDlBlockId(daylightBooking.getDlBlockId());
|
||||||
updateBooking.setDlExternalNo(daylightBooking.getDlExternalNo());
|
dbBooking.setDlExternalNo(daylightBooking.getDlExternalNo());
|
||||||
|
|
||||||
if (updateBooking.getWaitlistId() != null) {
|
if (dbBooking.getWaitlistId() != null) {
|
||||||
bookingDao.findById(updateBooking.getWaitlistId()).ifPresent(booking -> {
|
bookingDao.findById(dbBooking.getWaitlistId()).ifPresent(booking -> {
|
||||||
booking.setConfirmationNo(daylightBooking.getConfirmationNo());
|
booking.setConfirmationNo(daylightBooking.getConfirmationNo());
|
||||||
bookingDao.save(booking);
|
bookingDao.save(booking);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateBooking.setGroupId(daylightBooking.getGroupId());
|
// dbBooking.setGroupId(daylightBooking.getGroupId());
|
||||||
updateBooking.setDlReservationId(daylightBooking.getDlReservationId());
|
dbBooking.setDlReservationId(daylightBooking.getDlReservationId());
|
||||||
// 通过 dlRoomTypeId 查找 room type(与 createBookingFromDaylight 流程保持一致)
|
// 通过 dlRoomTypeId 查找 room type(与 createBookingFromDaylight 流程保持一致)
|
||||||
CfgRoomTypes daylightRoomType = roomTypeDao.findByDlRoomTypeId(daylightBooking.getDlRoomTypeId());
|
CfgRoomTypes daylightRoomType = roomTypeDao.findByDlRoomTypeId(daylightBooking.getDlRoomTypeId());
|
||||||
if(daylightRoomType!=null) {
|
if(daylightRoomType!=null) {
|
||||||
updateBooking.setRoomTypeId(daylightRoomType.getId());
|
dbBooking.setRoomTypeId(daylightRoomType.getId());
|
||||||
updateBooking.setRoomTypeCode(daylightRoomType.getCode());
|
dbBooking.setRoomTypeCode(daylightRoomType.getCode());
|
||||||
List<CfgRoomsRoomTypes> roomroomType = roomRoomTypeDao.findByRoomTypeId(daylightRoomType.getId());
|
List<CfgRoomsRoomTypes> roomroomType = roomRoomTypeDao.findByRoomTypeId(daylightRoomType.getId());
|
||||||
if(!roomroomType.isEmpty()) {
|
if(!roomroomType.isEmpty()) {
|
||||||
for(CfgRoomsRoomTypes r:roomroomType) {
|
for(CfgRoomsRoomTypes r:roomroomType) {
|
||||||
CfgRooms room = roomDao.findById(r.getRoomId()).orElse(null);
|
CfgRooms room = roomDao.findById(r.getRoomId()).orElse(null);
|
||||||
if(room!=null) {
|
if(room!=null) {
|
||||||
if(room.getPropertyId().equals(updateBooking.getPropertyId())) {
|
if(room.getPropertyId().equals(dbBooking.getPropertyId())) {
|
||||||
//updateBooking.setRoom(room.getName());
|
//dbBooking.setRoom(room.getName());
|
||||||
updateBooking.setRoomId(Math.toIntExact(room.getId()));
|
dbBooking.setRoomId(Math.toIntExact(room.getId()));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,52 +266,52 @@ public class BookingService {
|
|||||||
List<CfgDaylightView> bookingTypeOperas = daylightViewDao.findByMarketCodeIdAndRateCodeId(operaMarketCodeId,operaRateCodeId);
|
List<CfgDaylightView> bookingTypeOperas = daylightViewDao.findByMarketCodeIdAndRateCodeId(operaMarketCodeId,operaRateCodeId);
|
||||||
if(!bookingTypeOperas.isEmpty()) {
|
if(!bookingTypeOperas.isEmpty()) {
|
||||||
Long operaBookingTypeId = bookingTypeOperas.getFirst().getBookingTypeId();
|
Long operaBookingTypeId = bookingTypeOperas.getFirst().getBookingTypeId();
|
||||||
updateBooking.setBookingTypeId(Math.toIntExact(operaBookingTypeId));
|
dbBooking.setBookingTypeId(Math.toIntExact(operaBookingTypeId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if("CANCELED".equals(daylightBooking.getLastOperaStatus())) {
|
if("CANCELED".equals(daylightBooking.getLastOperaStatus())) {
|
||||||
updateBooking.setApproveStatus("C");
|
dbBooking.setApproveStatus("C");
|
||||||
daylightBooking.setApproveStatus("C");
|
daylightBooking.setApproveStatus("C");
|
||||||
}else {
|
}else {
|
||||||
if("C".equals(updateBooking.getApproveStatus())||daylightBooking.getConfirmationNo()!=null) {
|
if("C".equals(dbBooking.getApproveStatus())||daylightBooking.getConfirmationNo()!=null) {
|
||||||
updateBooking.setApproveStatus("N");
|
dbBooking.setApproveStatus("N");
|
||||||
daylightBooking.setApproveStatus("N");
|
daylightBooking.setApproveStatus("N");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateBooking.setLastOperaStatus(daylightBooking.getLastOperaStatus());
|
dbBooking.setLastOperaStatus(daylightBooking.getLastOperaStatus());
|
||||||
|
|
||||||
//get player info
|
//get player info
|
||||||
if(updateBooking.getMember()==null||StringUtils.isEmpty(updateBooking.getMember())) {
|
if(StringUtils.isEmpty(dbBooking.getMember())) {
|
||||||
if(!StringUtils.isEmpty(updateBooking.getPlayerId())) {
|
if(StringUtils.isNotEmpty(dbBooking.getPlayerId())) {
|
||||||
ServiceResult serviceResult = playerService.findWebPlayerProfileByPlayerId(updateBooking.getPlayerId());
|
ServiceResult serviceResult = playerService.findWebPlayerProfileByPlayerId(dbBooking.getPlayerId());
|
||||||
if(serviceResult.isSuccess()) {
|
if(serviceResult.isSuccess()) {
|
||||||
PlayerProfileApiResult profile = (PlayerProfileApiResult) serviceResult.getReturnData();
|
PlayerProfileApiResult profile = (PlayerProfileApiResult) serviceResult.getReturnData();
|
||||||
updateBooking.setMemberLastName(profile.getName());
|
dbBooking.setMemberLastName(profile.getName());
|
||||||
updateBooking.setMemberTitle(profile.getSalutation());
|
dbBooking.setMemberTitle(profile.getSalutation());
|
||||||
updateBooking.setMember(JSONObject.toJSONString(profile));
|
dbBooking.setMember(JSONObject.toJSONString(profile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//get user info
|
//get user info
|
||||||
boolean getUser = false;
|
boolean getUser = false;
|
||||||
String booker = StringUtils.trim(updateBooking.getBooker());
|
String booker = StringUtils.trim(dbBooking.getBooker());
|
||||||
if(booker==null||StringUtils.isEmpty(booker)) getUser=true;
|
if(StringUtils.isEmpty(booker)) getUser=true;
|
||||||
if(daylightBooking.getCreatedBy()!=null && !daylightBooking.getCreatedBy().equals(updateBooking.getCreatedBy())) {
|
if(daylightBooking.getCreatedBy()!=null && !daylightBooking.getCreatedBy().equals(dbBooking.getCreatedBy())) {
|
||||||
// updateBooking.setCreatedBy(daylightBooking.getCreatedBy());
|
// dbBooking.setCreatedBy(daylightBooking.getCreatedBy());
|
||||||
getUser=true;
|
getUser=true;
|
||||||
}
|
}
|
||||||
if(getUser) {
|
if(getUser) {
|
||||||
if(!StringUtils.isEmpty(updateBooking.getCreatedBy())) {
|
if(StringUtils.isNotEmpty(dbBooking.getCreatedBy())) {
|
||||||
ServiceResult userInfoRes = mgmUserService.findUserInfoByUserId(updateBooking.getCreatedBy());
|
ServiceResult userInfoRes = mgmUserService.findUserInfoByUserId(dbBooking.getCreatedBy());
|
||||||
if(userInfoRes.isSuccess()) {
|
if(userInfoRes.isSuccess()) {
|
||||||
UserInfoApiRecord userInfo = (UserInfoApiRecord)userInfoRes.getReturnData();
|
UserInfoApiRecord userInfo = (UserInfoApiRecord)userInfoRes.getReturnData();
|
||||||
updateBooking.setBooker(userInfo.getUserName());
|
dbBooking.setBooker(userInfo.getUserName());
|
||||||
updateBooking.setCreatedByName(userInfo.getUserName());
|
dbBooking.setCreatedByName(userInfo.getUserName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateBooking.setUpdatedAt(LocalDateTime.now());
|
dbBooking.setUpdatedAt(LocalDateTime.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bookings createBookingFromDaylight(Bookings daylightBooking) throws Exception {
|
public Bookings createBookingFromDaylight(Bookings daylightBooking) throws Exception {
|
||||||
@@ -412,7 +411,7 @@ public class BookingService {
|
|||||||
dbBooking.setDlReservationId(daylightBooking.getDlReservationId());
|
dbBooking.setDlReservationId(daylightBooking.getDlReservationId());
|
||||||
|
|
||||||
//get player info
|
//get player info
|
||||||
if(!StringUtils.isEmpty(dbBooking.getPlayerId())) {
|
if(StringUtils.isNotEmpty(dbBooking.getPlayerId())) {
|
||||||
ServiceResult serviceResult = playerService.findWebPlayerProfileByPlayerId(dbBooking.getPlayerId());
|
ServiceResult serviceResult = playerService.findWebPlayerProfileByPlayerId(dbBooking.getPlayerId());
|
||||||
if(serviceResult.isSuccess()) {
|
if(serviceResult.isSuccess()) {
|
||||||
PlayerProfileApiResult profile = (PlayerProfileApiResult) serviceResult.getReturnData();
|
PlayerProfileApiResult profile = (PlayerProfileApiResult) serviceResult.getReturnData();
|
||||||
@@ -423,7 +422,8 @@ public class BookingService {
|
|||||||
}
|
}
|
||||||
//get user info
|
//get user info
|
||||||
// 这个判断不会走进去,因为createdBy必定是null,因为eventData没有这个字段 by Mauve 20260806
|
// 这个判断不会走进去,因为createdBy必定是null,因为eventData没有这个字段 by Mauve 20260806
|
||||||
if(!StringUtils.isEmpty(dbBooking.getCreatedBy())) {
|
// 现在可以拿到createdBy了 by Mauve 20260920
|
||||||
|
if(StringUtils.isNotEmpty(dbBooking.getCreatedBy())) {
|
||||||
ServiceResult userInfoRes = mgmUserService.findUserInfoByUserId(dbBooking.getCreatedBy());
|
ServiceResult userInfoRes = mgmUserService.findUserInfoByUserId(dbBooking.getCreatedBy());
|
||||||
if(userInfoRes.isSuccess()) {
|
if(userInfoRes.isSuccess()) {
|
||||||
UserInfoApiRecord userInfo = (UserInfoApiRecord)userInfoRes.getReturnData();
|
UserInfoApiRecord userInfo = (UserInfoApiRecord)userInfoRes.getReturnData();
|
||||||
|
|||||||
@@ -127,7 +127,6 @@ server:
|
|||||||
logging:
|
logging:
|
||||||
config: classpath:logback.xml
|
config: classpath:logback.xml
|
||||||
|
|
||||||
|
|
||||||
springdoc:
|
springdoc:
|
||||||
swagger-ui:
|
swagger-ui:
|
||||||
path: /swagger-ui.html
|
path: /swagger-ui.html
|
||||||
@@ -154,3 +153,6 @@ apns:
|
|||||||
host: api.sandbox.push.apple.com
|
host: api.sandbox.push.apple.com
|
||||||
# Production Host
|
# Production Host
|
||||||
# host: api.push.apple.com
|
# host: api.push.apple.com
|
||||||
|
|
||||||
|
daylight:
|
||||||
|
url: http://localhost:9087/api/daylight/proxy
|
||||||
Reference in New Issue
Block a user