Skip to content

收款播报(虚拟设备):部署与使用 ​

更新时间:2026/11/6 21:59:36

一部闲置的安卓手机,装上收款播报 APP 并激活后,就是一台「虚拟设备」:收款成功时手机语音播报到账金额,接上蓝牙小票打印机还能同时出票。不需要采购云音箱、云打印机等实体硬件,用最低成本补齐「听得到到账、留得下小票」的收款体验。

功能简介 ​

能力说明
语音播报收款成功后播报到账金额与收款渠道;播报语音内置在 APP 中,不依赖手机 TTS,也不消耗流量
小票打印连接蓝牙小票打印机(支持经典蓝牙 SPP 与 BLE)后,收款成功自动出票,支持 58 / 80mm 两种纸宽
在线状态APP 定时向平台上报心跳,运营端与商户端都能看到设备是否在线
应用级开关每个支付应用可独立开启 / 关闭语音播报与小票打印,并选择小票版式
试播 / 试打运营端与商户端的设备列表均提供测试入口,不发起真实收款即可验证播报与打印链路

两点设计边界,避免误判为故障:

  • 线上 API、易支付来源的订单默认不播报、不打印:该功能面向人工收银场景,接口类订单没有店内播报需求;
  • 播报内容经设备密钥加密,接入账号在消息服务侧只允许订阅、不允许发布,防止伪造到账消息(平台已内置,无需配置)。

部署前置:打通消息管道 ​

播报消息由平台经 MQTT over WebSocket(wss) 长连接推送到手机。这条管道必须先打通,否则设备激活成功也收不到任何播报——九成「激活了但不播报」的问题都出在这一步。按部署方式二选一:

部署方式路径
运维面板 / 一键部署路径一(推荐),面板上点几下即可
源码自行部署、自建消息服务路径二,手动配置 Artemis

路径一:运维面板部署(推荐) ​

面板用户在「网关管理 → MQTT 接入」页完成(该页的完整说明见网关管理 - MQTT 接入):

  1. 一键应用配置:在「Artemis MQTT 接入」状态卡点击「一键应用配置」,面板自动完成消息服务的接入配置并创建接入账号(app-device);
  2. 绑定接入域名:填裸域名(如 mqtt.example.com),手机的实际接入地址就是 wss://<该域名>,不需要再拼端口与路径。HTTPS 证书在外层(外层网关 / 负载均衡 / CDN)配置;
  3. 记下接入凭据:页面「接入凭据」卡中可见接入账号 app-device 的密码(可显示、复制),下一步要用;
  4. 平台侧回填:管理端「系统管理 → 系统配置 → 平台配置 → 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 端口:

xml
<acceptor name="mqtt-ws">tcp://0.0.0.0:61614?protocols=MQTT</acceptor>

② 设备消息地址策略:在 <address-settings> 段内新增——设备主题用完自动清理、消息短过期(防止长期离线设备堆积消息):

xml
<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 角色)只可订阅、禁止发布,防伪造下发:

xml
<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 管理员):

bash
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 升级头与放长的超时:

nginx
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://。

开通与使用流程 ​

管道打通后,从生成设备到听见播报共四步:

第一步:运营端生成设备并绑定 ​

运营端「虚拟设备 → 设备管理」(支付系统菜单下):

  1. 「生成设备」创建一台虚拟设备,设备号由系统自动生成(VD 开头);
  2. 在设备行「绑定商户」,把设备分配给商户并指定归属应用——未绑定商户的设备无法激活;
  3. 需要验证链路时,用设备行的「试播」/「试打」入口(试打可选择纸宽)。

TIP

删除商户前请先解绑或删除其名下设备,删除商户不会自动清理设备。

第二步:商户查看设备与激活二维码 ​

商户端「商户中心 → 基础管理 → 收款设备」可看到被绑定的设备,设备行提供激活二维码入口;也可在此调整归属应用、绑定门店、启停设备。

第三步:手机 APP 扫码激活 ​

  1. 安装收款播报 APP(安卓手机,服务器地址由安装包编译期内置,获取方式见APP 使用要点);
  2. 打开 APP 扫描商户端展示的激活二维码——二维码内容为 daxpay:activate:{设备号},仅携带设备号,扫码即完成设备激活;无法扫码时,在激活页手动填写设备号;
  3. 激活成功后 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 / 易支付来源的订单不播报默认静音设计,该功能面向人工收银场景
小票上的时间是北京时间对外票据统一使用东八区时间,与平台后台展示的时区设置无关

更多问题见 常见问题 - 收款播报收不到消息排查。

相关链接 ​