Files
soccar2d/readme.md
T
2026-11-03 20:26:24 +05:30

103 lines
4.1 KiB
Markdown

# Admin and support-agent push notifications
The Unity game already registers a Firebase Installation ID and reacts to a fixed payload. This Next.js project (admin dashboard and customer support agent) needs two player routes, a send when an agent replies, and the admin broadcast actions.
Leave the existing support-agent app notifications as they are. Those still use that app's own registration tokens.
The game talks to `https://kkadmin.playpoolstudios.com` with the bearer token from `POST /api/support/player/login`. Use that same player auth on the new routes. A `401` signs the player out of support, so only return it when the bearer token is actually invalid.
## Store the game install
Add one row per player. A new registration replaces the previous one.
| Column | Value |
| --- | --- |
| `userId` | Support player id from the bearer token |
| `fid` | Firebase Installation ID from the game |
| `platform` | `android` |
| `updatedAt` | Set on every successful register |
This id is not the registration token already stored for the support-agent app. Keep those tables separate. The game id only works for the Android app `com.WalkInvest.KickKings` in the `kickkings-admin` Firebase project. The same service account can send to both apps.
### `POST /api/support/player/devices`
```json
{ "fid": "the-installation-id", "platform": "android" }
```
Upsert that player's row. Any `2xx` is enough. `{}` is fine. The game treats an empty success body as success.
### `DELETE /api/support/player/devices`
```json
{ "fid": "the-installation-id", "platform": "android" }
```
Delete the row only when both `userId` and `fid` match. If it is already gone, still return `2xx`. The game logs out even when this call fails.
## When an agent replies
After the staff message is saved, load that ticket's player and send to the stored `fid`. Do this only for a staff reply. A player message does not notify the player.
```json
{
"message": {
"fid": "<stored fid>",
"notification": {
"title": "Support",
"body": "Support replied to your ticket"
},
"data": {
"type": "support_reply",
"ticketId": "<ticket id>"
},
"android": {
"priority": "high",
"notification": { "channel_id": "support" }
}
}
}
```
`data.type` and `data.ticketId` must be those exact strings. `ticketId` is the same id the game already uses in `/api/support/player/tickets/{ticketId}`. Both data values have to be strings.
Keep the lock-screen body generic. Ticket text can include withdrawal or payment details, so do not put the message body in the notification.
With the Firebase Admin SDK, set `fid` to the stored id. On an older SDK that has no `fid` field, put that same id in `token`. During the current migration, `token` still accepts an installation id.
If FCM returns `UNREGISTERED`, delete that row and stop retrying it.
The game opens that ticket when it receives `support_reply`. If the player is already looking at it, the thread refreshes immediately.
## Admin notifications
Add two actions to the admin dashboard. Both use the same sender and the same Android channel.
### Everyone
This includes players who never opened support.
```json
{
"message": {
"topic": "kk_broadcast",
"notification": { "title": "<title>", "body": "<message>" },
"data": { "type": "announcement" },
"android": {
"priority": "high",
"notification": { "channel_id": "support" }
}
}
}
```
Do not prefix the topic with `/topics/`. The game subscribes to `kk_broadcast` on its own.
### One player
Use the same payload, with `fid` set to that player's stored id and no `topic`. If that player has no row, show that the game has not registered yet.
`announcement` does not open a screen. The title and body are the whole message, and they have to be in `notification`. The tray shows that text while the game is in the background. While the game is open, this build does not add its own banner.
Sending a support reply and an admin message is the same function. Only `fid` versus `topic`, and `support_reply` versus `announcement`, change.