- Mobile TokenPocket now opens the tpoutside:// sign deep link and returns to the original browser to finish login (no wallet in-app browser); desktop keeps the QR. Fixes mobile login + logout being trapped in TP's browser. - Desktop without an injected wallet shows a clear message instead of a dead button; TokenPocket login card is always available as a working path. - Raise toast z-index above the login modal so feedback is visible. - Add native TokenPocket-login strings across 7 locales. - Document that the live backend lacks favorites + TokenPocket routes (404), the real blocker for those features in production. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
162 lines
8.6 KiB
Markdown
162 lines
8.6 KiB
Markdown
# 后端需求与核对文档:钱包登录 + 收藏
|
||
|
||
> 面向后端(`Arkie-Library-Backend`)。
|
||
> 本文是在前端审计「登录 + 收藏」bug 与 UI 重设计时,对后端现有实现的逐条核对,以及由此产生的后端待办。
|
||
>
|
||
> **核心结论:后端目前几乎已经满足前端全部需求。本次重设计与 bug 修复基本是纯前端工作。后端真正需要新增的只有少量「可选项」,外加几处需要确认的契约。请不要把已完成的功能再派一遍。**
|
||
|
||
日期:2026-06-02(2026-06-02 更新:新增 §0.5 部署阻塞)
|
||
相关分支:`terry-wallet-login`
|
||
|
||
---
|
||
|
||
## 0.5 🔴 关键阻塞:线上后端是旧版本,收藏与 TokenPocket 端点未部署
|
||
|
||
> 源码(`Arkie-Library-Backend`)里这些端点都有;但**当前线上 / dev 代理指向的后端**(`https://ark-library.com/apnew`)是**旧构建**,下列路由全部 404。
|
||
> **前端已就绪,但收藏与 TokenPocket 扫码登录在生产上无法工作,直到后端把含这些路由的版本部署上线。** 这正是用户实测「收藏用不了、扫码登录用不了」的根因。
|
||
|
||
curl 实证(经 vite dev 代理打到线上后端,2026-06-02):
|
||
|
||
| 端点 | 方法 | 实测状态 | 结论 |
|
||
|---|---|---|---|
|
||
| `/api/auth/wallet/nonce` | POST | **200** | ✅ 已部署 |
|
||
| `/api/auth/wallet/verify` | POST | **400**(入参错误)| ✅ 已部署 |
|
||
| `/api/auth/wallet/me` | GET | **401**(需鉴权)| ✅ 已部署 |
|
||
| `/api/auth/wallet/tp-login-request` | POST | **404** | ❌ 未部署 |
|
||
| `/api/auth/wallet/tp-result` | GET | **404** | ❌ 未部署 |
|
||
| `/api/auth/wallet/tp-callback` | POST | **404** | ❌ 未部署 |
|
||
| `/api/me/favorites` | GET | **404**(应为 401)| ❌ 未部署 |
|
||
| `/api/me/favorites/ids` | GET | **404** | ❌ 未部署 |
|
||
| `/api/me/favorites/{id}` | POST | **404** | ❌ 未部署 |
|
||
|
||
**后端动作(必做,按优先级最高):**
|
||
1. 部署包含 favorites(`internal/handlers/favorites.go`)+ TokenPocket(`internal/handlers/wallet_tp.go`)路由的后端版本(`cmd/server/main.go` 已注册这些路由)。
|
||
2. 为 TokenPocket 登录设置 `PUBLIC_BASE_URL`(`buildTokenPocketSignURL` 需要它生成回调 URL,否则 tp-login-request 会 500)。
|
||
3. 确保 `wallet_tp_login_requests` / `user_favorites` 等表已迁移(`EnsureWalletAuthSchema` 会建表)。
|
||
|
||
> 复测命令:`curl -s -o /dev/null -w "%{http_code}" -X POST https://ark-library.com/apnew/api/auth/wallet/tp-login-request -d '{}'` 应返回 200(且 body 的 `qrUrl` 形如 `tpoutside://pull.activity?param=...`)。
|
||
|
||
---
|
||
|
||
## 0. 一句话给后端
|
||
|
||
> 钱包认证、TokenPocket 扫码、收藏列表/筛选/分页/可用性,**都已实现且符合前端契约**。
|
||
> 下面 §1 是「已完成、勿动」的核对;§2 是「真正可能要后端做的事」;§3 是「前端会改但与后端无关,别误接」。
|
||
|
||
---
|
||
|
||
## 1. 已实现并符合前端契约(✅ 无需改动)
|
||
|
||
逐条核对自后端源码(`internal/handlers/wallet_auth.go`、`wallet_tp.go`、`favorites.go`、`public.go`、`cmd/server/main.go`)。
|
||
|
||
### 1.1 钱包认证
|
||
|
||
| 端点 | 状态 | 说明 |
|
||
|---|---|---|
|
||
| `POST /api/auth/wallet/nonce` | ✅ | 返回 `{nonce, message}`,message 含一次性码,写入 `wallet_auth_nonces`,TTL 15 分钟 |
|
||
| `POST /api/auth/wallet/verify` | ✅ | EIP-191 `personal_sign` 验签恢复地址,签发 JWT |
|
||
| `GET /api/auth/wallet/me` | ✅ | Bearer JWT → `{wallet, role:"user"}` |
|
||
|
||
关键事实(对前端 bug 很重要):
|
||
|
||
- **验签完全链无关。** `recoverPersonalSign` 只做 EIP-191 文本哈希恢复,不校验任何 chainId。签名消息文案是
|
||
`"ARK Database — wallet sign-in … Sign this message to log in. No transaction or gas fee."`,**不引用任何链**。
|
||
→ 因此前端登录时强制切到 BNB 链(`ensureBnbChain`)是**多余的**,删除它**不影响后端**。这是一项纯前端修复。
|
||
- JWT:HS256,**有效期 30 天**(`SignUserWallet(..., 30*24h)`),无状态。
|
||
- nonce 用后即删,过期自动清理。
|
||
|
||
### 1.2 TokenPocket 扫码登录
|
||
|
||
| 端点 | 状态 |
|
||
|---|---|
|
||
| `POST /api/auth/wallet/tp-login-request` | ✅ 生成 actionId/nonce/message/qrUrl,写 `wallet_tp_login_requests` |
|
||
| `POST /api/auth/wallet/tp-callback` | ✅ 钱包回调写入签名,校验 `callbackToken` |
|
||
| `GET /api/auth/wallet/tp-result?actionId=` | ✅ 轮询返回 `pending/completed/expired/failed` |
|
||
|
||
→ 前端把扫码从「手机端」挪到「桌面端」只是 UI 位置调整,**后端无需改动**。
|
||
|
||
### 1.3 收藏
|
||
|
||
| 端点 | 状态 | 支持的能力 |
|
||
|---|---|---|
|
||
| `GET /api/me/favorites` | ✅ | `q`(title/description/body_text/tag ILIKE)、`category`(slug)、`sort`(`favorited_at`/`published_at`/`hot`)、`includeUnavailable`(默认 true)、`page`/`limit`(≤100)、返回 `total`、tags、`favoriteCount`、`availability` |
|
||
| `GET /api/me/favorites/ids?resourceIds=` | ✅ | 批量查询收藏状态 |
|
||
| `POST /api/me/favorites/{id}` | ✅ | 加收藏,返回 `{ok,resourceId,favorited,favoriteCount}` |
|
||
| `DELETE /api/me/favorites/{id}` | ✅ | 取消收藏,`favorite_count` 不低于 `favorite_base_count` |
|
||
|
||
关键事实:
|
||
|
||
- **下架资源可用性已支持。** `scanFavoriteItem` 会把 `status!='published' 或 is_public=false` 的资源标为
|
||
`availability:"unavailable"`,且默认 `includeUnavailable=true` 仍返回。→ 前端「不可用资源卡片」逻辑后端已就绪。
|
||
- `sort=hot` 定义 = `download_count + favorite_count + share_count` 降序。
|
||
- 鉴权失败统一返回 **401**。
|
||
|
||
---
|
||
|
||
## 2. 真正可能需要后端做的事
|
||
|
||
按优先级。除 2.1 外多为**可选/按产品决定**。
|
||
|
||
### 2.1 【需确认】CORS 允许前端源 + Authorization 头
|
||
|
||
前端通过 `apiBase` 调 `/api/me/favorites`,并带 `Authorization: Bearer <jwt>`。
|
||
若前端与 API 不同源,需确认 CORS 允许:
|
||
|
||
- 来源:前端正式域名(及预览/本地开发源)
|
||
- 方法:`GET, POST, DELETE`
|
||
- 请求头:`Authorization, Content-Type`
|
||
|
||
**动作**:确认现有 CORS 配置覆盖以上;若 `apiBase` 同源则可忽略。
|
||
|
||
### 2.2 【可选】服务端登出 / Token 失效
|
||
|
||
现状:JWT 无状态,前端「断开连接」只清本地 localStorage,旧 token 在 30 天内仍有效。
|
||
|
||
若产品需要「真正的远程登出 / 失效被盗 token」,后端需引入二选一:
|
||
|
||
- token 版本号(用户级 `token_version`,签发与校验时比对);或
|
||
- token 黑名单(jti 撤销表)
|
||
|
||
**默认建议**:第一版**不做**,保持无状态。仅在有安全需求时再做。
|
||
|
||
### 2.3 【可选】缩短或可配置 JWT 有效期
|
||
|
||
现为固定 30 天。若希望更安全或可配置,可将 TTL 提为环境变量(如 `USER_JWT_TTL`)。
|
||
|
||
**默认建议**:30 天对「只验证地址、无资产操作」的场景可接受,可暂不动。
|
||
|
||
### 2.4 【按产品决定】MetaMask / imToken 扫码兜底(WalletConnect/Reown)
|
||
|
||
如果前端最终保留 WalletConnect 扫码路径:**后端无需任何改动**——`/verify` 接受任何 `personal_sign` 签名,与连接方式无关。
|
||
此项列出只为说明「即便前端接了 WalletConnect,也不产生后端工作」。
|
||
|
||
### 2.5 【可选打磨】收藏列表 `q` 搜索性能
|
||
|
||
当前 `q` 用多列 `ILIKE '%..%'`,数据量大时无法走索引。量级变大后可考虑 `pg_trgm` 或全文索引。
|
||
|
||
**默认建议**:当前数据量下不必做,记录备查。
|
||
|
||
---
|
||
|
||
## 3. 前端会改、但与后端无关(请勿误派给后端)
|
||
|
||
这些是本次 bug/重设计的主体,**全部在前端完成,不涉及后端**:
|
||
|
||
1. 删除登录时强制切 BNB 链(`ensureBnbChain`)—— 验签链无关(见 §1.1)。
|
||
2. 桌面登录弹窗简化为「使用浏览器钱包登录」单一主操作;扫码降级为「其他方式」。
|
||
3. 扫码从手机端挪到桌面端。
|
||
4. 手机端「打开钱包 App」死路修复(反馈、未安装兜底)。
|
||
5. 移除/收敛未被登录流程使用的 RainbowKit/WalletConnect 装配(纯前端依赖与体积问题)。
|
||
6. 全站「我的收藏」入口缺失(导航 / 手机菜单 / 钱包下拉加入口)。
|
||
7. 收藏按钮状态视觉、收藏页筛选区移动端密度、空/错误状态打磨。
|
||
8. token 过期时前端自动登出并引导重新登录(消费后端已返回的 401,无需后端改)。
|
||
|
||
---
|
||
|
||
## 4. 给后端的「确认清单」
|
||
|
||
- [ ] §2.1 CORS 是否已允许前端源 + `Authorization` 头?(唯一可能的必做项)
|
||
- [ ] 是否需要 §2.2 服务端登出/撤销?(默认否)
|
||
- [ ] 是否需要 §2.3 可配置 JWT TTL?(默认否,维持 30 天)
|
||
- [ ] 知悉:§3 全部为前端工作,无需后端介入。
|