资讯详情

资讯详情

免验证码话费余额查询:HTML+API接口实现跨运营商快速查询

简介面向有自助查询话费余额需求的开发者和普通用户这套移动、电信、联通话费余额查询HTML源码与API接口资源无需验证码即可实时返回结果并支持自动识别运营商遇到携号转网号码时手动选择运营商即可。压缩包共6个文件以HTML页面为主配CSS样式、JS逻辑和2张PNG示意图片整体约133KB页面入口直观逻辑、样式与页面结构分离便于直接部署或二次开发。资源目前已吸引612人学习适合快速搭建话费查询demo、接入个人网站也可作为运营商查询接口的调用范例。开发者只需将源码中的apiKey替换为自己注册获取的密钥即可继续使用平台赠送的免费查询次数即便不熟悉配置也可借助评论区技术支持完成体验使用门槛较低。1. 免验证码话费余额查询一个HTML加接口搞定的跨运营商小工具客服系统里要查一个号码的话费余额传统做法是往用户手机上发条短信验证码等用户回填一次查询没个一分钟下不来。而这份移动电信联通手机话费余额查询HTML源码加配套的API接口把三大运营商的查询通道聚合在同一个页面里免去了验证码环节拿到号码点下查询就能看到余额。对做客服后台、话费报销核对、个人自用工具的人来说它省掉的是最磨人的等待环节留下的是一个能快速接入现有系统的轻量接口。整份资源由前端页面、查询接口和运营商通道配置三部分组成想快速搭一套查询工具、又不想重新造轮子的开发者可以直接拿来做底座。2. 技术构成与整体架构前端号段识别、查询接口与通道配置怎么协作这份资源的核心结构很收敛就是“前端页面 一个查询接口 多个上游通道配置”。前端负责收集手机号和展示结果接口负责把号码路由到对应的运营商通道上游返回原始数据后接口再做一次清洗统一成固定 JSON 吐给页面。整个过程不依赖数据库也不绑定复杂框架用 Python 或 Node 都能把接口部分跑起来。为什么把结构设计得这么简单因为话费查询这种工具型页面热点在“查得快、结果准”不在页面特效。多套一层服务就多一个故障点把核心逻辑收敛成一条单链路后续接监控、加缓存、换通道都更方便。下面按前端、后端、目录配置三个维度拆开看。2.1 号码输入与运营商初判号段表在前端的作用用户在输入框里填入 11 位手机号后前端第一件事不是立刻发请求而是先用号段表判断这个号码属于移动、电信还是联通。这样做有两个好处一是能提前拦住明显非法的号码二是可以在界面上直接展示运营商名称让用户确认后再发起查询减少误查。项目里的号段判断逻辑通常放在query.js中常见写法是根据号码前三位匹配运营商前缀表// 常见号段前缀实际使用时以项目里最新的 number_prefix.json 为准 const OPERATOR_PREFIX { cmcc: [134, 135, 136, 137, 138, 139, 150, 151, 152, 157, 158, 159, 172, 178, 182, 183, 184, 187, 188, 195, 197, 198], ctcc: [133, 149, 153, 173, 174, 177, 180, 181, 189, 190, 191, 193, 199], cucc: [130, 131, 132, 145, 146, 155, 156, 166, 167, 171, 175, 176, 185, 186, 196] }; function detectOperator(phone) { const prefix phone.slice(0, 3); for (const op in OPERATOR_PREFIX) { if (OPERATOR_PREFIX[op].includes(prefix)) return op; } return unknown; }这段代码的核心是phone.slice(0, 3)截取号码前三位再在三个运营商的号段数组里做查找。参数phone要求是 11 位数字字符串返回值cmcc、ctcc、cucc分别对应移动、电信、联通unknown表示号段表里没有匹配项。注意这里的前缀表不是全量号段实际应全部替换为项目内置的最新表。需要特别说明的是前端号段识别只承担“初判”职责真正路由时以后端接口结果为准。原因是号段表是静态的而号码可能已经携号转网前端识别结果只用于展示和提示。接着页面通过fetch发起查询async function queryBalance(phone) { // _t 参数是时间戳防止浏览器或中间层缓存 const url /query?phone encodeURIComponent(phone) _t Date.now(); const resp await fetch(url); const json await resp.json(); if (json.code 0) { renderResult(json.data); // data 里是余额、运营商、查询时间 } else { renderError(json.msg); } }这段交互代码把查询请求收敛成一个queryBalance函数页面里不管是按钮点击还是回车事件最终都调它。phone参数需要做一次encodeURIComponent防止特殊字符破坏 URL_t是防缓存的通用做法因为部分浏览器对 GET 请求有缓存偏好加时间戳后能保证每次点击都打到接口。返回结果里code 0才是成功其余情况都走错误分支这个约定在后面接口设计中会保持一致。2.2 后端查询接口一个 /query 入口统一返回三类运营商数据后端只暴露一个接口入口前端完全不用关心某个号码到底走哪家通道。这种设计的价值在于将来换了通道地址、加了新的运营商识别规则前端代码可以不动只需要后端在server.py里做调整。接口内部做四件事参数校验、运营商识别、通道转发、结果清洗。以常见的 Flask 写法为例import re from flask import request, jsonify app.route(/query, methods[GET]) def query_balance(): phone request.args.get(phone, ).strip() # 1. 参数校验必须是以 1 开头的 11 位数字 if not re.match(r^1\d{10}$, phone): return jsonify(code400, msg手机号格式不正确, dataNone) # 2. 识别运营商 operator route_by_number(phone) # 3. 读取对应通道配置并转发请求 channel_url load_channel_url(operator) raw forward_channel(channel_url, phone) # 4. 清洗结果统一返回 return jsonify(code0, msgsuccess, datanormalize_result(raw, operator, phone))接口的参数是 URL Query 里的phone校验正则^1\d{10}$能挡住空值、非数字、位数不对的输入。route_by_number负责把号码映射成运营商标识load_channel_url从配置里取对应通道地址forward_channel真正请求上游normalize_result在最后做数据统一。四个函数各管一段后续单独排查哪一步出了问题都方便。对外返回的 JSON 结构固定为三层code0 表示成功非 0 为错误码便于前端直接判断msg人类可读的提示信息错误时直接展示给用户data查询数据包含phone、operator、balance、unit、update_time这个统一返回格式是整个项目最重要的约定之一。上游通道返回的数据再乱到了边界层都必须收敛成同一套结构否则前端就要写一堆针对不同通道的判断那就违背了这份资源“轻量可改”的初衷。2.3 目录结构与配置文件拆开看这份资源由哪些文件组成整个项目从目录上分成三块静态页面、接口服务、配置与数据文件。拿到源码后先对照这张表确认文件用途跑起来会顺手很多文件作用index.html查询页面包含号码输入框和结果展示区assets/js/query.js号段识别、请求发送、结果渲染逻辑server.py接口服务校验参数、路由号码、转发通道config.json通道地址、超时、缓存、Mock 开关配置number_prefix.json号段表与前端识别逻辑同步维护config.json是二次开发时最先要碰的文件。典型内容长这样{ mock: true, channel: { cmcc: 请替换为移动通道地址, ctcc: 请替换为电信通道地址, cucc: 请替换为联通通道地址 }, timeout: 8, cache_ttl: 300, rate_limit: 10 }各键含义mock为true时接口不真正请求上游直接返回模拟余额方便先跑通页面channel里填的是各运营商查询通道的网关地址正式对接时替换成自己账号下的地址timeout是上游请求超时秒数cache_ttl是同一个号码的结果缓存时间rate_limit是接口侧每分钟最大查询数。我一般会把号段表单独拆成number_prefix.json而不是直接写死在页面里就是为了让前后端共享同一份数据。改号段时只动一个文件避免出现前端识别成联通、后端路由成移动这种低级不一致。3. 部署运行与联调本地起服务到第一次查出号码余额很多新手拿到这种“HTML源码接口”的资源第一反应是直接双击打开index.html然后发现页面报错、数据出不来。原因是浏览器直接打开本地文件时前端脚本请求接口会触发跨域限制。正确做法是先把整个项目放到本地服务下运行让页面和接口处于可访问状态再做联调。3.1 本地启动标准库静态服务加接口服务的组合跑法如果机器上已经装了 Python用标准库就能完成启动不需要额外pip install。打开两个终端窗口分别执行# 终端一把前端页面跑在 8080 端口 python -m http.server 8080 --directory ./web # 终端二把接口服务跑在 8000 端口 python server.py第一条命令里的-m http.server是 Python 内置的静态文件服务8080是端口号--directory ./web指定页面文件所在目录第二条命令直接运行接口脚本。两条命令的作用不同前者负责把 HTML、JS 这些静态资源发给浏览器后者负责处理/query这类动态请求。如果不想开两个端口也可以用一个支持静态资源和接口路由的框架把所有请求收在一起。常见做法是用 Node 起一个单文件服务既托管静态页面又挂/query路由天然同源省掉跨域配置。两种方式效果一样选自己顺手的即可。启动后query.js里设置的接口地址要和实际端口对应。方式一般有两种// 方式一跨端口时写全地址 const API_BASE http://127.0.0.1:8000; // 方式二同源部署时留空 const API_BASE ;两种方式的区别在于请求到底打到哪个服务。跨端口部署时接口地址必须写全否则浏览器会向页面所在端口的/query发请求结果就是 404同源部署时留空即可让请求自动走当前域名和端口。3.2 通道配置与 Mock 开关没有真实通道也能先跑通真实环境里的运营商查询通道对接通常要处理签名、白名单、内网访问等问题第一次跑项目最容易卡在这一步。这份资源的处理方式是给config.json增加一个mock开关mock为true时接口不发起真实请求直接返回一组固定的模拟余额让前端流程先完整跑通。服务端的 Mock 逻辑一般长这样if config.get(mock): return { balance: 88.60, unit: yuan, update_time: int(time.time()) }这段代码的含义是只要配置里mock是trueforward_channel就直接返回一个写死的余额结果不再走网络请求。这样在没有拿到上游通道地址之前也能验证页面渲染、错误提示、号码校验这些逻辑是否正确。切换真实通道时把config.json里channel对应键位的地址替换成自己的网关地址再把mock改成false即可。替换后建议先用curl单独测一遍接口确认上游通了再回到页面上做完整操作。提示Mock 返回的数据字段务必和真实通道保持一致否则切换时会漏改前端或清洗逻辑。3.3 联调验证curl 命令、浏览器 Network 面板与返回字段检查服务启动后先在终端里用curl做一次接口自测这能帮助你快速判断是接口问题还是页面问题curl http://127.0.0.1:8000/query?phone13800138000正常情况下会得到一个 JSON结构类似这样{ code: 0, msg: success, data: { phone: 13800138000, operator: cmcc, balance: 88.60, unit: yuan, update_time: 1750000000 } }拿到响应后依次检查三点code是否为 0operator是否和号段对应这里138开头应为cmccbalance是否是一个合理的数值。update_time是秒级时间戳确认它和当前时间差距不大避免拿到缓存过期或上游时间异常的数据。curl 通了之后再打开浏览器访问页面输入号码点击查询按 F12 打开 Network 面板找到名为query的请求看它的响应体是否和 curl 结果一致。如果页面报错而 curl 正常问题一般出在前端代码如果 curl 就报错问题在后端或上游通道。用这个顺序排查大多数联调问题都能在十分钟内定位。4. 常见问题与避坑号段误判、接口限流和返回格式差异这类查询项目用起来不复杂但真跑到线上踩坑的点往往集中在号段、限流和返回格式三块。这一章直接把常见问题按“现象 → 原因 → 解决”列出来每条都是实际开发里会遇到的。4.1 号段更新不及时导致运营商识别错误现象输入一个较新的手机号页面提示“无法识别运营商”或者把号码识别成错误的运营商查询结果自然也不对。原因运营商不定期放新号段而项目里的号段表是静态维护的一段时间不更新就会出现匹配不到或误匹配的情况。解决定期更新number_prefix.json。项目通常会附带一个更新脚本常见命令是python check_operator.py --update-prefix脚本会从上游拉取最新号段表并覆盖本地文件。如果项目没带脚本手动编辑 JSON 时注意保持格式一致。另外前端号段识别只用于展示路由和查询必须以后端接口为准不要在页面里把“号段等于运营商”当成绝对规则写死。4.2 查询频率过高触发通道限制现象连续查询五六个号码后接口返回“请求过于频繁”上游通道不再响应过一段时间才恢复。原因聚合查询通道对单 IP 或单个账号有频率限制短时间请求过多会被判定为异常访问。解决在后端加本地缓存同一个号码在cache_ttl时间内直接返回上次结果不重复请求上游cache.set(phone, result, excache_ttl)同时把rate_limit配置用起来在接口入口做每秒最大查询数限制超出时直接返回“请稍后再试”。遇到上游偶尔熔断可以做一次退避重试但如果连续失败两次就不要再试了等窗口期过去。真实项目里因为限流导致的服务不可用大多不是上游故意刁难而是自己没做缓存。4.3 携号转网号码按号段查询失败现象一个188开头的号码在页面上被识别成移动点击查询却提示“号码不存在”或者直接查询失败。188确实是移动的老号段但这个号码可能已经携号转网到联通或电信。原因识别依据是号段归属而不是号码当前实际所属网络。携号转网之后号码的网络归属和号段归属不一致了。解决接口侧在按原运营商通道查询失败后可以再做一次“换通道重试”并给前端返回一个提示字段try: return forward_channel(cmcc_url, phone) except ChannelError: data forward_channel(ctcc_url, phone) data[hint] 该号码可能已携号转网本次按电信通道查询 return data对用户体验来说提示“号码可能已携号转网”要比强行给出错误结果好得多。注意重试会增加一次上游请求要结合频率限制合理使用不能无条件重试两三次。4.4 余额单位不一致和缺失数据现象查询不同号码时返回的balance有时是88.60有时是8860个别号码还返回--或空字符串。原因不同通道的余额字段单位不一样有的以元返回有的以分返回已经销号或欠费异常的号码则可能返回占位符。解决在normalize_result清洗层统一处理。如果unit是fen就除以 100 转成元如果balance是--、空字符串或None直接置为null并让msg提示“暂无数据”。不要在页面上把--原样渲染给用户看。5. 核心模块代码拆解一次余额查询的完整请求链路前面章节已经把整体结构讲清楚了这一章深入到实现层把一次查询从“号码进来”到“结果返回”的完整请求链路拆成三个核心模块号码路由、请求转发、响应清洗。理解了这三段代码二次开发基本就有谱了。5.1 号码路由模块从号段表到通道选择号码路由是整个链路的入口职责是根据手机号前三位判断走哪家运营商的通道。Python 实现常见做法是加载号段表后做交集判断def route_by_number(phone: str) - str: prefix phone[:3] if prefix in NUMBER_PREFIX[cmcc]: return cmcc if prefix in NUMBER_PREFIX[ctcc]: return ctcc if prefix in NUMBER_PREFIX[cucc]: return cucc raise UnknownOperatorError(f未识别的号段: {prefix})参数phone是校验过格式的 11 位手机号函数先截取前三位prefix再依次在三个运营商的号段字典里查找。命中哪个就返回哪个运营商的短标识三个都不命中的时候抛出异常。这里有个设计细节值得注意路由失败时选择抛异常而不是默认返回cmcc或者其他运营商。原因很简单一个查不到号段的号码如果被强行路由到错误通道最后拿到的结果不会是对的反而浪费一次上游请求还会让用户看到无效数据。抛出异常后接口层可以把它转成一个明确的错误提示比如“无法识别该号码的运营商请核对号码”这对排查问题更友好。5.2 请求转发与超时控制把上游错误挡在返回层之前路由完成后服务端要根据配置的通道地址发起真实请求。这里需要重点处理超时和异常场景避免上游慢吞吞拖死整个页面。常见写法如下def forward_channel(channel_url: str, phone: str, timeout: float 8.0) - dict: try: resp requests.post(channel_url, json{phone: phone}, timeouttimeout) resp.raise_for_status() return resp.json() except requests.exceptions.Timeout: raise QueryTimeoutError(上游通道超时) except requests.exceptions.HTTPError: raise GatewayError(上游通道返回错误状态码) except requests.exceptions.JSONDecodeError: raise GatewayError(上游返回的不是合法JSON)参数channel_url是config.json里配置的通道地址phone是要查询的号码timeout默认 8 秒。请求用 POST 上传 JSON 体把手机号放在phone字段里这是多数查询通道的通用协议。超时时间设置成 8 秒而不是更长是因为客服场景下用户等太久就会关闭页面或重复点击。上游正常返回一般在 2~5 秒内8 秒已经能覆盖绝大多数情况超过就认定为失败。异常处理上超时、HTTP 错误码、非法 JSON 三种情况分别抛不同类型异常接口层可以针对不同异常给出不同提示也方便后续做监控告警。实际操作中还有一个细节不要在这里捕获所有异常然后返回一个空字典。如果上游失败却返回空结构清洗层会把这个空结构当成正常结果处理用户看到的是“成功但没数据”的假象比直接报错更难排查。宁可异常向上抛也要保证每次成功返回的都是真实数据。5.3 响应清洗与统一返回把各家结果规范成同一个JSON上游返回的数据格式往往五花八门有的把余额嵌在balance字段有的嵌在data.balance最近还要处理单位换算和缺省值。清洗层做的事情就是把这些差异收敛成统一结构def normalize_result(raw: dict, operator: str, phone: str) - dict: balance raw.get(balance) or raw.get(data, {}).get(balance) unit raw.get(unit, yuan) if balance in (None, --, ): balance None elif unit fen: balance round(float(balance) / 100, 2) return { phone: phone, operator: operator, balance: balance, unit: yuan, update_time: raw.get(update_time, int(time.time())) }这段代码里balance raw.get(balance) or raw.get(data, {}).get(balance)兼容了两种常见的上游返回结构unit fen时把分转成元并保留两位小数balance为None、--、空字符串时统一置为None避免把无意义字符传给前端。update_time字段的处理值得展开说优先使用上游返回的时间戳只有上游没给时才用服务器当前时间。原因是查询结果具有时效性如果上游返回的是后台缓存的数据用服务器当前时间会掩盖数据陈旧的问题做台账或趋势分析时时间不对会导致统计错位。清洗完成后接口层把结果包进统一 JSON 返回。到这里一次查询从号码进入到页面展示的完整链路就闭合了校验、路由、转发、清洗四个环节各自独立互不耦合任何一个环节出了问题都能单独定位。6. 二次开发方向台账记录、余额预警与更稳的查询习惯跑通查询功能只是第一步这类项目真正有价值的地方在于怎么把“查询”变成一个持续使用的服务。两个最常见的改造方向是把查询结果落库做台账以及定时查询做低余额预警。落库是最直接的刚需。客服平台里每次查询都应该留下记录方便后续核对“谁、什么时候、查了哪个号码、余额是多少”。在项目里加一张简单的 SQLite 表CREATE TABLE IF NOT EXISTS balance_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, phone TEXT NOT NULL, operator TEXT, balance REAL, update_time TEXT );接口每次成功查询后插入一条记录就能自然形成查询台账。更进一步可以写一个定时任务每天凌晨对一组常用号码做批量查询把结果持续写入这张表积累一段时间后就能看到余额变化趋势再配合阈值判断实现低余额提醒。预警功能可以挂在定时任务后面。批量查询完成后检测余额低于阈值比如 30 元的号码通过企业微信或钉钉机器人推送一条提醒消息。推送逻辑不复杂本质是把告警文本 POST 到机器人 Webhook 地址难的是避免重复告警所以建议把“已提醒状态”也落到表里例如追加一个alerted字段当天提醒过的号码不再重复推送。说到最后的习惯我以前在公司内部工具里吃过一亏上游通道返回的update_time有的是 GMT 字符串有的是毫秒时间戳我当时图省事统一用服务器当前时间覆盖结果月底对账时台账时间全乱了。从那以后我每次接查询类接口都强制要求响应里带上请求 ID 和统一格式的时间戳处理完上游数据后先把这两样落库再谈展示。这个习惯也推荐你保留。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →