HEROJOON 블로그(히로블)

FCM 서버 프로토콜을 이용한 Push 전송 본문

Backend

FCM 서버 프로토콜을 이용한 Push 전송

herojoon 2020. 3. 5. 00:40
반응형

2020/02/24 - [Backend] - FCM 시작하기

2020/02/24 - [Backend] - Android Studio 환경 셋업

2020/02/28 - [Backend] - Android 앱 프로젝트에 Firebase설정

2020/02/28 - [Backend] - Android 앱 프로젝트에 FCM설정 및 코드작성

2020/02/24 - [Backend] - Firebase Push전송 구현을 위한 준비

2021.08.15 - [Backend] - Push 전송 프로젝트 생성

2020/03/05 - [Backend] - Firebase Admin SDK를 이용한 Push 전송

4. FCM Push발송 API Server 프로젝트 생성 (Sender)

4-1. Firebase Push전송 구현을 위한 준비

4-2. Push 전송 프로젝트 생성

4-3. Firebase Admin SDK를 이용한 Push 전송

4-4. FCM 서버 프로토콜을 이용한 Push 전송

  • FCM 서버 엔드포인트
  • FCM 서버 프로토콜 인증
  • Push 발송 API 구현 - 특정 기기에 메시지 전송

목표

이 글의 목표는 FCM 서버 프로토콜을 이용하여 Android 앱에 Push를 전송하는 것이다.

(참고 docs : https://firebase.google.com/docs/cloud-messaging/migrate-v1?authuser=1)


FCM 서버 엔드포인트

HTTP Protocol을 이용하여 FCM메시지를 전송할 경우 FCM에서 제공하는 서버 엔드포인트가 필요합니다.

Push Sender는 이 FCM 엔드포인트 API로 메시지 전송하고, 전송된 메시지는 FCM으로 전달되어 최종적으로 안드로이드앱에 Push가 전송되는 Flow입니다.

 

FCM 서버 엔드포인트에 대한 설명은 위 참고 docs를 참고하시면 됩니다.

 

기존 HTTP에서 HTTP v1로 마이그레이션  |  Firebase

FCM의 기존 HTTP API를 사용하는 앱은 이 가이드의 안내에 따라 HTTP v1 API로 마이그레이션해야 합니다. HTTP v1 API는 기존 API에 비해 다음과 같은 장점이 있습니다. 액세스 토큰을 통한 보안 향상: HTTP v1 API는 OAuth2 보안 모델에 따라 수명이 짧은 액세스 토큰을 사용합니다. 액세스 토큰이 공개되는 경우에도 악의적으로 사용될 수 있는 시간은 만료되기 전 1시간 정도뿐입니다. 갱신 토큰이 이전 API에서 사용하는 보

firebase.google.com

FCM 서버 엔드포인트의 형식은

POST https://fcm.googleapis.com/v1/projects/{프로젝트ID}/messages:send

입니다.

 

프로젝트ID는 Firebase 콘솔화면 - 앱관리 화면에서 확인 가능합니다.

FCM 서버 프로토콜 인증

FCM 서버 프로토콜을 이용해서 Push 전송 시, 인증을 위하여 AccessToken이 필요합니다.

AccessToken을 얻기 위한 가이드는 위 참고 docs에서 [사용자 인증 정보를 사용하여 액세스 토큰 발급]을 참고하시면 됩니다.

service-account.json이라는 사용자 인증정보를 사용하여 액세스 토큰을 발급받을 수 있습니다.

(service-account.json을 얻는 방법은

2020/03/05 - [Backend] - Firebase Admin SDK를 이용한 Push 전송

를 참고해주세요.)

Push 발송 API 구현 - 특정 기기에 메시지 전송

FCM 서버 프로토콜을 이용하여 Push 전송 정리

 

1) 서버 엔드포인트와 (FCM 서버 프로토콜 API)

POST https://fcm.googleapis.com/v1/projects/{프로젝트ID}/messages:send

 

2) AccessToken을 이용해서 (인증을 위한 값)

사용자 인증정보(service-account.json)에서 얻은 AccessToken

 

3) 특정 기기에

특정 기기 token정보에 메시지 전송

(토큰 얻는 방법은

2020/02/28 - [Backend] - Android 앱 프로젝트에 FCM설정 및 코드작성

를 참고해주세요.)

 

4) 메시지 정보를

메시지 포맷은 위 참고 docs를 참고하시면 됩니다. 저는 아래 메시지 포맷으로 보내도록 하겠습니다.

{"message":{"data":{"title":"메시지를 보낼거야2","content":"너에게로2"},"token":"특정 기기 토큰정보"}}

 

보내면 됩니다.

 

 

코드작성 (by herojoon)

 

1) Controller 작성

package com.herojoon.pushsender.controller;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import okhttp3.*;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;

@RestController
@RequestMapping("push")
public class PushController {
    private static final String MESSAGING_SCOPE = "https://www.googleapis.com/auth/firebase.messaging";
    private static final String[] SCOPES = { MESSAGING_SCOPE };

    @Value("${fcm.devicetoken}")
    private String FCM_DEVICE_TOKEN;

    @Value("${fcm.apiurl}")
    private String FCM_API_URL;

    /**
     * HTTP Protocol을 이용한 Push 전송
     * @return
     */
    @RequestMapping("/send")
    public void send() {
        // 1. create message body
        JSONObject jsonValue = new JSONObject();
        jsonValue.put("title", "메시지를 보낼거야2");
        jsonValue.put("content", "너에게로2");

        JSONObject jsonData = new JSONObject();
        jsonData.put("token", FCM_DEVICE_TOKEN);
        jsonData.put("data", jsonValue);

        JSONObject jsonMessage = new JSONObject();
        jsonMessage.put("message", jsonData);

        // 2. create token & send push
        try {
            OkHttpClient okHttpClient = new OkHttpClient();
            Request request = new Request.Builder()
                    .addHeader("Authorization", "Bearer " + getAccessToken())
                    .addHeader("Content-Type", "application/json; UTF-8")
                    .url(FCM_API_URL)
                    .post(RequestBody.create(jsonMessage.toString(), MediaType.parse("application/json")))
                    .build();
            Response response = okHttpClient.newCall(request).execute();

            System.out.println("### response str : " + response.toString());
            System.out.println("### response result : " + response.isSuccessful());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String getAccessToken() throws IOException {
        ClassPathResource resource = new ClassPathResource("keystore/service-account.json");
        GoogleCredential googleCredential = GoogleCredential
                .fromStream(new FileInputStream(resource.getFile()))
                .createScoped(Arrays.asList(SCOPES));
        googleCredential.refreshToken();
        return googleCredential.getAccessToken();
    }
}

 

2) build.gradle 추가

compile group: 'org.json', name: 'json', version: '20190722'
compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.2.2'

 

반응형
Comments