跳转至

01 · 代理提现审核 API 需求书

目标读者:后台开发工程师、风控团队、技术 Leader 核心问题:代理提现审核当前人工重复性极高,能不能通过一个查询 API + Telegram 机器人一次性完成? 优先级:P0(副组长工作流中最耗时、最重复、判定规则最明确的任务) 配套: 副组长工作指南 4.5.4 代理提现反欺诈 作者:Bob | 最后更新:2026-04-11


一、业务背景与痛点

1.1 当前人工流程

副组长每天处理大量代理提现订单。对每一笔,需要依次访问多个后台页面做一系列判定:

  收到代理提现订单
        │
        ▼
  Step 1:锁定订单(防止同事重复处理)
        │
        ▼
  Step 2:进入代理信息页
        │      - 复制代理注册 IP
        │      - 复制代理登录 IP
        │      - 查代理账户余额
        │      - 查代理最近充值记录
        ▼
  Step 3:进入下级账号页
        │      - 逐个查看每个下级用户的注册 IP / 登录 IP
        │      - 页面高亮下级互相同 IP 的记录
        │      - 用浏览器 Ctrl+F 搜索是否有下级 IP 与代理同
        ▼
  Step 4:对每个疑似下级 → 查用户账户变动明细
        │      - 查最近一次领彩金(如邀请奖励)的时间点
        │      - 查领彩金前的账户余额
        │      - 查领彩金前后是否有充值
        │      - 查领彩金后的游戏盈亏
        ▼
  Step 5:综合判定
        │      - 是否 IP 碰撞?
        │      - 领彩金前是否有"自然余额"?
        │      - 彩金 + 彩金后盈亏是否都来自自刷?
        ▼
  Step 6:下结论
         - 通过 / 驳回 / 部分驳回(只扣刷单金额)
         - 如果驳回,还要锁定代理的下注 / 提现 / 佣金领取权限

1.2 痛点量化

维度 数值
单次审核耗时 5~15 分钟(多级跳转 + 多次复制粘贴 + 心算)
每天单数 几十笔起步(大促期翻倍)
每天总耗时 2~3 小时(副组长所有工作里占比最大)
错误后果 放过自刷代理 → 资金直接损失;误杀真实代理 → 客诉
心智负担 高(多级关联判断,容易眼花看错)

1.3 为什么应该自动化

  1. 数据完全在后台数据库 —— 无需人工观察
  2. 判定规则长期验证,可明文代码化 —— 见第三节
  3. 只需要返回"判定意见",最终决策仍由人工 —— 安全风险可控
  4. Telegram 已是团队标配沟通工具 —— 无需引入新系统
  5. 投入产出比极高 —— 一次开发,每天节省 2~3 小时

二、自动化方案总览

  运营副组长(在 Telegram)
        │
        │ /check <订单号>
        ▼
  ┌─────────────────────────────────────────┐
  │ Telegram Bot(部署在 VPS)               │
  │ - 接收命令                               │
  │ - 解析订单号                             │
  └──────────────┬──────────────────────────┘
                 │ HTTP GET + Bearer Token
                 │ IP 白名单校验
                 ▼
  ┌─────────────────────────────────────────┐
  │ 后台 API 网关(新开发)                  │
  │ /api/risk/agent-withdrawal-audit         │
  │ ?order_id=xxx                            │
  └──────────────┬──────────────────────────┘
                 │
                 ▼
  ┌─────────────────────────────────────────┐
  │ 数据聚合层                               │
  │ - 查代理信息                             │
  │ - 查下级账号                             │
  │ - 对每个下级查余额明细                   │
  │ - 查彩金领取记录                         │
  └──────────────┬──────────────────────────┘
                 │
                 ▼
  ┌─────────────────────────────────────────┐
  │ 判定引擎                                 │
  │ - IP 去重算法                            │
  │ - 余额溯源算法                           │
  │ - 自刷识别算法                           │
  └──────────────┬──────────────────────────┘
                 │
                 ▼
  ┌─────────────────────────────────────────┐
  │ Telegram 回复                            │
  │ - 建议:通过 / 驳回 / 部分驳回           │
  │ - 证据链(为什么这样判定)                │
  │ - 可扣款金额(如果部分驳回)              │
  └─────────────────────────────────────────┘

三、核心判定算法(可直接代码化)

这是整份需求书的灵魂,以下规则均由副组长长期实践验证。

3.1 规则 A · IP 去重(判断下级是否是自己小号)

目标:识别"代理注册 / 登录 IP" 和 "下级注册 / 登录 IP" 是否属于同一物理网络。

为什么不能精确匹配: - 大部分 ISP 会给用户动态 IP - 同一用户在家里的路由器后 IP 尾数可能变化 - 精确匹配会大量漏判

为什么不能全模糊: - 太模糊会大量误判(同省份/同城市的用户会被误杀)

算法:前缀匹配

┌────────────────────────────────────────────────────────────┐
│  输入:ip_a, ip_b(字符串)                                  │
│  输出:boolean(是否属于同一子网)                           │
│                                                              │
│  Step 1:判断 IP 版本                                        │
│    if ip 含 ":" → IPv6                                      │
│    else        → IPv4                                       │
│                                                              │
│  Step 2:归一化                                              │
│    IPv4:保留 "最后一个 . 之前" 的所有内容                  │
│            例:192.168.1.23  → "192.168.1"                   │
│               192.168.1.45  → "192.168.1"                   │
│                                                              │
│    IPv6:保留 "第三个 : 之前" 的所有内容                    │
│            例:2001:0db8:85a3:0000:0000:8a2e:0370:7334      │
│              → "2001:0db8:85a3"                              │
│              2001:0db8:85a3:abcd::1234                       │
│              → "2001:0db8:85a3"                              │
│                                                              │
│  Step 3:比较归一化后的字符串                                │
│    相等 → 判定为同 IP(同一物理网络)                       │
│    不等 → 判定为不同                                         │
└────────────────────────────────────────────────────────────┘

参考实现(Python 伪代码):

def normalize_ip(ip: str) -> str:
    """
    IP 归一化用于"同子网"判定
    - IPv4 保留最后一个 . 之前的部分(即 /24 子网)
    - IPv6 保留第三个 : 之前的部分(即 /48 子网)
    """
    if ':' in ip:  # IPv6
        parts = ip.split(':')
        # 取前 3 段
        return ':'.join(parts[:3])
    else:  # IPv4
        last_dot = ip.rfind('.')
        return ip[:last_dot] if last_dot > 0 else ip


def same_network(ip_a: str, ip_b: str) -> bool:
    """判断两个 IP 是否属于同一子网"""
    if not ip_a or not ip_b:
        return False
    return normalize_ip(ip_a) == normalize_ip(ip_b)


# 测试用例
assert same_network('192.168.1.23', '192.168.1.45') == True
assert same_network('192.168.1.23', '192.168.2.23') == False
assert same_network(
    '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
    '2001:0db8:85a3:abcd::1234',
) == True
assert same_network(
    '2001:0db8:85a3::1',
    '2001:0db8:ffff::1',
) == False

完整 IP 碰撞检测:

def detect_ip_collision(agent: dict, downlines: list[dict]) -> dict:
    """
    检测代理和下级之间是否存在 IP 碰撞

    检查两个维度:
    1. 代理的 IP(注册 / 登录)与任一下级的 IP
    2. 下级之间互相的 IP

    返回:
    {
      'has_collision': bool,
      'collisions': [
        { 'type': 'agent_vs_downline', 'downline_id': X, 'reason': '...' },
        { 'type': 'downline_vs_downline', 'downline_ids': [X, Y], 'reason': '...' },
      ]
    }
    """
    collisions = []
    agent_ips = [agent.get('register_ip'), agent.get('last_login_ip')]
    agent_ips = [ip for ip in agent_ips if ip]

    # 维度 1:代理 vs 下级
    for dl in downlines:
        dl_ips = [dl.get('register_ip'), dl.get('last_login_ip')]
        dl_ips = [ip for ip in dl_ips if ip]
        for a_ip in agent_ips:
            for d_ip in dl_ips:
                if same_network(a_ip, d_ip):
                    collisions.append({
                        'type': 'agent_vs_downline',
                        'downline_id': dl['user_id'],
                        'agent_ip': a_ip,
                        'downline_ip': d_ip,
                        'reason': f'代理 IP {a_ip} 与下级 {dl["user_id"]} IP {d_ip} 同子网',
                    })

    # 维度 2:下级互相
    for i in range(len(downlines)):
        for j in range(i + 1, len(downlines)):
            dl1, dl2 = downlines[i], downlines[j]
            dl1_ips = [dl1.get('register_ip'), dl1.get('last_login_ip')]
            dl2_ips = [dl2.get('register_ip'), dl2.get('last_login_ip')]
            for ip1 in dl1_ips:
                for ip2 in dl2_ips:
                    if ip1 and ip2 and same_network(ip1, ip2):
                        collisions.append({
                            'type': 'downline_vs_downline',
                            'downline_ids': [dl1['user_id'], dl2['user_id']],
                            'ip1': ip1,
                            'ip2': ip2,
                            'reason': f'下级 {dl1["user_id"]} 与下级 {dl2["user_id"]} IP 同子网',
                        })

    return {
        'has_collision': len(collisions) > 0,
        'collisions': collisions,
    }

3.2 规则 B · 余额溯源(判断彩金领取后的盈亏归属)

目标:对每个疑似下级,算出"如果这个用户是自刷的话,应当保留的余额"。

核心思想:一个真实用户领取彩金(如邀请奖励)之前的余额,是他自己充值或正常游戏赢来的 —— 这部分应该保留;彩金本身 + 彩金之后的游戏盈亏,如果判定为自刷,应当全部扣除

算法:

┌──────────────────────────────────────────────────────────────┐
│  输入:user_id(疑似下级)                                     │
│  输出:                                                         │
│    {                                                           │
│      balance_before_bonus: 领彩金前余额,                      │
│      bonus_amount: 彩金金额,                                   │
│      profit_after_bonus: 彩金后游戏净盈亏,                    │
│      deposit_between: 彩金前后是否有充值,                     │
│      recommendation: 'keep_original' | 'clawback' | 'partial' │
│    }                                                           │
│                                                                │
│  Step 1:查 user_id 的账户变动明细(时间倒序)                │
│                                                                │
│  Step 2:找到"最近一次领彩金"的记录                            │
│          (类型 = 邀请奖励 / 首充彩金 / 活动彩金等)            │
│                                                                │
│  Step 3:记录该彩金记录【前一刻】的账户余额                    │
│          → balance_before_bonus                                │
│                                                                │
│  Step 4:记录该彩金的金额                                      │
│          → bonus_amount                                        │
│                                                                │
│  Step 5:查该彩金之后的所有账户变动                            │
│          - 游戏输赢 → 累计到 profit_after_bonus                │
│          - 充值 → deposit_between 标记 True                    │
│          - 其它收入 → 记入 profit_after_bonus                  │
│                                                                │
│  Step 6:输出                                                  │
└──────────────────────────────────────────────────────────────┘

处理建议(基于 IP 碰撞 + 余额溯源的组合):

def recommend_action(ip_collision_result, balance_tracing) -> dict:
    """
    综合 IP 碰撞结果 + 余额溯源,给出处理建议
    """
    if not ip_collision_result['has_collision']:
        return {
            'action': 'approve',
            'reason': '未发现 IP 碰撞',
            'refund_amount': 0,
        }

    # 有 IP 碰撞 → 判定为自刷代理
    # 对每个疑似下级,计算应扣除金额
    total_clawback = 0
    details = []
    for downline_trace in balance_tracing:
        # 保留的:领彩金前余额
        keep = downline_trace['balance_before_bonus']
        # 扣除的:彩金 + 彩金后的净盈亏
        clawback = downline_trace['bonus_amount'] + max(
            downline_trace['profit_after_bonus'], 0
        )
        # ⚠️ 注意:彩金后如果有充值,这部分充值应保留(不是自刷)
        if downline_trace['deposit_between']:
            clawback -= downline_trace['deposit_amount']

        total_clawback += clawback
        details.append({
            'user_id': downline_trace['user_id'],
            'keep': keep,
            'clawback': clawback,
        })

    return {
        'action': 'reject_and_clawback',
        'reason': 'IP 碰撞 + 疑似自刷',
        'refund_amount': total_clawback,
        'details': details,
        'lock_actions': [
            'ban_betting',    # 禁止下注
            'ban_withdrawal',  # 禁止提现
            'ban_commission',  # 禁止佣金领取
        ],
    }

3.3 规则 C · 彩金类型识别

问题:不是所有"彩金"都要按自刷处理。

需要识别的彩金类型: - 邀请奖励 ⭐ —— 核心目标,自刷代理的主要套利点 - 首充彩金 —— 真实新人也会领,需要结合 IP 判定 - 活动彩金 —— 真实活跃用户也会领,不应因 IP 碰撞就扣 - VIP 周/月奖励 —— 自动发放,不涉及自刷 - 签到彩金 —— 每日固定,不涉及自刷 - 红包雨 —— 金额小,不涉及自刷

建议 API 返回中明确标注每笔彩金的类型,让判定引擎按类型决定是否扣除。


四、API 接口设计

4.1 端点

GET /api/risk/agent-withdrawal-audit

4.2 认证

Authorization: Bearer <API_TOKEN>

4.3 请求参数

参数 类型 必填 说明
order_id string 提现订单号

示例:

curl -X GET \
  "https://api.platform-a.example.com/api/risk/agent-withdrawal-audit?order_id=WO20260411001" \
  -H "Authorization: Bearer abc123..."

4.4 响应 Schema(完整)

{
  "order_id": "WO20260411001",
  "platform": "platform_a",
  "agent": {
    "user_id": 10001,
    "username": "agent_xiaoming",
    "register_ip": "103.45.67.89",
    "last_login_ip": "103.45.67.90",
    "balance": 8500.00,
    "withdrawal_amount": 5000.00,
    "total_commission_earned": 12000.00,
    "total_deposit": 500.00,
    "registered_at": "2026-01-15T10:30:00+07:00"
  },
  "downlines": [
    {
      "user_id": 10010,
      "username": "user_001",
      "register_ip": "103.45.67.91",
      "last_login_ip": "103.45.67.92",
      "registered_at": "2026-01-16T14:20:00+07:00",
      "current_balance": 150.00,
      "total_deposit": 100.00,
      "bonus_history": [
        {
          "type": "invite_reward",
          "amount": 88.00,
          "granted_at": "2026-01-16T14:25:00+07:00",
          "balance_before": 12.00,
          "deposit_between": false,
          "deposit_amount_between": 0,
          "profit_after": 45.00
        }
      ]
    }
  ],
  "risk_analysis": {
    "ip_collision": {
      "has_collision": true,
      "collisions": [
        {
          "type": "agent_vs_downline",
          "agent_ip": "103.45.67.89",
          "downline_id": 10010,
          "downline_ip": "103.45.67.91",
          "reason": "代理注册 IP 103.45.67.89 与下级 10010 注册 IP 103.45.67.91 同 /24 子网"
        }
      ]
    },
    "balance_tracing": {
      "suspicious_downlines": [
        {
          "user_id": 10010,
          "balance_before_bonus": 12.00,
          "bonus_amount": 88.00,
          "profit_after_bonus": 45.00,
          "deposit_between": false,
          "suggested_clawback": 133.00,
          "suggested_keep": 12.00
        }
      ]
    }
  },
  "recommendation": {
    "action": "reject_and_clawback",
    "confidence": "high",
    "reason": "代理与下级 10010 存在 IP 碰撞,且该下级账户余额主要来自邀请奖励后的自刷盈利",
    "suggested_clawback_total": 133.00,
    "suggested_lock_actions": [
      "ban_betting",
      "ban_withdrawal",
      "ban_commission"
    ],
    "evidence_summary": [
      "IP 碰撞:代理 103.45.67.89 vs 下级 10010 的 103.45.67.91(/24 同子网)",
      "下级 10010 领取邀请奖励前余额仅 12 元",
      "邀请奖励 88 元 + 后续游戏盈利 45 元,合计 133 元疑似自刷",
      "该下级彩金前后无充值记录"
    ]
  },
  "human_readable_summary": "⚠️ 建议驳回:\n- 代理与 1 名下级 IP 碰撞\n- 该下级领取邀请奖励 88 元前余额仅 12 元\n- 领奖后游戏盈利 45 元\n- 建议扣除 133 元并锁定下注/提现/佣金权限",
  "api_version": "v1",
  "generated_at": "2026-04-11T15:03:00+07:00"
}

4.5 错误响应

HTTP Error Code 含义
400 INVALID_ORDER_ID 订单号格式错误
401 UNAUTHORIZED Token 错误
403 IP_NOT_ALLOWED 调用方 IP 不在白名单
404 ORDER_NOT_FOUND 订单不存在
409 ORDER_NOT_AGENT_WITHDRAWAL 不是代理提现订单,不适用此 API
500 INTERNAL_ERROR 后台错误

五、安全设计

5.1 IP 白名单

  Telegram Bot 服务器
       │
       │ IP: 203.0.113.42
       ▼
  后台 API 网关
       │
       │ 防火墙规则:
       │   allow 203.0.113.42/32
       │   deny all others
       ▼
  API 端点

实施要点: - 只允许 Telegram Bot 所在服务器 IP 访问 - 如果 Bot 部署在 Cloud Run / Lambda 这类动态 IP 环境,改用 VPC Peering静态出口 IP - Bot 服务器做好加固:SSH 限 IP / 只装必要软件 / 定期补丁

5.2 Token 认证

  Authorization: Bearer <token>
  • Token 长度 ≥ 32 字节
  • 存储在 Bot 服务器的环境变量(不入代码库)
  • 每季度轮换一次
  • 泄漏应急流程:立刻作废,重新生成

5.3 只读 API

铁律:本 API 只查询、不修改。任何"驳回订单/锁定账户/扣款"动作都必须人工在后台执行

理由: - 即使 IP 白名单 + Token,一旦被绕过,只读 API 最多泄漏数据;有写权限的 API 会造成直接资金损失 - 判定结果返回给人,由副组长确认后再执行,保留人类审核环节

5.4 审计日志

后台必须记录:

{"timestamp":"2026-04-11T15:03:00Z","caller_ip":"203.0.113.42","order_id":"WO20260411001","agent_id":10001,"result":"reject_and_clawback","latency_ms":245}

用于: - 异常检测(调用频率突增 → 告警) - 事后审计 - 性能监控


六、Telegram Bot 交互设计

6.1 命令格式

/check <order_id>

6.2 交互示例

副组长发送:

/check WO20260411001

Bot 回复:

📋 订单 WO20260411001 审核结果

🎯 建议:❌ 驳回并扣款
置信度:高

📊 风险分析:
• IP 碰撞:代理 vs 下级 10010 (/24 同子网)
• 下级 10010 领奖前余额仅 12 元
• 邀请奖励 88 元 + 后续盈利 45 元
• 无有效充值记录

💰 建议扣款:133 元
🔒 建议锁定:下注 / 提现 / 佣金领取

📎 证据链:
1. 代理 IP 103.45.67.89 vs 下级 10010 IP 103.45.67.91
2. 余额溯源:12 → 领奖 88 → 盈利 45 → 当前 150

⏱ 审核耗时:245ms
🕐 生成时间:15:03:00

6.3 进阶:交互式按钮

[✅ 已按建议处理]  [❌ 我决定不采纳,原因:____]

点击后 Bot 记录决策日志,用于日后回顾判定引擎准确率。

6.4 Bot 核心代码(Python 参考)

# bot.py
import os
import httpx
from telegram import Update
from telegram.ext import Application, CommandHandler, ContextTypes

API_BASE = os.environ['API_BASE']           # 后台 API 根 URL
API_TOKEN = os.environ['API_TOKEN']         # Bearer token
BOT_TOKEN = os.environ['TG_BOT_TOKEN']      # Telegram Bot token

async def check_order(update: Update, context: ContextTypes.DEFAULT_TYPE):
    """处理 /check <order_id> 命令"""
    if not context.args:
        await update.message.reply_text('用法:/check <订单号>')
        return

    order_id = context.args[0]

    async with httpx.AsyncClient() as client:
        try:
            resp = await client.get(
                f'{API_BASE}/api/risk/agent-withdrawal-audit',
                params={'order_id': order_id},
                headers={'Authorization': f'Bearer {API_TOKEN}'},
                timeout=10.0,
            )
            resp.raise_for_status()
        except httpx.HTTPError as e:
            await update.message.reply_text(f'❌ API 错误:{e}')
            return

    data = resp.json()
    summary = data.get('human_readable_summary', '无结果')

    await update.message.reply_text(
        f'📋 订单 {order_id} 审核结果\n\n{summary}',
        parse_mode='Markdown',
    )

def main():
    app = Application.builder().token(BOT_TOKEN).build()
    app.add_handler(CommandHandler('check', check_order))
    app.run_polling()

if __name__ == '__main__':
    main()

七、预期收益

7.1 时间节省

维度 当前(人工) 自动化后 节省
单次审核耗时 5~15 分钟 10 秒 ~95%
每天总耗时(假设 30 单) 150~450 分钟 5~10 分钟 2~7 小时/天
每月节省 60~210 小时/月

7.2 错误率

维度 当前 自动化后
IP 碰撞漏判 存在(眼花) 0(算法覆盖所有组合)
余额计算错 存在(心算) 0(数据库直查)
彩金类型混淆 偶发 0(明确分类)
决策一致性 值班人之间有差异 完全一致

7.3 副产品

  • 审计链 —— 每次判定的完整证据链入库,方便事后追溯
  • 新人友好 —— 新上任副组长不用再记那一堆复杂规则,看机器人输出就行
  • 判定规则版本化 —— 规则调整后所有人同时生效,不用逐个通知

八、实施路线

8.1 Phase 0 · 对齐与评审(本文档)

副组长整理需求 → 技术 Leader 评审 → 安全团队 review IP 白名单方案

8.2 Phase 1 · 只读 MVP

后台工程师开发: - [x] API 端点 - [x] IP 归一化函数 - [x] 余额溯源查询 - [x] 判定引擎(可先用简化版) - [x] 审计日志

验收:手动 curl 能拿到完整 JSON,返回内容可人工复核

8.3 Phase 2 · Telegram Bot 接入

  • [ ] 部署 Bot 到 VPS
  • [ ] 配置 IP 白名单
  • [ ] Token 下发
  • [ ] /check 命令

验收:在 Telegram 里发订单号能收到判定结果

8.4 Phase 3 · 规则精调

副组长用 1 周,人机并行跑: - 每单都既手工审核又发给机器人 - 对比两者结论 - 差异的单独拉出来分析(是机器错还是人错) - 根据对比结果调整判定规则

8.5 Phase 4 · 全量切换

副组长默认信任机器人输出,只在机器人标 confidence: low 时人工复核

8.6 Phase 5 · 持续优化

  • 把机器人输出的"可扣款金额"和"锁定建议"做成按钮,一键执行(此时才需要写权限 API,安全要求更高)
  • 加入对"首充彩金""活动彩金"等更多彩金类型的精细化判定
  • 把判定引擎迁移成规则引擎(如 Drools / JSONLogic),运营能自助调参

九、测试用例(给后台开发参考)

用例 1:清白代理(无 IP 碰撞)

输入:
  order_id: WO_CLEAN_001
  代理 IP: 192.168.1.10
  下级 1 IP: 203.0.113.25
  下级 2 IP: 198.51.100.48
  (所有 IP 均不同子网)

期望输出:
  recommendation.action: approve
  risk_analysis.ip_collision.has_collision: false

用例 2:代理自刷(IP 碰撞 + 彩金自刷)

输入:
  order_id: WO_DIRTY_001
  代理 IP: 192.168.1.10
  下级 1 IP: 192.168.1.20  (同 /24)
  下级 1 彩金前余额: 0
  下级 1 彩金: 88
  下级 1 彩金后盈利: 50
  下级 1 无充值

期望输出:
  recommendation.action: reject_and_clawback
  recommendation.suggested_clawback_total: 138
  risk_analysis.ip_collision.has_collision: true

用例 3:IPv6 同网段

输入:
  代理 IP: 2001:0db8:85a3:0000:0000:8a2e:0370:7334
  下级 IP: 2001:0db8:85a3:ffff::1

期望输出:
  has_collision: true  (前 3 段都是 2001:0db8:85a3)

用例 4:IPv4 边界(相邻 /24)

输入:
  代理 IP: 192.168.1.255
  下级 IP: 192.168.2.0

期望输出:
  has_collision: false  (/24 不同)

用例 5:下级领彩金前有真实余额 + 有充值

输入:
  代理 IP vs 下级 IP: 碰撞
  下级 彩金前余额: 500
  下级 彩金: 88
  下级 彩金前后充值: 200
  下级 彩金后盈利: 100

期望输出:
  action: reject_and_clawback
  suggested_clawback: 88 + 100 - 200 = -12  (特殊情况)
  → 实际应按"保留 500 + 200 充值"处理,
    只扣除彩金 88 + 彩金后盈利 100 中能归因到自刷的部分

  ⚠️ 这是一个边界 case,需要和副组长对齐精细规则

备注:用例 5 暴露了一个规则细化点 —— 当下级确有部分真实行为时,如何精确切分"自刷部分"?这是 Phase 3 规则精调阶段要解决的问题。


十、风险与兜底

10.1 机器判错怎么办

兜底 1:人工复核环节不删

  • Bot 只给建议,副组长最终拍板
  • 不建议 Phase 1 就做"全自动驳回"

兜底 2:置信度字段

  • API 返回 confidence: high / medium / low
  • low 的强制人工复核
  • 例:IP 归一化结果恰好临界、余额溯源找不到明确的彩金记录

兜底 3:决策审计

  • 每次判定记录到 DB
  • 如果后来发现判错,可以查历史还原

10.2 API 挂了怎么办

  • Bot 收到 500 / 超时 → 回复"API 异常,请人工审核"
  • 不要降级为"默认通过" —— 宁可卡住不处理,也别放过欺诈单

10.3 规则漏洞

  • 留意代理反侦察:可能故意换设备换 IP 伪装
  • 引入设备指纹作为第二道检测(Phase 5)
  • 引入注册时间聚集作为第三道检测

十一、给技术团队的开发清单

[ ] 1. 后台开发
    [ ] 新建 /api/risk/agent-withdrawal-audit 端点
    [ ] 实现 IP 归一化函数(IPv4 /24, IPv6 /48)
    [ ] 实现 IP 碰撞检测(代理 vs 下级, 下级 vs 下级)
    [ ] 实现余额溯源查询(按时间倒序遍历账变)
    [ ] 实现判定引擎(基于 recommend_action 伪代码)
    [ ] 完整单元测试(用第九节的 5 个用例)
    [ ] 审计日志落库

[ ] 2. 安全配置
    [ ] IP 白名单(只允许 Bot 服务器)
    [ ] Bearer Token 签发
    [ ] Token 存 .env,不入代码
    [ ] 每季度轮换计划

[ ] 3. 运维
    [ ] 部署到测试环境
    [ ] 副组长联调(用历史订单作为测试数据)
    [ ] 上线
    [ ] 监控:QPS / 延迟 / 错误率
    [ ] 告警:延迟 > 5 秒 / 错误率 > 5%

[ ] 4. Telegram Bot
    [ ] 部署到 VPS
    [ ] 环境变量配置
    [ ] /check 命令
    [ ] 人机并行跑 1 周
    [ ] 规则精调
    [ ] 全量切换

十二、附录

12.1 术语表

术语 含义
代理 iGaming 平台的推广人,通过邀请下级赚取佣金
下级 被代理邀请注册的用户
自刷 代理创建小号,自己存钱下注,套取返水/佣金/邀请奖励
IP 碰撞 多个用户共享相似 IP,暗示他们是同一物理设备
/24 子网 IPv4 的一个 C 类子网(前 24 位相同)
/48 子网 IPv6 的一个子网(前 48 位相同)
彩金 平台发放的奖金类余额(邀请/首充/活动/签到/VIP 等)
余额溯源 从当前余额倒推资金来源的过程

12.2 参考资料

12.3 IP 地址归一化的数学基础

  • IPv4 /24 = 前 24 位 = 前 3 个字节 = X.X.X 前缀
  • IPv6 /48 = 前 48 位 = 前 3 组 16 位 = X:X:X 前缀
IPv4: 192.168.1.23
      ┬───┬───┬──
      │   │   │   └─ 最后 1 字节 = host (忽略)
      └───┴───┴───── 前 3 字节 = /24 network

IPv6: 2001:0db8:85a3:0000:...
      ┬────┬────┬────┬────
      │    │    │    └─ 后续位 (忽略)
      └────┴────┴────── 前 3 组 = /48 network

这个前缀匹配对应的是网络层面的"同一家庭/办公室/局域网",是 iGaming 风控的经典判定方法。