Files
medical-mall/server/README.md
2026-02-25 09:38:01 +08:00

195 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
如需我在本地使用你的 Supabase 凭证演示一次完整的注册→查询→发送流程,或将持久化切换为仅 Supabase移除本地 JSON 回退),请直接告诉我你的选择并提供测试凭证或确认权限范围。
---
## 故障排查记录(已执行)
- 我们在仓库中运行了两个辅助脚本以排查 Supabase 凭证问题:
- `server/probe_supa.js`:对单个 key 发起 REST 请求并打印响应(用于快速验证)。
- `server/try_supa_keys.js`:扫描仓库中形似 JWT 的字符串并逐一尝试对 Supabase REST 发起请求,打印每个 candidate 的 HTTP 状态与响应预览。
- 排查结果摘要:
- 在仓库中发现 6 个看起来像 JWT 的候选 key均对 `GET /rest/v1/push_devices?user_id=eq.<user>` 返回 HTTP 401包括 `PGRST301` / `Invalid authentication credentials`)。
- 说明这些仓库内的字符串不是当前 Supabase 项目可用的 `service_role` key或 Supabase 项目/Key 已被替换/撤销,或请求的 Supabase URL 与当时不同。
## 推荐操作(二选一)
### A使用正确的 Supabase `service_role` key推荐
1. 在 Supabase 控制台Project → Settings → API → Service role key复制该 key仅在后端使用切勿公开
2. 在服务器启动前注入环境变量并启动:
```powershell
$env:SUPA_URL='http://192.168.1.62:18000'
$env:SUPA_KEY='(粘贴你的 service_role key'
node server/push-server.js
```
或后台运行并记录日志:
```powershell
$env:SUPA_URL='http://192.168.1.62:18000'
$env:SUPA_KEY='(你的 key'
Start-Process node -ArgumentList 'server/push-server.js' -RedirectStandardOutput '.\\server.log' -RedirectStandardError '.\\server.err' -PassThru
```
运行后可检查 `server.log`(包含 `supaFetch` 调试输出),并用以下命令验证:
```powershell
Invoke-RestMethod -Uri 'http://localhost:7301/api/v1/push/devices?user_id=<user-uuid>' -Method GET | ConvertTo-Json -Depth 5
```
### B绕过 Supabase仅用于本地快速验证
如果你只是想立即验证下发链路,可把已知的 devicecid + user_id写入本地 `server/data/push_devices.json`,然后执行 mock 推送:
```powershell
# 查看本地 devices 文件
Get-Content .\server\data\push_devices.json -Raw | ConvertFrom-Json
# 手动追加(示例,替换 cid 与 user_id
$devs = Get-Content .\server\data\push_devices.json -Raw | ConvertFrom-Json
$devs += @{ cid='d9aa69ec415...'; user_id='a8e3a568-fc1f-4237-bcc5-5722e2fca0a3'; platform='android'; created_at=(Get-Date).ToString('o'); updated_at=(Get-Date).ToString('o'); active=$true }
$devs | ConvertTo-Json -Depth 5 | Set-Content .\server\data\push_devices.json -Encoding utf8
# 然后测试发送mock
Invoke-RestMethod -Uri 'http://localhost:7301/api/v1/push/send' -Method POST -ContentType 'application/json' -Body (@{ user_id='a8e3a568-fc1f-4237-bcc5-5722e2fca0a3'; notification=@{ title='测试'; body='hello' } } | ConvertTo-Json)
```
## 已添加的辅助脚本
- `server/probe_supa.js` — 对单个 key 发起请求并打印响应(用于快速验证)。
- `server/try_supa_keys.js` — 在仓库中查找 JWT 样式字符串并逐一尝试调用 Supabase REST打印每个 candidate 的状态与响应预览。
如果你把正确的 `service_role` key 提供给我(仅用于本次会话),我可以代为注入环境、重启服务并把 `supaFetch` 的调试输出和最终结果贴回给你;或我可以现在把截图中已有的 cid/user_id 写入本地 JSON 并立即做一次 mock 下发测试。
# Push Server (开发用)
这是一个用于本地开发与调试的轻量 Node.js 推送后端mock
功能:
- 注册/更新设备:`POST /api/v1/push/register` { cid, user_id, platform }
- 注销设备:`POST /api/v1/push/unregister` { cid | user_id }
- 列出设备:`GET /api/v1/push/devices?user_id=...&active=true|false`
- 发送推送(模拟):`POST /api/v1/push/send` { cids:[], user_id, notification, payload }
如果你有真实的推送服务端 API可以设置环境变量 `PUSH_PROXY_URL`(和可选的 `PUSH_PROXY_TOKEN`),服务器会将 `/api/v1/push/send` 请求代理到该 URL。
快速使用:
```bash
cd server
npm install
npm start
```
默认监听端口:`7301`,可通过 `PORT` 环境变量修改。
设备存储在 `server/data/push_devices.json`,用于本地持久化。
可选:直接写入 Supabase
服务器可以可选地将 `push_devices` 记录直接写入 Supabase/Postgres适用于生产或集成测试。启用方法在启动前设置下列环境变量
- `SUPA_URL` — Supabase 项目 URL例如 `https://xyzcompany.supabase.co`
- `SUPA_KEY` — Supabase `service_role` key仅在服务器端使用切勿暴露给客户端
当这两个变量存在时,服务会通过 PostgREST REST API 向 `/rest/v1/push_devices` 发起 upsert使用 `on_conflict=cid`),并在注销时将设备的 `is_active` 标记为 `false`。同时本地 JSON 存储仍会保留为回退。
示例PowerShell:
```powershell
$env:SUPA_URL = 'https://xyz.supabase.co'
$env:SUPA_KEY = 'eyJhbGci...'
npm start
```
请确保你的 Supabase 项目已经包含与仓库迁移脚本匹配的 `push_devices` 表:
`pages/mall/delivery/doc/需求文档/20260224_add_push_devices_and_notifications.sql`
Supabase 表结构与权限(快速参考)
下面是 `push_devices` 表的最小字段集合,供你在 Supabase 中快速验证或手动创建:
```sql
CREATE TABLE public.push_devices (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid NULL,
cid varchar(255) NOT NULL,
platform varchar(32) NOT NULL DEFAULT 'android',
appid varchar(128) NOT NULL DEFAULT 'default',
is_active boolean NOT NULL DEFAULT true,
last_seen_at timestamptz NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX IF NOT EXISTS ux_push_devices_appid_cid ON public.push_devices(appid, cid);
```
权限与安全建议:
- 生产环境请务必只在后端使用 `service_role``SUPA_KEY`),不要将其暴露给客户端。后端应负责向 Supabase 写入/更新设备记录。
- 如果你需要通过客户端直接调用 Supabase REST不推荐请配置 RLS 策略并只允许安全的最小操作。
- 推荐做法:后端使用 `service_role` 写入;客户端只调用后端的 `/api/v1/push/register`
示例:使用 `service_role` 通过 PostgREST 插入设备(等同于本服务中执行的请求):
```bash
curl -X POST "${SUPA_URL}/rest/v1/push_devices?on_conflict=cid" \
-H "apikey: ${SUPA_KEY}" \
-H "Authorization: Bearer ${SUPA_KEY}" \
-H "Content-Type: application/json" \
-d '[{"cid":"CID_TEST_001","user_id":"<user-uuid>","platform":"android","appid":"default","is_active":true}]'
```
注意事项:
- 如果你使用的是 Supabase 的 `uuid_generate_v4()` 功能,可能需要在数据库安装 `uuid-ossp` 或使用 `gen_random_uuid()`pgcrypto。迁移脚本中已包含兼容性处理。
- 本服务对 Supabase 的写入为异步非阻塞:写入失败不会阻止本地响应,但会在日志中记录错误。可根据需要修改为同步错误返回策略。
如需我把本地 JSON 回退移除并只保留 Supabase 持久化(需你确认并提供测试凭证),我可以继续实现并更新代码与文档。
## 服务说明(快速参考)
**服务简介**
- **目的**:为开发/集成阶段提供一个轻量的推送后端,用于接收客户端上报的推送客户端 IDCID、管理设备状态并在开发中触发/代理推送以验证链路。
- **主要职责**:接收设备注册/注销、列出设备、触发推送mock 或代理到真实推送服务)、可选将设备写入 Supabase。
**暴露的接口HTTP**
- `GET /health`:健康检查
- `POST /api/v1/push/register`注册或更新设备body: `{ cid, user_id, platform, ... }`
- `POST /api/v1/push/unregister`注销设备body: `{ cid | user_id }`
- `GET /api/v1/push/devices`列出设备query: `user_id`, `active`
- `POST /api/v1/push/send`:发送推送(开发环境为 mock可代理到 `PUSH_PROXY_URL`
**数据与持久化**
- 开发默认将设备保存在本地文件:`server/data/push_devices.json`(回退/离线使用)。
- 可选:当设置 `SUPA_URL``SUPA_KEY` 时,服务会通过 Supabase RESTPostgREST`push_devices` 表 upsert/patch 同步设备记录(异步、非阻塞)。
**重要环境变量**
- `PORT`:监听端口(默认 7301
- `PUSH_PROXY_URL` / `PUSH_PROXY_TOKEN`:将 `/api/v1/push/send` 代理到真实推送服务
- `SUPA_URL` / `SUPA_KEY` / `SUPA_SCHEMA`:启用 Supabase 同步(`SUPA_KEY` 应为服务端 `service_role`,仅服务器端使用)
**安全与部署注意**
- 切勿将 `SUPA_KEY`service_role暴露给客户端只能在后端使用。
- 生产场景应:后端持有凭证并负责写入/验证;对客户端使用后端接口,不直接对 Supabase 写入。
- 如直接允许客户端写 Supabase必须开启 RLS 并最小化权限(一般不推荐)。
**表结构与迁移**
- 已提供迁移脚本:`pages/mall/delivery/doc/需求文档/20260224_add_push_devices_and_notifications.sql`(包含 `push_devices``express_notifications` 表及触发器、索引)。
**快速测试示例**
PowerShell:
```powershell
Invoke-RestMethod -Uri 'http://localhost:7301/api/v1/push/register' -Method POST -ContentType 'application/json' -Body '{"cid":"CID_TEST_001","user_id":"user-1","platform":"android"}'
```
curl示例 upsert 到 Supabase需替换变量:
```bash
curl -X POST "${SUPA_URL}/rest/v1/push_devices?on_conflict=cid" \
-H "apikey: ${SUPA_KEY}" \
-H "Authorization: Bearer ${SUPA_KEY}" \
-H "Content-Type: application/json" \
-d '[{"cid":"CID_TEST_001","user_id":"<user-uuid>","platform":"android","appid":"default","is_active":true}]'
```
如需我在本地使用你的 Supabase 凭证演示一次完整的注册→查询→发送流程,或将持久化切换为仅 Supabase移除本地 JSON 回退),请直接告诉我你的选择并提供测试凭证或确认权限范围。