Skip to content

huiming-git/gemini-pro

Repository files navigation

Gemini Pro 订阅充值站

一个部署在 Vercel 上的 Gemini Pro 订阅自动激活平台。用户输入卡密和 Google 账号信息,系统自动完成 Gemini Pro 订阅的激活。

目录


项目架构

整体是一个前后端分离 + Serverless的架构:

┌─────────────────────────────────────────────────────────────┐
│                        Vercel                               │
│                                                             │
│  ┌──────────────┐     ┌──────────────────────────────────┐  │
│  │  静态前端     │     │  Serverless Functions (api/)     │  │
│  │  React SPA   │────>│  verify_card.js                  │  │
│  │  client/dist  │     │  submit_order.js                 │  │
│  │              │     │  query_orders.js                  │  │
│  └──────────────┘     └───────────────┬──────────────────┘  │
│                                       │                     │
│  ┌──────────────┐                     │                     │
│  │  Rewrites    │                     │                     │
│  │  (边缘代理)   │                     │                     │
│  │  /proxy/     │                     │                     │
│  └──────┬───────┘                     │                     │
└─────────┼─────────────────────────────┼─────────────────────┘
          │                             │
          ▼                             ▼
┌──────────────────┐          ┌──────────────────┐
│ gmailcheck 服务   │          │  aicloudv3.top   │
│ 邮箱状态检测       │          │  充值上游 API     │
└──────────────────┘          └────────┬─────────┘
                                       │
                                       ▼
                              ┌──────────────────┐
                              │  Google 账号系统   │
                              │  登录 + 激活订阅   │
                              └──────────────────┘

为什么需要 Serverless Functions?

前端(浏览器)不能直接调 aicloudv3.top,因为它不返回 CORS 头,浏览器会拦截跨域请求。所以需要一层服务端代理。Vercel Serverless Functions 就是这个代理层——浏览器请求同域的 /api/xxx,function 在服务端帮你转发给上游。


技术栈

层级 技术 用途
前端框架 React 18 UI 组件化
路由 React Router v7 SPA 路由
HTTP 客户端 Axios 前端和 serverless 都用它发请求
样式 Tailwind CSS 3 原子化 CSS,不写自定义样式文件
构建工具 Vite 5 开发热更新 + 生产构建
部署平台 Vercel 静态托管 + Serverless Functions + 边缘 Rewrites
后端 Vercel Serverless Functions (Node.js) 代理上游 API,处理 session

目录结构

gemini-pro/
├── api/                          # Vercel Serverless Functions
│   ├── verify_card.js            # 验证卡密(代理上游)
│   ├── submit_order.js           # 提交订单(核心:内含 session 管理)
│   └── query_orders.js           # 查询订单(代理上游)
│
├── client/                       # 前端 React 应用
│   ├── index.html                # HTML 入口
│   ├── package.json              # 前端依赖
│   ├── vite.config.js            # Vite 配置(含 dev proxy)
│   ├── tailwind.config.js        # Tailwind 品牌色配置
│   ├── postcss.config.js         # PostCSS 插件
│   └── src/
│       ├── main.jsx              # React 入口
│       ├── index.css             # 全局样式(Tailwind 指令 + 字体)
│       ├── App.jsx               # 根组件,路由配置
│       ├── api/
│       │   └── order.js          # 所有 API 调用封装
│       ├── pages/
│       │   └── RedeemPage.jsx    # 主页面,控制整个充值流程
│       └── components/
│           ├── Header.jsx        # 顶栏 logo
│           ├── Footer.jsx        # 底栏
│           ├── OrderForm.jsx     # 一体化表单(卡密+账号+2FA)
│           ├── GmailCheckPanel.jsx   # Gmail 邮箱状态检测
│           ├── OrderQueryPanel.jsx   # 按卡密查询历史订单
│           ├── OrderTracker.jsx      # 订单轮询追踪(5秒一次)
│           ├── OrderResult.jsx       # 最终结果展示(成功/失败/取消)
│           ├── ErrorAlert.jsx        # 通用错误提示条
│           ├── LoadingSpinner.jsx    # 加载动画
│           ├── CdkeyForm.jsx        # 独立的卡密验证表单(备用)
│           ├── GoogleAccountForm.jsx # 独立的账号信息表单(备用)
│           └── StepIndicator.jsx     # 步骤指示器(备用)
│
├── vercel.json                   # Vercel 部署配置
├── package.json                  # 根依赖(serverless 用的 axios)
└── B2B_代理对接文档模板.md         # 上游 B2B API 文档(参考)

备用组件说明CdkeyFormGoogleAccountFormStepIndicator 是早期分步流程的设计,后来合并成了 OrderForm 一个表单。保留在代码中但当前未使用。


核心流程

用户视角

1. 打开网站
2. 输入卡密兑换码(如 AP-F9879268E9)
3. 输入 Google 邮箱、密码
4. 选择验证方式:2FA 密钥 或 备用验证码
5. 点击提交
6. 等待系统自动激活(5秒轮询状态)
7. 看到结果:成功 / 失败 / 已取消

数据流

用户填写表单
    │
    ▼
RedeemPage.handleSubmitOrder(payload)
    │
    ▼
api/order.js → createOrder(payload)
    │
    │  POST /api/submit_order
    │  Body: { card_key, google_email, google_password, auth_type, auth_secret }
    │
    ▼
Vercel Serverless: api/submit_order.js
    │
    │  1) POST aicloudv3.top/api/verify_card  → 拿到 Set-Cookie: session=xxx
    │  2) POST aicloudv3.top/api/submit_order  → 带上 Cookie: session=xxx
    │
    ▼
返回 { code: 1, msg: "订单提交成功", remain_count: 0 }
    │
    ▼
前端进入 OrderTracker 轮询
    │
    │  每 5 秒 POST /api/query_orders { card_key }
    │  查找 google_email 匹配的订单
    │
    ▼
订单状态变为终态(SUCCESS / FAILED / DELETED)
    │
    ▼
OrderResult 展示最终结果

状态机

form ──提交──> submitting ──成功──> tracking ──终态──> result
  ▲                │                                    │
  │              失败                                    │
  │                │                                    │
  └────────────────┘────────────── 返回首页 ─────────────┘

前端详解

页面组成

RedeemPage 是唯一的页面,由三个区域组成:

┌──────────────────────────────────────────┐
│  ┌─────────────────┐ ┌────────────────┐  │
│  │ GmailCheckPanel │ │OrderQueryPanel │  │  ← 顶部双栏
│  │ 邮箱状态检测     │ │ 订单查询       │  │
│  └─────────────────┘ └────────────────┘  │
│                                          │
│  ┌──────────────────────────────────────┐│
│  │ OrderForm / OrderTracker / Result   ││  ← 主区域(根据状态切换)
│  └──────────────────────────────────────┘│
└──────────────────────────────────────────┘

关键组件

OrderForm — 一体化的充值表单

包含所有输入项:卡密、邮箱、密码、验证方式选择、验证码。提交时组装 payload 传给 RedeemPage

OrderTracker — 订单状态轮询

提交成功后自动进入此组件。每 5 秒调一次 queryOrdersByCdkey,在返回的订单列表中按 google_email 匹配当前订单,展示实时状态。最多轮询 120 次(10 分钟)。当状态变为 SUCCESS/FAILED/DELETED 时停止轮询,回调 onResult 切到结果页。

GmailCheckPanel — 邮箱预检

/proxy/gmailcheck/shaicha3.php 检测 Google 邮箱状态(正常/异常/不存在)。这个走的是 Vercel rewrites 代理到 koko.gmailcheck.com,不走 serverless。

OrderQueryPanel — 历史订单查询

输入卡密查看该卡密关联的所有订单和状态。

API 封装 (client/src/api/order.js)

四个函数,全部请求 /api/xxx(同域路径):

函数 请求 用途
validateCdkey(cdkey) POST /api/verify_card 验证卡密有效性
createOrder(payload) POST /api/submit_order 提交充值订单
queryOrdersByCdkey(cardKey) POST /api/query_orders 按卡密查询订单
checkGmail(email) POST /proxy/gmailcheck/shaicha3.php 检测 Gmail 状态

样式方案

  • Tailwind CSS — 所有样式都写在 JSX 的 className 里,没有单独的组件 CSS
  • 品牌色brand-500: #4285f4(Google 蓝),在 tailwind.config.js 中自定义
  • 字体 — 优先 Apple 系统字体,降级到微软雅黑、Helvetica
  • 背景#f8fafc(浅灰蓝)

后端详解(Serverless Functions)

api/ 目录下的三个文件就是全部后端代码。每个文件是一个独立的 Vercel Serverless Function。

api/submit_order.js — 核心

这是最关键的文件。它不是简单代理,而是在一个函数内串行调用两个上游接口

// 1) 先调 verify_card,拿到 session cookie
const verifyRes = await axios.post(UPSTREAM + '/api/verify_card', { card_key });
const cookie = verifyRes.headers['set-cookie'];  // session=eyJ...

// 2) 带着 cookie 调 submit_order
const submitRes = await axios.post(UPSTREAM + '/api/submit_order', body, {
  headers: { Cookie: cookie }
});

为什么要这样? 见下面的上游接口对接章节。

api/verify_card.js — 简单代理

前端也需要单独调 verify 来展示卡密余额信息,所以保留了一个纯代理。

api/query_orders.js — 简单代理

查询订单不需要 session,直接转发。

公共模式

三个 function 共享相同的结构:

  1. 设置 CORS 头(Access-Control-Allow-Origin: *
  2. 处理 OPTIONS 预检
  3. 检查 HTTP 方法
  4. try/catch 包裹,统一的错误处理

上游接口对接

这是整个项目最值得学习的部分——怎么和上游 aicloudv3.top 对上的

上游接口清单

接口 方法 功能
/api/verify_card POST 验证卡密,返回余额和是否可提交
/api/submit_order POST 提交充值订单
/api/query_orders POST 按卡密查询所有订单

接口请求/响应格式

verify_card

// 请求
{ "card_key": "AP-F9879268E9" }

// 成功响应
{ "code": 1, "msg": "验证通过", "can_submit": true, "remain_count": 1, "view_only": false }

// 失败响应
{ "code": -1, "msg": "无效的激活码" }

submit_order

// 请求
{
  "card_key": "AP-F9879268E9",
  "google_email": "user@gmail.com",
  "google_password": "password",
  "auth_type": "2FA",              // 或 "BACKUP_CODE"
  "auth_secret": "ABCDEFGH...",    // 32位密钥 或 备用验证码
  "auth_secret_secondary": ""      // 可选第二个备用验证码
}

// 成功响应
{ "code": 1, "msg": "订单提交成功", "remain_count": 0 }

// 未验证卡密时
{ "code": -1, "msg": "请先验证激活码" }

query_orders

// 请求
{ "card_key": "AP-F9879268E9" }

// 响应
{
  "code": 1,
  "orders": [
    {
      "google_email": "user@gmail.com",
      "status": "SUCCESS",           // QUEUED / PROCESSING / SUCCESS / FAILED / DELETED
      "result_message": "订阅成功",
      "partner_order_id": "...",
      "created_at": "2026-04-17 15:00:00"
    }
  ]
}

Session Cookie 机制(核心难点)

上游的 verify 和 submit 通过 HTTP session cookie 关联:

verify_card 请求 ──────────> aicloudv3.top
                  <──────── 响应头: Set-Cookie: session=eyJ2ZXJpZm...

submit_order 请求 ─────────> aicloudv3.top
(带上 Cookie: session=eyJ...)
                  <──────── { "code": 1, "msg": "订单提交成功" }

Session cookie 的内容(base64 解码后):

{ "verified_activation_code": "AP-F9879268E9" }

上游在 submit_order 时检查 cookie 里有没有已验证的卡密,没有就返回"请先验证激活码"。

这就是为什么不能用 Vercel Rewrites 代理——Rewrites 是边缘层的纯 URL 转发,不会把上游的 Set-Cookie 透传回浏览器(域名不匹配)。所以必须用 Serverless Function 在服务端一次性完成 verify + submit。

验证方式

auth_type auth_secret 内容 说明
2FA 32 位 Base32 TOTP 密钥 上游拿密钥自己生成 6 位验证码登录 Google
BACKUP_CODE 8 位数字备用验证码 直接用这个码登录 Google

上游 aicloudv3.top 收到账号信息后,会自动登录用户的 Google 账号,通过 2FA 验证,然后激活 Gemini Pro 订阅。整个过程对用户透明。

另一套 B2B 接口(ethgoogle.top)

项目里还有一份 B2B_代理对接文档模板.md,记录了另一套上游 API(ethgoogle.top),使用 Bearer Token 鉴权,接口格式不同。当前代码未使用这套接口,但它是 aicloudv3.top 的底层服务提供方(B2B 模式)。

aicloudv3.top(面向代理的前端接口,session 鉴权)
     │
     ▼
ethgoogle.top(底层 B2B API,Bearer Token 鉴权)
     │
     ▼
  Google 账号系统

Vercel 部署架构

vercel.json 配置解读

{
  // 构建命令:只构建前端
  "buildCommand": "cd client && npm install && npm run build",
  // 构建产物目录
  "outputDirectory": "client/dist",

  // Serverless Functions 配置
  "functions": {
    "api/**/*.js": {
      "memory": 1024,        // 1GB 内存
      "maxDuration": 60       // 最长 60 秒(submit_order 上游很慢)
    }
  },

  // URL 重写规则(按顺序匹配)
  "rewrites": [
    // Gmail 检测走边缘代理(不需要 session)
    { "source": "/proxy/gmailcheck/:path*", "destination": "https://koko.gmailcheck.com/:path*" },
    // /api 以外的所有路径走 SPA fallback
    { "source": "/((?!api/).*)", "destination": "/index.html" }
  ]
}

请求路由

浏览器请求                     Vercel 处理
──────────────────────────────────────────────────
GET /                    →  client/dist/index.html(静态文件)
GET /assets/xxx.js       →  client/dist/assets/xxx.js(静态文件)
POST /api/submit_order   →  api/submit_order.js(Serverless Function)
POST /api/verify_card    →  api/verify_card.js(Serverless Function)
POST /api/query_orders   →  api/query_orders.js(Serverless Function)
POST /proxy/gmailcheck/* →  Rewrite 到 koko.gmailcheck.com/*(边缘代理)
GET /anything-else       →  index.html(SPA fallback)

环境变量

当前项目没有使用 Vercel 环境变量,上游地址硬编码在 serverless function 里。如果要切换上游,改 api/*.js 里的 UPSTREAM 常量即可。


本地开发

# 安装依赖
npm install                # 根目录(serverless 用的 axios)
cd client && npm install   # 前端依赖

# 启动开发服务器
npm run dev                # 等于 cd client && npm run dev

# 访问 http://localhost:5173

本地开发时,/api/* 请求通过 Vite 的 proxy 配置转发到 aicloudv3.top

// client/vite.config.js
proxy: {
  '/api': {
    target: 'https://aicloudv3.top',
    changeOrigin: true,
  },
}

⚠️ 注意:本地 dev proxy 是简单转发,没有 session cookie 管理,所以本地 submit_order 可能会报"请先验证激活码"。完整流程需要部署到 Vercel 测试。


踩坑记录

1. CORS 被浏览器拦截

问题:前端直接请求 aicloudv3.top,浏览器发 OPTIONS 预检,上游不返回 Access-Control-Allow-Origin 头,请求被拦。

解决:所有请求走 Vercel 代理(Serverless Functions 或 Rewrites),浏览器只请求同域的 /api/xxx

2. "请先验证激活码"

问题:Serverless Function 代理 verify_card 和 submit_order 是两个独立请求,上游返回的 session cookie 没有传递。

排查过程

  1. 最初以为是 IP 关联 → 同 IP curl 测试仍然失败
  2. curl -sv 查看完整响应头 → 发现 Set-Cookie: session=...
  3. 带 cookie 请求 submit_order → 成功

解决:在 api/submit_order.js 内串行调用 verify + submit,手动提取和传递 session cookie。

3. Vercel Rewrites 不能透传 Cookie

问题:尝试用 Vercel 边缘 Rewrites 代理(类似 nginx 反代),但上游 Set-Cookie 的 domain 和 path 对不上浏览器的域名,cookie 被丢弃。

解决:必须用 Serverless Functions 在服务端完成 cookie 管理。Rewrites 只适合不需要 session 的接口(如 gmailcheck)。

4. submit_order 超时

问题:上游处理订单很慢(可达 30-60 秒),默认的 axios timeout 和 Vercel function maxDuration 不够。

解决

  • 前端 axios timeout 设为 65 秒
  • Vercel function maxDuration 设为 60 秒
  • 上游 submit_order 的 axios timeout 设为 60 秒

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages