's'调试支付

This commit is contained in:
eric
2026-03-08 06:43:48 -05:00
parent b99fba1c5a
commit 1f4473cb04
35 changed files with 1794 additions and 178 deletions

178
docs/SERVICES.md Normal file
View File

@@ -0,0 +1,178 @@
# 服务配置说明
支付、PocketBase、MinIO 存储已组件化、配置化,可通过环境变量和主题配置覆盖。
## 配置入口
- **`config/services.config.ts`** - 服务配置
- **`config/site.config.ts`** - 主题可覆盖 `services` 字段
## PocketBase
### 环境变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `NEXT_PUBLIC_POCKETBASE_URL` | 客户端可见的 PB 地址 | https://pocketbase.hackrobot.cn |
| `POCKETBASE_URL` | 服务端 PB 地址 | 同上 |
| `POCKETBASE_JOIN_COLLECTION` | 申请表单集合名 | solan |
| `POCKETBASE_EMAIL` | 管理员邮箱(创建记录用) | - |
| `POCKETBASE_PASSWORD` | 管理员密码 | - |
### 主题覆盖
`config/site.config.ts``THEME_CONFIGS[theme].services` 中:
```ts
services: {
pocketbaseJoinCollection: "solan", // 申请/加入表单集合
},
```
### 使用方式
```ts
import { pbLogin, pbRegister, pbSaveAuth, pbLogout, getStoredUserEmail } from "@/app/lib/pocketbase";
// 登录
const result = await pbLogin(email, password);
pbSaveAuth(result.token, result.record);
// 注册
const result = await pbRegister(email, password, passwordConfirm);
pbSaveAuth(result.token, result.record);
// 登出
pbLogout();
// 获取当前用户邮箱
const email = getStoredUserEmail();
```
## 支付
### 环境变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `PAYMENT_API_URL` | payjsapi 地址 | 开发: 127.0.0.1:8700 / 生产: api.hackrobot.cn |
| `PAYMENT_PROVIDER` | 支付提供商 | zpay |
| `PAYMENT_DEFAULT_AMOUNT` | 默认金额(分) | 80 |
| `PAYMENT_DEFAULT_TYPE` | 默认订单类型 | meetup |
| `ZPAY_SUBMIT_URL` | ZPAY 提交地址 | https://zpayz.cn/submit.php |
### 主题覆盖
`config/site.config.ts``THEME_CONFIGS[theme].services` 中:
```ts
services: {
join: {
amount: 80, // 加入费用(分)
type: "meetup", // 订单类型
},
},
```
### 使用方式
```ts
import {
getPayEnv,
getRecommendedChannel,
mustUseWxPay,
redirectToPay,
getDeviceFromEnv,
} from "@/app/lib/payment";
// 检测支付环境
const env = getPayEnv(); // "pc" | "h5" | "wechat"
const channel = getRecommendedChannel(env);
const device = getDeviceFromEnv(env);
// 发起支付跳转(加入场景,使用主题配置)
redirectToPay({
user_id: userId,
return_url: returnUrl,
channel,
device,
useJoinConfig: true, // 使用主题的 amount/type
});
```
## MinIO 存储
### 环境变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `MINIO_ENDPOINT` | 服务端点 | minioweb.hackrobot.cn |
| `MINIO_PORT` | 端口 | 9035 |
| `MINIO_USE_SSL` | 是否使用 SSL | false |
| `MINIO_BUCKET` | 存储桶 | hackrobot |
| `MINIO_ACCESS_KEY` | Access Key | - |
| `MINIO_SECRET_KEY` | Secret Key | - |
| `MINIO_REGION` | 区域 | china |
| `MINIO_PUBLIC_URL` | 公开访问 URL | https://{endpoint}/{bucket} |
| `MINIO_UPLOAD_PREFIX` | 上传路径前缀 | joins |
### 主题覆盖
`config/site.config.ts``THEME_CONFIGS[theme].services` 中:
```ts
services: {
minio: {
bucket: "my-bucket", // 存储桶
uploadPrefix: "joins", // 上传路径前缀
},
},
```
### 使用方式
```ts
import {
getMinioClient,
uploadBuffer,
generateObjectKey,
} from "@/app/lib/minio";
// 上传文件
const objectKey = generateObjectKey("jpg");
const { url } = await uploadBuffer(buffer, objectKey, "image/jpeg");
// 获取客户端(高级用法)
const client = getMinioClient();
```
## API 路由
- **`/api/join`** - 使用 `getPocketBaseConfig()` 和主题的 `pocketbaseJoinCollection`
- **`/api/pay`** - 使用 `getPaymentConfig()``getJoinPaymentConfig()`
- **`/api/pay/status`** - 使用 `getPaymentConfig()`
- **`/api/upload-media`** - 使用 `getMinioConfig()` 和主题的 `minio` 配置
## 目录结构
```
config/
services.config.ts # 服务配置
site.config.ts # 主题配置(含 services 覆盖)
app/lib/
pocketbase/
auth.ts # 认证login/register/logout
constants.ts # 存储 key
config.ts # 配置导出
index.ts
payment/
client.ts # redirectToPay
config.ts # 配置导出
types.ts # PayChannel, PayEnv
index.ts # 聚合 payEnv
minio/
config.ts # 配置导出
client.ts # getMinioClient, uploadBuffer, generateObjectKey
index.ts
```

154
docs/TEMPLATE.md Normal file
View File

@@ -0,0 +1,154 @@
# 站点模板使用指南
本项目已配置化为可复用模板可快速克隆并替换为不同主题数字游民、一人公司、TikTok 运营、独立开发等)。
## 目录结构
```
config/ # 配置层
site.config.ts # 主题配置(切换主题只需改 CURRENT_THEME
index.ts
content/themes/ # 内容层 - 按主题组织
digital-nomad/ # 数字游民主题
messages/
zh.json # 中文文案
en.json # 英文文案
data/
tools.json # 工具数据
app/ # 应用层 - 组件与页面
components/ # 通用 UI 组件
[locale]/ # 多语言路由
lib/
theme-data.ts # 主题数据加载器
```
## 切换主题
### 方式一:环境变量
```bash
# .env.local
NEXT_PUBLIC_THEME=solo-company
```
### 方式二:修改配置
编辑 `config/site.config.ts`
```ts
export const CURRENT_THEME: ThemeId =
(process.env.NEXT_PUBLIC_THEME as ThemeId) || "solo-company"; // 改默认值
```
## 新增主题步骤
### 1. 添加主题配置
`config/site.config.ts``THEME_CONFIGS` 中添加:
```ts
"your-theme-id": {
id: "your-theme-id",
name: "你的主题名",
nameEn: "Your Theme Name",
tagline: "一句话描述",
taglineEn: "Tagline in English",
meta: {
title: "站点标题 | Site Title",
description: "SEO 描述",
},
features: {
roadmap: true,
tools: true,
community: true,
join: false,
course: false,
ebook: true,
},
colors: { primary: "sky", accent: "amber" },
},
```
`THEME_IDS` 数组中添加 `"your-theme-id"`
### 2. 创建主题内容
复制 `content/themes/digital-nomad/``content/themes/your-theme-id/`
```
content/themes/your-theme-id/
messages/
zh.json # 修改为你的中文文案
en.json # 修改为你的英文文案
data/
tools.json # 修改为你的工具数据
```
### 3. 注册数据加载
`app/lib/theme-data.ts``getThemeMessages``getThemeToolsData` 的 switch 中添加:
```ts
case "your-theme-id": {
const mod = locale === "zh"
? await import("@/content/themes/your-theme-id/messages/zh.json")
: await import("@/content/themes/your-theme-id/messages/en.json");
return mod.default;
}
```
## 文案结构 (messages)
参考 `content/themes/digital-nomad/messages/zh.json`
- `common` - 站点名、导航、按钮等
- `hero` - 首页主视觉
- `features` - 特性介绍
- `roadmap` - 学习路径、天数、电子书、课程
- `tools` - 工具区块
- `community` - 社区区块
- `footer` - 页脚
- `auth` - 登录注册
## 工具数据 (tools.json)
```json
{
"categories": [
{
"id": "category-id",
"icon": "🔧",
"title": "分类名",
"color": "from-sky-500 to-cyan-500",
"bg": "bg-sky-50",
"text": "text-sky-700",
"tools": [
{ "name": "工具名", "desc": "描述", "href": "https://..." }
]
}
]
}
```
## 7 天学习路径 (days)
Day 内容当前在 `app/data/days.ts`,后续可迁移到 `content/themes/[theme]/data/days.json` 实现按主题切换。
## 服务配置支付、PocketBase
详见 [docs/SERVICES.md](./SERVICES.md)。支付和 PocketBase 已配置化,可通过环境变量和主题 `services` 覆盖。
## 功能开关 (features)
在主题配置中可关闭某些模块:
- `roadmap` - 7 天学习路径
- `tools` - 工具推荐
- `community` - 社区区块
- `join` - 加入社区页
- `course` - 课程页
- `ebook` - 电子书
(功能开关的 UI 条件渲染待接入)