Backend server for AmaryPay implementing Event-Driven UI using Firebase Cloud Messaging (FCM).
Event-Driven UI is an architectural pattern where the mobile app UI automatically updates its state based on events/notifications sent from the server. This is similar to the Server-Driven UI or Event Bus concept.
- Mobile app performs action (e.g., transfer money)
- Mobile app calls server API to send data
- Server processes data and sends FCM notification to mobile app
- Mobile app receives notification and updates UI state automatically
- UI refreshes without manual pull-to-refresh
- Open Firebase Console
- Create new project or use existing project
- Add Android app and iOS app to project
- In Firebase Console, open Project Settings > Service Accounts
- Click Generate New Private Key
- Download JSON file
- Rename file to
firebase-service-account.json - Copy file to
server/src/main/resources/firebase-service-account.json
IMPORTANT: Do not commit firebase-service-account.json to git! This file is already in .gitignore.
Make sure the following file is in .gitignore:
server/src/main/resources/firebase-service-account.json
POST /api/notifications/send
Content-Type: application/json
{
"deviceToken": "FCM_DEVICE_TOKEN",
"payload": {
"eventType": "BALANCE_UPDATED",
"title": "Balance Updated",
"body": "Your balance has been updated",
"data": {
"newBalance": "1000000",
"currency": "IDR"
},
"priority": "HIGH",
"silent": false
}
}POST /api/notifications/send-bulk
Content-Type: application/json
{
"deviceTokens": ["TOKEN_1", "TOKEN_2", "TOKEN_3"],
"payload": {
"eventType": "PAYMENT_SUCCESS",
"title": "Payment Successful",
"body": "Your payment has been processed",
"data": {
"transactionId": "TRX123456",
"amount": "50000"
},
"priority": "HIGH",
"silent": false
}
}POST /api/notifications/send-topic
Content-Type: application/json
{
"topic": "all-users",
"payload": {
"eventType": "NEW_PROMOTION",
"title": "New Promotion!",
"body": "Get 50% cashback for all transactions",
"data": {
"promoCode": "CASHBACK50",
"validUntil": "2024-12-31"
},
"priority": "NORMAL",
"silent": false
}
}POST /api/notifications/trigger-event
Content-Type: application/x-www-form-urlencoded
deviceToken=FCM_DEVICE_TOKEN
&eventType=BALANCE_UPDATED
&title=Balance Updated
&body=Your balance has been updated
&silent=true
&newBalance=1000000
¤cy=IDRAvailable event types for Event-Driven UI:
PAYMENT_SUCCESS- Payment successfulPAYMENT_FAILED- Payment failedPAYMENT_PENDING- Payment pendingPAYMENT_REFUNDED- Payment refunded
TRANSACTION_CREATED- Transaction createdTRANSACTION_UPDATED- Transaction updatedTRANSACTION_CANCELLED- Transaction cancelled
BALANCE_UPDATED- Balance updatedACCOUNT_VERIFIED- Account verifiedACCOUNT_SUSPENDED- Account suspended
NEW_PROMOTION- New promotionSYSTEM_MAINTENANCE- System maintenanceSECURITY_ALERT- Security alert
REFRESH_HOME- Refresh home screenREFRESH_TRANSACTIONS- Refresh transaction listREFRESH_PROFILE- Refresh profileUPDATE_BADGE_COUNT- Update badge count
CUSTOM_EVENT- Custom event
./gradlew :server:run./gradlew :server:build# Health check
curl http://localhost:8080/health
# Test notification (replace with valid device token)
curl -X POST http://localhost:8080/api/notifications/trigger-event \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "deviceToken=YOUR_DEVICE_TOKEN&eventType=BALANCE_UPDATED&silent=true&newBalance=1000000"Mobile app needs to:
- Setup Firebase Cloud Messaging
- Get FCM device token
- Listen for incoming notifications
- Parse
eventTypefrom notification data - Update UI state based on event type
Example flow in mobile app:
// When receiving FCM notification
onMessageReceived { remoteMessage ->
val eventType = remoteMessage.data["eventType"]
val timestamp = remoteMessage.data["timestamp"]
when (eventType) {
"BALANCE_UPDATED" -> {
val newBalance = remoteMessage.data["newBalance"]
// Update UI state
viewModel.updateBalance(newBalance)
}
"PAYMENT_SUCCESS" -> {
// Navigate to success screen
// Refresh transaction list
}
// ... handle other events
}
}- Do not commit
firebase-service-account.jsonto repository - Use environment variables for production
- Implement authentication for API endpoints
- Validate device tokens before sending notifications
- Rate limiting to prevent spam