103 lines
4.1 KiB
Markdown
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.
|