☰
自助设备扫码支付改造指南:从硬件选型到支付链路完整实现
2026/10/21 19:50:01 网站建设 项目流程

小区楼下那排自助洗衣机换过一次收费方式:投币口被堵死,侧面贴了一张二维码,扫一下、付款、选程序,滚筒就开始转。很多人觉得这就是“把投币器换成了扫码器”,实际完全不是一回事。那台机器里多了一个带联网能力的控制终端——用户扫码付费,后台确认钱到账,终端再决定是否给设备通电。我做的这个项目代号叫 dz-683,全称是“智能扫码付费控制器收费系统”,说白了就是做一个能代替人蹲在设备旁边收钱的小盒子。

这文章适合谁看?一类是做自助设备、共享设备硬件的工程师,想把“扫码支付+设备控制”这条链路跑通;另一类是自己在运营洗衣机、充电桩、饮水机这类点位,想搞懂设备底层的收费逻辑。我会从需求分析、系统架构、硬件选型、支付流程、安全机制一直写到调试实录和成本测算,不绕弯子,把能直接参考的东西都摆出来。

1. 这个设备到底解决什么问题:从自助洗衣机的收费闭环说起

1.1 一枚硬币的消失与一个App的登场

以前的投币式设备,收费逻辑特别简单:投币器识别硬币,累计到金额后给控制器一个信号,洗衣机开始工作。硬币的识别本身就是一种“防伪校验”,运营者隔几天去掏一次硬币箱,清点、记账、扛去银行换纸币。

这套模式的痛点很明显。第一,零钱管理成本高,假币、残币、卡币都能让机器“吃”了钱不干活,最后还得运营者兜底。第二,投币器有被撬的风险,金属外壳的投币箱往往是破坏分子最先下手的地方。第三,用户没带零钱就是做不成生意,这在移动支付普及的今天等于自动放弃一部分流量。

扫码付费要解决的,本质上还是同一个问题:如何确认“钱到了”,然后“让设备动起来”。只是原来的硬币变成了数字支付凭证,原来的机械识别变成了网络回调。所以这个控制器,在硬件层面要干三件事:维持网络连接、对外通信订单状态、控制继电器通断。至于控制的是洗衣机、充电桩还是饮水机,那是负载端的事,跟控制器本身关系不大。

1.2 扫码控制器并不只服务洗衣机

我把 dz-683 能覆盖的场景梳理了一遍,做个分类能帮你判断自己手头的设备适不适合改造成扫码头:

场景计费方式负载特征对控制器的特殊要求
自助洗衣机按次/按程序电机+加热,功率300W~2kW继电器带10A就够,需要防水外壳
电动自行车充电桩按时长/按电量220V插座,单端口最大500W左右需要多路继电器,最好带电量计量
共享饮水机/售水机按流量/按金额加热罐+水泵需要流量计信号接入,控水阀
共享按摩椅按时长电机,几百瓦每次启动时长固定,倒计时结束断电
智能寄存柜按次/押金电磁锁需要锁状态反馈,防止误动作
临时摊位电源按时长任意负载功率上限高,可能要接接触器

可以看出,这些东西的“大脑”是同一套逻辑:订单生成、支付确认、控制输出、计时结束。dz-683 的思路就是把这套逻辑做成一个通用盒子,接什么设备就配什么输出板卡,而不是每做一种设备重新设计一遍。

2. 系统架构:把支付链路和控制链路拆成两件事

2.1 三个层次各司其职

我最初犯的错误是想把所有逻辑都塞进设备端:设备自己生成订单、设备直接调支付平台接口、设备自己处理回调。后来发现这条路走不通——支付平台的密钥存在设备里,一旦设备被别人拆走,密钥就泄漏了;而且设备网络不稳定,支付结果处理很容易断在半路。

dz-683 最终采用了经典的三层结构:

  • 终端设备层:MCU、显示模块(二维码屏/静态贴纸+语音模块)、继电器输出、通信模块。设备只管两件事:向云平台上报状态、在收到“已支付”指令后执行继电器动作。
  • 云平台服务层:负责对接支付平台、管理订单、维护设备连接、下发控制指令。设备的唯一“上级”就是云平台,不直接跟支付平台打交道。
  • 管理端:网页后台、小程序。运营者在这里看流水、远程控制设备、处理退款。

这样拆完以后,每一层的职责都很清晰。云平台是绝对的核心,它既连接支付平台,又连接硬件设备,还接运营者的管理界面。

2.2 两种收钱方式的取舍

扫码支付落到硬件上,有两种截然不同的实现路线:

第一种是静态收款码方案。设备上贴一张固定的微信/支付宝收款码,用户扫了直接付款,付款时在备注里填设备编号。这种方式实现最简单,零开发成本,但没法自动对账,也没法确认是哪台设备的订单。我身边有几个小运营商在初期用过,最后都吐槽“对账对到崩溃”,只能淘汰。

第二种是动态二维码方案。设备屏幕实时生成一个带订单号的二维码,订单信息在云端生成,用户扫码后进入一个支付页面,金额、设备号、订单号全部是关联的。支付平台回调云平台后,再通知设备放行。这个方案体验最好,也是 dz-683 最终走的路线。

两者对比如下:

维度静态收款码动态二维码
用户操作扫码→付款→手动备注扫码→付款→自动关联订单
是否需要对账基本靠人工全自动核对
防截屏套利难订单失效机制可防
设备端成本低,一张贴纸高,需要显示模块
适用阶段测试、小规模正式运营

2.3 折中后的完整数据流

dz-683 的完整链路是这样走的:

  1. 用户在设备上选择“开始充电/开始洗衣”等操作,设备向云平台发送创建订单请求。
  2. 云平台收到请求后,在支付平台侧生成预支付订单,得到支付链接,并将支付链接以二维码形式返给设备。
  3. 设备屏幕显示二维码,用户可以扫码。二维码本身带订单号和金额。
  4. 用户完成支付,支付平台异步回调云平台的 notify_url,通知“订单 xxx 已支付”。
  5. 云平台校验签名、校验金额、校验订单状态,将订单标记为已支付,然后通过 MQTT 或者设备轮询接口下发“放行”指令。
  6. 设备收到指令后,再次确认订单号与金额,闭合继电器,开始计费。
  7. 服务结束后,设备上报“完成”,云平台记录结束时间,订单闭环。

这条链路里,支付平台只跟云平台通信,设备只跟云平台通信,从安全性上讲分布非常合理。

3. 硬件选型:主控、扫码模块与继电器的三重权衡

3.1 主控芯片选哪颗

dz-683 的主控,我实际对比过三条路线:

  • STM32F103C8T6:稳定、外设丰富、资料多,但是要自己处理网络协议栈,配一个串口转WiFi/4G模块,开发周期偏长。适合追求极致成本、出货量很大的产品。
  • ESP32系列:自带 WiFi + 蓝牙,双核,跑 RTOS 或者裸机都行,联网开发资料丰富,OTA 升级也方便。我最终选了 ESP32,主要理由是开发效率高,原型到量产的时间能压缩很多。
  • 全志/瑞芯微等Linux方案:跑得了 Linux,能接触摸屏,能做复杂界面,但成本高、功耗高,对纯收费控制器来说功能过剩。

我的结论很简单:如果你的设备有屏幕、需要复杂人机交互,选 Linux 方案;如果只是做“扫码+继电器”这种轻量控制,ESP32 是性价比最高的选择。需要注意 ESP32 的 ADC 线性度一般,如果要做电量计量或者电流采集,建议外挂计量芯片,不要依赖 MCU 内置 ADC。

3.2 二维码显示与语音播报

动态码方案里,显示模块是关键。我在 dz-683 上试过串口屏和墨水屏:串口屏刷新快、能显示彩色界面和二维码,但成本稍高;墨水屏省电、断电能保持显示,但刷新慢,不适合频繁切页。实际量产我更推荐小尺寸串口屏,开发工具和模板都成熟,能让设备界面迅速统一起来。

静态码方案配语音播报模块就够了。“用户扫了码、付了款、设备开始工作”这三件事,语音模块一响,用户心里就踏实了。语音模块选带 SPI-flash 的,可以预存多条语音,比如“订单已创建,请扫码支付”“支付成功,设备启动”,比让云平台下发 TTS 再播报要稳,省流量。

3.3 继电器输出和电源设计是硬功夫

控制器的本质是“收钱后给电”,所以继电器输出电路是安全核心。给到负载侧的继电器,我强烈建议按负载的 1.5~2 倍余量选型:普通小家电用 10A/250VAC 的继电器,大功率加热设备就得用 16A 或 25A,再加交流接触器扩展。驱动侧建议用光耦隔离,MCU 的 GPIO 不直接驱动线圈,继电器线圈两端并联续流二极管,防止断电瞬间的自感电动势倒灌。

我踩过一个大坑:继电器吸合的瞬间,MCU 直接重启。原因是继电器线圈吸合时瞬态电流太大,把 5V 电源瞬间拉低。后来我把 MCU 供电和继电器驱动供电彻底分开,两个电源之间用光耦隔离,再在 MCU 电源输入侧加大容量电容,问题才消掉。这个坑在第六章的调试实录里会详细展开。

3.4 单套硬件成本大致概念

有人会问,这套控制器做下来要多少钱。我按中等批量的物料价格估一下:

物料用途成本区间
ESP32 模组主控+WiFi15~30元
串口屏/显示模块二维码显示与人机交互40~80元
4G Cat.1模组(可选)室外无WiFi环境60~120元
继电器+光耦+驱动电路输出控制10~25元
电源模块220V转5V/12V20~40元
外壳/端子/线材结构10~30元

单套 BOM 在一百多到三百元之间,取决于要不要 4G 模块和屏的尺寸。如果是室内有 Wi-Fi 的场景,ESP32 直接联网,成本压得很低;户外充电桩那种无 Wi-Fi 场景,4G 模块的钱就省不掉。

4. 支付流程落地:订单状态机、回调幂等与设备通知

4.1 订单状态机的设计

订单状态是整个系统的核心数据结构,我把它设计成不可回退的线性状态机:

待支付(CREATED)→ 已支付(PAID)→ 已完成(FINISHED)
待支付(CREATED)→ 已关闭(CLOSED)
已支付(PAID)→ 退款中(REFUNDING)→ 已退款(REFUNDED)

设计的时候有几个细节值得注意。金额一律用整数“分”,不用浮点,否则累计误差早晚要出问题。订单号必须全局唯一,我直接用“设备编号+时间戳+自增序号”拼,保证并发下不重复。超时关单是必须的:用户停在支付页面不付款,订单会一直挂着,设备端会被占住,所以创建订单时给 2 分钟的支付超时时间,云平台定时扫描关闭超时订单。

4.2 二维码内容不是“收款码”

动态二维码的内容,准确地说是一个支付链接。微信/支付宝开放平台会返回一个支付链接或拉起支付的 URL,云平台把这个 URL 转成二维码返回给设备。用户扫码后进入一个 H5 收银台,上面有订单号和金额,而不是你扫我、我扫你的个人收款码。

这样做的好处是,每一笔支付都对应一个订单号,支付平台回调时也会带这个号,对账逻辑全部自动完成。如果直接把个人收款码贴上去,钱到了,但不知道是哪台设备、哪笔订单,这就是我之前说的人工对账噩梦。

4.3 回调处理:验签、幂等、金额校验一个都不能少

支付平台支付完成后,会向云平台配置的 notify_url 发起异步回调。回调处理写不好,会出现“重复扣款”“金额被篡改”“支付成功但设备没动”等各种异常。我的回调处理伪码类似这样:

def handle_payment_callback(order_no, trade_no, amount, sign): # 1. 验签:确保回调来自支付平台,而非伪造请求 if not verify_sign(sign): return "sign error" # 2. 幂等:已支付的订单不再重复处理 order = get_order(order_no) if order is None: return "order not found" if order.status == "paid": log_duplicate_callback(order_no, trade_no) return "success" # 3. 金额校验:以创建订单时的金额为准 if order.amount != int(amount): mark_amount_mismatch(order_no) return "amount mismatch" # 4. 更新订单状态,并通知设备 order.status = "paid" order.trade_no = trade_no save(order) notify_device(order) return "success"

幂等处理是重中之重。支付平台回调为了保证送达,会有重试机制,同一个成功通知可能来两三次。如果回调处理不具备幂等性,第二次进来再把订单状态改成已支付、再给设备发一次放行,就可能出现重复启动。我在代码里每次进来都先查订单状态,已支付就直接返回,不再下发控制指令。

设备端收到“已支付”指令后也不能盲目执行,要带上订单号和金额再确认一次。设备端本地缓存最近几笔已执行订单号,防止同一笔订单被重复启动。

4.4 设备怎么知道“钱到账了”:MQTT 还是轮询

云平台确认支付成功后,要把消息推到设备端。两条路:MQTT 长连接或者 HTTP 轮询。

MQTT 的优点是真的实时,支付成功到设备通电基本在 1 秒内。缺点是要部署和维护 MQTT Broker,设备端还要处理断线重连、订阅关系。HTTP 轮询就简单多了,设备每隔 3~5 秒请求一次云平台接口:我这台设备有没有已支付的订单?实现简单,延迟也能接受。

dz-683 在正式版里用了 MQTT 做主通道、HTTP 轮询做兜底:设备 MQTT 在线时秒级启动;MQTT 掉线时,云平台会把待通知订单缓存起来,设备轮询时拉取到再执行。这样即使网络环境差,也不至于“钱扣了设备没动”。

4.5 计费逻辑:预付费和后付费

按次计费的场景,比如洗衣机、按摩椅,适合预付费:先付钱,再启动,服务时长到了就断电。按电量计费的充电桩,适合后付费:先启动,结束充电后按实际用电量结算。dz-683 的云平台把这两种计费模式都做成配置项,硬件层面只需要知道“收到启动指令”“收到结束指令”。真正算钱的逻辑全部在云端,设备端不做复杂运算,这样后续改计费规则就不用动嵌入式固件。

预付费场景要特别处理“时长没跑完”的退款:用户付费 30 分钟,但 15 分钟就停止了,剩余的钱是原路退回、存进账户余额还是转成优惠券,产品层要想清楚。dz-683 默认做了原路退回到支付账户,退款接口由云平台在后台触发。

5. 控制输出与安全机制:通电这件事没那么简单

5.1 硬件保护设计

继电器的输出往小了说是“给洗衣机通电”,往大了说就是“给大功率设备接 220V”,安全措施得当才能避免设备站在那儿变成隐患。

第一道防线是保险丝。220V 进线处加符合负载电流的保险丝,过流直接熔断,比让继电器硬扛更安全。第二道防线是继电器粘死检测。继电器是有机械寿命的,触点也可能烧蚀黏连。我设计了一个反馈回路:断开状态下,通过负载侧的分压采样电路检测负载端是否还有电,如果控制端没给信号但负载侧依然有电压,就判断继电器粘死,后台报警,并切断上一级接触器。第三道防线是输出超时自动断电。设备端在计费结束后如果网络异常、云平台指令迟迟没到,本地还得有一个兜底定时器,时间一到无论云端怎么说都强制断开。

MCU 端跑独立看门狗,程序跑飞了自动重启,避免设备死机后继电器一直吸合。这些细节不写进需求文档没人提,但运营一段时间后,安全设计才是真正决定口碑的部分。

5.2 防作弊与防重放

扫码设备天然面临几种攻击手段,我把最常见的几种列出来:

  • 截屏套利:动态二维码被截屏发到群里,多人扫码付款。防御方式:订单支付超时设为 2 分钟,一笔订单只允许支付一次,支付成功后二维码立即失效。
  • 伪造回调:攻击者模拟支付平台向云平台发“已支付”通知。防御方式:验签。云平台配置支付平台公钥,回调签名验不过直接丢弃,这是绝对的红线。
  • 重放攻击:把曾经合法的回调消息原样重发。防御方式:订单幂等,已支付回调直接忽略。
  • 设备篡改:拆机、短接继电器、绕过控制器给负载供电。防御方式:物理防拆开关,拆机后设备上报云平台并自锁;更彻底的方案是把控制继电器锁在金属壳内,让用户无法直接短接。

5.3 支付与执行分离:日志对账机制

我最想强调的一个设计理念:支付成功和设备动作是两个独立事件,不能只记一个状态。

云平台里要同时记录两套日志:支付事件日志(收到回调时间、订单号、交易号、金额)和执行事件日志(设备收到指令时间、设备回复的启动结果、运行结束时间)。用户说“我付了钱但设备没动”,后台一查就知道是支付没到、回调没到、设备断线还是继电器故障,各环节的时间戳对得上。

日终再跑一遍对账:下载支付平台当天的账单,跟订单表逐笔比对,找出“支付平台已扣款但本地订单不匹配”的记录,自动标记送人工处理。这个机制让我在运营阶段省了很多扯皮的时间。

6. 调试与部署实录:五个典型坑的完整排查链路

6.1 坑:支付平台回调一直收不到

现象:测试时用户扫码支付成功,钱包扣了钱,但云平台后台一点反应都没有,设备自然是铁板一块。

排查过程我是这样走的:先看支付平台商户平台配置的回调地址是不是正确填了,这一查就是一个常见错误——我把测试环境的回调地址填成了内网地址,支付平台从公网根本访问不到。然后把回调地址改成外网可访问的 HTTPS 地址,再测,还是收不到。接着查云平台日志,发现请求没进来,判断是防火墙或网关层拦截了,放行对应路径后终于通了。

经验教训:支付平台的回调必须用公网可达的 HTTPS 地址,不能用 http 更不能写 localhost。调试阶段可以把回调收到后的数据转发到一个在线 Webhook 调试工具,方便实时看报文。

6.2 坑:签名一直报错,最后发现是时间不对

现象:云平台调用支付平台接口时,返回“请求时间超时”。

排查过程:先怀疑是签名算法写错了,把参数按字典序排序、拼接、加密流程检查了三遍,都没问题。后来对比了一下本地服务器的时间,发现差了 12 分钟。很多签名校验都会带上时间戳,防止重放攻击,服务器时间偏差超过 5 分钟就拒绝请求。

解决:给云服务器配置 NTP 自动对时,设备端的通信时间戳也全部以云平台返回的时间为准,不信任设备本地 RTC。这个问题排查花了半天,原因说出来其实很简单,但确实容易忽略。

6.3 坑:一合继电器,MCU 就重启

现象:设备单独测试继电器正常,单独测联网也正常,一跑全流程,显示屏黑屏重启。

排查链路:先用万用表量 MCU 供电电压,发现在继电器吸合的瞬间,5V 电压跌落到 3V 以下。用示波器看,继电器线圈产生了一个很大的尖峰干扰。根因是继电器驱动电路没有做隔离,线圈感性负载的能量通过共地干扰了 MCU 电源。

解决:把 MCU 供电、继电器驱动供电分开,用光耦隔离信号,继电器线圈两端并联续流二极管,同时 MCU 电源输入侧并联 470uF 电容缓冲瞬态电流。改完后同样的操作跑了上千次没有再出现重启。

这个案例说明,嵌入式项目里很多问题不是逻辑写错,而是电源和干扰处理不到位。真到了现场才发现的这类硬件坑,往往比调试软件费劲得多。

6.4 坑:断网期间用户已经付了款,恢复联网后设备不认账

现象:某一台设备处于弱网环境,用户扫码后进入了支付页面,钱扣了,但设备当时离线,一直没收到放行指令。网络恢复后设备才从云平台拉取到待通知订单。

这个问题的本质是回调通知不是“持久化”的,设备离线期间云平台推不出去。解决方法是把通知行为拆成两个动作:云平台收到回调后先落库标记订单为已支付,然后尝试通知设备;如果设备不在线,订单仍然在“待通知列表”里,设备恢复心跳后主动向云平台拉取“该设备待执行订单”,拉到订单再执行。

实际运营中我还会设一个保护策略:设备离线超过 10 分钟,屏幕上显示“网络异常,暂不可用”,从源头上减少用户在弱网状态下扫码付款但设备不动的纠纷。

6.5 坑:动态二维码被截屏,一码多人付

现象:调试时同事把设备屏上的二维码拍照发到群里,结果群里好几个人好奇去扫,付了多笔钱,只有第一笔成功启动了设备。

扫码支付的“一码一付”思路在动态二维码场景下要有更严格的处理:订单创建后 2 分钟超时,二维码内容里的订单号只允许被支付一次,支付成功回调一到,订单立即置为已支付,后续支付平台侧的支付请求会因订单已关闭被拒绝。

严格来讲,这笔防御是云平台和支付平台共同来做的:本地订单状态机是主防线,支付平台的订单关闭是次防线。两道防线同时失效的概率很小,日常运营基本不用担心。

7. 成本、运营收益与下一步的玩法

dz-683 整机做下来,单套硬件成本可以压到 200 元以内,带 4G 模块和屏幕的版本也不过 300 元上下。配套成本就两块:一块是云服务器的费用,小规模跑起来的资源开销很低;另一块是设备联网流量费,Cat.1 模组一天也就是几百 KB 的上报量,包年费用很低。

收益测算要看具体设备的使用频率。我拿自助洗衣机举个例子:单次收费 5 元,一天被用 10 次,一天流水就是 50 元。一个月下来,一套几百块的控制器成本早就收回来了。真正有价值的还不只是“收钱”,而是运营者坐在家里就能看到每台设备的状态、流水和故障报警,不需要再去点位现场掏钱箱、修投币器。

这套系统跑通以后,项目的扩展空间也很大。硬件上给它加一个计量芯片,就能从“按时长收费”升级成“按电量收费”,直接应用到充电桩场景;给它加一个人脸识别模块,就能支持刷脸支付;软件上把设备管理后台开放成多租户模式,就能卖给多个点位运营商,变成一套多商户管理系统。

最后分享一点个人体会。这类扫码付费控制器,核心并不是“扫码”这个动作,而是“订单”和“控制”两件事的彻底解耦。把支付状态机设计清、把回调幂等处理好、把设备断电逻辑做成多层兜底,整台设备的稳定性自然就上来了。建议你先拿一台小功率设备,比如饮水机或者洗衣机,把从创建订单到继电器闭合的完整链路跑通,再去加计费规则、加多设备管理。地基打得稳,后面的功能加得再花哨都不会乱。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询