小票打印
后端 POST 一次,门店的热敏小票机就出纸。ESC/POS 指令原样直通,PDF 交给本地驱动渲染,打没打出来由 Webhook 告诉你。
打印机离收银员一米,离你的服务器隔着整个 NAT。这段距离就是问题本身。
window.print() 会弹对话框、选不了小票机,也不告诉你纸有没有出来。kiosk 启动参数能用,直到某次 Windows 更新把默认打印机换掉。
你的服务跑在机房,打印机在门店路由器后面。把 9100 端口暴露到公网不是任何人该选的方案。
驱动会重排 ESC/POS,纸会在班中用完,线会被踢掉。没有状态回传,你只能等顾客问「我的小票呢」。
门店侧一条外发连接,你这边一次 REST 调用。不用 VPN、不用端口映射、不暴露任何设备。
门店里任意一台电脑,Windows / macOS / Linux 都行。本机装过的打印机自动注册,每台拿到一个数字 printer_code。
用 content_type: raw 发 ESC/POS 拿到字节级一致的输出,或者发 PDF 交给本地驱动渲染。按 printer_code 指定机器,而不是靠用户上次选了什么。
任务沿 queued → dispatched → printing → completed 推进,终态由带签名的 Webhook 推回来,失败时附原因码。
import { renderReceipt } from './receipt.js';
// ESC/POS 字节:对齐、加粗、条码、切纸,你怎么写就怎么到打印机
const escpos = renderReceipt(order);
await fetch('https://api.printbase.cloud/v1/print-jobs', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PRINTBASE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
printer_code: store.receiptPrinterCode, // 来自你的门店 -> 打印机映射表
content_type: 'raw', // 'pdf' 则交给本地驱动渲染
content: escpos.toString('base64'),
copies: 1,
}),
});content_type: raw 表示字节原样透传,所以同一张小票在每台机器上打出来都一样——不经过打印 CSS,也不被驱动重新解释。
只要是「某张小票必须从某个地点的某台机器出来、且不该由人来选」的场景。
收银员点结账,小票就出来。不弹对话框、不选打印机、不用一小时点四十次。
后厨单进后厨机,顾客小票进前台机——同一段代码,换一个 printer_code。
网上下的单,支付成功几秒内就在门店、仓库或后台打出来。
取票、排队号、寄存码,没有浏览器对话框,机器上也不需要有人登录。
对齐、加粗、倍高、指定代码页的文字、条码、切纸指令,写成什么样到打印机就是什么样。
发 PDF 由本地驱动渲染,适合你的报表系统已经能生成 80mm 版式的情况。
completed 或 failed,附 PRINTER_OFFLINE、PRINT_ERROR 等五种原因码,以及打印机名和电脑名——告警能直接说清是哪家店的哪台机器。
按门店或客户拆组织、发带作用域的 API key,不额外收费,也不需要单独买一个多租户套餐。
可以。把 content_type 设为 raw,内容用 base64 编码,字节会原封不动到达打印机,包括条码、指定代码页的文字和切纸指令。
只要装 Agent 的那台电脑能打的都支持。走 RAW 时,打印机需要能理解你发的指令——绝大多数热敏小票机是 ESC/POS,如爱普生、Star、佳博、芯烨及兼容机型。
把文字按打印机的代码页编码(国产机型多为 GBK)再以 raw 发送。PrintBase 不改动字节,编码完全由你控制。
订阅 Webhook。PrintBase 会推送带签名的 print_job.completed 或 print_job.failed,失败时带 PRINTER_OFFLINE 这类原因码,以及打印机名和电脑名。也可以轮询 GET /v1/print-jobs/{id}。
可以。在自己库里存一张门店到 printer_code 的映射表按门店路由即可;需要更强隔离时,组织功能在所有套餐里都包含。
有。每月 100 个打印任务、1 台电脑,永久免费,不用绑卡。