'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
```