Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
package vom.spring.domain.member.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import vom.spring.domain.member.domain.Member;

import java.util.Optional;

@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByEmail(String email);
Optional<Member> findByNickname(String nickname);
boolean existsByEmail(String email);
boolean existsByNickname(String nickname);
Optional<Member> findById(Long id);

// ID로 닉네임 조회
@Query("SELECT m.nickname FROM Member m WHERE m.id = :id")
String findNicknameById(@Param("id") Long id);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package vom.spring.domain.webcam.service;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -19,6 +20,7 @@
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import vom.spring.domain.webpush.service.WebpushService;

@Service
@RequiredArgsConstructor
Expand All @@ -28,6 +30,9 @@ public class WebcamServiceImpl implements WebcamServcie{
private final MemberWebcamRepository memberWebcamRepository;
private final WebpushRepository webpushRepository;

@Autowired
private WebpushService webpushService;

/**
* 화상채팅 방 생성
*/
Expand All @@ -45,13 +50,7 @@ public WebcamResponseDto.CreateWebcamDto createWebcamRoom(WebcamRequestDto.Creat
MemberWebcam toMemberWebcam = MemberWebcam.builder().member(toMember).webcam(newWebcam).build();
memberWebcamRepository.save(fromMemberWebcam);
memberWebcamRepository.save(toMemberWebcam);
webpushRepository.save(
Webpush.builder()
.createdAt(LocalDateTime.now())
.fromMember(fromMember)
.toMember(toMember)
.webcam(newWebcam)
.build());
webpushService.createWebpush(fromMember, toMember, newWebcam);
return WebcamResponseDto.CreateWebcamDto.builder().webcamId(newWebcam.getId()).build();
}

Expand All @@ -65,6 +64,8 @@ public void deleteWebcamRoom(WebcamRequestDto.DeleteWebcamDto request) {
Member fromMember = memberRepository.findByEmail(email).orElseThrow(() -> new RuntimeException("존재하지 않은 유저입니다"));
//해당 방 찾기
Webcam webcam = webcamRepository.findById(request.getRoomId()).orElseThrow(() -> new IllegalArgumentException("존재하지 않은 방입니다"));
//해당 방 관련 웹 푸시 알림 삭제
webpushService.deleteWebpushByWebcamId(webcam.getId());
//해당 방 관련 연관관계 삭제
memberWebcamRepository.deleteByWebcam(webcam);
//해당 방 삭제
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,23 @@ public ResponseEntity<ApiResponseWrapper<Object>> pushMessage(

return new ResponseEntity<>(arw, HttpStatus.OK);
}

// 웹 푸시 메세지 내용 테스트용
@PostMapping("/api/v3/fcm/send/{member_id}")
public ResponseEntity<ApiResponseWrapper<Object>> sendPushMessage(
@PathVariable("member_id") Long memberId
) throws IOException {
log.debug("[+] 푸시 메시지를 전송합니다. ");

int result = fcmService.sendMessageTo(memberId);

ApiResponseWrapper<Object> arw = ApiResponseWrapper
.builder()
.result(result)
.resultCode(SuccessCode.SELECT_SUCCESS.getStatus())
.resultMsg(SuccessCode.SELECT_SUCCESS.getMessage())
.build();

return new ResponseEntity<>(arw, HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,4 @@ public ResponseEntity<List<WebpushDto>> getWebpushes(
) {
return new ResponseEntity<>(webpushService.getWebpushes(memberId), HttpStatus.OK);
}

// @PostMapping("/api/webpush/send")
// public String sendNotification(
// @RequestBody NotificationRequest request)
// {
// webpushService.sendNotification(request.getTargetToken(), request.getTitle(), request.getBody());
// return "Notification sent successfully!";
// }
//
// @Getter
// public static class NotificationRequest {
// private String targetToken;
// private String title;
// private String body;
//
// // Getters and Setters
// }

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import vom.spring.domain.member.domain.Member;
import vom.spring.domain.webcam.domain.Status;
import vom.spring.domain.webcam.domain.Webcam;

import java.time.LocalDateTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@Getter
@Builder
public class FcmMessageDto {
private boolean validateOnly;

private FcmMessageDto.Message message;

@Builder
Expand Down
21 changes: 0 additions & 21 deletions src/main/java/vom/spring/domain/webpush/dto/FcmSendDto.java

This file was deleted.

9 changes: 5 additions & 4 deletions src/main/java/vom/spring/domain/webpush/dto/WebpushDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
import lombok.Getter;

import java.time.LocalDateTime;
import lombok.Setter;

@Getter
@Getter @Setter
public class WebpushDto {
private Long fromMemberId;
private String fromMemberNickname;
private LocalDateTime createdAt;
private Long webcamId;

public WebpushDto(Long fromMemberId, LocalDateTime createdAt, Long webcamId) {
this.fromMemberId = fromMemberId;
public WebpushDto(String fromMemberNickname, LocalDateTime createdAt, Long webcamId) {
this.fromMemberNickname = fromMemberNickname;
this.createdAt = createdAt;
this.webcamId = webcamId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,25 @@ public void save(Webpush webpush) {

public List<WebpushDto> findByToMemberId(Long toMemberId) {
return em.createQuery(
"select new WebpushDto(w.fromMember.id, w.createdAt, w.webcam.id) " +
"select new WebpushDto(w.fromMember.nickname, w.createdAt, w.webcam.id) " +
"from Webpush w where w.toMember.id = :toMemberId",
WebpushDto.class)
.setParameter("toMemberId", toMemberId)
.getResultList();
}

public Webpush findByWebcamId(Long webcamId) {
return em.createQuery("SELECT w FROM Webpush w WHERE w.webcam.id = :webcamId", Webpush.class)
.setParameter("webcamId", webcamId)
.getSingleResult();
}

public void delete(Webpush webpush) {
if (em.contains(webpush)) {
em.remove(webpush);
} else {
Webpush mergedWebpush = em.merge(webpush); // 비영속 상태라면 병합 후 삭제
em.remove(mergedWebpush);
}
}
}
58 changes: 27 additions & 31 deletions src/main/java/vom/spring/domain/webpush/service/FcmService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.auth.oauth2.GoogleCredentials;
import java.util.NoSuchElementException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down Expand Up @@ -55,48 +57,42 @@ public void setFcmToken(String fcmToken, Long member_id) {
}

/**
* 푸시 메시지 처리를 수행하는 비즈니스 로직
* 푸시 메시지 전송
*
* @return 성공(1), 실패(0)
*/
public int sendMessageTo(Long memberId) throws IOException {
try {
Fcm fcm = fcmRepository.findByMember_id(memberId);

Fcm fcm = fcmRepository.findByMember_id(memberId);
if (fcm == null) {
throw new NoSuchElementException("해당 멤버가 알림 설정을 하지 않았습니다.");
}

if (fcm == null) {
// log.error("Fcm token not found for memberId: " + memberId);
// throw new IllegalArgumentException("Fcm token not found for memberId: " + memberId);
System.out.println("해당 멤버가 알림 설정을 하지 않았습니다.");
return 0;
}
String message = makeMessage(fcm);

String message = makeMessage(fcm);
RestTemplate restTemplate = new RestTemplate();
RestTemplate restTemplate = new RestTemplate();

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + getAccessToken());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer " + getAccessToken());

HttpEntity entity = new HttpEntity<>(message, headers);
HttpEntity entity = new HttpEntity<>(message, headers);

String API_URL = "https://fcm.googleapis.com/v1/projects/vomvom-fd09b/messages:send";
// String API_URL = "https://fcm.googleapis.com/fcm/send";
ResponseEntity<String> response = null;
String API_URL = "https://fcm.googleapis.com/v1/projects/vomvom-fd09b/messages:send";

try {
response = restTemplate.exchange(API_URL, HttpMethod.POST, entity, String.class);
System.out.println(response.getStatusCode());
ResponseEntity<String> response = restTemplate.exchange(API_URL, HttpMethod.POST, entity, String.class);
System.out.println("Response: " + response.getBody());
System.out.println("Status Code: " + response.getStatusCode());
return response.getStatusCode() == HttpStatus.OK ? 1 : 0;
} catch (Exception e) {
log.error("[-] FCM 전송 오류 :: " + e.getMessage());
System.err.println("[-] FCM 전송 오류 :: " + e.getMessage());
return 0;
}
}

/**
* Firebase Admin SDK의 비공개 키를 참조하여 Bearer 토큰을 발급 받습니다.
*
* playground에서 발급받은 토큰
* Firebase Admin SDK의 비공개 키를 참조하여 Bearer 토큰 발급
*
* @return Bearer token
*/
Expand All @@ -106,7 +102,8 @@ private String getAccessToken() throws IOException {

GoogleCredentials googleCredentials = GoogleCredentials
.fromStream(new ClassPathResource(firebaseConfigPath).getInputStream())
.createScoped(List.of("https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/firebase.messaging"));
.createScoped(List.of("https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/firebase.messaging"));

googleCredentials.refreshIfExpired();

Expand All @@ -116,25 +113,24 @@ private String getAccessToken() throws IOException {
}

/**
* FCM 전송 정보를 기반으로 메시지를 구성합니다.
* FCM 내용 생성
*
* @return String
*/
private String makeMessage(Fcm fcm) throws JsonProcessingException {

ObjectMapper om = new ObjectMapper();

System.out.println(fcm.getFcmToken());
FcmMessageDto fcmMessageDto = FcmMessageDto.builder()
.message(FcmMessageDto.Message.builder()
.token(fcm.getFcmToken())
.notification(FcmMessageDto.Notification.builder()
.title("VOM")
.body("화상 채팅 요청 알림\n클릭하여 접속!")
.image(null)
.body("화상 채팅 요청 알림 클릭하여 접속!")
.image("https://cdn-icons-png.flaticon.com/512/1762/1762755.png")
.build()
).build()).validateOnly(false).build();
).build()).build();

return om.writeValueAsString(fcmMessageDto);
}
}
}
Loading
Loading