Skip to content

Commit

Permalink
feat: FCM 발송방식 수정 (#333)
Browse files Browse the repository at this point in the history
* docs: github workflow 설정 추가

* refactor: 알림 발송형태 수정

* refactor: 컬럼명 수정

(cherry picked from commit 6df04f2)
  • Loading branch information
Choi-JJunho committed May 9, 2024
1 parent 9e360af commit 0ed26d3
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 35 deletions.
6 changes: 6 additions & 0 deletions .github/pr-labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
기능: feature/*
버그: fix/*
리팩터링: refactor/*
문서: docs/*
테스트: test/*
인프라: infra/*
12 changes: 12 additions & 0 deletions .github/workflows/pr-labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: PR Labeler
on:
pull_request:
types: [ opened ]

jobs:
pr-labeler:
runs-on: ubuntu-latest
steps:
- uses: TimonVS/pr-labeler-action@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
package in.koreatech.koin.global.domain.notification.model;

import static jakarta.persistence.EnumType.STRING;
import static jakarta.persistence.FetchType.LAZY;
import static jakarta.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;

import in.koreatech.koin.domain.user.model.User;
import in.koreatech.koin.global.domain.BaseEntity;
import in.koreatech.koin.global.fcm.MobileAppPath;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import static jakarta.persistence.EnumType.STRING;
import jakarta.persistence.Enumerated;
import static jakarta.persistence.FetchType.LAZY;
import jakarta.persistence.GeneratedValue;
import static jakarta.persistence.GenerationType.IDENTITY;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import static lombok.AccessLevel.PROTECTED;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -27,8 +29,9 @@ public class Notification extends BaseEntity {
@GeneratedValue(strategy = IDENTITY)
private Long id;

@Column(name = "url", nullable = false)
private String url;
@Enumerated(STRING)
@Column(name = "app_path", nullable = false)
private MobileAppPath mobileAppPath;

@Column(name = "title", nullable = false)
private String title;
Expand All @@ -51,14 +54,14 @@ public class Notification extends BaseEntity {
private boolean isRead = false;

public Notification(
String url,
MobileAppPath appPath,
String title,
String message,
String imageUrl,
NotificationType type,
User user
) {
this.url = url;
this.mobileAppPath = appPath;
this.title = title;
this.message = message;
this.imageUrl = imageUrl;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,20 @@
package in.koreatech.koin.global.domain.notification.model;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import in.koreatech.koin.domain.user.model.User;
import in.koreatech.koin.global.fcm.MobileAppPath;

@Component
public class NotificationFactory {

private final String koinAppUrl;

public NotificationFactory(
@Value("${fcm.koin.url}") String koinAppUrl
) {
this.koinAppUrl = koinAppUrl;
}

public Notification generateOwnerNotification(
MobileAppPath path,
String shopName,
User target
) {
return new Notification(
koinAppUrl,
path,
"새로운 이벤트가 개설되었어요!",
"%s 가게의 이벤트가 오픈되었어요!🎁"
.formatted(shopName),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

import in.koreatech.koin.domain.user.model.User;
import in.koreatech.koin.domain.user.repository.UserRepository;
import in.koreatech.koin.global.domain.notification.model.NotificationSubscribe;
import in.koreatech.koin.global.domain.notification.dto.NotificationStatusResponse;
import in.koreatech.koin.global.domain.notification.dto.NotificationSubscribePermitRequest;
import in.koreatech.koin.global.domain.notification.model.Notification;
import in.koreatech.koin.global.domain.notification.model.NotificationSubscribe;
import in.koreatech.koin.global.domain.notification.model.NotificationSubscribeType;
import in.koreatech.koin.global.domain.notification.repository.NotificationRepository;
import in.koreatech.koin.global.domain.notification.repository.NotificationSubscribeRepository;
Expand All @@ -34,7 +34,7 @@ public void push(Notification notification) {
notification.getTitle(),
notification.getMessage(),
notification.getImageUrl(),
notification.getUrl(),
notification.getMobileAppPath(),
notification.getType()
);
}
Expand Down
86 changes: 71 additions & 15 deletions src/main/java/in/koreatech/koin/global/fcm/FcmClient.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package in.koreatech.koin.global.fcm;

import static com.google.firebase.messaging.AndroidConfig.Priority.HIGH;

import java.util.Map;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import com.google.firebase.messaging.AndroidConfig;
import com.google.firebase.messaging.AndroidNotification;
import com.google.firebase.messaging.ApnsConfig;
import com.google.firebase.messaging.ApnsFcmOptions;
import com.google.firebase.messaging.Aps;
import com.google.firebase.messaging.ApsAlert;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.Message;
import com.google.firebase.messaging.Notification;

import static com.google.firebase.messaging.AndroidConfig.Priority.HIGH;
import lombok.extern.slf4j.Slf4j;

@Slf4j
Expand All @@ -21,32 +28,81 @@ public void sendMessage(
String title,
String content,
String imageUrl,
String url,
MobileAppPath path,
String type
) {
if (targetDeviceToken == null) {
return;
}
log.info("call FcmClient sendMessage: title: {}, content: {}", title, content);
Notification notification = Notification.builder()
.setTitle(title)
.setBody(content)
.setImage(imageUrl)
.build();

AndroidConfig androidConfig = generateAndroidConfig(title, content, imageUrl, path, type);
ApnsConfig apnsConfig = generateAppleConfig(title, content, imageUrl, path, type);

Message message = Message.builder()
.setToken(targetDeviceToken)
.setNotification(notification)
.putData("url", url)
.putData("type", type)
.setAndroidConfig(AndroidConfig.builder()
.setPriority(HIGH)
.build()
).build();
.setApnsConfig(apnsConfig)
.setAndroidConfig(androidConfig).build();
try {
String result = FirebaseMessaging.getInstance().send(message);
log.info("FCM 알림 전송 성공: {}", result);
} catch (Exception e) {
log.warn("FCM 알림 전송 실패", e);
}
}

private ApnsConfig generateAppleConfig(
String title,
String content,
String imageUrl,
MobileAppPath path,
String type
) {
return ApnsConfig.builder()
.setAps(
Aps.builder()
.setAlert(
ApsAlert.builder()
.setTitle(title)
.setBody(content)
.build()
)
.setSound("default")
.setCategory(path.getApple())
.setMutableContent(true)
.build()
)
.setFcmOptions(
ApnsFcmOptions.builder()
.setImage(imageUrl)
.build()
)
.putAllCustomData(
Map.of(
"type", type
)
)
.build();
}

private AndroidConfig generateAndroidConfig(
String title,
String content,
String imageUrl,
MobileAppPath path,
String type
) {
AndroidNotification androidNotification = AndroidNotification.builder()
.setTitle(title)
.setBody(content)
.setImage(imageUrl)
.setClickAction(path.getAndroid())
.build();

return AndroidConfig.builder()
.setNotification(androidNotification)
.putData("type", type)
.setPriority(HIGH)
.build();
}
}
18 changes: 18 additions & 0 deletions src/main/java/in/koreatech/koin/global/fcm/MobileAppPath.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package in.koreatech.koin.global.fcm;

import lombok.Getter;

@Getter
public enum MobileAppPath {
HOME("home", "home"),
LOGIN("login", "login"),
;

private final String android;
private final String apple;

MobileAppPath(String android, String apple) {
this.android = android;
this.apple = apple;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE `notification`
CHANGE COLUMN url app_path VARCHAR(255);

0 comments on commit 0ed26d3

Please sign in to comment.