Skip to content

Commit

Permalink
[#27] FCM을 이용한 Push 알림 서버 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
kohseongyeon committed Aug 26, 2021
1 parent 8249740 commit 656d559
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 0 deletions.
63 changes: 63 additions & 0 deletions push-notification-api/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
plugins {
id "org.ec4j.editorconfig" version "0.0.3"
id "checkstyle"
}

java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

compileJava.options.encoding = "UTF-8"
compileTestJava.options.encoding = "UTF-8"

idea {
module {
outputDir file("build/classes/main")
testOutputDir file("build/classes/test")
}
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
}

ext {
FIREBASE_ADMIN_VERSION = "6.8.1"
OKHTTP_VERSION = "4.2.2"
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.google.firebase:firebase-admin:${FIREBASE_ADMIN_VERSION}")
implementation("com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}")

compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")

testImplementation("org.springframework.boot:spring-boot-starter-test")

testCompileOnly("org.projectlombok:lombok")
testAnnotationProcessor("org.projectlombok:lombok")
}

test {
useJUnitPlatform()
}

editorconfig {
excludes = ["build"]
}

check.dependsOn editorconfigCheck

checkstyle {
configFile = file("${project.rootDir}/rule/naver-checkstyle-rules.xml")
configProperties = [config_loc: ".."]
toolVersion = "8.24"
ignoreFailures = false
maxErrors = 0
maxWarnings = 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.bluebird.pipit.fcm.controller;

import com.bluebird.pipit.fcm.dto.PushNotificationRequest;
import com.bluebird.pipit.fcm.service.PushNotificationService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class PushNotificationController {
private final PushNotificationService pushNotificationService;

public void sendMessage(@RequestBody PushNotificationRequest request) {
pushNotificationService.sendMessageTo(request.getTargetToken(), request.getTitle(), request.getBody());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.bluebird.pipit.fcm.domain;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Builder
@Getter
@AllArgsConstructor
public class PushNotificationMessage {
private boolean validate_only;
private Message message;

@Builder
@Getter
@AllArgsConstructor
public static class Message {
private Notification notification;
private String token;
}

@Builder
@Getter
@AllArgsConstructor
public static class Notification {
private String title;
private String body;
private String image;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.bluebird.pipit.fcm.dto;

import lombok.Value;

@Value
public class PushNotificationRequest {
String targetToken;
String title;
String body;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.bluebird.pipit.fcm.service;

import com.bluebird.pipit.fcm.domain.PushNotificationMessage;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.auth.oauth2.GoogleCredentials;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.http.HttpHeaders;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;

@Slf4j
@Service
@RequiredArgsConstructor
public class PushNotificationService {
private static final String FIREBASE_CONFIG_PATH = "firebase/firebase_service_key.json"; // TODO : add firebase project service key file
private static final String API_URL = "https://fcm.googleapis.com/v1/projects/{firebase-project-id}/messages:send";
private static final String OAUTH_SCOPE = "https://www.googleapis.com/auth/cloud-platform";

private final ObjectMapper objectMapper;


private String getAccessToken() {
GoogleCredentials googleCredentials;
try {
googleCredentials = GoogleCredentials
.fromStream(new ClassPathResource(FIREBASE_CONFIG_PATH).getInputStream())
.createScoped(List.of(OAUTH_SCOPE));
} catch (IOException e) {
throw new RuntimeException("Failed to open Firebase Configuration File.", e);
}

try {
googleCredentials.refreshIfExpired();
} catch (IOException e) {
log.error("Failed to refresh Google Credentials.", e);
}

return googleCredentials.getAccessToken().getTokenValue();
}

private String makeMessage(String targetToken, String title, String body) throws JsonProcessingException {
PushNotificationMessage message = PushNotificationMessage.builder()
.message(
PushNotificationMessage.Message.builder()
.token(targetToken)
.notification(
PushNotificationMessage.Notification.builder()
.title(title)
.body(body)
.image(null)
.build()
).build())
.validate_only(false)
.build();

return objectMapper.writeValueAsString(message);

}

public void sendMessageTo(String targetToken, String title, String body) {
String message;
try {
message = makeMessage(targetToken, title, body);
} catch (JsonProcessingException e) {
throw new RuntimeException("Failed to make Message.", e);
}

OkHttpClient client = new OkHttpClient();
RequestBody requestBody = RequestBody.create(message, MediaType.get("application/json; charset=utf-8"));

Request request = new Request.Builder()
.url(API_URL)
.post(requestBody)
.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + getAccessToken())
.build();

try {
client.newCall(request).execute();
} catch (IOException e) {
log.error("Failed to send request.", e);
}
}



}
2 changes: 2 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ rootProject.name = 'pipit'
include 'pipit-api'
include 'authentication-api'
include 'support'
include 'push-notification-api'

0 comments on commit 656d559

Please sign in to comment.