技术博客
条码查询接口接入扫码枪收银:从「滴」一声到商品档案的完整架构

条码查询接口接入扫码枪收银:从「滴」一声到商品档案的完整架构

作者: 万维易源
2026-09-05
条码查询接口扫码枪收银缓存架构零售
# 条码查询接口接入扫码枪收银:从「滴」一声到商品档案的完整架构 > 接口:showapi 条码查询接口(apiCode=66)· 接入点 66-22(混合门店加 66-24)|请求方式:POST/GET|返回格式:JSON|适用人群:零售收银、进销存系统的开发者与架构师|阅读时间:约 8 分钟|最后实测核对:2026-09-05 **核心要点** - 收银场景的关键不是"会调接口",而是三层架构:扫码捕获 → 本地缓存 → 接口回退,缓存命中率决定成本。 - `note` 是混着原始库字段的拼接文本(实测 2026-09-05),商品档案入库时按文本提取,别当结构化字段。 - 失败不扣费(实测 5 次失败全部 fee_num=0),这让"66-24 先查、66-22 回退"的交叉策略零成本。 扫码枪"滴"一声之后的几百毫秒里,收银系统要完成捕获、查询、落库、出商品四件事。showapi 条码查询接口(apiCode=66)在这条链路里只负责一件事:查不到的商品档案,用一条条形码换回来。这篇讲完整架构和每一层的实现要点。 ## 数据流架构 ``` 扫码枪「滴」(键盘设备,输出条码 + 回车) ▼ ① 捕获层:始终聚焦的输入框,正则预检(6~14 位数字) ▼ ② 缓存层:barcode → 商品档案(SQLite / Redis,正缓存不过期) ├─ 命中:直接出商品,成本 0 └─ 未命中 ▼ ③ 回退层(失败不扣费,实测 2026-09-05): 66-22 查商品属性 ├─ ret_code=0 → ④ 落库(含图片下载)→ 出商品 ├─ 门店有药品 → 66-24 再查一次(拿用法用量) └─ 都失败 → ⑤ 人工快速录入(只填名称/售价/分类) ``` ## ① 捕获层:接住扫码枪 ```html <input id="scanner" autofocus placeholder="请扫商品条码" /> <script> document.getElementById("scanner").addEventListener("keydown", async (e) => { if (e.key !== "Enter") return; // 扫码枪以回车结尾 const code = e.target.value.trim(); e.target.value = ""; if (/^\d{6,14}$/.test(code)) await onScan(code); // 预检:位数不对不进接口 }); </script> ``` 枪型不发回车的,去硬件设置里开"回车后缀"。预检省掉的是注定失败的调用——格式错误虽然不扣费,但省一次网络往返。 ## ② 缓存层:正负缓存两张表 ```sql CREATE TABLE barcode_cache ( -- 查到的:长期缓存(条码映射基本不变) barcode TEXT PRIMARY KEY, payload TEXT NOT NULL, -- showapi_res_body 原样 JSON img_local TEXT, -- 转存后的本地图片路径 hit_count INTEGER DEFAULT 1, fetched_at INTEGER NOT NULL ); CREATE TABLE barcode_negative ( -- 查不到的:30 天负缓存(库会更新) barcode TEXT PRIMARY KEY, remark TEXT, expire_at INTEGER NOT NULL ); ``` 条码到商品信息的映射一经上市就不变,正缓存不用过期;未收录是长尾常态,负缓存 30 天防止同一支查不到的商品反复打接口。查询封装的完整 Python 实现(含 `classify` 判错)在字段全解篇。 ## ③ 回退层:路由与降级 ```python def on_scan(code: str, db, session): body = query_6622(code, db, session) # 先查商品点 if body is None and code.startswith("69"): body = query_6624(code, db, session) # 药品回退,失败不扣费 if body is None: return manual_entry(code) # 人工快速录入,收银不等接口 return to_pos_screen(body) ``` 实测事实支撑这个顺序:2026-09-05 五次失败请求全部 `showapi_fee_num=0`,交叉回退不加一分钱成本。66-24 未收录的文案是"条形码药品未收录",66-22 未收录是"条形码不正确,现在可支持 UPC EAN-13 EAN-8"或"未查到相关信息!",判定别依赖文案、用 `ret_code`。 ## ④ 落库层:字段取舍与图片转存 | 收银环节 | 用什么 | 为什么 | |---------|--------|--------| | 商品显示名 / 品牌 / 规格 | `goodsName` / `trademark` / `spec` | 直接可用 | | 分类归入 | `goodsType` 取 `>>` 末级挂类目树 | 层级文本,别整串塞进去 | | 结算价 | **自己的价格表** | `price` 是"参考价格"且实测常为空(2026-09-05),定价必须自己管 | | 商品图 | `img` 转存本地 | URL 24 小时时效(官方口径),`img_local` 存路径 | | 尺寸重量 | 基本别指望 | `width/depth/gw` 实测多为空;要重量上电子秤 | 图片转存脚本(超时 10s,失败不阻塞主流程,用后台任务重试): ```python import requests, pathlib def save_image(img_url: str, barcode: str, img_dir="img/") -> str | None: if not img_url: return None try: r = requests.get(img_url, timeout=10) path = pathlib.Path(img_dir) / f"{barcode}.jpg" path.write_bytes(r.content) return str(path) except requests.RequestException: return None ``` ## ⑤ 人工录入兜底 长尾商品查不到是常态(文档口径库 2000 多万条,不是全量)。录入窗只收名称、售价、分类三项,先卖货后补全;补录数据打上本地来源标记,之后走缓存不再出网。 ## FAQ **Q1:为什么正缓存不过期,数据改了怎么办?** 条码映射的商品基础信息(名称、厂商、规格)变化极少;真错了,删该条码缓存重查即可。真正时效敏感的是图片 URL,但它已经转存本地,不受缓存影响。 **Q2:负缓存为什么设 30 天而不是永久?** 条码库"不定期更新"(文档口径),今天未收录的下月可能有。30 天是起点,按你新品上架节奏调。 **Q3:断网时收银怎么办?** 接口是外部依赖,主流程不能等:缓存有就出商品,没有就人工录入,网络恢复后台补查。 **Q4:门店有进口商品,UPC 查不到怎么办?** 实测 2026-09-05 美国常见 UPC-A `049000050110` 未命中("未查到相关信息!")。进口占比高的门店,人工补录流程要当成主路径设计,不要当例外。 **Q5:这套架构和方案选型有什么关系?** 缓存命中率上去了,接口路线的单位成本才成立。选型层面的完整对比(自建 / 公开数据源 / 本接口)见方案对比篇。 ## 下一步阅读 - [条码查询接口返回字段全解:66-22 与 66-24 的字段差异和失败文案](https://www.showapi.com/guides/barcode-response-fields-66)——判错函数 `classify` 依赖的文案对照表。 - [商品条码信息怎么查:自建数据库、公开数据源与 showapi 条码查询接口对比](https://www.showapi.com/guides/barcode-plan-comparison-66)——这条技术路线值不值,先看这篇。 - [条码查询接口快速开始:一个 code 参数查出商品信息](https://www.showapi.com/guides/barcode-quickstart-66)——基础调用代码。 - **本系列共 6 篇**:查看[条码查询接口指南总目录](https://www.showapi.com/guides/barcode-guides-66)