收款播报(虚拟设备):部署与使用
一部闲置的安卓手机,装上收款播报 APP 并激活后,就是一台「虚拟设备」:收款成功时手机语音播报到账金额,接上蓝牙小票打印机还能同时出票。不需要采购云音箱、云打印机等实体硬件,用最低成本补齐「听得到到账、留得下小票」的收款体验。
功能简介
| 能力 | 说明 |
|---|---|
| 语音播报 | 收款成功后播报到账金额与收款渠道;播报语音内置在 APP 中,不依赖手机 TTS,也不消耗流量 |
| 小票打印 | 连接蓝牙小票打印机(支持经典蓝牙 SPP 与 BLE)后,收款成功自动出票,支持 58 / 80mm 两种纸宽 |
| 在线状态 | APP 定时向平台上报心跳,运营端与商户端都能看到设备是否在线 |
| 应用级开关 | 每个支付应用可独立开启 / 关闭语音播报与小票打印,并选择小票版式 |
| 试播 / 试打 | 运营端与商户端的设备列表均提供测试入口,不发起真实收款即可验证播报与打印链路 |
两点设计边界,避免误判为故障:
- 线上 API、易支付来源的订单默认不播报、不打印:该功能面向人工收银场景,接口类订单没有店内播报需求;
- 播报内容经设备密钥加密,接入账号在消息服务侧只允许订阅、不允许发布,防止伪造到账消息(平台已内置,无需配置)。
部署前置:打通消息管道
播报消息由平台经 MQTT over WebSocket(wss) 长连接推送到手机。这条管道必须先打通,否则设备激活成功也收不到任何播报——九成「激活了但不播报」的问题都出在这一步。按部署方式二选一:
| 部署方式 | 路径 |
|---|---|
| 运维面板 / 一键部署 | 路径一(推荐),面板上点几下即可 |
| 源码自行部署、自建消息服务 | 路径二,手动配置 Artemis |
路径一:运维面板部署(推荐)
面板用户在「网关管理 → MQTT 接入」页完成(该页的完整说明见网关管理 - MQTT 接入):
- 一键应用配置:在「Artemis MQTT 接入」状态卡点击「一键应用配置」,面板自动完成消息服务的接入配置并创建接入账号(
app-device); - 绑定接入域名:填裸域名(如
mqtt.example.com),手机的实际接入地址就是wss://<该域名>,不需要再拼端口与路径。HTTPS 证书在外层(外层网关 / 负载均衡 / CDN)配置; - 记下接入凭据:页面「接入凭据」卡中可见接入账号
app-device的密码(可显示、复制),下一步要用; - 平台侧回填:管理端「系统管理 → 系统配置 → 平台配置 → MQTT 接入」页签,填入接入地址(
wss://mqtt.example.com)、接入账号与密码,保存。
接入域名不建议套 CDN
手机与消息服务之间是常驻长连接,多数 CDN 对长连接支持有限(超时短或直接断开),会造成设备频繁掉线、漏播报。接入域名请单独解析到源站 IP,或经支持 WebSocket 长连接的外层网关 / 负载均衡终结 HTTPS。
平台配置的生效时机
接入地址与账号随设备激活下发到手机;之后再修改这里的配置,已激活的设备不会自动切换,需要在 APP 中重新激活一次才使用新配置。
路径二:手动部署(自建 Artemis)
源码部署的用户系统本就依赖 Artemis 消息服务,在其 broker 上手动补齐以下配置即可。以下片段与运维面板自动注入的内容一致,可直接粘贴。
主题契约(Artemis 2.33+ / ARTEMIS-4532):设备订阅斜杠主题,平台发布点号多段 core 地址,两者由 broker 映射到同一地址:
| 方向 | 值 | 说明 |
|---|---|---|
| 设备订阅(激活下发) | daxpay/device/audio/{设备号} | APP 原样订阅;/ 是 MQTT 层级分隔符 |
| broker core 地址 | daxpay.device.audio.{设备号} | 斜杠主题映射为多段地址,ACL / address-setting 按此匹配 |
| 平台发布(JMS Topic) | daxpay.device.audio.{设备号} | 与订阅队列同址,broker 直接路由 |
不要用点号主题订阅,也不要发布转义字面量
Artemis 2.33+ 按 MQTT 官方语义处理主题:/ 是层级分隔符,. 是字面字符并被转义为 \.。设备若订阅点号 daxpay.device.audio.{设备号},实际落点是单段地址 daxpay\.device\.audio\.{设备号},不命中 security-setting match="daxpay.device.#",订阅会被拒(SUBACK 0x80,broker 日志通常没有明确原因);平台若发布到转义字面量 daxpay\.device\.audio\.{设备号},与斜杠订阅创建的多段队列不同址,消息会静默无人接收。设备凭证里的 topic 是激活时固化的,主题契约调整后存量设备必须重新激活一次。
① 开放 MQTT over WebSocket 接入端口:在 broker.xml 的 <acceptors> 段内新增 61614 端口:
<acceptor name="mqtt-ws">tcp://0.0.0.0:61614?protocols=MQTT</acceptor>② 设备消息地址策略:在 <address-settings> 段内新增——设备主题用完自动清理、消息短过期(防止长期离线设备堆积消息):
<address-setting match="daxpay.device.#">
<auto-delete-addresses>true</auto-delete-addresses>
<auto-delete-queues>true</auto-delete-queues>
<expiry-delay>600000</expiry-delay>
</address-setting>③ 设备地址权限矩阵:在 <security-settings> 段内新增——平台(amq 角色)可发布,接入账号(app-device 角色)只可订阅、禁止发布,防伪造下发:
<security-setting match="daxpay.device.#">
<permission type="send" roles="amq"/>
<permission type="createAddress" roles="amq"/>
<permission type="consume" roles="app-device"/>
<permission type="createNonDurableQueue" roles="app-device"/>
<permission type="createDurableQueue" roles="app-device"/>
<permission type="createAddress" roles="app-device"/>
</security-setting>权限必须列全
security-setting 按最具体地址匹配且不继承默认段的权限,本段必须完整列出 amq 与 app-device 双方所需的全部权限。缺了 amq 的 send / createAddress,平台无法发布播报;缺了 app-device 的 createAddress,手机先于平台订阅时会被拒绝——两种缺失在日志里都看不到明确原因。
Artemis 2.33+ 统一按斜杠主题
面板固定使用 apache/artemis:2.57.0-alpine;2.44 等其他 2.3x/2.5x 版本同样按上述斜杠主题订阅。旧文档中「订阅队列落址不匹配 daxpay.device.#,把 catch-all # 段的 consume/create 权限放宽给 app-device」的做法不再推荐:它只能绕过 ACL,不能修正点号订阅的地址映射,且会把全部地址的订阅权限开放给设备账号,违背最小权限。订阅始终失败时,先核对设备订阅主题是否为斜杠形态、后端是否已升级并重新激活,而不是放宽 #。
多角色写法
roles 属性写多个角色时必须逗号分隔(amq,app-device),用空格分隔在旧版本会静默失效;正常按上方精确矩阵授权时不需要多角色,此条仅用于核对既有配置。
④ 核心端口收窄:把 61616 端口 acceptor 的 protocols 参数中的 MQTT 删掉(若存在),让 61614 成为唯一 MQTT 入口;未声明 protocols 的可不处理。
⑤ 创建接入账号(在 Artemis 实例目录执行,<管理员账号> 为 broker 管理员):
cd /var/lib/artemis-instance
./bin/artemis user add \
--user '<管理员账号>' --password '<管理员密码>' \
--user-command-user 'app-device' --user-command-password '<自定义接入密码>' \
--role 'app-device'⑥ 重启 Artemis 使配置生效。
⑦ 对外暴露 wss 入口:生产环境由 nginx 等反向代理终结 HTTPS 并转发到 61614,注意 WebSocket 升级头与放长的超时:
server {
listen 443 ssl;
server_name mqtt.example.com;
# ... 证书配置 ...
location / {
proxy_pass http://127.0.0.1:61614;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 长连接空闲超时须大于客户端心跳间隔的两倍,过短会频繁掐线掉消息
proxy_read_timeout 180s;
proxy_send_timeout 180s;
proxy_buffering off;
}
}最后确认主应用能访问该 broker(主应用本就连着 Artemis 收发消息,同机部署无需额外动作),再到管理端「平台配置 → MQTT 接入」填入 wss:// 接入地址与 app-device 账号密码。内网调试时也可以临时用 ws://(非加密)地址,生产环境请使用 wss://。
开通与使用流程
管道打通后,从生成设备到听见播报共四步:
第一步:运营端生成设备并绑定
运营端「虚拟设备 → 设备管理」(支付系统菜单下):
- 「生成设备」创建一台虚拟设备,设备号由系统自动生成(
VD开头); - 在设备行「绑定商户」,把设备分配给商户并指定归属应用——未绑定商户的设备无法激活;
- 需要验证链路时,用设备行的「试播」/「试打」入口(试打可选择纸宽)。
TIP
删除商户前请先解绑或删除其名下设备,删除商户不会自动清理设备。
第二步:商户查看设备与激活二维码
商户端「商户中心 → 基础管理 → 收款设备」可看到被绑定的设备,设备行提供激活二维码入口;也可在此调整归属应用、绑定门店、启停设备。
第三步:手机 APP 扫码激活
- 安装收款播报 APP(安卓手机,服务器地址由安装包编译期内置,获取方式见APP 使用要点);
- 打开 APP 扫描商户端展示的激活二维码——二维码内容为
daxpay:activate:{设备号},仅携带设备号,扫码即完成设备激活;无法扫码时,在激活页手动填写设备号; - 激活成功后 APP 自动连接消息管道并进入后台监听,激活过程中的异常会有页面提示。
第四步:验证收款播报与打印
发起一笔小额收款(或用设备行的「试播」),手机应在收款成功后立即播报到账金额;连接了打印机的会同时出票。运营端与商户端设备列表中的在线状态随之更新。
按应用控制播报与打印
播报与小票打印按支付应用粒度控制,在两端的「应用管理」中配置(运营端「商户与应用 → 应用配置」、商户端「商户与应用 → 应用管理」的设备区块):
| 配置项 | 说明 |
|---|---|
| 语音播报 | 开关,关闭后该应用的收款不播报 |
| 小票打印 | 开关,关闭后该应用的收款不出票 |
| 小票版式 | 版式模板选择,当前内置「标准收款小票」一种 |
设备收款时按其归属应用的开关联动:播报与打印相互独立,可只播不印,也可只印不播。
APP 使用要点
- 获取与安装:APP 为安卓安装包(APK)。开源版可直接下载 daxpay-virtual-device-release.apk(当前 v0.1.0,Android 8.0+),也可从官网产品页与系统演示页的下载区获取;商业版安装包走商业版发布渠道。两版安装包可共存安装;
- 保活设置:为避免被手机系统清理,安装后按引导关闭对本应用的电池优化、允许自启动与后台弹出权限(各厂商设置路径略有差异)。被清理后重新打开 APP 即恢复监听;
- 连接打印机:在 APP 内连接蓝牙小票打印机(支持 SPP 与 BLE),并在 APP 中把纸宽设置(58 / 80mm)与实际用纸保持一致,纸宽不符会导致小票排版异常;
- 换用其他服务器环境的安装包会强制重新激活:服务器地址由安装包编译期内置,换用指向其他环境的安装包后 APP 会要求重新激活,防止新旧环境凭证混用——按提示重新扫码即可,属预期行为;
- 更多能力:桌面金额小部件、本机收款流水查询、免打扰时段等能力可在 APP 内使用。
常见问题
| 现象 | 说明与处理 |
|---|---|
| 激活成功但收不到播报 | 九成是 MQTT 消息管道不通(接入地址错 / 证书问题 / 消息服务未开放 61614 / 平台 MQTT 配置未填),按收款播报收不到消息排查逐步排查 |
| 收款了但不打印 | 依次检查:应用的「小票打印」开关是否开启、打印机是否已在 APP 内连接、APP 纸宽设置与实际用纸是否一致、打印机是否缺纸卡纸 |
| 换用其他服务器环境的安装包后 APP 提示重新激活 | 预期行为,防止新旧环境凭证混用;重新扫码激活即可 |
| 线上 API / 易支付来源的订单不播报 | 默认静音设计,该功能面向人工收银场景 |
| 小票上的时间是北京时间 | 对外票据统一使用东八区时间,与平台后台展示的时区设置无关 |
更多问题见 常见问题 - 收款播报收不到消息排查。
相关链接
- 网关管理 - MQTT 接入:面板侧消息管道配置详解
- 支付平台配置 - MQTT 接入:平台侧接入地址与账号配置
- 收款播报收不到消息排查:管道不通的完整排查步骤
- 移动端使用入门:各移动应用的定位区分