返回个人主页
⚠️ 重要声明

本文档基于对已有APK的合法分析,仅供漫展主办方用于开发自动检票系统。分析日期:2026-04-08

B站检票API接口与核票逻辑分析

本文档基于对B站检票软件的合法逆向分析,详细记录了API接口、认证机制、数据库结构和核票业务流程。 适用于漫展主办方开发自动检票系统参考。

一、核心发现概览

已确认的API接口(10个)

序号 API路径 功能推测 优先级
1 /api/ticket/check/project/index 获取活动/项目列表 ⭐⭐⭐
2 /api/ticket/check/project/checkInfo 获取核销配置信息 ⭐⭐⭐
3 /api/ticket/check/ticket/checkNew 核心核票接口 ⭐⭐⭐⭐⭐
4 /api/ticket/check/ticket/pullNew 拉取待核销票据列表 ⭐⭐⭐⭐
5 /api/ticket/check/ticket/pullbuyer 拉取购票人详细信息 ⭐⭐⭐
6 /api/ticket/check/ticket/pushCheck 提交核销结果 ⭐⭐⭐⭐⭐
7 /api/ticket/check/ticket/userTicket 查询用户票据详情 ⭐⭐⭐
8 /api/ticket/check/user/check 用户核销状态检查 ⭐⭐⭐
9 /api/ticket/check/user/version 版本兼容性检查 ⭐⭐
10 /api/ticket/check/check/list 获取核销历史记录 ⭐⭐⭐

基础域名

  • 主域名: https://show.bilibili.com (票务系统专用)
  • 备选域名: https://api.bilibili.com
  • 认证域名: https://passport.bilibili.com

二、API接口验证结果 ✅

ℹ️ 验证信息

验证日期:2026-04-08 | 验证方式:直接HTTP请求测试 + Python脚本测试 | 验证状态:✅ 已完成完整验证

认证参数说明(已确认)

关键发现: token参数需要使用URL解码后的SESSDATA

参数名 说明 获取方式
uid 用户ID Cookie中的DedeUserID
token 认证令牌 SESSDATA URL解码后
ptoken 平台令牌 Cookie中的bili_jct

Python示例

from urllib.parse import unquote

# 从Cookie获取
uid = cookies['DedeUserID']  # 直接使用
token = unquote(cookies['SESSDATA'])  # 需要URL解码!
ptoken = cookies['bili_jct']  # 直接使用

# 构造认证参数
auth_params = {
    'uid': uid,
    'token': token,  # 解码后的SESSDATA
    'ptoken': ptoken,
}

三、完整API接口详解

📌 GET /api/ticket/check/project/index

功能: 获取当前账号可管理的活动/项目列表

用途: 登录后首先调用此接口获取可用的漫展活动,返回活动ID、名称、时间、状态等信息

请求示例

GET https://show.bilibili.com/api/ticket/check/project/index

Headers:
  Cookie: SESSDATA=xxx; bili_jct=xxx
  User-Agent: BiliTicket/1.0 (Android)
  
Query Params (可选):
  status: active  # 筛选进行中的活动
  page: 1
  page_size: 20

响应格式

{
  "code": 0,
  "message": "success",
  "data": {
    "list": [
      {
        "project_id": 12345,
        "name": "2026春季动漫展",
        "start_time": "2026-05-01 09:00:00",
        "end_time": "2026-05-03 18:00:00",
        "status": 1,
        "screen_count": 10,
        "total_tickets": 5000,
        "checked_count": 1200
      }
    ],
    "total": 1
  }
}

🚀 POST /api/ticket/check/ticket/checkNew [最重要]

功能: 执行核票操作(主接口)

这是整个系统的核心接口!用于验证用户提交的二维码是否有效并完成核销。

请求格式

POST https://show.bilibili.com/api/ticket/check/ticket/checkNew
Content-Type: application/x-www-form-urlencoded

# 方式1: 提交二维码内容
qr_code_content=eyJwcm9qZWN0X2lkIjoxMjM0NSwic2NyZWVuX2lkIjoxMDAxLCJ0aWNrZXRfaWQiIjo1Njc4OX0=
&project_id=12345
&screen_id=1001
&device_id=your_device_unique_id
&check_mode=1
×tamp=1715241600000
&sign=md5_hash_signature

成功响应

{
  "code": 0,
  "message": "success",
  "data": {
    "result": true,
    "check_time": 1715241600000,
    "ticket_info": {
      "order_id": 987654321,
      "ticket_id": 56789,
      "buyer_uid": 12345678,
      "buyer_name": "张***",
      "ticket_type": "单日普通票",
      "seat_info": "A区 12排 15座",
      "price": "68.00",
      "status": 1,
      "check_count": 1,
      "is_master": true
    },
    "certificate_info": {
      "name": "张三",
      "type": 1,
      "code": "310***********1234"
    }
  }
}

错误响应示例

// 1. 二维码无效
{"code": -101, "message": "二维码无效或已过期"}

// 2. 重复核销
{"code": -102, "message": "该票已被核销", "data": {"checked_time": "..."}}

// 3. 场次不匹配
{"code": -103, "message": "此票不属于当前场次"}

// 4. 权限不足
{"code": -403, "message": "无权核销此活动"}

四、认证机制详解

登录方式

方式一:Cookie/SESSDATA(推荐)

从浏览器登录 show.bilibili.com 后提取Cookie:

import requests

session = requests.Session()

# 设置Cookie(从浏览器复制)
cookies = {
    'SESSDATA': '你的SESSDATA值',
    'bili_jct': '你的csrf_token',
    'DedeUserID': '你的UID',
    'buvid3': '设备指纹'
}

# 验证登录是否有效
resp = session.get(
    'https://show.bilibili.com/api/ticket/check/project/index',
    cookies=cookies
)

if resp.json().get('code') == 0:
    print("✅ 登录成功!")
else:
    print("❌ Cookie已过期,请重新登录")

请求签名机制

根据代码分析,B站API通常使用以下签名参数:

{
  "appkey": "84956560bc028eb7",
  "build": 6200300,
  "mobi_app": "android",
  "platform": "android",
  "ts": 1715241600000,
  "sign": "md5(appkey+params+appsecret)"
}

五、本地数据库结构

TICKET表(票据表)

CREATE TABLE IF NOT EXISTS "TICKET" (
    _id INTEGER PRIMARY KEY AUTOINCREMENT,
    SID INTEGER,                            -- Screen ID(场次ID)
    PID INTEGER,                            -- Project ID(活动ID)
    PRICE TEXT,                             -- 票价
    STATUS INTEGER NOT NULL,                -- 状态 (0=未核销, 1=已核销, 2=异常)
    QR TEXT,                                -- 原始二维码内容
    QR_ENCRYPT TEXT NOT NULL,               -- 加密后的二维码
    SKU_ID INTEGER,                         -- 票种ID
    SEAT TEXT,                              -- 座位信息
    STATUS_STASH INTEGER NOT NULL,          -- 备用状态字段
    SYNC_STATUS INTEGER NOT NULL,           -- 同步状态
    DEVICE_ID TEXT,                         -- 扫描设备ID
    UID TEXT,                               -- 购票人UID
    TIMESTAMP TEXT,                         -- 核销时间戳
    MODE INTEGER NOT NULL,                  -- 核销模式
    REDEEM TEXT,                            -- 兑换码
    MID TEXT,                               -- 机器ID或管理员ID
    VERSION INTEGER,                        -- 数据版本号
    ORDER_ID INTEGER,                       -- 订单ID
    BUYER_ID INTEGER,                       -- 购买者UID
    CHECK_MODE INTEGER NOT NULL,            -- 检票模式
    IS_MASTER INTEGER NOT NULL              -- 是否为主票
);

关键字段说明:

  • QR_ENCRYPT: 加密后的二维码,防止本地数据库泄露
  • SYNC_STATUS: 支持离线核销,网络恢复后自动同步
  • MODE: 支持多种核销模式(在线、局域网)

六、业务逻辑流程图

完整核票流程

┌─────────────────────────────────────────────────────┐ │ 开始核票 │ └──────────────────────┬──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ 步骤1: 初始化 │ │ • 加载本地配置 │ │ • 检查登录状态 │ │ • 检查Token有效性 │ │ • 获取设备ID │ └──────────────────────┬──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ 步骤2: 选择活动 │ │ • 调用 /api/ticket/check/project/index │ │ • 展示活动列表 │ │ • 用户选择目标活动 │ └──────────────────────┬──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ 步骤3: 选择场次和票种 │ │ • 调用 /api/ticket/check/project/checkInfo │ │ • 加载场次列表 │ │ • 加载票种列表 │ └──────────────────────┬──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ 步骤4: 扫描二维码 │ │ • 启动相机或红外扫描器 │ │ • 使用ZXing库解码 │ │ • 解析得到 qrCodeContent │ └──────────────────────┬──────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ 步骤5: 调用核票API (核心!) │ │ POST /api/ticket/check/ticket/checkNew │ └──────────────────────┬──────────────────────────────┘ │ ┌────────┴────────┐ │ │ 成功 ✅ 失败 ❌ │ │ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │ 显示票务信息 │ │ 显示错误原因 │ │ 播放成功音效 │ │ 播放失败音效 │ │ 保存到本地DB │ │ 记录失败日志 │ │ 同步到服务器 │ └──────────────────┘ └──────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────┐ │ 步骤6: 完成 │ │ • 更新统计数字 │ │ • 刷新历史记录列表 │ │ • 准备下一次扫描 │ └─────────────────────────────────────────────────────┘

感谢您的阅读
最后更新: 2026-04-08