From dd765dc4c954b89ed2c7327ab68a83463392831a Mon Sep 17 00:00:00 2001 From: HyoBN Date: Sun, 28 Jan 2024 02:31:58 +0900 Subject: [PATCH 1/2] =?UTF-8?q?:sparkles:=20Feat:=20FCM=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=EC=84=B8=ED=8C=85=20=EB=B0=8F=20AOS=20=ED=91=B8?= =?UTF-8?q?=EC=8B=9C=EC=95=8C=EB=A6=BC=20=EC=9E=84=EC=8B=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 + .../apiResponse/code/ResponseStatus.java | 5 +- .../handler/NotificationException.java | 10 ++ src/main/java/cmc/peerna/domain/FcmToken.java | 34 +++++ .../java/cmc/peerna/domain/PushAlarm.java | 35 +++++ .../peerna/domain/enums/NotificationType.java | 13 ++ src/main/java/cmc/peerna/fcm/FCMService.java | 134 ++++++++++++++++++ .../cmc/peerna/fcm/dto/FcmAOSMessage.java | 35 +++++ .../cmc/peerna/fcm/dto/FcmTokenRequest.java | 12 ++ .../cmc/peerna/fcm/service/FcmService.java | 72 ++++++++++ .../java/cmc/peerna/feign/FCMFeignClient.java | 18 +++ .../peerna/feign/config/FCMFeignConfig.java | 27 ++++ .../cmc/peerna/feign/dto/FCMResponseDto.java | 10 ++ .../peerna/repository/FcmTokenRepository.java | 10 ++ .../repository/PushAlarmRepository.java | 17 +++ .../java/cmc/peerna/service/RootService.java | 3 + .../service/serviceImpl/RootServiceImpl.java | 23 +++ .../peerna/web/controller/RootController.java | 12 ++ .../web/dto/requestDto/RootRequestDto.java | 8 ++ src/main/resources/application.yml | 4 + src/main/resources/firebase-adminsdk-key.json | 13 ++ 21 files changed, 498 insertions(+), 1 deletion(-) create mode 100644 src/main/java/cmc/peerna/apiResponse/exception/handler/NotificationException.java create mode 100644 src/main/java/cmc/peerna/domain/FcmToken.java create mode 100644 src/main/java/cmc/peerna/domain/PushAlarm.java create mode 100644 src/main/java/cmc/peerna/domain/enums/NotificationType.java create mode 100644 src/main/java/cmc/peerna/fcm/FCMService.java create mode 100644 src/main/java/cmc/peerna/fcm/dto/FcmAOSMessage.java create mode 100644 src/main/java/cmc/peerna/fcm/dto/FcmTokenRequest.java create mode 100644 src/main/java/cmc/peerna/fcm/service/FcmService.java create mode 100644 src/main/java/cmc/peerna/feign/FCMFeignClient.java create mode 100644 src/main/java/cmc/peerna/feign/config/FCMFeignConfig.java create mode 100644 src/main/java/cmc/peerna/feign/dto/FCMResponseDto.java create mode 100644 src/main/java/cmc/peerna/repository/FcmTokenRepository.java create mode 100644 src/main/java/cmc/peerna/repository/PushAlarmRepository.java create mode 100644 src/main/resources/firebase-adminsdk-key.json diff --git a/build.gradle b/build.gradle index f404fb4..973e6e1 100644 --- a/build.gradle +++ b/build.gradle @@ -52,6 +52,10 @@ dependencies { implementation 'io.springfox:springfox-swagger-ui:2.9.2' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' + // fcm + implementation 'com.google.firebase:firebase-admin:9.2.0' +// implementation group: 'com.squareup.okhttp3', name: 'okhttp', version : '4.2.2' + annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" } diff --git a/src/main/java/cmc/peerna/apiResponse/code/ResponseStatus.java b/src/main/java/cmc/peerna/apiResponse/code/ResponseStatus.java index 16354ca..2ee3276 100644 --- a/src/main/java/cmc/peerna/apiResponse/code/ResponseStatus.java +++ b/src/main/java/cmc/peerna/apiResponse/code/ResponseStatus.java @@ -1,5 +1,6 @@ package cmc.peerna.apiResponse.code; +import com.google.api.Http; import lombok.AllArgsConstructor; import lombok.Getter; import org.springframework.http.HttpStatus; @@ -48,6 +49,7 @@ public enum ResponseStatus implements BaseCode { INVALID_ACCESS_TOKEN(UNAUTHORIZED, 4016, "액세스 토큰이 없거나 유효하지 않습니다."), + FCM_TOKEN_NOT_FOUND(BAD_REQUEST, 4017, "해당 유저의 FCM 토큰이 존재하지 않습니다."), WRONG_POST_TEST(BAD_REQUEST, 4101, "잘못된 POST 테스트 요청입니다."), @@ -58,8 +60,9 @@ public enum ResponseStatus implements BaseCode { // 500번대 에러 _INTERNAL_SERVER_ERROR(INTERNAL_SERVER_ERROR, 5000, "서버 에러, 관리자에게 문의 바랍니다."), - FEIGN_CLIENT_ERROR_500(HttpStatus.INTERNAL_SERVER_ERROR, 5001, "Inter server Error in feign client"); + FEIGN_CLIENT_ERROR_500(HttpStatus.INTERNAL_SERVER_ERROR, 5001, "Inter server Error in feign client"), + FCM_ACCESS_TOKEN_REQUEST_ERROR(INTERNAL_SERVER_ERROR, 5002, "서버 에러, FCM 서버에 AccessToken 요청할 때 에러 발생."); private final HttpStatus httpStatus; private final Integer code; diff --git a/src/main/java/cmc/peerna/apiResponse/exception/handler/NotificationException.java b/src/main/java/cmc/peerna/apiResponse/exception/handler/NotificationException.java new file mode 100644 index 0000000..155dab5 --- /dev/null +++ b/src/main/java/cmc/peerna/apiResponse/exception/handler/NotificationException.java @@ -0,0 +1,10 @@ +package cmc.peerna.apiResponse.exception.handler; + +import cmc.peerna.apiResponse.code.ResponseStatus; +import cmc.peerna.apiResponse.exception.GeneralException; + +public class NotificationException extends GeneralException { + public NotificationException(ResponseStatus code){ + super(code); + } +} diff --git a/src/main/java/cmc/peerna/domain/FcmToken.java b/src/main/java/cmc/peerna/domain/FcmToken.java new file mode 100644 index 0000000..cdb8430 --- /dev/null +++ b/src/main/java/cmc/peerna/domain/FcmToken.java @@ -0,0 +1,34 @@ +package cmc.peerna.domain; + +import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + +@Getter +@Builder +@Entity +@DynamicInsert +@DynamicUpdate +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class FcmToken { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + private Member member; + + private String token; + + public FcmToken(final String token, final Member member) { + this.token = token; + this.member = member; + } + + public void update(final String token) { + this.token = token; + } +} diff --git a/src/main/java/cmc/peerna/domain/PushAlarm.java b/src/main/java/cmc/peerna/domain/PushAlarm.java new file mode 100644 index 0000000..2160733 --- /dev/null +++ b/src/main/java/cmc/peerna/domain/PushAlarm.java @@ -0,0 +1,35 @@ +package cmc.peerna.domain; + +import cmc.peerna.domain.common.BaseEntity; +import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.DynamicInsert; +import org.hibernate.annotations.DynamicUpdate; + +@Entity +@Getter +@Builder +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@DynamicInsert +@DynamicUpdate +public class PushAlarm extends BaseEntity { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String title; + + private String body; + + private Boolean isConfirmed; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "owner_id") + private Member ownerMember; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member targetMember; + +} diff --git a/src/main/java/cmc/peerna/domain/enums/NotificationType.java b/src/main/java/cmc/peerna/domain/enums/NotificationType.java new file mode 100644 index 0000000..6f66caf --- /dev/null +++ b/src/main/java/cmc/peerna/domain/enums/NotificationType.java @@ -0,0 +1,13 @@ +package cmc.peerna.domain.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum NotificationType { + COMMENT("comment"), + EVENT("event"); + + private final String type; +} diff --git a/src/main/java/cmc/peerna/fcm/FCMService.java b/src/main/java/cmc/peerna/fcm/FCMService.java new file mode 100644 index 0000000..a922464 --- /dev/null +++ b/src/main/java/cmc/peerna/fcm/FCMService.java @@ -0,0 +1,134 @@ +//package cmc.peerna.fcm; +// +//import cmc.peerna.apiResponse.code.ResponseStatus; +//import cmc.peerna.apiResponse.exception.handler.MemberException; +//import cmc.peerna.apiResponse.exception.handler.NotificationException; +//import cmc.peerna.domain.FcmToken; +//import cmc.peerna.domain.Member; +//import cmc.peerna.domain.Notification; +//import cmc.peerna.domain.enums.NotificationType; +//import cmc.peerna.repository.FcmTokenRepository; +//import cmc.peerna.repository.MemberRepository; +//import com.google.auth.oauth2.GoogleCredentials; +//import lombok.RequiredArgsConstructor; +//import org.springframework.beans.factory.annotation.Value; +//import org.springframework.core.io.ClassPathResource; +//import org.springframework.http.*; +//import org.springframework.stereotype.Service; +//import org.springframework.web.client.RestTemplate; +// +//import java.io.IOException; +//import java.util.List; +// +//@Service +//@RequiredArgsConstructor +//public class FCMService { +// +// +// private static final String PREFIX_ACCESS_TOKEN = "Bearer "; +// private static final String PREFIX_FCM_REQUEST_URL = "https://fcm.googleapis.com/v1/projects/"; +// private static final String POSTFIX_FCM_REQUEST_URL = "/messages:send"; +// private static final String FIREBASE_KEY_PATH = "firebase/firebase-adminsdk-key.json"; +// private static final String GOOGLE_AUTH_URL = "https://www.googleapis.com/auth/cloud-platform"; +//// private static final Map> GENERATOR_MAP = +//// Map.of( +//// NotificationType.EVENT, EventNotificationMessageGenerator::new, +//// NotificationType.COMMENT, CommentNotificationMessageGenerator::new +//// ); +// +// +// private final FcmTokenRepository fcmTokenRepository; +// private final MemberRepository memberRepository; +// +// private final RestTemplate restTemplate; +// +// @Value("${firebase.project.id}") +// private String projectId; +// +// public void sendMessageTo(final Long receiverId, final Notification notification) { +// +// // 알림 요청 받는 사람의 FCM Token이 존재하는지 확인 +// final FcmToken fcmToken = fcmTokenRepository.findByMemberId(receiverId) +// .orElseThrow(() -> new NotificationException(ResponseStatus.FCM_TOKEN_NOT_FOUND)); +// +// // 메시지 생성 +// final String message = makeMessage(fcmToken.getToken(), notification); +// +// final HttpHeaders httpHeaders = new HttpHeaders(); +// httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); +// +// //OAuth 2.0 사용 +// httpHeaders.add(HttpHeaders.AUTHORIZATION, PREFIX_ACCESS_TOKEN + getAccessToken()); +// +// final HttpEntity httpEntity = new HttpEntity<>(message, httpHeaders); +// +// final String fcmRequestUrl = PREFIX_FCM_REQUEST_URL + projectId + POSTFIX_FCM_REQUEST_URL; +// +// final ResponseEntity exchange = restTemplate.exchange( +// fcmRequestUrl, +// HttpMethod.POST, +// httpEntity, +// String.class +// ); +// } +// +// +// private String makeMessage(final String targetToken, final Notification notification) { +// +// final Long senderId = notification.getSenderId(); +// final Member sender = memberRepository.findById(senderId) +// .orElseThrow(() -> new MemberException(ResponseStatus.MEMBER_NOT_FOUND)); +// +// final Data messageData = new Data( +// sender.getName(), senderId.toString(), +// notification.getReceiverId().toString(), notification.getMessage(), +// sender.getOpenProfileUrl() +// ); +// +// final Message message = new Message(messageData, targetToken); +// +// final FcmMessage fcmMessage = new FcmMessage(DEFAULT_VALIDATE_ONLY, message); +// +// try { +// return objectMapper.writeValueAsString(fcmMessage); +// } catch (JsonProcessingException e) { +// log.error("메세지 보낼 때 JSON 변환 에러", e); +// throw new NotificationException(CONVERTING_JSON_ERROR); +// } +// } +// +// +// +// +// +//// private String getAccessToken() { +//// try { +//// final GoogleCredentials googleCredentials = GoogleCredentials +//// .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()) +//// .createScoped(List.of(GOOGLE_AUTH_URL)); +//// +//// googleCredentials.refreshIfExpired(); +//// +//// return googleCredentials.getAccessToken().getTokenValue(); +//// } catch (IOException e) { +//// throw new NotificationException(ResponseStatus.FCM_ACCESS_TOKEN_REQUEST_ERROR); +//// } +//// } +// +// +// +//// FCM 서버 AccessToken 발급 +// +// private String getAccessToken(){ +// try { +// GoogleCredentials googleCredentials = GoogleCredentials +// .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()) +// .createScoped(List.of("https://www.googleapis.com/auth/cloud-platform")); +// googleCredentials.refreshIfExpired(); +// return googleCredentials.getAccessToken().getTokenValue(); +// } catch(IOException e){ +// throw new NotificationException(ResponseStatus.FCM_ACCESS_TOKEN_REQUEST_ERROR); +// } +// } +// +//} diff --git a/src/main/java/cmc/peerna/fcm/dto/FcmAOSMessage.java b/src/main/java/cmc/peerna/fcm/dto/FcmAOSMessage.java new file mode 100644 index 0000000..8ee771a --- /dev/null +++ b/src/main/java/cmc/peerna/fcm/dto/FcmAOSMessage.java @@ -0,0 +1,35 @@ +package cmc.peerna.fcm.dto; + +import lombok.*; + +@Builder +@Getter +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class FcmAOSMessage { + + private boolean validateOnly; + private Message message; + + @Builder + @Getter + @AllArgsConstructor(access = AccessLevel.PROTECTED) + @NoArgsConstructor(access = AccessLevel.PROTECTED) + public static class Message{ + private Data data; + private String token; + } + + + @Builder + @Getter + @AllArgsConstructor(access = AccessLevel.PROTECTED) + @NoArgsConstructor(access = AccessLevel.PROTECTED) + public static class Data{ + private String title; + private String body; + private String targetView; + private String targetPK; + private String targetNotificationPK; + } +} \ No newline at end of file diff --git a/src/main/java/cmc/peerna/fcm/dto/FcmTokenRequest.java b/src/main/java/cmc/peerna/fcm/dto/FcmTokenRequest.java new file mode 100644 index 0000000..2eee904 --- /dev/null +++ b/src/main/java/cmc/peerna/fcm/dto/FcmTokenRequest.java @@ -0,0 +1,12 @@ +package cmc.peerna.fcm.dto; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public class FcmTokenRequest { + + private final String token; + private final Long memberId; +} \ No newline at end of file diff --git a/src/main/java/cmc/peerna/fcm/service/FcmService.java b/src/main/java/cmc/peerna/fcm/service/FcmService.java new file mode 100644 index 0000000..1bb1d30 --- /dev/null +++ b/src/main/java/cmc/peerna/fcm/service/FcmService.java @@ -0,0 +1,72 @@ +package cmc.peerna.fcm.service; + +import cmc.peerna.apiResponse.code.ResponseStatus; +import cmc.peerna.apiResponse.exception.handler.NotificationException; +import cmc.peerna.fcm.dto.FcmAOSMessage; +import cmc.peerna.feign.FCMFeignClient; +import cmc.peerna.feign.dto.FCMResponseDto; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.auth.oauth2.GoogleCredentials; +import lombok.RequiredArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.json.JsonParseException; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.IOException; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class FcmService { + private final ObjectMapper objectMapper; + private final FCMFeignClient fcmFeignClient; + Logger logger = LoggerFactory.getLogger(FcmService.class); + + private static final String FIREBASE_KEY_PATH = "firebase/firebase-adminsdk-key.json"; + @Value("${firebase.project.id}") + private String projectId; + + + @Transactional + public void sendMessageTo(String targetToken, String title, String body, String targetNotification) throws IOException { + String aosMessage = makeAOSMessage(targetToken, title, body, targetNotification); + + FCMResponseDto fcmResponse = fcmFeignClient.getFCMResponse("Bearer " + getAccessToken(),aosMessage); + logger.info("성공? : {}",fcmResponse); + logger.info("보낸 메세지 : {}",aosMessage); + } + + private String makeAOSMessage(String targeToken, String title, String body, String targetNotification) throws JsonParseException, JsonProcessingException { + FcmAOSMessage fcmMessage = FcmAOSMessage.builder() + .message( + FcmAOSMessage.Message.builder() + .token(targeToken). + data(FcmAOSMessage.Data.builder() + .title(title) + .body(body) + .targetNotificationPK(targetNotification).build() + ). + build() + ) + .validateOnly(false).build(); + return objectMapper.writeValueAsString(fcmMessage); + } + + private String getAccessToken(){ + try { + GoogleCredentials googleCredentials = GoogleCredentials + .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()) + .createScoped(List.of("https://www.googleapis.com/auth/cloud-platform")); + googleCredentials.refreshIfExpired(); + return googleCredentials.getAccessToken().getTokenValue(); + } catch(IOException e){ + throw new NotificationException(ResponseStatus.FCM_ACCESS_TOKEN_REQUEST_ERROR); + } + } +} diff --git a/src/main/java/cmc/peerna/feign/FCMFeignClient.java b/src/main/java/cmc/peerna/feign/FCMFeignClient.java new file mode 100644 index 0000000..83f20ab --- /dev/null +++ b/src/main/java/cmc/peerna/feign/FCMFeignClient.java @@ -0,0 +1,18 @@ +package cmc.peerna.feign; + +import cmc.peerna.feign.config.FCMFeignConfig; +import cmc.peerna.feign.dto.FCMResponseDto; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; + +@FeignClient(name = "FCMFeign", url = "https://fcm.googleapis.com", configuration = FCMFeignConfig.class) +@Component +public interface FCMFeignClient { + + @PostMapping("/v1/projects/peerna-68c2d/messages:send") + FCMResponseDto getFCMResponse(@RequestHeader("Authorization") String token, @RequestBody String fcmAOSMessage); +} diff --git a/src/main/java/cmc/peerna/feign/config/FCMFeignConfig.java b/src/main/java/cmc/peerna/feign/config/FCMFeignConfig.java new file mode 100644 index 0000000..2ffa0c9 --- /dev/null +++ b/src/main/java/cmc/peerna/feign/config/FCMFeignConfig.java @@ -0,0 +1,27 @@ +package cmc.peerna.feign.config; + +import cmc.peerna.feign.exception.FeignClientExceptionErrorDecoder; +import feign.Logger; +import feign.RequestInterceptor; +import feign.codec.ErrorDecoder; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; + +@RequiredArgsConstructor +public class FCMFeignConfig { + + @Bean + public RequestInterceptor requestInterceptor(){ + return template -> template.header("Content-Type", "application/json;charset=UTF-8"); + } + + @Bean + public ErrorDecoder errorDecoder() { + return new FeignClientExceptionErrorDecoder(); + } + + @Bean + Logger.Level feignLoggerLevel() { + return Logger.Level.FULL; + } +} diff --git a/src/main/java/cmc/peerna/feign/dto/FCMResponseDto.java b/src/main/java/cmc/peerna/feign/dto/FCMResponseDto.java new file mode 100644 index 0000000..f69b5f5 --- /dev/null +++ b/src/main/java/cmc/peerna/feign/dto/FCMResponseDto.java @@ -0,0 +1,10 @@ +package cmc.peerna.feign.dto; + +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +public class FCMResponseDto { + String name; +} diff --git a/src/main/java/cmc/peerna/repository/FcmTokenRepository.java b/src/main/java/cmc/peerna/repository/FcmTokenRepository.java new file mode 100644 index 0000000..d39828e --- /dev/null +++ b/src/main/java/cmc/peerna/repository/FcmTokenRepository.java @@ -0,0 +1,10 @@ +package cmc.peerna.repository; + +import cmc.peerna.domain.FcmToken; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface FcmTokenRepository extends JpaRepository { + Optional findByMemberId(Long memberId); +} diff --git a/src/main/java/cmc/peerna/repository/PushAlarmRepository.java b/src/main/java/cmc/peerna/repository/PushAlarmRepository.java new file mode 100644 index 0000000..d547cc1 --- /dev/null +++ b/src/main/java/cmc/peerna/repository/PushAlarmRepository.java @@ -0,0 +1,17 @@ +package cmc.peerna.repository; + +import cmc.peerna.domain.Member; +import cmc.peerna.domain.PushAlarm; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface PushAlarmRepository extends JpaRepository { + + Page findByOwnerMember(Member member, PageRequest pageRequest); + + + List findByTitleAndOwnerMemberAndIsConfirmedFalse(String title, Member member); +} diff --git a/src/main/java/cmc/peerna/service/RootService.java b/src/main/java/cmc/peerna/service/RootService.java index e3826b1..28032f5 100644 --- a/src/main/java/cmc/peerna/service/RootService.java +++ b/src/main/java/cmc/peerna/service/RootService.java @@ -4,6 +4,7 @@ import cmc.peerna.web.dto.responseDto.RootResponseDto; import cmc.peerna.web.dto.responseDto.TestResponseDto; +import java.io.IOException; import java.util.List; public interface RootService { @@ -13,5 +14,7 @@ public interface RootService { List getTotalEvaluationList(Member member); RootResponseDto.AllFeedbackDto getFeedbackList(Member member, Integer page); + + void testFCMService(String fcmToken) throws IOException; } diff --git a/src/main/java/cmc/peerna/service/serviceImpl/RootServiceImpl.java b/src/main/java/cmc/peerna/service/serviceImpl/RootServiceImpl.java index d7397cb..0065172 100644 --- a/src/main/java/cmc/peerna/service/serviceImpl/RootServiceImpl.java +++ b/src/main/java/cmc/peerna/service/serviceImpl/RootServiceImpl.java @@ -8,6 +8,7 @@ import cmc.peerna.domain.enums.PeerCard; import cmc.peerna.domain.enums.PeerGrade; import cmc.peerna.domain.enums.TestType; +import cmc.peerna.fcm.service.FcmService; import cmc.peerna.repository.*; import cmc.peerna.service.RootService; import cmc.peerna.utils.TestResultCalculator; @@ -21,7 +22,9 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -36,7 +39,9 @@ public class RootServiceImpl implements RootService { private final PeerFeedbackRepository peerFeedbackRepository; private final PeerGradeResultRepository peerGradeResultRepository; private final PeerTestRepository peerTestRepository; + private final PushAlarmRepository pushAlarmRepository; private final TestResultCalculator testResultCalculator; + private final FcmService fcmService; @Value("${paging.size}") private Integer pageSize; @Override @@ -131,4 +136,22 @@ public RootResponseDto.AllFeedbackDto getFeedbackList(Member member, Integer pag return allFeedbackDto; } + + @Override + @Transactional + public void testFCMService(String fcmToken) throws IOException + { + String title = "피어나 FCM 테스트"; + String body = "피어나 안드로이드 FCM 테스트"; + + PushAlarm pushAlarm = pushAlarmRepository.save(PushAlarm.builder() + .title(title) + .body(body) + .isConfirmed(false) + .build()); + + + fcmService.sendMessageTo(fcmToken,title,body,pushAlarm.getId().toString()); + } + } diff --git a/src/main/java/cmc/peerna/web/controller/RootController.java b/src/main/java/cmc/peerna/web/controller/RootController.java index 892bb7c..7e1ff93 100644 --- a/src/main/java/cmc/peerna/web/controller/RootController.java +++ b/src/main/java/cmc/peerna/web/controller/RootController.java @@ -4,6 +4,7 @@ import cmc.peerna.apiResponse.exception.handler.MemberException; import cmc.peerna.apiResponse.response.ResponseDto; import cmc.peerna.service.MemberService; +import cmc.peerna.service.RootService; import cmc.peerna.web.dto.requestDto.RootRequestDto; import cmc.peerna.web.dto.responseDto.MemberResponseDto; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -13,6 +14,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; +import java.io.IOException; + @RestController @RequiredArgsConstructor @ApiResponses({ @@ -23,6 +26,7 @@ public class RootController { private final MemberService memberService; + private final RootService rootService; @GetMapping("/health") public String healthCheck() { @@ -51,4 +55,12 @@ public ResponseDto searchMember(@PathVariabl MemberResponseDto.MemberGetTestDto memberDto = memberService.findMember(memberId); return ResponseDto.of(memberDto); } + + @Operation(summary = "FCM 테스트 API", description = "테스트용") + @PostMapping("/test/fcm") + public ResponseDto testFCM(@RequestBody RootRequestDto.FCMTestDto fcmToken) throws IOException + { + rootService.testFCMService(fcmToken.getFcmToken()); + return ResponseDto.of(null); + } } diff --git a/src/main/java/cmc/peerna/web/dto/requestDto/RootRequestDto.java b/src/main/java/cmc/peerna/web/dto/requestDto/RootRequestDto.java index 75ed773..e858432 100644 --- a/src/main/java/cmc/peerna/web/dto/requestDto/RootRequestDto.java +++ b/src/main/java/cmc/peerna/web/dto/requestDto/RootRequestDto.java @@ -10,4 +10,12 @@ public class RootRequestDto { public static class PostTestDto{ private String body; } + + @Builder + @Getter + @AllArgsConstructor(access = AccessLevel.PROTECTED) + @NoArgsConstructor(access = AccessLevel.PROTECTED) + public static class FCMTestDto{ + String fcmToken; + } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index dd4f4df..410e1aa 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -70,3 +70,7 @@ web: paging: size : 10 + +firebase: + project: + id: ${firebase.project.id} \ No newline at end of file diff --git a/src/main/resources/firebase-adminsdk-key.json b/src/main/resources/firebase-adminsdk-key.json new file mode 100644 index 0000000..d02256c --- /dev/null +++ b/src/main/resources/firebase-adminsdk-key.json @@ -0,0 +1,13 @@ +{ + "type": "service_account", + "project_id": "peerna-68c2d", + "private_key_id": "ec9da851aa94f029adef064995e0a191e419fa90", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDNcNzIDbbv8J38\nEtpicqz+k9KW5q4m+VrlSmE/dzPwnoAF68nP5YlFp7oA82HXrOX3VqkcMDjqr2Ee\n5bPrWNSIvILSIsuUMxCZFqodTFaG27L0bB6LTCm3Je6bquAAOI3vSTvfGWQs680w\nFe6yDWTjl1qMl/GpDplz+jMOzaS5OdW+OiNcvfsdIXv17Y4o0KxZciXS95BwdXgx\nxYB4RlneGdZbnYevSj6X8bacBmplTha3IVuegenXkVeWhZCm97CH4dEkKTwcKRNX\nmaOmzysMgKqhuEmYejqV7xMVHfE4tEFokBhqlWvT8RGHSsJSDGdQhZ39dHzS9Bc3\nfslCBQBFAgMBAAECggEABPqOezGr5Io4Be8eCEM/soa6FIqgH1UtMP/ZtfxJT7RD\npYEWmbl2F3BOZ23+icfIpfMdc4+unW9lIubNsq8rLWomIHoT5XJMXW1pb37VXPzP\njDFflyAgJa5fZznfplm4hNtJPmmi3hzT0u3BJGMDNinJmb0n7+Eo8mDWom3050E2\nsQtr/TjzqdIjWjXLlCSxdaZTrsNrGmGuQUdr9XZFn0Br1UjlGdRS5YRz6K7NwPOy\nAkrbyc1rD63jjLGWJLXnzjhxTSV1KtMa7zvFIFG1a0YNN3WglUJmR6AfZvoL2QR/\nC5JzO3LTCrIyDre29EvhsjCROqLr7NkN7UdYItvyyQKBgQDpm5GXuFPLRwT5EWiV\nXvQNIqDEj0fID4zABfo9AfNyc05nmKhNvrFrzv6IP/p4UYKJ3hqXEqCib7d7UE8m\ntt/sdJEZTIlkDuSXY0Jy2VUfqvXEMKg/6I/x2Tls8RK58kQXIw21II8vAnMeZLvU\nfJwAZR5JnaK4MkeR/9I6d0KWGQKBgQDhIh3CyLselghV3cQmSuLFR1+mzPVlM8Wu\nJNWpbfxVtAuw5O5QWTeiLGJekmlxQBarCAhoKYZQDbeScFcUbB2lgsYtXwRpjiFY\nPOu+d/7SSNiNTia3tAc11ZZ+6rYEsYeRItC24RWsJxUjtKChrDPWpg1cpHWZ83w9\n66wrJdCJDQKBgG8RFvSyn6xbNMMSgs3Z2mDQYO1zTeaRdhLqBKKy5cM5jUJ18zcb\nfhFK1fuDp5tC7bSM08mWAqeYQ/0uHqPCeM5cUYxctknLRuWvPK2MJQusZbMEi0nv\nUVjkNYhVSdj8lWEGuoKuW0U3ffIqZJ9PK4CIkxDfELlQtnR008gWYaMpAoGAWO5B\nE1B3mf1qDYEsmnO6YHNxNVKBHRj2XXPvcp4frzsP4zCLcvHLKCSgNvte632FdsoV\niA/fHoBMo2v8+fQ7QcYGwqVl+MxMH67w8Kw13Jsp76ePY8GZl4pniHruq6v1AT/f\ncl43UWme0Bvp1/NOBtxRKudMDSRBT7RoriKh3YECgYAKncKC3C/y6RkNcLIkKLwF\nI5Bb7STKBQ96504kLN4Vd1cmnyhlBwPwoTO+BRvmbgJ1xa9hMssFHZoIu0UeRWM1\nAjbjMBfoUtZ7Axq2AoCAFZMEEn/0gscSUlpaJ5ro7nI+g2KROavJ5duoYVZfawi6\n1b/u+15n0u5SaD74GWZG8g==\n-----END PRIVATE KEY-----\n", + "client_email": "firebase-adminsdk-m9f35@peerna-68c2d.iam.gserviceaccount.com", + "client_id": "102007965304250253664", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-m9f35%40peerna-68c2d.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" +} From 3e0f130b5bfd64a8d3837ff4aab8184f5b8b45e0 Mon Sep 17 00:00:00 2001 From: HyoBN Date: Sun, 28 Jan 2024 14:10:17 +0900 Subject: [PATCH 2/2] =?UTF-8?q?:recycle:=20Refactor:=20FCM=20-=20adminSdk?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/cmc/peerna/fcm/FCMService.java | 134 ------------------ src/main/java/cmc/peerna/fcm/FcmInit.java | 35 +++++ .../cmc/peerna/fcm/service/FcmService.java | 72 +++------- .../java/cmc/peerna/service/RootService.java | 2 - .../service/serviceImpl/RootServiceImpl.java | 21 +-- .../peerna/web/controller/RootController.java | 7 +- src/main/resources/application.yml | 3 +- 7 files changed, 63 insertions(+), 211 deletions(-) delete mode 100644 src/main/java/cmc/peerna/fcm/FCMService.java create mode 100644 src/main/java/cmc/peerna/fcm/FcmInit.java diff --git a/src/main/java/cmc/peerna/fcm/FCMService.java b/src/main/java/cmc/peerna/fcm/FCMService.java deleted file mode 100644 index a922464..0000000 --- a/src/main/java/cmc/peerna/fcm/FCMService.java +++ /dev/null @@ -1,134 +0,0 @@ -//package cmc.peerna.fcm; -// -//import cmc.peerna.apiResponse.code.ResponseStatus; -//import cmc.peerna.apiResponse.exception.handler.MemberException; -//import cmc.peerna.apiResponse.exception.handler.NotificationException; -//import cmc.peerna.domain.FcmToken; -//import cmc.peerna.domain.Member; -//import cmc.peerna.domain.Notification; -//import cmc.peerna.domain.enums.NotificationType; -//import cmc.peerna.repository.FcmTokenRepository; -//import cmc.peerna.repository.MemberRepository; -//import com.google.auth.oauth2.GoogleCredentials; -//import lombok.RequiredArgsConstructor; -//import org.springframework.beans.factory.annotation.Value; -//import org.springframework.core.io.ClassPathResource; -//import org.springframework.http.*; -//import org.springframework.stereotype.Service; -//import org.springframework.web.client.RestTemplate; -// -//import java.io.IOException; -//import java.util.List; -// -//@Service -//@RequiredArgsConstructor -//public class FCMService { -// -// -// private static final String PREFIX_ACCESS_TOKEN = "Bearer "; -// private static final String PREFIX_FCM_REQUEST_URL = "https://fcm.googleapis.com/v1/projects/"; -// private static final String POSTFIX_FCM_REQUEST_URL = "/messages:send"; -// private static final String FIREBASE_KEY_PATH = "firebase/firebase-adminsdk-key.json"; -// private static final String GOOGLE_AUTH_URL = "https://www.googleapis.com/auth/cloud-platform"; -//// private static final Map> GENERATOR_MAP = -//// Map.of( -//// NotificationType.EVENT, EventNotificationMessageGenerator::new, -//// NotificationType.COMMENT, CommentNotificationMessageGenerator::new -//// ); -// -// -// private final FcmTokenRepository fcmTokenRepository; -// private final MemberRepository memberRepository; -// -// private final RestTemplate restTemplate; -// -// @Value("${firebase.project.id}") -// private String projectId; -// -// public void sendMessageTo(final Long receiverId, final Notification notification) { -// -// // 알림 요청 받는 사람의 FCM Token이 존재하는지 확인 -// final FcmToken fcmToken = fcmTokenRepository.findByMemberId(receiverId) -// .orElseThrow(() -> new NotificationException(ResponseStatus.FCM_TOKEN_NOT_FOUND)); -// -// // 메시지 생성 -// final String message = makeMessage(fcmToken.getToken(), notification); -// -// final HttpHeaders httpHeaders = new HttpHeaders(); -// httpHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); -// -// //OAuth 2.0 사용 -// httpHeaders.add(HttpHeaders.AUTHORIZATION, PREFIX_ACCESS_TOKEN + getAccessToken()); -// -// final HttpEntity httpEntity = new HttpEntity<>(message, httpHeaders); -// -// final String fcmRequestUrl = PREFIX_FCM_REQUEST_URL + projectId + POSTFIX_FCM_REQUEST_URL; -// -// final ResponseEntity exchange = restTemplate.exchange( -// fcmRequestUrl, -// HttpMethod.POST, -// httpEntity, -// String.class -// ); -// } -// -// -// private String makeMessage(final String targetToken, final Notification notification) { -// -// final Long senderId = notification.getSenderId(); -// final Member sender = memberRepository.findById(senderId) -// .orElseThrow(() -> new MemberException(ResponseStatus.MEMBER_NOT_FOUND)); -// -// final Data messageData = new Data( -// sender.getName(), senderId.toString(), -// notification.getReceiverId().toString(), notification.getMessage(), -// sender.getOpenProfileUrl() -// ); -// -// final Message message = new Message(messageData, targetToken); -// -// final FcmMessage fcmMessage = new FcmMessage(DEFAULT_VALIDATE_ONLY, message); -// -// try { -// return objectMapper.writeValueAsString(fcmMessage); -// } catch (JsonProcessingException e) { -// log.error("메세지 보낼 때 JSON 변환 에러", e); -// throw new NotificationException(CONVERTING_JSON_ERROR); -// } -// } -// -// -// -// -// -//// private String getAccessToken() { -//// try { -//// final GoogleCredentials googleCredentials = GoogleCredentials -//// .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()) -//// .createScoped(List.of(GOOGLE_AUTH_URL)); -//// -//// googleCredentials.refreshIfExpired(); -//// -//// return googleCredentials.getAccessToken().getTokenValue(); -//// } catch (IOException e) { -//// throw new NotificationException(ResponseStatus.FCM_ACCESS_TOKEN_REQUEST_ERROR); -//// } -//// } -// -// -// -//// FCM 서버 AccessToken 발급 -// -// private String getAccessToken(){ -// try { -// GoogleCredentials googleCredentials = GoogleCredentials -// .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()) -// .createScoped(List.of("https://www.googleapis.com/auth/cloud-platform")); -// googleCredentials.refreshIfExpired(); -// return googleCredentials.getAccessToken().getTokenValue(); -// } catch(IOException e){ -// throw new NotificationException(ResponseStatus.FCM_ACCESS_TOKEN_REQUEST_ERROR); -// } -// } -// -//} diff --git a/src/main/java/cmc/peerna/fcm/FcmInit.java b/src/main/java/cmc/peerna/fcm/FcmInit.java new file mode 100644 index 0000000..caa2c54 --- /dev/null +++ b/src/main/java/cmc/peerna/fcm/FcmInit.java @@ -0,0 +1,35 @@ +package cmc.peerna.fcm; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.firebase.FirebaseApp; +import com.google.firebase.FirebaseOptions; +import com.google.firebase.messaging.FirebaseMessaging; +import jakarta.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; + +import java.io.IOException; +import java.io.InputStream; + +@Configuration +public class FcmInit { + @Value("${firebase.admin-sdk}") + private String FIREBASE_KEY_PATH; + + @PostConstruct + public void firebaseMessaging() throws IOException { + ClassPathResource resource = new ClassPathResource(FIREBASE_KEY_PATH); + InputStream credentialStream = resource.getInputStream(); + try { + FirebaseOptions options = FirebaseOptions.builder() + .setCredentials(GoogleCredentials.fromStream(credentialStream)) + .build(); + FirebaseApp.initializeApp(options); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/cmc/peerna/fcm/service/FcmService.java b/src/main/java/cmc/peerna/fcm/service/FcmService.java index 1bb1d30..5b18231 100644 --- a/src/main/java/cmc/peerna/fcm/service/FcmService.java +++ b/src/main/java/cmc/peerna/fcm/service/FcmService.java @@ -1,72 +1,36 @@ package cmc.peerna.fcm.service; -import cmc.peerna.apiResponse.code.ResponseStatus; -import cmc.peerna.apiResponse.exception.handler.NotificationException; -import cmc.peerna.fcm.dto.FcmAOSMessage; -import cmc.peerna.feign.FCMFeignClient; -import cmc.peerna.feign.dto.FCMResponseDto; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.auth.oauth2.GoogleCredentials; +import com.google.firebase.messaging.FirebaseMessaging; +import com.google.firebase.messaging.FirebaseMessagingException; +import com.google.firebase.messaging.Message; +import com.google.firebase.messaging.Notification; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.json.JsonParseException; -import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.io.IOException; -import java.util.List; - @Service @RequiredArgsConstructor @Transactional(readOnly = true) public class FcmService { - private final ObjectMapper objectMapper; - private final FCMFeignClient fcmFeignClient; Logger logger = LoggerFactory.getLogger(FcmService.class); - private static final String FIREBASE_KEY_PATH = "firebase/firebase-adminsdk-key.json"; - @Value("${firebase.project.id}") - private String projectId; - - - @Transactional - public void sendMessageTo(String targetToken, String title, String body, String targetNotification) throws IOException { - String aosMessage = makeAOSMessage(targetToken, title, body, targetNotification); - - FCMResponseDto fcmResponse = fcmFeignClient.getFCMResponse("Bearer " + getAccessToken(),aosMessage); - logger.info("성공? : {}",fcmResponse); - logger.info("보낸 메세지 : {}",aosMessage); - } - - private String makeAOSMessage(String targeToken, String title, String body, String targetNotification) throws JsonParseException, JsonProcessingException { - FcmAOSMessage fcmMessage = FcmAOSMessage.builder() - .message( - FcmAOSMessage.Message.builder() - .token(targeToken). - data(FcmAOSMessage.Data.builder() - .title(title) - .body(body) - .targetNotificationPK(targetNotification).build() - ). - build() - ) - .validateOnly(false).build(); - return objectMapper.writeValueAsString(fcmMessage); - } - - private String getAccessToken(){ + public void testFCMService(String fcmToken) + { + Message message = Message.builder() + .setToken(fcmToken) + .setNotification( + Notification.builder() + .setTitle("PeerNa FCM 테스트입니당") + .setBody("테스트 성공했나요??") + .build()) + .build(); try { - GoogleCredentials googleCredentials = GoogleCredentials - .fromStream(new ClassPathResource(FIREBASE_KEY_PATH).getInputStream()) - .createScoped(List.of("https://www.googleapis.com/auth/cloud-platform")); - googleCredentials.refreshIfExpired(); - return googleCredentials.getAccessToken().getTokenValue(); - } catch(IOException e){ - throw new NotificationException(ResponseStatus.FCM_ACCESS_TOKEN_REQUEST_ERROR); + String response = FirebaseMessaging.getInstance().send(message); + logger.info("the response of request FCM : {}",response); + }catch (FirebaseMessagingException e){ + e.printStackTrace(); } } } diff --git a/src/main/java/cmc/peerna/service/RootService.java b/src/main/java/cmc/peerna/service/RootService.java index 28032f5..ecad512 100644 --- a/src/main/java/cmc/peerna/service/RootService.java +++ b/src/main/java/cmc/peerna/service/RootService.java @@ -14,7 +14,5 @@ public interface RootService { List getTotalEvaluationList(Member member); RootResponseDto.AllFeedbackDto getFeedbackList(Member member, Integer page); - - void testFCMService(String fcmToken) throws IOException; } diff --git a/src/main/java/cmc/peerna/service/serviceImpl/RootServiceImpl.java b/src/main/java/cmc/peerna/service/serviceImpl/RootServiceImpl.java index 0065172..c27b6d5 100644 --- a/src/main/java/cmc/peerna/service/serviceImpl/RootServiceImpl.java +++ b/src/main/java/cmc/peerna/service/serviceImpl/RootServiceImpl.java @@ -15,6 +15,10 @@ import cmc.peerna.web.dto.responseDto.MemberResponseDto; import cmc.peerna.web.dto.responseDto.RootResponseDto; import cmc.peerna.web.dto.responseDto.TestResponseDto; +import com.google.firebase.messaging.FirebaseMessaging; +import com.google.firebase.messaging.FirebaseMessagingException; +import com.google.firebase.messaging.Message; +import com.google.firebase.messaging.Notification; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -137,21 +141,4 @@ public RootResponseDto.AllFeedbackDto getFeedbackList(Member member, Integer pag } - @Override - @Transactional - public void testFCMService(String fcmToken) throws IOException - { - String title = "피어나 FCM 테스트"; - String body = "피어나 안드로이드 FCM 테스트"; - - PushAlarm pushAlarm = pushAlarmRepository.save(PushAlarm.builder() - .title(title) - .body(body) - .isConfirmed(false) - .build()); - - - fcmService.sendMessageTo(fcmToken,title,body,pushAlarm.getId().toString()); - } - } diff --git a/src/main/java/cmc/peerna/web/controller/RootController.java b/src/main/java/cmc/peerna/web/controller/RootController.java index 7e1ff93..320b3f0 100644 --- a/src/main/java/cmc/peerna/web/controller/RootController.java +++ b/src/main/java/cmc/peerna/web/controller/RootController.java @@ -3,6 +3,8 @@ import cmc.peerna.apiResponse.code.ResponseStatus; import cmc.peerna.apiResponse.exception.handler.MemberException; import cmc.peerna.apiResponse.response.ResponseDto; +import cmc.peerna.converter.MemberConverter; +import cmc.peerna.fcm.service.FcmService; import cmc.peerna.service.MemberService; import cmc.peerna.service.RootService; import cmc.peerna.web.dto.requestDto.RootRequestDto; @@ -26,6 +28,7 @@ public class RootController { private final MemberService memberService; + private final FcmService fcmService; private final RootService rootService; @GetMapping("/health") @@ -60,7 +63,7 @@ public ResponseDto searchMember(@PathVariabl @PostMapping("/test/fcm") public ResponseDto testFCM(@RequestBody RootRequestDto.FCMTestDto fcmToken) throws IOException { - rootService.testFCMService(fcmToken.getFcmToken()); - return ResponseDto.of(null); + fcmService.testFCMService(fcmToken.getFcmToken()); + return ResponseDto.of("FCM 테스트 성공!"); } } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 410e1aa..8f3e9c9 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -72,5 +72,4 @@ paging: size : 10 firebase: - project: - id: ${firebase.project.id} \ No newline at end of file + admin-sdk: firebase-adminsdk-key.json