搜 索

agent订阅转 API 从入门到放弃

  • 9阅读
  • 2026年10月03日
  • 0评论
首页 / AI/大数据 / 正文

0. 起因:一个订阅,养活一群 app

事情是这样的。

手上有一个 ChatGPT 订阅,平时用 Codex 写代码用得挺爽。但人一旦闲下来就容易犯错:我手上还躺着好几个半成品 app,每个都想接个大模型。去官方开 API key 吧,按 token 计费,钱包隐隐作痛;不开吧,订阅里那堆额度每周刷新,不用白不用。

于是一个危险的念头冒了出来:能不能把订阅转成 API,部署在一台 Linux 服务器上,给我所有 app 的后端统一调用?

紧接着第二个念头:订阅额度总有用完的时候,到时候总不能所有 app 一起躺平吧? 得有个便宜的备胎顶上,还得让用户知道"现在是省钱模式",也得让我自己知道"该充钱了"。

一搜,订阅转 API 社区里早就有两条路:

  • sub2api:走 Codex 官方客户端的 OAuth 通道,做成 API 网关
  • web2api(以及 chat2api、webchat2api 这一大家子):走网页版 ChatGPT,把浏览器会话包装成 API

本文分两部分:前半部分是两者的选型,后半部分是我自己写的一个降级网关,订阅用完自动切 DeepSeek,顺便到处哭穷。先剧透结论:多 app 后端场景选 sub2api,前面再套一层降级网关。

1. 先搞清楚两者到底在"转"什么

很多人把它们当成同一类东西,其实上游完全不同。

1.1 sub2api:伪装成"官方客户端"

ChatGPT 订阅(Plus / Pro)登录 Codex CLI 或 Codex Desktop 之后,走的是一条 OAuth + Responses 的专用通道,额度按订阅的窗口(5 小时 / 7 天)计算。sub2api 做的事情,就是拿着这个 OAuth 凭据,在服务端代替官方客户端去请求上游,然后对外暴露一个标准的 OpenAI 兼容接口。

flowchart LR A1[App A 后端] -->|key-A| G A2[App B 后端] -->|key-B| G A3[App C 后端] -->|key-C| G subgraph G[sub2api 网关] K[API Key 鉴权与限额] --> S[账号调度 / 故障转移] S --> U[用量统计] end S -->|Codex OAuth| O1[ChatGPT 账号 1] S -->|Codex OAuth| O2[ChatGPT 账号 2 可选] O1 --> UP[(OpenAI Codex 上游)] O2 --> UP

它的本质是一个API 网关:多账号号池、按 key 分发、计量、故障切换,这些都是网关该干的活。

1.2 web2api:远程遥控一个浏览器

web2api 这一派的思路更"物理":你在 Chrome 里登录 ChatGPT,工具通过扩展或者逆向网页接口,把你的提问塞进网页、再把回答抠出来。

flowchart LR APP[App 后端] -->|OpenAI 兼容请求| L[本地 companion 服务] L --> EXT[Chrome 扩展] EXT --> TAB[ChatGPT 网页标签页] TAB -->|网页会话 Cookie| WEB[(chatgpt.com)] WEB -.->|Turnstile / 风控| TAB

注意这里的上游是 chatgpt.com 网页,不是 Codex 通道。它消耗的是网页对话那份额度,全程要过网页那一套风控,而且需要一个真实的、登录着的浏览器。

2. 正面对比

维度sub2apiweb2api 一派
上游Codex OAuth 通道ChatGPT 网页会话
部署Docker / 单二进制,适合扔服务器依赖一个开着的 Chrome,更像本机工具
并发号池调度 + 故障转移基本靠标签页,近似串行
多 app 管理每个 app 发独立 key,分组、限额、统计基本没有
流式 / 工具调用原生 Responses 链路网页模拟,部分实现把 tool call 拼成普通文本
风控压力跟随官方客户端特征Turnstile、网页改版,随时可能挂
适合谁后端服务、多应用共享个人本机脚本、尝鲜

几个点展开说一下。

部署形态决定了生死。 后端服务要的是 7×24 在线、能重启、能水平扩。web2api 依赖一个真实的浏览器会话,你总不能在 Linux 服务器上常驻一个登录状态的 Chrome 还指望它不出事。sub2api 一个 docker compose up 就完事。

工具调用是硬伤。 我的 app 后端大量依赖 function calling 和结构化输出。网页上根本没有"工具调用"这个概念,web 方案只能把 tool_calls 和 role=tool 的消息转成一段普通文本喂给模型,再从回答里解析。玩具场景能跑,生产环境里这就是一颗定时炸弹。

多 app 共享需要网关能力。 几个 app 共用一份额度,最怕某个 app 写了个死循环把额度一口气烧光,其他 app 全部陪葬。这需要按 key 限额、按 app 统计,这恰恰是 sub2api 的本职工作。

3. 决策树

flowchart TD Q1{用在哪里?} -->|服务器后端 / 多个 app| SUB[sub2api] Q1 -->|本机脚本 / 偶尔玩玩| Q2{手上是什么订阅?} Q2 -->|ChatGPT 走 Codex / Claude Code / Gemini CLI| SUB Q2 -->|只想用网页版 ChatGPT / Gemini / Grok| WEB[web2api] SUB --> Q3{这个 app 要对外正式服务吗?} Q3 -->|是 / 关键链路| API[老老实实用官方 API key] Q3 -->|否 / 个人项目| OK[sub2api + 降级网关]

4. 在 Linux 上部署 sub2api

4.1 用 Docker 部署

sub2api 依赖 PostgreSQL 和 Redis。官方的一键脚本只装 sub2api 本体,数据库要你自己准备;Docker 方案会把 PostgreSQL 和 Redis 一起拉起来,省心很多,我选后者:

mkdir -p /opt/sub2api && cd /opt/sub2api
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash

脚本会生成 docker-compose.yml 和 .env,并自动生成 JWT、TOTP、数据库密码这些密钥。启动之前先改一个地方:

# .env
BIND_HOST=127.0.0.1   # 默认是 0.0.0.0,务必改掉
SERVER_PORT=8080

为什么必须改?这是 Linux 上一个经典大坑:Docker 发布的端口会绕过 ufw。你以为 ufw deny 8080 就安全了,实际上 Docker 自己改了 iptables,8080 照样对公网敞开。绑到 127.0.0.1,从根上解决。

docker compose up -d
docker compose logs -f sub2api
⚠️ GitHub 上 fork 一大堆,有的还在 README 里夹带各种中转站广告。认准 Wei-Shaw/sub2api,官方声明只用 sub2api.org 和 pincc.ai 两个域名。

4.2 通过 SSH 隧道进后台

管理后台不对公网开放,本机开个隧道访问:

ssh -L 8080:127.0.0.1:8080 user@your-server
# 然后浏览器打开 http://127.0.0.1:8080

首次进入是设置向导(数据库、Redis、管理员账号)。之后大致三步:

  1. 添加上游账号:选 Codex / OpenAI OAuth,用 ChatGPT 账号完成授权。
  2. 建分组:把账号放进分组,分组决定可用模型和调度策略。
  3. 给每个 app 发一个 key:一个 app 一个 key,各自设限额。千万别所有 app 共用一个 key,出事了你都不知道是谁干的。

到这里,sub2api 已经能用了。但我的 app 不直接连 sub2api,中间还要再隔一层,下面细说。

5. 订阅用完了怎么办:穷鬼网关 qiong-gateway

5.1 需求

ChatGPT 订阅的额度是窗口制的,5 小时窗口或者 7 天窗口用完,sub2api 也变不出额度来。我想要的是:

  1. 自动降级:订阅额度用完,自动切到便宜的官方 API(DeepSeek),业务不中断
  2. 提示用户:app 能知道当前是"省钱模式",给用户展示一句说明
  3. 提示自己:手机上收到通知"订阅用完了""DeepSeek 余额也快没了"
  4. 体面停机:DeepSeek 也没钱了,返回一个明确的错误,而不是一堆莫名其妙的 502
  5. 自动恢复:订阅窗口重置后,自动切回来

5.2 为什么不让每个 app 自己 try/catch

最直觉的做法是每个 app 自己捕获 429,然后改调 DeepSeek。我想了想,放弃了:

  • 重复实现:N 个 app 写 N 遍降级逻辑,Java、Go、Python 各来一遍
  • 状态不共享:订阅用完之后,每个 app 都要自己撞一次墙才知道,每次请求都先白跑一趟
  • 通知轰炸:N 个 app 各发一遍"没钱了",手机直接炸了
  • 密钥扩散:DeepSeek key 要分发到每个 app,这是在花真金白银的 key

所以集中处理:在 sub2api 前面加一层很薄的网关,所有 app 只认这一个地址。

flowchart LR subgraph Apps[各个 app 后端] A1[App A] A2[App B] A3[App C] end Apps -->|HTTPS| NG[Nginx] NG --> QG[qiong-gateway :9000] QG -->|主通道| S2A[sub2api :8080] S2A -->|Codex OAuth| GPT[(ChatGPT 订阅)] QG -.->|降级通道| DS[(DeepSeek 官方 API)] QG -.->|状态变化| NT[ntfy / Telegram] QG -.->|定时巡检余额| DS

5.3 三档状态

整个网关的核心就是一个三档状态机:

stateDiagram-v2 [*] --> normal normal --> budget: 订阅号池耗尽 budget --> normal: 冷却后重试主通道成功 budget --> broke: DeepSeek 返回 402 余额不足 broke --> budget: 余额恢复 broke --> normal: 订阅窗口重置 note right of normal: 走 ChatGPT 订阅 note right of budget: 走 DeepSeek,提示用户省钱模式 note right of broke: 直接返回 503 budget_exhausted
  • normal:一切正常,走订阅
  • budget:订阅用完,DeepSeek 顶班
  • broke:DeepSeek 也没钱了,所有 AI 功能暂停

每次档位变化发一条通知,只在变化时发,不会每个请求都轰炸一次。

5.4 怎么判断"订阅用完了"?我去翻了 sub2api 源码

降级网关最关键的问题是:sub2api 返回一个错误,到底是订阅用完了,还是网络抖了一下,还是请求本身有问题?判断错了,要么白花 DeepSeek 的钱,要么该降级的时候没降级。

我翻了一下 sub2api 的源码(2026 年 10 月的 main 分支),总结出这张表:

sub2api 返回含义网关动作
503 + No available accounts号池里的账号全被限流或不可用,也就是订阅用完了全局降级到 budget
429 + Upstream rate limit exceededOpenAI 上游限流,带 Retry-After全局降级,冷却时间取 Retry-After
502 + Upstream access forbidden / authentication failed上游拒绝访问,账号可能出事了全局降级 + 发告警
其他 429某个 app 自己的 key 限额到了,或者排队满了仅本次请求走 DeepSeek
其他 5xx / 连不上sub2api 自己出问题仅本次走 DeepSeek,连续 5 次发告警
其他 4xx请求本身有问题原样返回,不降级

最后一条很重要:请求本身错了,换个模型也救不了,别浪费钱。

对应的代码:

// classify 依据 sub2api 的错误响应判断该怎么降级。
// 文案匹配基于 2026 年 10 月的 sub2api 源码,升级后记得复查。
func classify(resp *http.Response, errBody []byte, err error) attempt {
    if err != nil {
        return upstream
    }
    if resp.StatusCode < 400 {
        return ok
    }
    msg := string(errBody)
    switch {
    case strings.Contains(msg, "No available accounts"),
        strings.Contains(msg, "Upstream rate limit exceeded"):
        return quota
    case strings.Contains(msg, "Upstream access forbidden"),
        strings.Contains(msg, "Upstream authentication failed"):
        return forbidden
    case resp.StatusCode == 429:
        return overflow
    case resp.StatusCode >= 500:
        return upstream
    default:
        return client
    }
}

靠错误文案做判断确实不优雅,但 sub2api 没有给出更结构化的信号,只能这样。好在兜底逻辑是安全的:哪怕哪天文案变了匹配不上,5xx 也会走"仅本次降级",业务不会断,只是不会切档位、不会发通知。每次升级 sub2api 后,回来看一眼这张表。

5.5 一次请求的完整路径

sequenceDiagram participant App participant QG as qiong-gateway participant S2A as sub2api participant DS as DeepSeek participant Me as 我的手机 App->>QG: POST /v1/chat/completions QG->>S2A: 原样转发(带 app 自己的 key) S2A-->>QG: 503 No available accounts QG->>QG: 档位 normal → budget,冷却 15 分钟 QG-)Me: 💸 订阅额度用完了,已切到 DeepSeek QG->>DS: 改写 model 后转发(用 DeepSeek key) DS-->>QG: 200(SSE 流) QG-->>App: 200 + X-LLM-Tier: budget Note over QG: 冷却期内的请求直接走 DeepSeek,
不再白跑 sub2api

几个实现细节:

  • 鉴权:app 用的是自己在 sub2api 里的 key,网关维护一份白名单(APP_KEYS)。主通道把这个 key 原样透传,sub2api 那边的按 app 统计照常有效;降级通道换成网关自己的 DeepSeek key,DeepSeek key 永远不出服务器。
  • 冷却与半开:判定订阅用完后,冷却期(默认 15 分钟,或者上游给的 Retry-After)内所有请求直接走 DeepSeek。冷却期过了,下一个请求会再试一次主通道,成功就切回 normal。这就是熔断器的半开状态,写过 Sentinel 的应该很眼熟。
  • 流式:错误都发生在响应头之前,所以降级可以无缝进行;一旦开始往客户端吐 SSE 了,就不能再切换了。
  • 请求改写:发给 DeepSeek 前把 model 换成 FALLBACK_MODEL,用 UseNumber() 解析 JSON,避免大整数被转成 float64。如果某些 OpenAI 专有字段被 DeepSeek 拒绝(400/422),加到 STRIP_FIELDS 里删掉。

完整代码约 500 行,只用标准库,go build 出来一个二进制直接扔服务器,随文附上 main.go。

5.6 提示用户:响应头 + 状态接口

网关不改响应体,只加响应头,app 自己决定怎么展示:

信号含义
X-LLM-Tier: normal订阅正常
X-LLM-Tier: budget + X-LLM-Model: deepseek-flash这次是 DeepSeek 回答的
HTTP 503 + code: budget_exhausted彻底没钱了
GET /status当前档位 + 一段现成的中文提示语,给前端横幅用
// GET /status
{
  "tier": "budget",
  "message": "作者的 ChatGPT 订阅额度用完了,现在由更便宜的 DeepSeek 临时顶班,回答风格和质量可能略有不同。",
  "since": "2026-10-09T17:25:22Z"
}

app 侧(Python 为例,with_raw_response 能拿到响应头):

from openai import OpenAI, APIStatusError

client = OpenAI(
    base_url="https://llm.example.com/v1",
    api_key="sk-app-a-xxxx",  # app 在 sub2api 里的 key
)

def ask(prompt: str) -> tuple[str, str | None]:
    """返回 (回答, 给用户看的提示)"""
    try:
        raw = client.chat.completions.with_raw_response.create(
            model="gpt-5.5",  # 以 sub2api 后台模型列表为准
            messages=[{"role": "user", "content": prompt}],
        )
    except APIStatusError as e:
        if e.status_code == 503 and "budget_exhausted" in str(e.body):
            return "", "作者的额度和余额都花光了,AI 功能暂停一下,等作者发工资 🥲"
        raise

    notice = None
    if raw.headers.get("x-llm-tier") == "budget":
        notice = "当前为省钱模式:由 DeepSeek 临时顶班,回答可能和平时略有不同"
    return raw.parse().choices[0].message.content, notice

流式请求同理,响应头在第一个 chunk 之前就到了,用 with_streaming_response 读即可。

5.7 提示自己:只在状态变化时叫我

通知支持 ntfy 和 Telegram,配哪个用哪个。会收到的消息一共就这几种:

场景通知
normal → budget💸 ChatGPT 订阅额度用完了,已切到 DeepSeek 顶班。省着点用。
→ broke🪦 DeepSeek 余额也没了,所有 app 的 AI 功能已暂停。该充钱了。
→ normal🎉 ChatGPT 订阅额度恢复,已切回主通道。
余额低于阈值🪫 DeepSeek 余额只剩 X 了,记得充值。
上游拒绝访问⚠️ ChatGPT 账号可能出问题了,去后台看看。
sub2api 连续报错🔧 sub2api 可能挂了。

余额预警靠 DeepSeek 的 GET /user/balance 接口,网关每 30 分钟查一次,余额跌破阈值时通知一次,回到阈值以上再重新布防,不会反复刷屏。

用 ntfy.sh 公共服务的话,topic 名字取一个猜不到的随机串,否则谁都能订阅你的"哭穷频道"。

5.8 为什么备胎选 DeepSeek

选 DeepSeek 有三个理由:

  1. 便宜。下表是 2026 年 10 月官方定价页的数字(美元 / 百万 token):
模型输入(缓存命中)输入(缓存未命中)输出
deepseek-flash(V4.1-Flash)0.0060.301.20
deepseek-v4-pro0.0441.323.96

以上是高峰价。非高峰时段直接半价,高峰时段是工作日 UTC 01:00–04:00 和 06:00–10:00(北京时间 09:00–12:00、14:00–18:00),周末和中国法定节假日全天都按非高峰算。顶班用 deepseek-flash 就够了。

  1. 协议兼容。OpenAI Chat Completions 格式直接兼容,支持工具调用和 JSON 输出,base URL 就是 https://api.deepseek.com。官方文档也列了 Responses API 支持,不过为了两边都稳,我让 app 统一用 Chat Completions,这是两个上游的最大公约数。
  2. 预付费,天然有上限。DeepSeek 是先充值后扣费,余额用完返回 402 Insufficient Balance。也就是说,最坏情况下我只会亏掉充进去的那点钱,不会某天早上醒来收到一张天价账单。这对一个"穷鬼网关"来说是最重要的特性。

两个注意事项:

  • 模型名一直在变。deepseek-chat 和 deepseek-reasoner 已经在 2026 年 7 月 24 日下线,deepseek-v4-flash 9 月 10 日也退役了(旧名字暂时还能用,背后是新模型)。所以模型名一定要放配置里,不要写死在代码里。
  • 思考模式默认开启。思考过程也按输出 token 计费,如果顶班场景不需要深度推理,可以按官方 Thinking Mode 文档在请求里关掉,更省。

5.9 部署 qiong-gateway

编译(本地交叉编译,传到服务器):

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o qiong-gateway .
scp qiong-gateway user@your-server:/usr/local/bin/

配置 /etc/qiong-gateway.env(记得 chmod 600):

LISTEN=127.0.0.1:9000
PRIMARY_BASE=http://127.0.0.1:8080
FALLBACK_BASE=https://api.deepseek.com
FALLBACK_KEY=sk-deepseek-xxxx
FALLBACK_MODEL=deepseek-flash
# app 在 sub2api 里的 key:app 名称,逗号分隔
APP_KEYS=sk-s2a-aaaa:appA,sk-s2a-bbbb:appB
COOLDOWN=15m
BALANCE_THRESHOLD=10     # 单位是 DeepSeek 账户币种
BALANCE_CHECK=30m
NTFY_URL=https://ntfy.sh/qiong-a8f3k2x9
# TG_BOT_TOKEN=
# TG_CHAT_ID=
# STRIP_FIELDS=store,service_tier

systemd /etc/systemd/system/qiong-gateway.service:

[Unit]
Description=qiong-gateway (ChatGPT subscription -> DeepSeek fallback)
After=network-online.target docker.service
Wants=network-online.target

[Service]
EnvironmentFile=/etc/qiong-gateway.env
ExecStart=/usr/local/bin/qiong-gateway
Restart=always
RestartSec=3
DynamicUser=yes
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now qiong-gateway
journalctl -u qiong-gateway -f

Nginx,只对外暴露 /v1/ 和 /status,其他一律 404:

server {
    listen 443 ssl http2;
    server_name llm.example.com;

    ssl_certificate     /etc/letsencrypt/live/llm.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/llm.example.com/privkey.pem;

    location /v1/ {
        proxy_pass http://127.0.0.1:9000;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_buffering off;        # SSE 流式必须关,否则一坨一坨地吐
        proxy_read_timeout 600s;    # 非流式长回答要等很久
        client_max_body_size 32m;
    }

    location = /status {
        proxy_pass http://127.0.0.1:9000;
    }

    location / {
        return 404;
    }
}
sub2api README 里提醒过:如果 Codex CLI 直接经 Nginx 连 sub2api,要在 http 块加 underscores_in_headers on;,因为 Nginx 默认会丢掉带下划线的请求头(比如 session_id),多账号粘性会话就失效了。我们的 app 走 qiong-gateway + Chat Completions,不涉及这个问题;但如果你自己的 Codex CLI 也要从外网连 sub2api,记得加上。

最终的端口布局:

flowchart LR NET((公网)) -->|443| NG[Nginx] NG -->|/v1/ /status| QG[qiong-gateway
127.0.0.1:9000] QG --> S2A[sub2api
127.0.0.1:8080] S2A --> PG[(PostgreSQL)] S2A --> RD[(Redis)] ME((我)) -->|SSH 隧道| S2A NET -.-|禁止直连| S2A

5.10 演练一次降级

上线前务必演练一次,不然真到没额度那天才发现通知没配好,就尴尬了:

  1. SSH 隧道进 sub2api 后台,把 ChatGPT 账号临时停用,号池空了,sub2api 就会返回 No available accounts
  2. 发一个请求,确认响应头是 X-LLM-Tier: budget,手机收到 💸 通知
  3. 访问 /status,确认档位和提示语
  4. 重新启用账号,等冷却期过去再发一个请求,确认切回 normal,收到 🎉 通知

我自己用假上游把七种情况(未知 key、正常、请求错误透传、app 限额溢出、号池耗尽、余额不足、恢复)都跑了一遍,行为和预期一致。

6. 踩坑预警(从入门到放弃的"放弃"部分)

6.1 升级!升级!升级!

今年 8 月 sub2api 修了一个高危账号接管漏洞:攻击者只需要知道受害者邮箱,就能借 OAuth 登录补全流程把自己的第三方身份绑到别人账号上直接登录。

所以:版本别躺着不动,订阅一下 release;管理后台绝不暴露公网,SSH 隧道是最省心的方案。另外,升级之后记得回去对一下 5.4 节那张错误文案表。

6.2 额度是窗口制,不是按量计费

订阅额度按 5 小时和 7 天两个窗口算。多个 app 共用时,跟按量计费的心智模型完全不同:不是"花多少付多少",而是"窗口内用完就没了"。某个 app 跑批量任务,可能直接把其他 app 的额度挤没。

建议:批量 / 离线任务单独一个 key,在 sub2api 里把它的限额压低。

6.3 app 限额"溢出"会花真钱

注意 5.4 节表里的"其他 429":某个 app 撞到了自己在 sub2api 的 key 限额,网关会让这次请求走 DeepSeek。这个设计的语义是"订阅份额用完,超出部分自费"。

如果你设 key 限额的本意是"这个 app 到此为止",那就要改一下 overflow 分支,直接把 429 原样返回给 app。好在 DeepSeek 是预付费的,最坏也就是把余额烧光,触发 broke。

6.4 指纹收敛开关

8 月中旬的版本有一个破坏性变更:Codex OAuth 账号的"指纹收敛"默认值改成了关闭,之前没显式配置的账号会恢复透传客户端原始标识。

多个 app 从同一个账号出去时,上游看到的到底是"一个客户端"还是"一堆奇怪的客户端",这件事值得想清楚。在账号编辑里显式选一个档位,别吃默认值。

6.5 降级不是无感的

DeepSeek 和 GPT 毕竟是两个模型。针对 GPT 调好的 prompt,换到 DeepSeek 上输出风格、格式遵循程度都可能不一样。依赖严格 JSON 输出的 app,降级后的解析一定要做好兜底。这也是为什么要明明白白告诉用户"现在是省钱模式",而不是假装什么都没发生。

6.6 能力边界

主通道只能用 Codex 通道开放的模型。embedding、语音这类能力,别指望从这里拿。

7. 丑话说在前面

最后必须严肃一下。

把个人订阅转成 API 给多个后端调用,并不在订阅条款预期的使用方式之内。 不管是 sub2api 还是 web2api,本质上都是在灰色地带折腾,账号被限流甚至封禁的风险由你自己承担。社区里这类项目的作者自己也是这么写免责声明的。

我的原则是:

  • 个人项目、实验性 app:sub2api + 穷鬼网关,挂了就挂了
  • 要对外正式服务、或者在关键链路上的 app:老老实实用官方 API key

而 qiong-gateway 这一层,恰好让"转正"变得很容易:app 永远只认网关地址,哪天要正式上线,把 PRIMARY_BASE 指向官方 API(或者把官方 key 接进 sub2api),业务代码一行不用改。先用订阅验证想法,跑通了再无痛切到正规军。

flowchart LR APP[所有 app] --> QG[qiong-gateway] QG -->|阶段一:验证想法| SUBS[ChatGPT 订阅 via sub2api] QG -.->|阶段二:正式上线| KEY[官方 API key] QG -.->|任何阶段的备胎| DS[DeepSeek]

8. 总结

  • 多 app 后端共享、要稳定、要工具调用:sub2api
  • 只有网页订阅、本机玩玩:web2api
  • 订阅会用完:前面套一层降级网关,DeepSeek 顶班,响应头告诉用户,手机通知告诉自己
  • 正式对外的服务:官方 API key,别省这个钱

折腾到这里,入门是入门了。至于什么时候放弃——等手机弹出 🪦 那条通知的时候吧。


评论区
暂无评论
avatar