# zsAPI 一键部署 · 完整教程

> OpenAI 兼容 API 平台（中转站）：网关转发 + 用户/分组/倍率计费 + 充值 + 卡密 + 模型广场 + 管理后台。
> 本教程按顺序做就行，每一步都写了「点哪里、填什么、怎么验证」。

---

## 0. 准备什么

| 项目 | 要求 | 说明 |
|---|---|---|
| 服务器 | Ubuntu 20.04/22.04/24.04 或 Debian 11/12，1核1G 起 | 必须是 **root** 权限；建议 2核2G 以上（要编译） |
| 域名 | 可选，**强烈建议** | 用于 HTTPS、支付回调、发信 |
| 上游 API | 必需 | 你从别处买/自己有的 OpenAI 兼容接口（base_url + key） |
| 磁盘 | ≥ 8G 可用 | 源码 + Go 工具链 + node_modules |

域名解析：在域名服务商把 `api.你的域名.com` 解析到服务器 IP（A 记录），**先解析再部署**，脚本就能顺便把 HTTPS 证书签好。

---

## 1. 部署（两条命令）

SSH 登录服务器，以 root 执行：

```bash
curl -fsSL https://deploy.0lt.top/zsapi.sh -o zsapi.sh
bash zsapi.sh
```

脚本会依次问你 4 个问题（直接回车 = 用括号里的默认值）：

1. 站点域名 → 填 `api.你的域名.com`，没有就回车（只能用 IP 访问）
2. 站点名称 → 显示在导航栏和首页，例如 `XX API`
3. 管理员用户名 → 默认 `admin`
4. 管理员密码 → 回车会自动生成一个随机密码

然后等 5～15 分钟。脚本自动完成：

```
装 nginx / php-cli / curl / python3
装 Go 1.25+、Node 22（已装过就跳过）
下载源码 → 建数据库（SQLite）→ 编译后端 → 编译前端
生成 /etc/zsapi/app.php 配置
注册 systemd 服务 zsapi-go（开机自启）
写好 nginx 站点、启动
域名解析正确的话，自动申请 Let's Encrypt 证书并强制 HTTPS
```

结束时屏幕上会打印**站点地址、管理员账号密码**，请立刻记下来。

> 想一步不落地自动化（不问答）：
> ```bash
> DOMAIN=api.example.com SITE_NAME="我的API" ADMIN_PASS='自己设的密码' bash zsapi.sh --yes
> ```

**验证**：浏览器打开站点地址，能看到落地页 = 成功。

---

## 2. 首次登录 & 后台地图

用管理员账号登录后，直接访问这些地址（都是只有管理员能看）：

| 地址 | 作用 |
|---|---|
| `/system-settings` | 系统设置：站点标题、开放注册、签到、维护公告 |
| `/channels` | 渠道管理：添加上游、获取模型、测试连通 |
| `/models` | 模型配置：对外模型名、价格、动态计费 |
| `/groups` | 分组管理：分组 = 用户能看到哪些模型 + 倍率 |
| `/users` | 用户管理：改余额、改分组、封禁 |
| `/cards` | 卡密管理：生成充值卡密 |
| `/packages` | 套餐管理：包月/包量套餐 |
| `/codex` | Codex 账号池（可选，共享 ChatGPT 号池用） |
| `/channel-status` | 渠道状态：各渠道成功率统计 |

普通用户页面：`/keys`（API Key）、`/wallet`（余额充值）、`/model-plaza`（模型广场）、`/playground`（在线体验）、`/settings`（账号设置）。

---

## 3. 配置网站名称（站名 / 公告 / 注册）

打开 `/system-settings`：

| 字段 | 说明 |
|---|---|
| **站点标题** | 导航栏、标签页标题显示的名字 |
| **开放注册** | 关掉后新用户不能注册（老用户仍可登录） |
| 邀请注册奖励（元） | 老用户拉新，邀请人拿多少余额 |
| 每日签到 / 签到奖励 | 用户每天领余额，用来留人 |
| 所有模型最低价 | 防止把价格设得过低（默认 0.001） |
| 计划维护 | 填开始/结束时间 + 公告文字，到点自动进维护页 |
| 永久停服 | 一般不用管 |

改完点右下 **保存设置**，刷新页面就能看到新站名。

---

## 4. 配置网站 LOGO 和标签页图标

LOGO 就是前端 `public/favicon.png`（导航栏和启动页都用它）。**两种改法，选一种**：

**方法 A：不想重新编译（最快，推荐新手）**

```bash
# 1. 把你自己的 512x512 PNG 传到服务器，替换产物里的图标
cp 你的logo.png /opt/zsapi-vue/dist/favicon.png
cp 你的logo.ico /opt/zsapi-vue/dist/favicon.ico     # ico 可选

# 2. 顺手改标签页标题（把「API 平台」换成你的站名）
sed -i 's#<title>.*</title>#<title>你的站名</title>#' /opt/zsapi-vue/dist/index.html

# 3. 浏览器强刷（Ctrl+F5）即可看到
```

> 注意：以后如果重新 `npm run build`，dist 会被覆盖，上面的改动会丢，要重做或改用方法 B。

**方法 B：改源码重新编译（一劳永逸）**

```bash
# 1. 替换源码里的图标
cp 你的logo.png /opt/zsapi-vue/public/favicon.png
cp 你的logo.ico /opt/zsapi-vue/public/favicon.ico

# 2. 改标签页标题
sed -i 's#<title>.*</title>#<title>你的站名</title>#' /opt/zsapi-vue/index.html

# 3. 重新编译（约 30 秒）
cd /opt/zsapi-vue && npm run build
```

---

## 5. 接入上游渠道 + 模型（中转站的核心）

中转站的本质：**用户拿你的 key 调你的站 → 你转手调上游的 API → 赚差价**。所以先要有上游。

### 5.1 添加渠道

打开 `/channels` → 顶部「添加渠道」：

| 字段 | 填什么 |
|---|---|
| 名称 | 自定义，例如 `OpenAI 官方`、`XX专线` |
| 上游地址 | 上游 base_url，例如 `https://api.openai.com`（不要带 `/v1`） |
| 上游 Key | 上游给你的 sk-xxx |
| 分组 | 勾选这个渠道要给哪些分组用（详见 5.3） |

点保存。然后在「渠道列表」里：

1. 点该渠道的 **获取模型** → 自动拉取上游支持的模型列表
2. 点 **测试** → 选一个模型发一条测试请求，确认通（失败会显示上游报错原文）

### 5.2 配置对外模型和价格

打开 `/models`：会列出刚拉到的模型。

| 字段 | 说明 |
|---|---|
| 对外名 | 用户实际调用的模型名，可以改名（例如把 `gpt-4o-mini` 对外叫 `gpt-4o-mini`） |
| 官方参考名 | 用来匹配官方价（点页面右上「批量刷新官方价」自动填） |
| 输入价 / 输出价 / 缓存价（元/百万token） | 你的售价，比上游成本高就是利润 |
| 动态计费 | 可选：按时间段/Token 量做阶梯价 |

改完点 **保存全部**。

### 5.3 分组与倍率

打开 `/groups`：分组决定「用户能用哪些模型、按几倍计费」。

- 新建分组：填名称（例如 `默认分组`、`高级分组`）+ 计费倍率（1.0 = 不打折，0.5 = 五折，越低越便宜）
- 分组可以设上级分组（做成层级）
- 「隐藏」的分组不出现在模型广场，但用户仍可用（适合内部专用）
- **渠道和模型都要挂到分组上，用户才能调用**（渠道页面勾选分组、模型页面选分组）

最后：把用户分到对应分组（`/users` 里改用户的 group）。

### 5.4 自测一遍

1. `/keys` 页面给自己建一个 API Key
2. 用 curl 试：

```bash
curl https://你的域名/v1/chat/completions \
  -H "Authorization: Bearer 你的key" \
  -H "Content-Type: application/json" \
  -d '{"model":"对外模型名","messages":[{"role":"user","content":"你好"}]}'
```

返回正常内容 = 中转链路通了。也可以直接站内 `/playground` 在线试。

---

## 6. 配置易支付（收款，充值时用到）

易支付是「聚合支付」：一次接入，支持支付宝/微信扫码。下面以标准易支付（`submit.php` 接口）为例。

### 6.1 先拿到三个值

去易支付平台（你买的那个）注册商户 → 商户后台找：

- **接口地址**：形如 `https://pay.xxx.com/submit.php`
- **商户 ID（pid）**：一串数字
- **商户密钥（key）**：一串字母数字（**不要泄露**）

### 6.2 写进配置文件

编辑 `/etc/zsapi/app.php`：

```bash
nano /etc/zsapi/app.php
```

找到易支付那几行，填上（注意保持引号）：

```php
    'vmq_submit'    => 'https://pay.xxx.com/submit.php',
    'vmq_epay_key'  => '你的商户密钥',
    'vmq_notify'    => '',                       // 留空即可，用下面的 public_base_url 自动拼
    'public_base_url' => 'https://你的域名',      // 必须是公网能访问的 https 地址
```

保存退出（nano 是 `Ctrl+O` 回车 → `Ctrl+X`），然后重启后端：

```bash
systemctl restart zsapi-go
```

### 6.3 在易支付后台设置回调

在易支付商户后台填「异步通知地址 / 回调地址」：

```
https://你的域名/api/payment/notify
```

（有些易支付平台要求回调地址不带下划线，那台机器上也可以用 `https://你的域名/payment/vmq-notify`，效果一样。）

### 6.4 验证

1. 用一个普通账号打开 `/wallet` → 充值 1 元 → 会跳到支付页
2. 付完回来余额应该 +1；到账逻辑在 `/api/payment/orders` 里能查到订单
3. 没到账就看日志：`tail -f /var/log/zsapi-go.log`（会打印回调内容）

> 也支持其它通道，都在同一个文件里（留空 = 不启用）：
> `izf_*`（第二套易支付）、`alipay_*`（支付宝当面付，需企业资质）、
> `zsso_*` / `wskme_*`（第三方码支付，需要对方提供 host/key）。
> **没填的项一律不影响运行，不用担心。**

---

## 7. 配置邮件（注册验证码 / 找回密码）

不配邮件，注册/找回密码的验证码就发不出去。推荐 **Resend**（HTTP 发信，服务器不用装邮件服务）：

1. 去 resend.com 注册 → 添加并验证你的域名（加几条 DNS 记录）
2. 创建 API Key（`re_` 开头）
3. 编辑 `/etc/zsapi/app.php`：

```php
    'resend_key'  => 're_你的key',
    'resend_from' => 'API Platform <noreply@你的域名>',   // 域名必须是 Resend 里验证过的
```

4. `systemctl restart zsapi-go`，然后注册一个测试账号收验证码。

> 调试不想真发信：把 `'mail_dryrun' => '1'`，验证码会写进 `/var/log/zsapi-go.log`。
> 也可以用 SMTP：填 `smtp_host / smtp_port / smtp_user / smtp_pass / smtp_from` 即可。

---

## 8. 开放注册 & 给用户发 Key

1. `/system-settings` → 打开「开放注册」（想控制人数就关掉，用邀请制）
2. 用户注册后，在 `/keys` 自己建 Key（Key 只在创建时显示一次）
3. 余额来源：`/cards` 生成卡密给用户兑换，或者用户在 `/wallet` 在线充值
4. 想送额度：`/users` 里直接改用户余额

---

## 9. 运维速查

```bash
systemctl status zsapi-go          # 服务状态
systemctl restart zsapi-go         # 重启后端（改完 app.php 必须执行）
tail -f /var/log/zsapi-go.log      # 实时日志
nginx -t && systemctl reload nginx # 检查并重载网站配置

# 改后端代码后重新编译
cd /opt/zsapi-go && go build -o zsapi-go-server . && systemctl restart zsapi-go

# 改前端后重新编译
cd /opt/zsapi-vue && npm run build

# 备份数据库（重要！）
cp /opt/zsapi/data/zsapi.sqlite ~/zsapi-$(date +%F).sqlite
```

升级/重装：再次运行 `bash zsapi.sh` 会因检测到已有目录而停止；要覆盖就加 `FORCE=1`（**会覆盖后端/前端目录，数据库不动**）。

| 路径 | 内容 |
|---|---|
| `/opt/zsapi-go` | 后端源码 + 二进制 |
| `/opt/zsapi-vue` | 前端源码 + `dist` 产物 |
| `/opt/zsapi/data/zsapi.sqlite` | 数据库（用户/渠道/key/订单都在这） |
| `/etc/zsapi/app.php` | 配置（支付、邮件、短信） |
| `/var/log/zsapi-go.log` | 后端日志 |

---

## 10. 常见问题

**Q：打不开网站？**
`systemctl status zsapi-go` 和 `nginx -t`；再看 `/var/log/zsapi-go.log`。多半是 nginx 或后端没起来。

**Q：能登录但不能调用模型？**
99% 是权限链没配通：上游渠道是否勾了分组 → 模型是否挂到分组 → 用户是否在该分组。去 `/channel-status` 看渠道成功率。

**Q：调用报 401/上游错误？**
上游 Key 过期或余额不足。`/channels` 里点「测试」，它会带回上游的原始报错。

**Q：充值不到账？**
看日志里的回调记录；确认易支付后台的回调地址是 `https://你的域名/api/payment/notify`，且域名是 HTTPS、公网可达。回调地址填错是最常见原因。

**Q：没有域名能用吗？**
能，但支付回调、邮件链接会不正常，也不会有 HTTPS。建议尽快加域名，然后改 `public_base_url` 并跑 `certbot --nginx -d 你的域名`。

**Q：怎么改端口 / 加内存优化？**
后端固定监听 `127.0.0.1:8026`（只对本机开放，外部只能经 nginx 访问），一般不用改。

**Q：想换成自己的品牌名 / 配色？**
站名在 `/system-settings`；LOGO 见第 4 节；整体配色改 `/opt/zsapi-vue/src/styles/main.css` 里的 CSS 变量（`--primary` 等）后重新 `npm run build`。

---

*部署脚本：`https://deploy.0lt.top/zsapi.sh` ｜ 源码包：`https://deploy.0lt.top/zsapi-deploy.tar.gz`*
