Backend ini digunakan untuk mengirim notifikasi dari server ke aplikasi Kotlin Android melalui Firebase Cloud Messaging. FCM mendukung pengiriman pesan dari backend menggunakan Firebase Admin
SDK atau HTTP v1 API.
1. Struktur Project
firebase-push-backend/
├── main.go
├── firebase-service-account.json
├── go.mod
└── .env
2. Init Project Golang
mkdir firebase-push-backend
cd firebase-push-backend
go mod init firebase-push-backend
go get github.com/gin-gonic/gin
go get firebase.google.com/go/v4
go get google.golang.org/api/option
3. Ambil Firebase Service Account
Di Firebase Console:
Project Settings
→ Service accounts
→ Generate new private key
Simpan file JSON ke project:
firebase-service-account.json
Jangan upload file ini ke GitHub.
4. Buat .env
PORT=8080
FIREBASE_CREDENTIALS=firebase-service-account.json
5. Kode Backend main.go
package main
import (
"context"
"log"
"net/http"
"os"
firebase "firebase.google.com/go/v4"
"firebase.google.com/go/v4/messaging"
"github.com/gin-gonic/gin"
"google.golang.org/api/option"
)
type SendNotificationRequest struct {
Token string `json:"token" binding:"required"`
Title string `json:"title" binding:"required"`
Body string `json:"body" binding:"required"`
Data map[string]string `json:"data"`
}
func main() {
r := gin.Default()
ctx := context.Background()
credentialFile := os.Getenv("FIREBASE_CREDENTIALS")
if credentialFile == "" {
credentialFile = "firebase-service-account.json"
}
opt := option.WithCredentialsFile(credentialFile)
app, err := firebase.NewApp(ctx, nil, opt)
if err != nil {
log.Fatalf("error initialize firebase app: %v", err)
}
client, err := app.Messaging(ctx)
if err != nil {
log.Fatalf("error initialize firebase messaging: %v", err)
}
r.POST("/api/notification/send", func(c *gin.Context) {
var req SendNotificationRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"message": "request tidak valid",
"error": err.Error(),
})
return
}
message := &messaging.Message{
Token: req.Token,
Notification: &messaging.Notification{
Title: req.Title,
Body: req.Body,
},
Data: req.Data,
}
response, err := client.Send(ctx, message)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"message": "gagal mengirim notifikasi",
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "notifikasi berhasil dikirim",
"firebase_id": response,
})
})
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
r.Run(":" + port)
}
6. Jalankan Backend
export FIREBASE_CREDENTIALS=firebase-service-account.json
export PORT=8080
go run main.go
7. Test Kirim Notifikasi dari Postman
Endpoint:
POST http://localhost:8080/api/notification/send
Body JSON:
{
"token": "FCM_DEVICE_TOKEN_DARI_ANDROID",
"title": "Approval Baru",
"body": "Ada pengajuan asset yang perlu kamu approve",
"data": {
"type": "APPROVAL",
"asset_id": "123"
}
}
Jika berhasil:
{
"firebase_id": "projects/your-project/messages/0:xxxxx",
"message": "notifikasi berhasil dikirim"
}
FCM HTTP v1 dan Admin SDK bisa mengirim pesan ke token device, topic, atau condition. Untuk device tertentu, target utamanya adalah registration token dari aplikasi Android.
8. Endpoint Kirim ke Topic
Tambahkan endpoint ini:
type SendTopicRequest struct {
Topic string `json:"topic" binding:"required"`
Title string `json:"title" binding:"required"`
Body string `json:"body" binding:"required"`
Data map[string]string `json:"data"`
}
r.POST("/api/notification/topic", func(c *gin.Context) {
var req SendTopicRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"message": "request tidak valid",
"error": err.Error(),
})
return
}
message := &messaging.Message{
Topic: req.Topic,
Notification: &messaging.Notification{
Title: req.Title,
Body: req.Body,
},
Data: req.Data,
}
response, err := client.Send(ctx, message)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"message": "gagal mengirim notifikasi topic",
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "notifikasi topic berhasil dikirim",
"firebase_id": response,
})
})
Test body:
{
"topic": "admin",
"title": "Reminder Approval",
"body": "Ada data asset yang perlu disetujui",
"data": {
"screen": "approval"
}
}
9. Simpan FCM Token ke Database
Untuk production, backend sebaiknya menyimpan token dari aplikasi Android.
Struktur tabel:
CREATE TABLE firebase_tokens (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL,
token TEXT NOT NULL,
platform VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Endpoint contoh:
POST /api/firebase-token/save
Body:
{
"user_id": 1,
"token": "FCM_DEVICE_TOKEN",
"platform": "android"
}
10. Best Practice
✅ Jangan taruh service account JSON di frontend
✅ Simpan FCM token ke database backend
✅ Update token ketika onNewToken terpanggil
✅ Hapus token saat user logout
✅ Gunakan topic untuk role seperti admin, manager, approval
✅ Gunakan data payload untuk navigasi screen
✅ Jangan commit firebase-service-account.json ke GitHub
SEO Slug
backend-golang-firebase-push-notification-fcm
Tags
Golang
Firebase
FCM
Push Notification
REST API
Gin
Kotlin Android
Backend
Mobile Development