diff --git a/pom.xml b/pom.xml index 1faa3b2..f2ab9df 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,7 @@ UTF-8 21 + 11.0.25 4.2.18.Final 5.6.4 5.2.3 diff --git a/src/main/java/com/mgm/mcrm/apigateway/common/services/ConfigurableTrustHandler.java b/src/main/java/com/mgm/mcrm/apigateway/common/services/ConfigurableTrustHandler.java index ffd5a5e..4259311 100644 --- a/src/main/java/com/mgm/mcrm/apigateway/common/services/ConfigurableTrustHandler.java +++ b/src/main/java/com/mgm/mcrm/apigateway/common/services/ConfigurableTrustHandler.java @@ -1,10 +1,16 @@ package com.mgm.mcrm.apigateway.common.services; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import javax.net.ssl.X509TrustManager; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; public class ConfigurableTrustHandler implements X509TrustManager { private final boolean skipValidation; private final X509TrustManager defaultTrustManager; + private final Logger logger = LoggerFactory.getLogger(ConfigurableTrustHandler.class); public ConfigurableTrustHandler(boolean skipValidation, X509TrustManager defaultTrustManager) { this.skipValidation = skipValidation; @@ -12,25 +18,25 @@ public class ConfigurableTrustHandler implements X509TrustManager { } @Override - public java.security.cert.X509Certificate[] getAcceptedIssuers() { + public X509Certificate[] getAcceptedIssuers() { if (skipValidation) { return new java.security.cert.X509Certificate[0]; }else{ - return defaultTrustManager != null ? defaultTrustManager.getAcceptedIssuers() : new java.security.cert.X509Certificate[0]; + return defaultTrustManager != null ? defaultTrustManager.getAcceptedIssuers() : new X509Certificate[0]; } } @Override - public void checkServerTrusted(java.security.cert.X509Certificate[] chain, - String authType) throws java.security.cert.CertificateException { + public void checkServerTrusted(X509Certificate[] chain, + String authType) throws CertificateException { if (!skipValidation && defaultTrustManager != null) { defaultTrustManager.checkServerTrusted(chain, authType); } } @Override - public void checkClientTrusted(java.security.cert.X509Certificate[] chain, - String authType) throws java.security.cert.CertificateException { + public void checkClientTrusted(X509Certificate[] chain, + String authType) throws CertificateException { if (!skipValidation && defaultTrustManager != null) { defaultTrustManager.checkClientTrusted(chain, authType); } diff --git a/src/main/java/com/mgm/mcrm/apigateway/daylight/common/httpclient/HttpSslSupport.java b/src/main/java/com/mgm/mcrm/apigateway/daylight/common/httpclient/HttpSslSupport.java index ae4b4f5..cef29f8 100644 --- a/src/main/java/com/mgm/mcrm/apigateway/daylight/common/httpclient/HttpSslSupport.java +++ b/src/main/java/com/mgm/mcrm/apigateway/daylight/common/httpclient/HttpSslSupport.java @@ -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} diff --git a/src/main/java/com/mgm/mcrm/apigateway/daylight/common/scheduler/DaylightConfigurationScheduler.java b/src/main/java/com/mgm/mcrm/apigateway/daylight/common/scheduler/DaylightConfigurationScheduler.java index 9050903..4405028 100644 --- a/src/main/java/com/mgm/mcrm/apigateway/daylight/common/scheduler/DaylightConfigurationScheduler.java +++ b/src/main/java/com/mgm/mcrm/apigateway/daylight/common/scheduler/DaylightConfigurationScheduler.java @@ -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() { LogUtil.info(DaylightConfigurationScheduler.class, "Start scheduled task: fetchDaylightAllData"); try { diff --git a/src/main/java/com/mgm/mcrm/apigateway/daylight/common/services/DaylightFetchConfigurationService.java b/src/main/java/com/mgm/mcrm/apigateway/daylight/common/services/DaylightFetchConfigurationService.java index 00a1e8f..871dd40 100644 --- a/src/main/java/com/mgm/mcrm/apigateway/daylight/common/services/DaylightFetchConfigurationService.java +++ b/src/main/java/com/mgm/mcrm/apigateway/daylight/common/services/DaylightFetchConfigurationService.java @@ -24,8 +24,9 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import java.nio.charset.StandardCharsets; -import java.text.SimpleDateFormat; import java.time.Duration; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -37,6 +38,9 @@ import java.util.Optional; public class DaylightFetchConfigurationService { 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(); @Resource @@ -73,8 +77,6 @@ public class DaylightFetchConfigurationService { return response; } - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); - for (CfgProperties property : allProperties) { String dlPropertyId = property.getDlPropertyId(); if (StringUtils.isBlank(dlPropertyId)) { @@ -90,7 +92,8 @@ public class DaylightFetchConfigurationService { "Configuration", dlPropertyId, "SUCCESS"); boolean hasSavedConfig = cfgDaylightConfigurationDao.existsSavedConfigurationByDlPropertyId(dlPropertyId); 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); } else { 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 fetchDaylightProperties() { BaseApiResponse response = new BaseApiResponse<>(); @@ -269,71 +272,55 @@ public class DaylightFetchConfigurationService { return response; } - String path = "/api-gateway/configuration/v1/properties"; + String path = "/api-gateway/permission-management/v1/users/me/units"; String apiUrl = daylightApiSetting.getServerUrl() + path; - int pageNumber = 1; List allResults = new ArrayList<>(); - String pagingNext = null; - do { - HttpHeaders headers = new HttpHeaders(); - headers.set("authorization", "Bearer " + daylightApiToken.getAccessToken()); + HttpHeaders headers = new HttpHeaders(); + headers.set("authorization", "Bearer " + daylightApiToken.getAccessToken()); - String queryString = "pageSize=500&statusCode=Published&recursive=true&isActive=true&pageNumber=" + pageNumber; - log.info("Fetching properties page {}", pageNumber); + String queryString = "pageSize=200"; + log.info("Fetching properties from current user units"); - ResponseEntity requestResponse = webProxyService.invokeRequest( - WebProxyService.DAYLIGHT_API, - HttpMethod.GET, - apiUrl, - queryString, - headers, - new byte[0], - Duration.ofSeconds(daylightApiSetting.getApiTimeout()), - httpErrorHandler - ).block(); + ResponseEntity requestResponse = webProxyService.invokeRequest( + WebProxyService.DAYLIGHT_API, + HttpMethod.GET, + apiUrl, + queryString, + headers, + new byte[0], + Duration.ofSeconds(daylightApiSetting.getApiTimeout()), + httpErrorHandler + ).block(); - if (requestResponse == null) { - response.setSuccess(false); - response.setMessage("Http request server can not visit."); - return response; - } + if (requestResponse == null) { + response.setSuccess(false); + response.setMessage("Http request server can not visit."); + return response; + } - response.setStatusCode(requestResponse.getStatusCode().value()); + response.setStatusCode(requestResponse.getStatusCode().value()); - if (!requestResponse.getStatusCode().is2xxSuccessful()) { - byte[] errorBody = requestResponse.getBody(); - response.setSuccess(false); - response.setMessage(errorBody != null ? new String(errorBody, StandardCharsets.UTF_8) : "Request failed"); - return response; - } + if (!requestResponse.getStatusCode().is2xxSuccessful()) { + byte[] errorBody = requestResponse.getBody(); + response.setSuccess(false); + response.setMessage(errorBody != null ? new String(errorBody, StandardCharsets.UTF_8) : "Request failed"); + return response; + } - byte[] responseBody = requestResponse.getBody(); - if (responseBody == null) { - break; - } + byte[] responseBody = requestResponse.getBody(); + if (responseBody == null) { + throw new IllegalStateException("Daylight units response body is empty"); + } - String jsonStr = new String(responseBody, StandardCharsets.UTF_8); - JSONObject responseJson = JSONObject.parseObject(jsonStr); + String jsonStr = new String(responseBody, StandardCharsets.UTF_8); + JSONObject responseJson = JSONObject.parseObject(jsonStr); + if (responseJson == null || responseJson.getJSONArray("results") == null) { + throw new IllegalStateException("Daylight units response is missing results"); + } - // 累积 results 数组 - List pageResults = responseJson.getJSONArray("results").toJavaList(JSONObject.class); - if (pageResults != null) { - allResults.addAll(pageResults); - } - - // 判断是否有下一页 - pagingNext = null; - 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); + // 完整保存 results 数组,不筛选 unit 类型或发布状态 + allResults.addAll(responseJson.getJSONArray("results").toJavaList(JSONObject.class)); // 保存为一条 CfgDaylightConfiguration,configName = "Property" if (!allResults.isEmpty()) { @@ -504,8 +491,6 @@ public class DaylightFetchConfigurationService { return response; } - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); - for (CfgProperties property : allProperties) { dlPropertyId = property.getDlPropertyId(); if (StringUtils.isBlank(dlPropertyId)) { @@ -520,7 +505,8 @@ public class DaylightFetchConfigurationService { CfgDaylightConfiguration existingConfig = cfgDaylightConfigurationDao .findByDlPropertyIdAndConfigName(dlPropertyId, "BlockCode"); 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); } else { if (lastSync.isPresent() && existingConfig == null) { diff --git a/src/main/java/com/mgm/mcrm/apigateway/daylight/webhook/eventhandlers/impl/ReservationNotificationHandler.java b/src/main/java/com/mgm/mcrm/apigateway/daylight/webhook/eventhandlers/impl/ReservationNotificationHandler.java index f1fa444..2f76968 100644 --- a/src/main/java/com/mgm/mcrm/apigateway/daylight/webhook/eventhandlers/impl/ReservationNotificationHandler.java +++ b/src/main/java/com/mgm/mcrm/apigateway/daylight/webhook/eventhandlers/impl/ReservationNotificationHandler.java @@ -116,7 +116,7 @@ public class ReservationNotificationHandler implements DaylightWebhookHandler { BaseApiResponse response = daylightApiService.getDaylightReservationByDlId(eventData.getReservationId(), eventData.getPropertyId()); - if (response.isSuccess()) { + if (response.isSuccess() && Objects.nonNull(response.getData())) { JSONObject embedded = response.getData().getJSONObject("_embedded"); if (embedded != null) { JSONArray customFields = embedded.getJSONArray("customFields"); diff --git a/src/main/java/com/mgm/mcrm/apigateway/notification/controllers/NotificationController.java b/src/main/java/com/mgm/mcrm/apigateway/notification/controllers/NotificationController.java index 4634c9f..e8619c3 100644 --- a/src/main/java/com/mgm/mcrm/apigateway/notification/controllers/NotificationController.java +++ b/src/main/java/com/mgm/mcrm/apigateway/notification/controllers/NotificationController.java @@ -35,34 +35,4 @@ public class NotificationController { 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> 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 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); - } } diff --git a/src/main/java/com/mgm/mcrm/apigateway/proxy/config/WebClientConfig.java b/src/main/java/com/mgm/mcrm/apigateway/proxy/config/WebClientConfig.java index d9ebcf7..ad60f03 100644 --- a/src/main/java/com/mgm/mcrm/apigateway/proxy/config/WebClientConfig.java +++ b/src/main/java/com/mgm/mcrm/apigateway/proxy/config/WebClientConfig.java @@ -9,6 +9,7 @@ import com.mgm.mcrm.apigateway.common.services.ConfigurableTrustHandler; import io.netty.channel.ChannelOption; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.SslContextBuilder; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutHandler; import org.apache.commons.lang3.StringUtils; @@ -16,8 +17,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.ssl.SslBundle; -import org.springframework.boot.ssl.SslBundles; +import org.springframework.boot.ssl.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.reactive.ReactorClientHttpConnector; @@ -29,7 +29,9 @@ import reactor.netty.resources.ConnectionProvider; import reactor.netty.transport.ProxyProvider; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLException; +import javax.net.ssl.SSLParameters; import java.time.Duration; import java.util.concurrent.TimeUnit; @@ -64,7 +66,7 @@ public class WebClientConfig { @Bean public WebClient daylightWebClient() { - ConnectionProvider provider = ConnectionProvider.builder("proxy-pool") + ConnectionProvider provider = ConnectionProvider.builder("daylight-proxy-pool") .maxConnections(maxConnectionPool) .pendingAcquireTimeout(Duration.ofSeconds(60)) .maxIdleTime(Duration.ofSeconds(30)) @@ -75,7 +77,13 @@ public class WebClientConfig { .responseTimeout(Duration.ofSeconds(readTimeout)) .secure(spec -> { 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) { throw new RuntimeException(e); } @@ -103,7 +111,7 @@ public class WebClientConfig { @Bean public WebClient esbWebClient() { - ConnectionProvider provider = ConnectionProvider.builder("proxy-pool") + ConnectionProvider provider = ConnectionProvider.builder("esb-proxy-pool") .maxConnections(maxConnectionPool) .pendingAcquireTimeout(Duration.ofSeconds(60)) .maxIdleTime(Duration.ofSeconds(30)) @@ -114,7 +122,13 @@ public class WebClientConfig { .responseTimeout(Duration.ofSeconds(readTimeout)) .secure(spec -> { 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) { throw new RuntimeException(e); } @@ -142,7 +156,7 @@ public class WebClientConfig { @Bean public WebClient limoWebClient() { - ConnectionProvider provider = ConnectionProvider.builder("proxy-pool") + ConnectionProvider provider = ConnectionProvider.builder("limo-proxy-pool") .maxConnections(maxConnectionPool) .pendingAcquireTimeout(Duration.ofSeconds(60)) .maxIdleTime(Duration.ofSeconds(30)) @@ -153,7 +167,13 @@ public class WebClientConfig { .responseTimeout(Duration.ofSeconds(readTimeout)) .secure(spec -> { 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) { throw new RuntimeException(e); } @@ -181,7 +201,7 @@ public class WebClientConfig { @Bean public WebClient operaWebClient() { - ConnectionProvider provider = ConnectionProvider.builder("proxy-pool") + ConnectionProvider provider = ConnectionProvider.builder("opera-proxy-pool") .maxConnections(maxConnectionPool) .pendingAcquireTimeout(Duration.ofSeconds(60)) .maxIdleTime(Duration.ofSeconds(30)) @@ -192,7 +212,13 @@ public class WebClientConfig { .responseTimeout(Duration.ofSeconds(readTimeout)) .secure(spec -> { 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) { 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){ if (StringUtils.isNotBlank(authUserName) && StringUtils.isNotBlank(authPassword)) { @@ -323,14 +348,14 @@ public class WebClientConfig { } 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 { SslBundle sslBundle = sslBundles.getBundle(sslBundleName); SSLContext netSslContext = sslBundle.createSslContext(); return SslContextBuilder.forClient() - .sslContextProvider(netSslContext.getProvider()) + .sslContextProvider(netSslContext.getProvider()).endpointIdentificationAlgorithm("") .build(); } } diff --git a/src/main/java/com/mgm/mcrm/apigateway/proxy/controllers/NotificationProxyController.java b/src/main/java/com/mgm/mcrm/apigateway/proxy/controllers/NotificationProxyController.java index a1e4b7e..4b4e3dd 100644 --- a/src/main/java/com/mgm/mcrm/apigateway/proxy/controllers/NotificationProxyController.java +++ b/src/main/java/com/mgm/mcrm/apigateway/proxy/controllers/NotificationProxyController.java @@ -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.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.services.NotificationProxyService; 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.MediaType; 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.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -29,7 +33,11 @@ public class NotificationProxyController { @Autowired 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> invokeNotificationApiProxy(HttpServletRequest request, @RequestBody SendNotificationRequest notificationRequest) throws Exception { //--Check authorization String appId = request.getHeader("application-id"); @@ -40,6 +48,37 @@ public class NotificationProxyController { 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> 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 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) { boolean isAuth=false; if(StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(securityKey)){ diff --git a/src/main/java/com/mgm/mcrm/apigateway/proxy/services/WebProxyService.java b/src/main/java/com/mgm/mcrm/apigateway/proxy/services/WebProxyService.java index 809ea2d..41275bd 100644 --- a/src/main/java/com/mgm/mcrm/apigateway/proxy/services/WebProxyService.java +++ b/src/main/java/com/mgm/mcrm/apigateway/proxy/services/WebProxyService.java @@ -1,6 +1,5 @@ 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.proxy.exception.ProxyErrorHandler; import lombok.RequiredArgsConstructor; diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 83467ed..dab80a2 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -178,5 +178,9 @@ apns: # host: api.push.apple.com 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 system-id: 3a151ad3-46be-4644-b656-71d3b037b309