-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
580 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
app/batch/src/main/java/org/example/service/MessageService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.example.service; | ||
|
||
import org.example.service.dto.request.MultipleTargetsMessageBatchRequest; | ||
import org.example.service.dto.request.SingleTargetMessageBatchRequest; | ||
|
||
public interface MessageService { | ||
|
||
void send(SingleTargetMessageBatchRequest request); | ||
|
||
void send(MultipleTargetsMessageBatchRequest request); | ||
} |
11 changes: 11 additions & 0 deletions
11
...tch/src/main/java/org/example/service/dto/request/MultipleTargetsMessageBatchRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.example.service.dto.request; | ||
|
||
import java.util.List; | ||
import org.example.message.MessageParam; | ||
|
||
public record MultipleTargetsMessageBatchRequest( | ||
List<String> fcmTokens, | ||
MessageParam message | ||
) { | ||
|
||
} |
12 changes: 12 additions & 0 deletions
12
app/batch/src/main/java/org/example/service/dto/request/SingleTargetMessageBatchRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.example.service.dto.request; | ||
|
||
import lombok.Builder; | ||
import org.example.message.MessageParam; | ||
|
||
@Builder | ||
public record SingleTargetMessageBatchRequest( | ||
String fcmToken, | ||
MessageParam message | ||
) { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
dependencies { | ||
implementation project(':app:batch') | ||
|
||
implementation 'com.google.firebase:firebase-admin:9.2.0' | ||
} |
86 changes: 86 additions & 0 deletions
86
app/infrastructure/fcm/src/main/java/org/showpot/client/FCMClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package org.showpot.client; | ||
|
||
import com.google.firebase.messaging.BatchResponse; | ||
import com.google.firebase.messaging.FirebaseMessaging; | ||
import com.google.firebase.messaging.FirebaseMessagingException; | ||
import com.google.firebase.messaging.Message; | ||
import com.google.firebase.messaging.MulticastMessage; | ||
import com.google.firebase.messaging.Notification; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class FCMClient { | ||
|
||
private final FirebaseMessaging firebaseMessaging; | ||
|
||
public void sendNotification(String fcmToken, Notification notification) { | ||
try { | ||
firebaseMessaging.send( | ||
Message.builder() | ||
.setToken(fcmToken) | ||
.setNotification(notification) | ||
.build() | ||
); | ||
} catch (FirebaseMessagingException e) { | ||
log.error( | ||
""" | ||
푸시 알림 전송에 실패했습니다. | ||
실패 사유: {} | ||
fcm_token: {}""", | ||
e.getMessagingErrorCode().name(), | ||
fcmToken | ||
); | ||
} | ||
} | ||
|
||
public void sendNotification(List<String> fcmTokens, Notification notification) { | ||
if (fcmTokens.size() > 500) { | ||
log.warn("한 번에 요청할 수 있는 푸시 알림의 수는 500개입니다."); | ||
throw new IllegalArgumentException("한 번에 요청할 수 있는 푸시 알림의 수는 500개입니다."); | ||
} | ||
|
||
try { | ||
BatchResponse response = firebaseMessaging.sendEachForMulticast( | ||
MulticastMessage.builder() | ||
.addAllTokens(fcmTokens) | ||
.setNotification(notification) | ||
.build() | ||
); | ||
|
||
loggingFirebaseMessaging(response); | ||
} catch (FirebaseMessagingException e) { | ||
log.error("푸시 알림 전송에 실패했습니다.", e); | ||
} | ||
} | ||
|
||
private void loggingFirebaseMessaging(BatchResponse response) { | ||
log.info( | ||
""" | ||
푸시 알림 전송 결과: 성공 {}, 실패 {} | ||
에러코드별 실패 횟수 | ||
{} | ||
""", | ||
response.getSuccessCount(), | ||
response.getFailureCount(), | ||
getCountByErrorCode(response) | ||
); | ||
} | ||
|
||
private Map<String, Integer> getCountByErrorCode(BatchResponse response) { | ||
return response.getResponses().stream() | ||
.filter(it -> !it.isSuccessful()) | ||
.collect( | ||
Collectors.groupingBy( | ||
it -> it.getException().getMessagingErrorCode().name(), | ||
Collectors.summingInt(it -> 1) | ||
) | ||
); | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
app/infrastructure/fcm/src/main/java/org/showpot/config/FCMConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package org.showpot.config; | ||
|
||
import com.google.auth.oauth2.GoogleCredentials; | ||
import com.google.firebase.FirebaseApp; | ||
import com.google.firebase.FirebaseOptions; | ||
import com.google.firebase.messaging.FirebaseMessaging; | ||
import java.io.IOException; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.showpot.property.FCMProperty; | ||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.ComponentScan; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
@EnableConfigurationProperties(FCMProperty.class) | ||
@ComponentScan(basePackages = "org.showpot") | ||
@RequiredArgsConstructor | ||
public class FCMConfig { | ||
|
||
private final FCMProperty fcmProperty; | ||
|
||
@Bean | ||
public FirebaseMessaging firebaseMessaging() { | ||
FirebaseApp firebaseApp; | ||
|
||
try { | ||
firebaseApp = getApp(); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
|
||
return FirebaseMessaging.getInstance(firebaseApp); | ||
} | ||
|
||
private FirebaseApp getApp() throws IOException { | ||
List<FirebaseApp> apps = FirebaseApp.getApps(); | ||
|
||
if (apps.isEmpty()) { | ||
return initializeApp(); | ||
} | ||
|
||
for (FirebaseApp app : apps) { | ||
if (app.getName().equals(FirebaseApp.DEFAULT_APP_NAME)) { | ||
return app; | ||
} | ||
} | ||
|
||
return initializeApp(); | ||
} | ||
|
||
private FirebaseApp initializeApp() throws IOException { | ||
FirebaseOptions options = FirebaseOptions.builder() | ||
.setCredentials( | ||
GoogleCredentials.fromStream(fcmProperty.toInputStream()) | ||
) | ||
.build(); | ||
|
||
return FirebaseApp.initializeApp(options); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
app/infrastructure/fcm/src/main/java/org/showpot/dto/param/FCMMessageParam.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package org.showpot.dto.param; | ||
|
||
import com.google.firebase.messaging.Notification; | ||
import lombok.Builder; | ||
import org.example.message.MessageParam; | ||
|
||
@Builder | ||
public record FCMMessageParam( | ||
String title, | ||
String body | ||
) { | ||
|
||
public static FCMMessageParam from(MessageParam param) { | ||
return FCMMessageParam.builder() | ||
.title(param.title()) | ||
.body(param.body()) | ||
.build(); | ||
} | ||
|
||
public Notification toNotification() { | ||
return Notification.builder() | ||
.setTitle(title()) | ||
.setBody(body()) | ||
.build(); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
app/infrastructure/fcm/src/main/java/org/showpot/property/FCMProperty.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package org.showpot.property; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import java.io.ByteArrayInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.nio.charset.StandardCharsets; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
|
||
@ConfigurationProperties(prefix = "fcm") | ||
public record FCMProperty( | ||
String type, | ||
@JsonProperty("project_id") | ||
String projectId, | ||
@JsonProperty("private_key_id") | ||
String privateKeyId, | ||
@JsonProperty("private_key") | ||
String privateKey, | ||
@JsonProperty("client_email") | ||
String clientEmail, | ||
@JsonProperty("client_id") | ||
String clientId, | ||
@JsonProperty("auth_uri") | ||
String authUri, | ||
@JsonProperty("token_uri") | ||
String tokenUri, | ||
@JsonProperty("auth_provider_x509_cert_url") | ||
String authProviderX509CertUrl, | ||
@JsonProperty("client_x509_cert_url") | ||
String clientX509CertUrl, | ||
@JsonProperty("universe_domain") | ||
String universeDomain | ||
) { | ||
|
||
public InputStream toInputStream() throws IOException { | ||
ObjectMapper objectMapper = new ObjectMapper(); | ||
String jsonString = objectMapper.writeValueAsString(this); | ||
|
||
return new ByteArrayInputStream(jsonString.getBytes(StandardCharsets.UTF_8)); | ||
} | ||
} |
Oops, something went wrong.