This commit is contained in:
Mauve
2026-10-12 15:17:12 +08:00
parent 727c76e4a6
commit 5b87fe58bc
11 changed files with 147 additions and 143 deletions
+1
View File
@@ -20,6 +20,7 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>21</java.version> <java.version>21</java.version>
<tomcat.version>11.0.25</tomcat.version>
<netty.version>4.2.18.Final</netty.version> <netty.version>4.2.18.Final</netty.version>
<httpclient5.version>5.6.4</httpclient5.version> <httpclient5.version>5.6.4</httpclient5.version>
<httpclient5-win.version>5.2.3</httpclient5-win.version> <httpclient5-win.version>5.2.3</httpclient5-win.version>
@@ -1,10 +1,16 @@
package com.mgm.mcrm.apigateway.common.services; package com.mgm.mcrm.apigateway.common.services;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class ConfigurableTrustHandler implements X509TrustManager { public class ConfigurableTrustHandler implements X509TrustManager {
private final boolean skipValidation; private final boolean skipValidation;
private final X509TrustManager defaultTrustManager; private final X509TrustManager defaultTrustManager;
private final Logger logger = LoggerFactory.getLogger(ConfigurableTrustHandler.class);
public ConfigurableTrustHandler(boolean skipValidation, X509TrustManager defaultTrustManager) { public ConfigurableTrustHandler(boolean skipValidation, X509TrustManager defaultTrustManager) {
this.skipValidation = skipValidation; this.skipValidation = skipValidation;
@@ -12,25 +18,25 @@ public class ConfigurableTrustHandler implements X509TrustManager {
} }
@Override @Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() { public X509Certificate[] getAcceptedIssuers() {
if (skipValidation) { if (skipValidation) {
return new java.security.cert.X509Certificate[0]; return new java.security.cert.X509Certificate[0];
}else{ }else{
return defaultTrustManager != null ? defaultTrustManager.getAcceptedIssuers() : new java.security.cert.X509Certificate[0]; return defaultTrustManager != null ? defaultTrustManager.getAcceptedIssuers() : new X509Certificate[0];
} }
} }
@Override @Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, public void checkServerTrusted(X509Certificate[] chain,
String authType) throws java.security.cert.CertificateException { String authType) throws CertificateException {
if (!skipValidation && defaultTrustManager != null) { if (!skipValidation && defaultTrustManager != null) {
defaultTrustManager.checkServerTrusted(chain, authType); defaultTrustManager.checkServerTrusted(chain, authType);
} }
} }
@Override @Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, public void checkClientTrusted(X509Certificate[] chain,
String authType) throws java.security.cert.CertificateException { String authType) throws CertificateException {
if (!skipValidation && defaultTrustManager != null) { if (!skipValidation && defaultTrustManager != null) {
defaultTrustManager.checkClientTrusted(chain, authType); defaultTrustManager.checkClientTrusted(chain, authType);
} }
@@ -124,33 +124,6 @@ public class HttpSslSupport {
} }
} }
/**
* 使用自定义证书(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} * 获取(或创建)指定协议版本的 {@link SSLContext}
@@ -94,9 +94,10 @@ public class DaylightConfigurationScheduler {
} }
/** /**
* 每天凌晨2点执行一次,拉取 Daylight 配置数据 * 按配置的时间和时区执行,拉取 Daylight 配置数据,默认北京时间每天凌晨2点
*/ */
@Scheduled(cron = "0 0 2 * * ?") @Scheduled(cron = "${daylight.scheduler.configuration-cron:0 0 2 * * ?}",
zone = "${daylight.scheduler.configuration-zone:Asia/Shanghai}")
public void fetchDaylightConfigurationDaily() { public void fetchDaylightConfigurationDaily() {
LogUtil.info(DaylightConfigurationScheduler.class, "Start scheduled task: fetchDaylightAllData"); LogUtil.info(DaylightConfigurationScheduler.class, "Start scheduled task: fetchDaylightAllData");
try { try {
@@ -24,8 +24,9 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.Duration; import java.time.Duration;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
@@ -37,6 +38,9 @@ import java.util.Optional;
public class DaylightFetchConfigurationService { public class DaylightFetchConfigurationService {
private static final Logger log = LoggerFactory.getLogger(DaylightFetchConfigurationService.class); private static final Logger log = LoggerFactory.getLogger(DaylightFetchConfigurationService.class);
private static final DateTimeFormatter UTC_UPDATED_AT_FORMATTER = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
.withZone(ZoneOffset.UTC);
private final HttpProxyErrorHandler httpErrorHandler = new HttpProxyErrorHandler(); private final HttpProxyErrorHandler httpErrorHandler = new HttpProxyErrorHandler();
@Resource @Resource
@@ -73,8 +77,6 @@ public class DaylightFetchConfigurationService {
return response; return response;
} }
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
for (CfgProperties property : allProperties) { for (CfgProperties property : allProperties) {
String dlPropertyId = property.getDlPropertyId(); String dlPropertyId = property.getDlPropertyId();
if (StringUtils.isBlank(dlPropertyId)) { if (StringUtils.isBlank(dlPropertyId)) {
@@ -90,7 +92,8 @@ public class DaylightFetchConfigurationService {
"Configuration", dlPropertyId, "SUCCESS"); "Configuration", dlPropertyId, "SUCCESS");
boolean hasSavedConfig = cfgDaylightConfigurationDao.existsSavedConfigurationByDlPropertyId(dlPropertyId); boolean hasSavedConfig = cfgDaylightConfigurationDao.existsSavedConfigurationByDlPropertyId(dlPropertyId);
if (lastSync.isPresent() && hasSavedConfig) { if (lastSync.isPresent() && hasSavedConfig) {
updatedAtParam = "&updatedAt=" + sdf.format(lastSync.get().getLastSyncAt()); updatedAtParam = "&updatedAt="
+ UTC_UPDATED_AT_FORMATTER.format(lastSync.get().getLastSyncAt().toInstant());
log.info("Property {} incremental sync, updatedAt: {}", dlPropertyId, updatedAtParam); log.info("Property {} incremental sync, updatedAt: {}", dlPropertyId, updatedAtParam);
} else { } else {
if (lastSync.isPresent() && !hasSavedConfig) { if (lastSync.isPresent() && !hasSavedConfig) {
@@ -255,7 +258,7 @@ public class DaylightFetchConfigurationService {
} }
/** /**
* 从 Daylight API 拉取 properties 列表,存入 cfg_daylight_configuration 表 * 从 Daylight units API 拉取 units 列表,存入 cfg_daylight_configuration 表
*/ */
public BaseApiResponse<Void> fetchDaylightProperties() { public BaseApiResponse<Void> fetchDaylightProperties() {
BaseApiResponse<Void> response = new BaseApiResponse<>(); BaseApiResponse<Void> response = new BaseApiResponse<>();
@@ -269,18 +272,15 @@ public class DaylightFetchConfigurationService {
return response; return response;
} }
String path = "/api-gateway/configuration/v1/properties"; String path = "/api-gateway/permission-management/v1/users/me/units";
String apiUrl = daylightApiSetting.getServerUrl() + path; String apiUrl = daylightApiSetting.getServerUrl() + path;
int pageNumber = 1;
List<JSONObject> allResults = new ArrayList<>(); List<JSONObject> allResults = new ArrayList<>();
String pagingNext = null;
do {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.set("authorization", "Bearer " + daylightApiToken.getAccessToken()); headers.set("authorization", "Bearer " + daylightApiToken.getAccessToken());
String queryString = "pageSize=500&statusCode=Published&recursive=true&isActive=true&pageNumber=" + pageNumber; String queryString = "pageSize=200";
log.info("Fetching properties page {}", pageNumber); log.info("Fetching properties from current user units");
ResponseEntity<byte[]> requestResponse = webProxyService.invokeRequest( ResponseEntity<byte[]> requestResponse = webProxyService.invokeRequest(
WebProxyService.DAYLIGHT_API, WebProxyService.DAYLIGHT_API,
@@ -310,30 +310,17 @@ public class DaylightFetchConfigurationService {
byte[] responseBody = requestResponse.getBody(); byte[] responseBody = requestResponse.getBody();
if (responseBody == null) { if (responseBody == null) {
break; throw new IllegalStateException("Daylight units response body is empty");
} }
String jsonStr = new String(responseBody, StandardCharsets.UTF_8); String jsonStr = new String(responseBody, StandardCharsets.UTF_8);
JSONObject responseJson = JSONObject.parseObject(jsonStr); JSONObject responseJson = JSONObject.parseObject(jsonStr);
if (responseJson == null || responseJson.getJSONArray("results") == null) {
// 累积 results 数组 throw new IllegalStateException("Daylight units response is missing results");
List<JSONObject> pageResults = responseJson.getJSONArray("results").toJavaList(JSONObject.class);
if (pageResults != null) {
allResults.addAll(pageResults);
} }
// 判断是否有下一页 // 完整保存 results 数组,不筛选 unit 类型或发布状态
pagingNext = null; allResults.addAll(responseJson.getJSONArray("results").toJavaList(JSONObject.class));
JSONObject paging = responseJson.getJSONObject("paging");
if (paging != null) {
int totalCount = paging.getIntValue("totalCount");
int pageSize = paging.getIntValue("pageSize");
if (pageNumber * pageSize < totalCount) {
pagingNext = "next";
pageNumber++;
}
}
} while (pagingNext != null);
// 保存为一条 CfgDaylightConfiguration,configName = "Property" // 保存为一条 CfgDaylightConfiguration,configName = "Property"
if (!allResults.isEmpty()) { if (!allResults.isEmpty()) {
@@ -504,8 +491,6 @@ public class DaylightFetchConfigurationService {
return response; return response;
} }
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
for (CfgProperties property : allProperties) { for (CfgProperties property : allProperties) {
dlPropertyId = property.getDlPropertyId(); dlPropertyId = property.getDlPropertyId();
if (StringUtils.isBlank(dlPropertyId)) { if (StringUtils.isBlank(dlPropertyId)) {
@@ -520,7 +505,8 @@ public class DaylightFetchConfigurationService {
CfgDaylightConfiguration existingConfig = cfgDaylightConfigurationDao CfgDaylightConfiguration existingConfig = cfgDaylightConfigurationDao
.findByDlPropertyIdAndConfigName(dlPropertyId, "BlockCode"); .findByDlPropertyIdAndConfigName(dlPropertyId, "BlockCode");
if (lastSync.isPresent() && existingConfig != null) { if (lastSync.isPresent() && existingConfig != null) {
updatedAtParam = "&updatedAt=" + sdf.format(lastSync.get().getLastSyncAt()); updatedAtParam = "&updatedAt="
+ UTC_UPDATED_AT_FORMATTER.format(lastSync.get().getLastSyncAt().toInstant());
log.info("Property {} BlockCode incremental sync, updatedAt: {}", dlPropertyId, updatedAtParam); log.info("Property {} BlockCode incremental sync, updatedAt: {}", dlPropertyId, updatedAtParam);
} else { } else {
if (lastSync.isPresent() && existingConfig == null) { if (lastSync.isPresent() && existingConfig == null) {
@@ -116,7 +116,7 @@ public class ReservationNotificationHandler implements DaylightWebhookHandler {
BaseApiResponse<JSONObject> response = BaseApiResponse<JSONObject> response =
daylightApiService.getDaylightReservationByDlId(eventData.getReservationId(), eventData.getPropertyId()); daylightApiService.getDaylightReservationByDlId(eventData.getReservationId(), eventData.getPropertyId());
if (response.isSuccess()) { if (response.isSuccess() && Objects.nonNull(response.getData())) {
JSONObject embedded = response.getData().getJSONObject("_embedded"); JSONObject embedded = response.getData().getJSONObject("_embedded");
if (embedded != null) { if (embedded != null) {
JSONArray customFields = embedded.getJSONArray("customFields"); JSONArray customFields = embedded.getJSONArray("customFields");
@@ -35,34 +35,4 @@ public class NotificationController {
return ResponseEntity.status(HttpStatus.OK).body(result); return ResponseEntity.status(HttpStatus.OK).body(result);
} }
/**
* 接收后端A转发过来的邮件请求,字段名与 SendEmailRequest 不同,这里做转换。
* showTemp 为 HTML 正文,优先于 content;有 cc 时按群发模式发送。
*/
@PostMapping(value = "/proxy/send_email", produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<Void>> handleSendEmailProxyRequest(
@RequestBody(required = true) EmailProxyRequest requestData,
HttpServletRequest request
) {
logger.info("handleSendEmailProxyRequest start, id={}, subject={}, to={}, cc={}, sender={}",
requestData.getId(), requestData.getSubject(), requestData.getTo(),
requestData.getCc(), requestData.getSender());
SendEmailRequest sendEmailRequest = new SendEmailRequest();
sendEmailRequest.setSendTo(requestData.getTo());
sendEmailRequest.setCc(requestData.getCc());
sendEmailRequest.setSubject(requestData.getSubject());
String bodyContent = StringUtils.isNotBlank(requestData.getShowTemp())
? requestData.getShowTemp()
: requestData.getContent();
sendEmailRequest.setBodyContent(bodyContent);
sendEmailRequest.setContentType("HTML");
sendEmailRequest.setSender(requestData.getSender());
// 有 cc 时用群发模式(false),让 to + cc 在同一封邮件里
sendEmailRequest.setSendSeparately(StringUtils.isBlank(requestData.getCc()));
BaseApiResponse<Void> result = emailNotificationService.sendEmailByRequest(sendEmailRequest, emailProxySetting);
logger.info("handleSendEmailProxyRequest end, id={}, success={}, statusCode={}, message={}",
requestData.getId(), result.isSuccess(), result.getStatusCode(), result.getMessage());
return ResponseEntity.status(HttpStatus.OK).body(result);
}
} }
@@ -9,6 +9,7 @@ import com.mgm.mcrm.apigateway.common.services.ConfigurableTrustHandler;
import io.netty.channel.ChannelOption; import io.netty.channel.ChannelOption;
import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder; import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutHandler;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@@ -16,8 +17,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ssl.SslBundle; import org.springframework.boot.ssl.*;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.http.client.reactive.ReactorClientHttpConnector;
@@ -29,7 +29,9 @@ import reactor.netty.resources.ConnectionProvider;
import reactor.netty.transport.ProxyProvider; import reactor.netty.transport.ProxyProvider;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException; import javax.net.ssl.SSLException;
import javax.net.ssl.SSLParameters;
import java.time.Duration; import java.time.Duration;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -64,7 +66,7 @@ public class WebClientConfig {
@Bean @Bean
public WebClient daylightWebClient() { public WebClient daylightWebClient() {
ConnectionProvider provider = ConnectionProvider.builder("proxy-pool") ConnectionProvider provider = ConnectionProvider.builder("daylight-proxy-pool")
.maxConnections(maxConnectionPool) .maxConnections(maxConnectionPool)
.pendingAcquireTimeout(Duration.ofSeconds(60)) .pendingAcquireTimeout(Duration.ofSeconds(60))
.maxIdleTime(Duration.ofSeconds(30)) .maxIdleTime(Duration.ofSeconds(30))
@@ -75,7 +77,13 @@ public class WebClientConfig {
.responseTimeout(Duration.ofSeconds(readTimeout)) .responseTimeout(Duration.ofSeconds(readTimeout))
.secure(spec -> { .secure(spec -> {
try { try {
spec.sslContext(this.createDaylightSslContent()); spec.sslContext(this.createDaylightSslContent())
.handlerConfigurator(sslHandler -> {
SSLEngine engine = sslHandler.engine();
SSLParameters params = engine.getSSLParameters();
params.setEndpointIdentificationAlgorithm("");
engine.setSSLParameters(params);
});
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -103,7 +111,7 @@ public class WebClientConfig {
@Bean @Bean
public WebClient esbWebClient() { public WebClient esbWebClient() {
ConnectionProvider provider = ConnectionProvider.builder("proxy-pool") ConnectionProvider provider = ConnectionProvider.builder("esb-proxy-pool")
.maxConnections(maxConnectionPool) .maxConnections(maxConnectionPool)
.pendingAcquireTimeout(Duration.ofSeconds(60)) .pendingAcquireTimeout(Duration.ofSeconds(60))
.maxIdleTime(Duration.ofSeconds(30)) .maxIdleTime(Duration.ofSeconds(30))
@@ -114,7 +122,13 @@ public class WebClientConfig {
.responseTimeout(Duration.ofSeconds(readTimeout)) .responseTimeout(Duration.ofSeconds(readTimeout))
.secure(spec -> { .secure(spec -> {
try { try {
spec.sslContext(this.createEsbSslContent()); spec.sslContext(this.createEsbSslContent())
.handlerConfigurator(sslHandler -> {
SSLEngine engine = sslHandler.engine();
SSLParameters params = engine.getSSLParameters();
params.setEndpointIdentificationAlgorithm("");
engine.setSSLParameters(params);
});
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -142,7 +156,7 @@ public class WebClientConfig {
@Bean @Bean
public WebClient limoWebClient() { public WebClient limoWebClient() {
ConnectionProvider provider = ConnectionProvider.builder("proxy-pool") ConnectionProvider provider = ConnectionProvider.builder("limo-proxy-pool")
.maxConnections(maxConnectionPool) .maxConnections(maxConnectionPool)
.pendingAcquireTimeout(Duration.ofSeconds(60)) .pendingAcquireTimeout(Duration.ofSeconds(60))
.maxIdleTime(Duration.ofSeconds(30)) .maxIdleTime(Duration.ofSeconds(30))
@@ -153,7 +167,13 @@ public class WebClientConfig {
.responseTimeout(Duration.ofSeconds(readTimeout)) .responseTimeout(Duration.ofSeconds(readTimeout))
.secure(spec -> { .secure(spec -> {
try { try {
spec.sslContext(this.createLimoSslContent()); spec.sslContext(this.createLimoSslContent())
.handlerConfigurator(sslHandler -> {
SSLEngine engine = sslHandler.engine();
SSLParameters params = engine.getSSLParameters();
params.setEndpointIdentificationAlgorithm("");
engine.setSSLParameters(params);
});
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -181,7 +201,7 @@ public class WebClientConfig {
@Bean @Bean
public WebClient operaWebClient() { public WebClient operaWebClient() {
ConnectionProvider provider = ConnectionProvider.builder("proxy-pool") ConnectionProvider provider = ConnectionProvider.builder("opera-proxy-pool")
.maxConnections(maxConnectionPool) .maxConnections(maxConnectionPool)
.pendingAcquireTimeout(Duration.ofSeconds(60)) .pendingAcquireTimeout(Duration.ofSeconds(60))
.maxIdleTime(Duration.ofSeconds(30)) .maxIdleTime(Duration.ofSeconds(30))
@@ -192,7 +212,13 @@ public class WebClientConfig {
.responseTimeout(Duration.ofSeconds(readTimeout)) .responseTimeout(Duration.ofSeconds(readTimeout))
.secure(spec -> { .secure(spec -> {
try { try {
spec.sslContext(this.createOperaSslContent()); spec.sslContext(this.createOperaSslContent())
.handlerConfigurator(sslHandler -> {
SSLEngine engine = sslHandler.engine();
SSLParameters params = engine.getSSLParameters();
params.setEndpointIdentificationAlgorithm("");
engine.setSSLParameters(params);
});
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@@ -306,7 +332,6 @@ public class WebClientConfig {
} }
//---------- //----------
private void setProxySettingByConfig(ProxyProvider.TypeSpec proxy, String proxyHost, int proxyPort, String authUserName, String authPassword){ private void setProxySettingByConfig(ProxyProvider.TypeSpec proxy, String proxyHost, int proxyPort, String authUserName, String authPassword){
if (StringUtils.isNotBlank(authUserName) && StringUtils.isNotBlank(authPassword)) { if (StringUtils.isNotBlank(authUserName) && StringUtils.isNotBlank(authPassword)) {
@@ -323,14 +348,14 @@ public class WebClientConfig {
} }
private SslContext createDefaultSslContext(ConfigurableTrustHandler trustHandler) throws SSLException { private SslContext createDefaultSslContext(ConfigurableTrustHandler trustHandler) throws SSLException {
return SslContextBuilder.forClient().trustManager(trustHandler).build(); return SslContextBuilder.forClient().trustManager(trustHandler).endpointIdentificationAlgorithm("").build();
} }
private SslContext createSslContextByConfig(String sslBundleName) throws SSLException { private SslContext createSslContextByConfig(String sslBundleName) throws SSLException {
SslBundle sslBundle = sslBundles.getBundle(sslBundleName); SslBundle sslBundle = sslBundles.getBundle(sslBundleName);
SSLContext netSslContext = sslBundle.createSslContext(); SSLContext netSslContext = sslBundle.createSslContext();
return SslContextBuilder.forClient() return SslContextBuilder.forClient()
.sslContextProvider(netSslContext.getProvider()) .sslContextProvider(netSslContext.getProvider()).endpointIdentificationAlgorithm("")
.build(); .build();
} }
} }
@@ -2,6 +2,9 @@ package com.mgm.mcrm.apigateway.proxy.controllers;
import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse; import com.mgm.mcrm.apigateway.common.dtos.BaseApiResponse;
import com.mgm.mcrm.apigateway.common.dtos.config.EmailProxySetting; import com.mgm.mcrm.apigateway.common.dtos.config.EmailProxySetting;
import com.mgm.mcrm.apigateway.notification.dtos.EmailProxyRequest;
import com.mgm.mcrm.apigateway.notification.dtos.SendEmailRequest;
import com.mgm.mcrm.apigateway.notification.services.EmailNotificationService;
import com.mgm.mcrm.apigateway.proxy.dtos.request.SendNotificationRequest; import com.mgm.mcrm.apigateway.proxy.dtos.request.SendNotificationRequest;
import com.mgm.mcrm.apigateway.proxy.services.NotificationProxyService; import com.mgm.mcrm.apigateway.proxy.services.NotificationProxyService;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -14,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@@ -29,7 +33,11 @@ public class NotificationProxyController {
@Autowired @Autowired
private EmailProxySetting emailProxySetting; private EmailProxySetting emailProxySetting;
@RequestMapping(value="/api/notification/proxy/**",produces = "application/json;charset=UTF-8",consumes = MediaType.APPLICATION_JSON_VALUE) @Resource
private EmailNotificationService emailNotificationService;
@RequestMapping(value="/api/notification/proxy/send_notification",produces = "application/json;charset=UTF-8",consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<BaseApiResponse<Void>> invokeNotificationApiProxy(HttpServletRequest request, @RequestBody SendNotificationRequest notificationRequest) throws Exception { public ResponseEntity<BaseApiResponse<Void>> invokeNotificationApiProxy(HttpServletRequest request, @RequestBody SendNotificationRequest notificationRequest) throws Exception {
//--Check authorization //--Check authorization
String appId = request.getHeader("application-id"); String appId = request.getHeader("application-id");
@@ -40,6 +48,37 @@ public class NotificationProxyController {
return ResponseEntity.status(HttpStatus.OK).body(notificationProxyService.sendNotificationByRequest(notificationRequest,notificationRequest.getRequestorId())); return ResponseEntity.status(HttpStatus.OK).body(notificationProxyService.sendNotificationByRequest(notificationRequest,notificationRequest.getRequestorId()));
} }
/**
* 接收后端A转发过来的邮件请求,字段名与 SendEmailRequest 不同,这里做转换。
* showTemp 为 HTML 正文,优先于 content;有 cc 时按群发模式发送。
*/
@PostMapping(value = "/api/notification/proxy/send_email", produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseApiResponse<Void>> handleSendEmailProxyRequest(
@RequestBody(required = true) EmailProxyRequest requestData,
HttpServletRequest request
) {
logger.info("handleSendEmailProxyRequest start, id={}, subject={}, to={}, cc={}, sender={}",
requestData.getId(), requestData.getSubject(), requestData.getTo(),
requestData.getCc(), requestData.getSender());
SendEmailRequest sendEmailRequest = new SendEmailRequest();
sendEmailRequest.setSendTo(requestData.getTo());
sendEmailRequest.setCc(requestData.getCc());
sendEmailRequest.setSubject(requestData.getSubject());
String bodyContent = StringUtils.isNotBlank(requestData.getShowTemp())
? requestData.getShowTemp()
: requestData.getContent();
sendEmailRequest.setBodyContent(bodyContent);
sendEmailRequest.setContentType("HTML");
sendEmailRequest.setSender(requestData.getSender());
// 有 cc 时用群发模式(false),让 to + cc 在同一封邮件里
sendEmailRequest.setSendSeparately(StringUtils.isBlank(requestData.getCc()));
BaseApiResponse<Void> result = emailNotificationService.sendEmailByRequest(sendEmailRequest, emailProxySetting);
logger.info("handleSendEmailProxyRequest end, id={}, success={}, statusCode={}, message={}",
requestData.getId(), result.isSuccess(), result.getStatusCode(), result.getMessage());
return ResponseEntity.status(HttpStatus.OK).body(result);
}
private boolean isAuthorizated(String appId, String securityKey) { private boolean isAuthorizated(String appId, String securityKey) {
boolean isAuth=false; boolean isAuth=false;
if(StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(securityKey)){ if(StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(securityKey)){
@@ -1,6 +1,5 @@
package com.mgm.mcrm.apigateway.proxy.services; package com.mgm.mcrm.apigateway.proxy.services;
import com.mgm.mcrm.apigateway.common.utils.NetworkUtil;
import com.mgm.mcrm.apigateway.common.utils.mockup.HttpUtilMockup; import com.mgm.mcrm.apigateway.common.utils.mockup.HttpUtilMockup;
import com.mgm.mcrm.apigateway.proxy.exception.ProxyErrorHandler; import com.mgm.mcrm.apigateway.proxy.exception.ProxyErrorHandler;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
+4
View File
@@ -178,5 +178,9 @@ apns:
# host: api.push.apple.com # host: api.push.apple.com
daylight: daylight:
scheduler:
# Cron fields: second minute hour day-of-month month day-of-week. Restart after changes.
configuration-cron: "0 0 2 * * ?"
configuration-zone: "Asia/Shanghai"
url: http://localhost:9087/api/daylight/proxy url: http://localhost:9087/api/daylight/proxy
system-id: 3a151ad3-46be-4644-b656-71d3b037b309 system-id: 3a151ad3-46be-4644-b656-71d3b037b309