Commit Graph

49 Commits

Author SHA1 Message Date
erio
c326c6edf1 docs: ZPay 超链接 + 明文 URL 方便复制
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 08:19:20 +08:00
erio
5992c06d67 docs: 同步英文 README,ZPay 链接明文显示,添加 release workflow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 08:17:59 +08:00
erio
90ad0e0895 docs: README 补充易支付协议说明、ZPay 推荐及免责声明
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 08:03:02 +08:00
erio
52aa484202 feat: 列表页占满宽度,充值页保持居中卡片,嵌入模式优化
- maxWidth 新增 'lg' 选项(max-w-6xl),'full' 改为无限制
- 充值页 PC 端使用 'lg',管理后台/我的订单使用 'full' 占满宽度
- 嵌入模式:减小外边距、隐藏装饰光斑、取消 min-h-screen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 05:54:46 +08:00
erio
42da18484c feat: 管理后台订单列表展示用户备注,用户信息摊平显示
- 新增 userNotes 字段,创建订单时从 Sub2API 读取用户 notes 保存
- 管理后台订单列表将用户名、邮箱、备注拆分为独立列,节约行高

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 04:37:39 +08:00
erio
f4709b784f fix: 有 src_host 时隐藏订单页「返回充值」按钮
从 iframe 嵌入(带 src_host)时不显示返回充值按钮,避免用户跳出。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 03:55:26 +08:00
erio
880f0211f3 feat: 管理后台统一 PayPageLayout 布局,支持 dark mode
管理后台使用与充值页面相同的 PayPageLayout 组件,OrderTable 和
OrderDetail 组件新增 dark prop,所有样式支持暗色模式切换。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 03:31:20 +08:00
erio
930ce60fcc fix: 审查修复 — 来源字段长度限制、鉴权超时、支付配置启动校验
- src_host max 253, src_url max 2048
- Sub2API 鉴权请求加 5s AbortController 超时
- initPaymentProviders 启动时校验 ENABLED_PAYMENT_TYPES 与已注册 provider 一致性

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 01:56:22 +08:00
erio
8cf78dc295 fix: frame-ancestors 自动从 SUB2API_BASE_URL 推导,无需手动配置
不再依赖 IFRAME_ALLOW_ORIGINS 手动配置 Sub2API 域名,
自动从 SUB2API_BASE_URL 提取 origin 加入 CSP frame-ancestors。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 01:36:22 +08:00
erio
21cc90a71f feat: 管理后台支持 Sub2API 管理员 token 认证
保留原有 ADMIN_TOKEN 认证,同时支持传入 Sub2API 用户 token,
通过 /api/v1/auth/me 验证 role=admin 身份。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 00:41:27 +08:00
erio
c9462f4f14 feat: 管理后台订单列表显示来源域名(srcHost)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 00:19:01 +08:00
erio
d952942627 feat: 订单来源追踪,保存 src_host / src_url 到订单记录
iframe 嵌入充值页面时 URL 自动附带来源参数,写入数据库用于追踪分析。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:40:16 +08:00
erio
c083880cbc docs+feat: 完善 README 帮助内容配置说明,支持多行文字
- README (中/英) 修正 NEXT_PUBLIC_PAY_HELP_* → PAY_HELP_*
- 新增 PAYMENT_PROVIDERS 配置说明(两步配置服务商+渠道)
- 说明帮助图片支持外部 URL 或本地 uploads/ 两种方式
- PAY_HELP_TEXT 支持 \n 换行,渲染为多行段落
v1.2.6
2026-03-02 04:17:51 +08:00
erio
a9ea9d4862 feat: 帮助图片点击放大(lightbox)
点击支付页右侧帮助区域的联系二维码图片,在屏幕正中以全屏遮罩放大展示;
点击背景或再次点击可关闭。
v1.2.5
2026-03-02 03:39:49 +08:00
erio
e170d5451e fix: 帮助内容改为服务端变量经 API 下发,运行时可配无需重新构建 v1.2.4 2026-03-02 02:46:51 +08:00
erio
e5424e6c5e feat: 显式 PAYMENT_PROVIDERS 配置服务商,缺密钥启动即报错 v1.2.3 2026-03-02 02:04:53 +08:00
erio
310fa1020f fix: loadUserAndOrders 开始时重置 userNotFound,防止状态残留 v1.2.2 2026-03-02 01:23:04 +08:00
erio
85239e97f8 fix: 用户不存在时前端提示错误;修正微信支付图标;beta compose 改用 Docker Hub 镜像 v1.2.1 2026-03-02 01:05:01 +08:00
erio
c6815fc2a3 feat: 插件化支付渠道限额 — provider 自声明单笔/每日默认限额
- PaymentProvider 接口新增 defaultLimits(单笔 singleMax + 每日 dailyMax)
- EasyPay 默认:支付宝/微信各 单笔 ¥1000、每日 ¥10000
- Stripe 默认:不限额(0 = unlimited)
- getMethodDailyLimit / getMethodSingleLimit 优先读 env var,再回退 provider 默认
- queryMethodLimits 返回 singleMax,PaymentForm 按渠道动态调整最大单笔金额
- MAX_DAILY_AMOUNT_* 改为可选 env var 覆盖(不再有硬编码默认值)
v1.2.0
2026-03-01 22:51:09 +08:00
erio
136723b8af feat: 支付渠道每日限额(渠道维度全平台统计)
- config.ts:新增 MAX_DAILY_AMOUNT_ALIPAY/WXPAY/STRIPE(默认 alipay/wxpay 各 1w,stripe 不限)
- lib/order/limits.ts:getMethodDailyLimit + queryMethodLimits 共用工具,支持动态渠道兜底
- order/service.ts:createOrder 校验渠道限额,超限抛 METHOD_DAILY_LIMIT_EXCEEDED
- api/limits/route.ts:公开接口 GET /api/limits,返回各渠道今日用量/剩余/是否可用
- api/user/route.ts:config 响应中加入 methodLimits,前端一次请求即可获取限额状态
- PaymentForm.tsx:额度已满的渠道置灰 + 标注「今日额度已满」,无法选择
- pay/page.tsx:AppConfig 加 methodLimits,传给 PaymentForm,新增错误码映射
v1.1.0
2026-03-01 21:53:09 +08:00
erio
0c2476f340 fix: 无 token 不显示余额;充值完成后立即预取最新余额
- UserInfo.balance 改为可选字段
- 无 token 时不设 balance,PaymentForm 不渲染余额行
- COMPLETED 触发时立即调 loadUserAndOrders 刷新余额
  2.2s 结果页展示期间余额已在后台拉取,回表单时即刻呈现新值
v1.0.1
2026-03-01 21:24:11 +08:00
erio
81b4573edd refactor: 版本号改为以 git tag 为单一来源
- 删除 VERSION 文件
- publish.sh:用 git describe --exact-match 读当前 commit 的 tag
  若无精确 tag 则拒绝构建并打印提示
- tag 支持 v1.2.3 或 1.2.3,推送时自动去掉 v 前缀
- 构建流程:git tag vX.Y.Z → git push origin vX.Y.Z → git pull --tags → bash scripts/publish.sh
v1.0.0
2026-03-01 21:09:47 +08:00
erio
c226b1188d feat: 版本管理 — VERSION 文件 + 构建发布脚本
- VERSION 文件:版本号单一来源(当前 1.0.0)
- docker-compose.hub.yml / app.yml:镜像 tag 改为 \${IMAGE_TAG:-latest}
- scripts/publish.sh:自动读取 VERSION、打双标签(x.y.z + latest)、推送到 Docker Hub
2026-03-01 21:05:51 +08:00
erio
149a08f1a3 docs: 完整中英双语 README + Docker Hub 发布 Compose 文件
- README.md:中文主文档(功能、环境变量、部署、集成说明)
- README.en.md:英文版本,内容与中文对应
- docker-compose.hub.yml:从 Docker Hub 拉取镜像,含自带 PostgreSQL
- docker-compose.app.yml:仅应用容器,适配外部数据库
- 镜像已发布至 touwaeriol/sub2apipay:latest
2026-03-01 20:50:42 +08:00
erio
b4eebb0b1b feat: 分页组件统一封装 + 移动端无限滚动
- 新增 PaginationBar 组件,支持 isDark / loading / 页码导航 / 每页大小切换
- 重写 pay/orders/page.tsx 使用 PaginationBar,summary 来自 API groupBy 全量统计
- admin/page.tsx 替换内联分页 UI 为 PaginationBar
- MobileOrderList 支持无限滚动:IntersectionObserver 哨兵 + hasMore/loadingMore props
- pay/page.tsx 新增 loadMoreOrders(append 模式),初始化/刷新时重置分页状态
2026-03-01 20:12:32 +08:00
erio
292c14b882 feat: 订单列表支持分页查询,分页大小可选 20/50/100
- /api/orders/my 新增 page/page_size 参数,返回分页信息和全局状态统计
- 用户订单页:分页控件(首/上/下/末页)+ 分页大小选择,摘要卡片改为全局统计
- 管理员订单页:分页大小选择器(20/50/100)+ 首尾页跳转按钮
2026-03-01 20:04:49 +08:00
erio
e4005da38e fix: 支付网关失败时返回友好错误信息
捕获支付提供商配置缺失或调用失败,
包装成 PAYMENT_GATEWAY_ERROR 错误码并返回中文提示,
前端同步处理该错误码显示具体原因。
2026-03-01 19:56:41 +08:00
erio
902c4349c2 config: 每日限额默认值改为 10000 2026-03-01 19:49:42 +08:00
erio
4374ca9126 feat: 每日充值限额 + 单笔上限默认 1000 + 前端金额校验优化
- 新增 MAX_DAILY_RECHARGE_AMOUNT 环境变量(0=不限制),
  创建订单时统计当日已付款总额,超限返回友好提示
- MAX_RECHARGE_AMOUNT 默认值从 10000 改为 1000
- PaymentForm 快速金额按钮过滤掉超过 maxAmount 的选项
- 金额超限时前端显示明确提示(单笔最低/最高 ¥xxx)
- 支付说明栏展示每日限额信息
2026-03-01 19:41:44 +08:00
erio
c41933db70 security: 隐私接口全面加固,统一 token 鉴权
- /api/orders/[id] 只返回 id/status/expiresAt,移除 user_name/pay_url 等隐私字段
- /api/orders/[id]/cancel 改为 token 鉴权,服务端验证用户身份后执行取消
- /api/orders (POST 响应) 过滤 userName/userBalance,不向客户端暴露
- /api/user 移除 username/email/balance,只返回 id/status 和 config
- /api/users/[id] 只返回 {id, exists},不暴露任何隐私信息
- pay/page.tsx 恢复从服务端动态获取 config,无 token 时只显示用户 ID
- pay/orders/page.tsx 无 token 时不查询隐私接口,统一按钮样式
- PaymentQRCode 新增 token prop,无 token 时隐藏取消按钮
- 创建订单失败改为中文错误提示
2026-03-01 19:25:14 +08:00
erio
47f609a58d Merge branch 'worktree-feature/stripe' 2026-03-01 18:45:17 +08:00
erio
5a315a8f08 refactor: unify cancel logic with cancelOrderCore and show blocked UI
- Extract cancelOrderCore() shared by user cancel, admin cancel, and timeout expire
- Query payment platform before cancelling: if already paid, run confirmPayment
- Simplify timeout.ts to delegate to cancelOrderCore
- Cancel API returns already_paid outcome for frontend handling
- Show "订单已支付,无法取消" prompt with back button when cancel is blocked
2026-03-01 18:44:49 +08:00
erio
7bb6464d5a fix: cancel order handles already-paid case 2026-03-01 18:16:06 +08:00
erio
5751638f7b fix: handle cancel when order already paid — check status immediately
When cancel API returns error (order already PAID/COMPLETED), immediately
re-poll the order status instead of silently doing nothing. Also check
terminal status before attempting cancel to avoid unnecessary API call.
2026-03-01 18:15:52 +08:00
erio
f089368a29 feat: Stripe payment integration with active timeout cancellation
- Stripe Checkout Session payment flow (new window + polling)
- Payment provider abstraction layer (EasyPay + Stripe unified)
- Webhook signature verification with raw body handling
- Active timeout: query platform status before expiring, recover paid orders
- Frontend: URL validation, anti-duplicate click, responsive Stripe button
- Idempotency keys, amount rounding, async payment event handling
2026-03-01 17:58:45 +08:00
erio
d9ab65ecf2 feat: integrate Stripe payment with bugfixes and active timeout cancellation
- Add Stripe payment provider with Checkout Session flow
- Payment provider abstraction layer (EasyPay + Stripe unified interface)
- Stripe webhook with proper raw body handling and signature verification
- Frontend: Stripe button with URL validation, anti-duplicate click, noopener
- Active timeout cancellation: query platform before expiring, recover paid orders
- Singleton Stripe client, idempotency keys, Math.round for amounts
- Handle async_payment events, return null for unknown webhook events
- Set Checkout Session expires_at aligned with order timeout
- Add cancelPayment to provider interface (Stripe: sessions.expire, EasyPay: no-op)
- Enable stripe in frontend payment type list
2026-03-01 17:58:08 +08:00
erio
2f45044073 refactor: extract pay page components and migrate zpay → easypay
Components:
- Add PayPageLayout, OrderFilterBar, MobileOrderList, OrderTable, OrderSummaryCards
- Extract shared pay-utils (types, constants, helper functions)
- Simplify pay/page.tsx and orders/page.tsx

EasyPay migration:
- Remove src/lib/zpay/, api/zpay/notify, zpay test, zpay.md
- Simplify config.ts: single envSchema, no ZPAY_* fallback
- Rename DB field zpay_trade_no → payment_trade_no (migration added)
- Update OrderDetail label: ZPAY订单号 → 支付单号
- Update CLAUDE.md project structure
2026-03-01 15:55:43 +08:00
erio
d2e856b89c fix: align pay page header layout to match orders page 2026-03-01 15:00:27 +08:00
erio
04abbf1dd1 fix: add refresh+orders to header, remove 订单中心 card 2026-03-01 14:53:00 +08:00
erio
8656f1ab8f fix: move refresh+orders buttons into 订单中心 card, remove from header 2026-03-01 14:41:05 +08:00
erio
3052886ca1 fix: add refresh button next to 我的订单 in desktop header 2026-03-01 14:36:56 +08:00
erio
dadf7b228f fix: remove dead zpay/client, fix zpay notify route type imports 2026-03-01 14:27:49 +08:00
erio
9c80d519b1 fix: correct import name ZPayNotifyParams -> EasyPayNotifyParams 2026-03-01 14:25:12 +08:00
erio
07dfd06775 fix: suppress type error in pickRequired/pickOptional helpers 2026-03-01 14:23:42 +08:00
erio
75f521e2cd fix: add dark prop to OrderStatus component 2026-03-01 14:22:17 +08:00
erio
e0ea57cfc3 fix: add qrcode dependency missing from package.json 2026-03-01 14:20:14 +08:00
erio
ceb09659f8 feat: add refresh button to orders panel and admin page
- Desktop orders card in pay/page.tsx: refresh button next to "订单中心"
- Admin orders page: refresh button next to the page title
2026-03-01 14:17:18 +08:00
erio
98f7912131 feat: add payment icons missing from master branch
Bring alipay and wxpay SVG icons from the main branch — these are
referenced by PaymentQRCode but were absent in master.
2026-03-01 13:55:06 +08:00
erio
d5719bf213 feat: migrate payment provider to easy-pay, add order history and refund support
- Replace zpay with easy-pay payment provider (new lib/easy-pay/ module)
- Add order history page for users (pay/orders)
- Add GET /api/orders/my endpoint to list user's own orders
- Add GET /api/users/[id] endpoint for sub2api user lookup
- Add order status tracking module (lib/order/status.ts)
- Update config to support easy-pay credentials (merchant ID, key, gateway)
- Update PaymentForm and PaymentQRCode components for easy-pay flow
- Update pay page and admin page with new order management UI
- Update order service to support easy-pay, cancellation, and refund
2026-03-01 03:04:24 +08:00