本文档定义了停车场管理系统(SmartParking)与中央缴费机(如 pof-parking-payment-machine)之间的对接规范,涵盖通信架构、接口定义、业务流程及错误码说明。目标是使功能开发者能够依据本文档独立完成缴费机与停车管理系统的集成开发。
中央缴费机采用 TCP/IP 网络通信方式接入系统 [4],即缴费机与后端服务器通过局域网或互联网建立网络连接。
⚠️ 重要:对接 不是 通过串口串联方式,不是 MQTT 长连接,而是基于 HTTP/HTTPS 的 RESTful API 请求-响应模式。每次业务操作均为独立的 HTTP 请求 [2][7][16]。
实际对接中存在两种协议形式,取决于缴费机型号与系统版本:
| 协议 | 传输层 | 数据格式 | 适用场景 |
|---|---|---|---|
| SmartParking 标准集成协议 | HTTPS | JSON | 外部客户平台(通用缴费机)与 SmartParking 系统集成 [2][17] |
| POF 缴费机专用协议 | HTTP | JSON | 睿泊科技 POF 缴费机与停车系统后端对接 [7] |
下文分别详述两套协议的接口定义。
该协议用于外部客户平台(如中央缴费机)与 SmartParking 系统的标准化集成 [2][16][17]。
接口: POST /sp/login
用途: 获取 accessToken,用于后续所有接口调用的权限验证 [2]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| userName | String | 是 | 用户名 |
| passWord | String | 是 | 32位大写 MD5 加密后的密码 |
请求示例:
{
"userName": "paystation001",
"passWord": "E10ADC3949BA59ABBE56E057F20F883E"
}
成功返回:
{
"accessToken": "xxxxxxxxxxxx",
"sessionId": "yyyyyyyyyyyy",
"expireInSeconds": 1800
}
字段说明:
accessToken: 访问令牌,有效期 30 分钟,后续接口调用时需使用此值作为会话凭证 [2]sessionId: 会话 IDexpireInSeconds: 令牌有效时长(秒)接口: POST /sp/charge/payCost
用途: 实时计算当前车辆的停车费用,供缴费机完成预支付 [2][17]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| sessionId | String | 是 | 登录返回的 accessToken |
| carNum | String | 是 | 车牌号 |
| parkingLotCode | String | 是 | 停车场 ID(默认 0001)[2] |
成功返回:
{
"carAccessCurId": "车辆业务ID",
"freeOutTime": 15,
"inParkTime": 1714000000,
"receivableMoney": 12.00,
"payedMoney": 0.00,
"favorableAmount": 0.00,
"ticketNum": "TICKET001"
}
字段说明:
| 字段 | 类型 | 说明 |
|---|---|---|
| carAccessCurId | String | 车辆业务 ID,车辆入场后生成,一次进出场业务唯一 [2] |
| freeOutTime | Int | 支付后免费出场分钟数 [2] |
| inParkTime | Long | 入场时间戳 [2] |
| receivableMoney | Decimal | 应收金额(消费金额)[2] |
| payedMoney | Decimal | 已付金额 [2] |
| favorableAmount | Decimal | 优惠金额 [2] |
| ticketNum | String | 票据号 [2] |
接口: POST /sp/charge/notify
用途: 客户平台将支付账单插入 SmartParking,通知支付成功并触发放行 [2][17]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| sessionId | String | 是 | 登录返回的 accessToken |
| carAccessCurId | String | 是 | 车辆业务 ID(查询费用时返回)[2] |
| carNum | String | 是 | 车牌号或 UUID(无牌车)[2] |
| consumeMoney | Decimal | 是 | 消费金额 [2] |
| consumeTimeStr | String | 是 | 支付时间 [2] |
| feeAmount | Decimal | 是 | 实际支付金额 [2] |
| feeType | Int | 是 | 支付方式类型:1-现金,9-支付宝,10-微信支付,16-微信公众号支付 [2] |
| orderStatus | String | 是 | 订单状态 [2] |
| parkingLotCode | String | 是 | 停车场 ID [2] |
| serialNumber | String | 是 | 订单支付流水号(需保证唯一)[2] |
| ticketNum | String | 否 | 票据号 [2] |
说明: [2]
serialNumber 重复,返回错误码 0021(流水号已存在)| 错误码 | 说明 |
|---|---|
| 0000 | 成功 |
| 0001 | 失败(具体错误见 errMsg 字段)[2] |
| 0004 | 登录密码错误 [2] |
| 0006 | 认证失败,请重新登录 [2] |
| 0007 | 请求参数不存在 [2] |
| 0017 | 支付金额不足 [2] |
| 0021 | 流水号已存在(重复通知)[2] |
该协议定义 POF 停车缴费机与停车系统后端之间的完整接口规范 [7]。
{"Result":0, "Data":{}, "ReMark":"失败原因"} [7]{"Result":1, ...}Token 参数 [1]接口: POST /api/login
用途: 操作员登录,获取 Token,用于后续接口鉴权 [7]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| UserName | String | 是 | 用户名 |
| Password | String | 是 | 登录密码,当前必须传明文 UTF-8 字符串;不支持 MD5 或 bcrypt 哈希 |
请求示例:
{"UserName":"admin","Password":"admin"}
成功返回:
{"Result":1,"Token":"123456"}
接口: POST /api/queryprice
用途: 按车牌查询车辆停车费用 [7]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Token | String | 是 | 认证令牌 |
| Data.CarNo | String | 是 | 查询车牌 |
| Data.QueryTime | String | 是 | 请求时间 yyyy-MM-dd HH:mm:ss |
成功返回:
{
"Result": 1,
"Data": {
"OrderId": "123456",
"CarNo": "B88888",
"InTime": "2023-04-25 12:00:01",
"OutTime": "2023-04-26 09:03:23",
"StopTime": "1小时20分钟",
"Price": "12",
"CardNo": "00001",
"Remark": "收费标准0001",
"InPic": ""
}
}
字段说明: [7]
| 字段 | 说明 |
|---|---|
| OrderId | 订单号(后续所有操作的核心关联标识)[1] |
| CarNo | 车牌号 |
| InTime | 入场时间 |
| OutTime | 出场时间 |
| StopTime | 停放时长 |
| Price | 应收金额 |
| CardNo | 卡号(月租/会员卡) |
| Remark | 计费规则说明 |
| InPic | 入场图片 |
接口: POST /api/paysuccess
用途: 缴费机完成支付后通知后端 [7]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Token | String | 是 | 认证令牌 |
| Data.OrderId | String | 是 | 订单号 |
| Data.CarNo | String | 是 | 车牌 |
| Data.Money | String | 是 | 缴费金额 |
| Data.PayTime | String | 是 | 支付时间 yyyy-MM-dd HH:mm:ss |
| Data.PayType | num | 是 | 支付方式:0-现金,1-刷卡 [1][7] |
| Data.PayDev | num | 是 | 支付设备:1-岗亭,2-POF,3-平板 [1][7] |
| Data.DevId | String | 是 | 设备标识(如 "PoF-01")[1] |
| Data.ReMark | String | 是 | 备注 |
接口: POST /api/heartbeat
用途: 心跳检测,返回服务器时间 [1]
请求参数: Token(认证令牌)
返回: 服务器系统时间。
接口: POST /api/ticket
用途: 向订单推送优惠券 [7]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Token | String | 是 | 认证令牌 |
| Data.OrderId | String | 是 | 订单号 |
| Data.CarNo | String | 是 | 车牌 |
| Data.TicketNo | String | 是 | 优惠券编号 |
| Data.TicketType | num | 是 | 优惠券类型:0-减免金额,1-减免时长,2-全免 [1] |
| Data.Money | String | 是 | 减免金额 |
| Data.Minutes | num | 是 | 减免时间(分钟) |
| Data.OperTime | String | 是 | 操作时间 |
| Data.ShopName | String | 是 | 商户名称或卡号 |
| Data.ReMark | String | 是 | 备注 |
接口: POST /api/paylist
用途: 上报缴费机投币/找零明细 [7]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Token | String | 是 | 认证令牌 |
| Data.OrderId | String | 是 | 订单号 |
| Data.VoucherNo | String | 是 | 凭证编号 |
| Data.DevIp | String | 是 | 设备 IP |
| Data.EventDate | Datetime | 是 | 发生时间 |
| Data.InOutType | num | 是 | 0-接收,1-找零 [7] |
| Data.CoinCashType | num | 是 | 0-硬币,1-纸币 [7] |
| Data.MValue | String | 是 | 面值 |
| Data.Num | Int | 是 | 数量 |
接口: POST /api/payfail
用途: 记录现金支付找零失败事件 [7]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Token | String | 是 | 认证令牌 |
| Data.OrderId | String | 是 | 订单号 |
| Data.CarNo | String | 是 | 凭证编号(字段名与备注可能不符,需与后端确认)[7] |
| Data.Intime | String | 是 | 入场时间 |
| Data.Change1 | decimal | 是 | 应收金额 |
| Data.Change2 | decimal | 是 | 实收金额 |
| Data.Change3 | decimal | 是 | 应找零金额 |
| Data.Change4 | decimal | 是 | 实际找零金额 |
| Data.EventTime | Datetime | 是 | 找零时间 |
接口: POST /api/devstatus
用途: 上报缴费机设备运行状态 [7]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Token | String | 是 | 认证令牌 |
| Data.Printer | string | 是 | 0-余量充足,1-余量不足,2-无可用打印纸 [7] |
| Data.Temperature | string | 是 | 设备温度(摄氏度) |
| Data.Payment.CurrencyInfo | array | 是 | 货币类型/面值/数量 |
| Data.Payment.Online | bool | 是 | POS 在线状态 |
接口: POST /api/pof-login
用途: 操作员交班身份验证 [7][19]
请求参数: 与操作员登录接口相同(UserName + Password),返回的 Token 用于交班场景 [7]。
接口: POST /api/pof-querymoney
用途: 查询指定设备在指定时间范围内的收费总额,用于交班对账 [7][19]
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Token | String | 是 | 认证令牌 |
| Data.DevId | String | 是 | 设备标识(如 "PoF-01") |
| Data.QueryTime | String | 是 | 请求时间 |
成功返回:
{"Result":1,"Data":{"TotalMoney":"12","Remark":"收费标准0001"}}
| 接口 | 现状 | 说明 |
|---|---|---|
/api/paystatus |
已实现 | 按 OrderId 查询数字票和支付状态;具体兼容字段见 4.13 |
/api/checkpassword |
参数已知 | 密码验证(Data.Password),但具体用途待确认 [7] |
接口: POST /api/paystatus
用途: 支付通知超时、网络异常或缴费机重启后,查询订单在管理端的最终支付状态。该接口只读数据库,不会重复扣款或新增支付记录。
请求示例:
{"Token":"登录返回的Token","Data":{"OrderId":"数字票号","CarNo":"湘A12345","DevId":"设备标识"}}
OrderId 必填;CarNo 和 DevId 用于日志及一致性核对,可选。系统仍以 Token 绑定的设备身份认证,并校验设备所属停车场权限。
成功返回:
{"Result":1,"Data":{"OrderId":"...","CarNo":"湘A12345","State":"paid","PayStatus":"paid","PaymentStatus":"paid","Fee":"12.00","Money":"12.00","PaidAmount":"12.00","PayTime":"2026-09-04 12:00:00"},"ReMark":"success"}
PayStatus 为 unpaid 或 paid;State 还可能为 pending_payment、exited 等数字票生命周期状态。订单不存在、车牌不匹配、设备无权访问或 Token 无效时返回 Result=0 及失败原因。
⚠️ 上述接口在实际对接时需与后端开发确认完整定义。 [1][7]
缴费机从查询费用到完成支付的完整流程如下 [9]:
┌─────────┐ ┌──────────────┐ ┌─────────┐
│ 缴费机 │ │ 停车系统后端 │ │ 用户 │
└────┬────┘ └──────┬───────┘ └────┬────┘
│ 1. 用户输入车牌 │ │
│──────────────────→│ │
│ 2. /api/login │ │
│──────────────────→│ 返回 Token │
│←──────────────────│ │
│ 3. /api/queryprice│ │
│ (或 /sp/charge/ │ │
│ payCost) │ │
│──────────────────→│ 返回车辆信息+费用 │
│←──────────────────│ │
│ 4. 用户支付 │ │
│ │ │←─── 现金/刷卡/扫码
│ 5. /api/paysuccess│ │
│ (或 /sp/charge/ │ │
│ notify) │ │
│──────────────────→│ 记录支付+放行 │
│←──────────────────│ 返回成功 │
│ 6. 打印小票 │ │
流程步骤说明: [9]
在支付完成前或完成后,可调用优惠券接口(/api/ticket)应用减免 [9]。
现金支付产生找零时,若找零失败,通过 /api/payfail 上报记录,便于后续人工处理 [9]。
┌─────────┐ ┌──────────────┐
│ 缴费机 │ │ 停车系统后端 │
└────┬────┘ └──────┬───────┘
│ 1. /api/pof-login│
│──────────────────→│ 交班登录验证
│←──────────────────│ 返回 Token
│ 2. /api/pof-querymoney│
│──────────────────→│ 查询收费总额
│←──────────────────│ 返回 TotalMoney
│ 3. 核对金额,完成交班│
流程说明: [19]
| 字段 | 所属协议 | 说明 |
|---|---|---|
| Token / accessToken | 两套协议 | 认证令牌,接口鉴权凭证 [2][7] |
| OrderId | POF 协议 | 订单号,核心关联标识 [1] |
| carAccessCurId | 标准协议 | 车辆业务 ID [2] |
| CarNo / carNum | 两套协议 | 车牌号(无牌车用 UUID)[2][7] |
| Price / receivableMoney | 两套协议 | 应收金额 [2][7] |
| Money / feeAmount | 两套协议 | 实付金额 [2][7] |
| PayType | POF 协议 | 支付方式:0-现金,1-刷卡 [1] |
| feeType | 标准协议 | 支付方式:1-现金,9-支付宝,10-微信,16-公众号 [2] |
| PayDev | POF 协议 | 支付设备:1-岗亭,2-POF,3-平板 [1] |
| DevId | POF 协议 | 设备标识(如 "PoF-01")[1] |
| serialNumber | 标准协议 | 支付流水号(唯一)[2] |
| TicketType | POF 协议 | 优惠券类型:0-减金额,1-减时长,2-全免 [1] |
标准协议中,若实际支付金额低于应收金额,系统返回错误码 0017(支付金额不足)[2]。测试用例显示系统允许部分支付(生成支付记录但不视为完全支付)[6],缴费机应根据业务需求决定是否接受部分支付。
若支付通知的流水号已存在,返回错误码 0021。缴费机收到该错误码时应视为已通知成功,避免重复处理 [2]。
标准协议中 accessToken 有效期 30 分钟 [2]。收到 0006(认证失败)时应重新调用登录接口获取新 Token。
实际对接时需与后端确认以下问题: [1][7]
/api/devstatus 的完整请求/响应定义缺失;/api/paystatus 已按本项目兼容格式实现/api/paylist 的 OrderId 参数逻辑(投币明细通常与设备会话相关,而非订单)/api/payfail 的 CarNo 参数备注为"凭证编号",是否为笔误/api/checkpassword 的具体业务用途本项目已按 POF 专用协议实现以下公开 HTTP POST 接口:
| 接口 | 实现状态 | 约定 |
|---|---|---|
/api/login |
已实现 | 使用中央缴费机设备账号登录,返回 30 分钟有效的设备 Token |
/api/queryprice |
已实现 | 按当前在场会话实时计费,返回数字票号作为 OrderId |
/api/paysuccess |
已实现 | 写入支付记录、更新数字票和在场车辆为已支付;不会主动开闸或关闭停车会话 |
/api/heartbeat |
已实现 | 返回服务器时间 |
接口统一挂载在后端服务的公开 /api 路径,并在每个业务接口内校验 POF 设备 Token;不会使用后台 Web 用户的 JWT,也不会使用 admin/123456。
OrderId 固定映射为 digital_ticket.ticket_no,是本项目 POF 支付的唯一订单标识。/api/queryprice 只允许查询仍在场、数字票状态为 pending_payment 且未支付的车辆。费用以服务端当前时间实时计算。/api/paysuccess 必须携带 PayDev=2。DevId 作为协议和审计字段记录,但不参与阻断式认证;系统以 Token 绑定的设备身份为准。PayType=0 映射 cash(展示名“现金支付”),PayType=1 映射 pos;若管理员停用了 POS 支付方式,刷卡通知会被拒绝,需先在支付方式配置中启用。Money 与当前应收金额不一致时,返回“金额已变化,请重新查询”。OrderId + 支付方式 + 应收金额 实现订单级幂等:相同通知重试成功但不会产生第二条收费记录;数据不一致的重复通知失败。所有请求(Token 已脱敏)写入 central_payment_request_log 供联调与对账。厂商资料的 /api/queryprice 参数表使用 Data.QueryTime,示例却使用 Data.InTime。当前服务同时接收这两个字段,但不将其作为入场时间或计费时间,均以系统已记录的入场时间和服务器当前时间为准。
启动应用一次后,系统会创建仅用于本地联调的模拟设备:
| 项目 | 值 |
|---|---|
| 设备 ID | POF-SIM-01 |
| 用户名 | admin |
| 密码 | admin |
| 支付入口 | central_payment_machine |
安全提示:上述凭据仅限本机或隔离测试网。真机安装前必须禁用或删除该模拟设备,并为每台真机创建独立设备 ID、账号和密码。
先在系统中准备一条未支付的在场车辆记录,再从 lc_garage 目录运行:
go run ./cmd/pof-simulator -base-url http://127.0.0.1:8888 -plate 粤A12345
模拟桩会依次调用 login -> queryprice -> paysuccess -> heartbeat,并打印每个接口原始 JSON 响应。仅验证登录、查询和心跳时使用:
go run ./cmd/pof-simulator -base-url http://127.0.0.1:8888 -plate 粤A12345 -no-pay
生产或局域网部署时,缴费机访问的是后端监听地址,例如 http://<服务器IP>:8888/api/login;不是桌面前端 WebView 内的代理地址。实际端口以 config.yaml 的 system.addr 为准。
中央缴费机请求进入管理端后,后端运行日志会依次输出“收到请求”和“处理成功/失败”两类记录。登录请求包含以下不敏感联调字段:
source_ip:缴费机来源 IP;username:提交的设备账号;password_format:密码格式识别结果;password_length:密码字符长度。系统不会记录登录密码明文、密码哈希或设备 Token。Password 当前必须按 JSON 字符串传输明文,例如 "Password":"admin";日志中的 plain-text_expected 表示格式符合当前协议。出现 md5-32-hex_unsupported 或 bcrypt-hash_unsupported 时,说明缴费机传入了摘要/哈希值,当前服务会按密码错误处理,设备应改为发送明文密码。
处理结果同时写入 SQLite 的 central_payment_request_log 表,包含 endpoint、source_ip、device_id、result、remark 和已脱敏的 request_body,可用于重启后的联调追溯。
应用使用默认配置时,运行日志按日期写入 log\YYYY-MM-DD\info.log(收到请求、处理成功)和 log\YYYY-MM-DD\warn.log(解析或鉴权失败)。实时观察登录联调日志可执行:
Get-Content (Join-Path .\log (Join-Path (Get-Date -Format 'yyyy-MM-dd') 'info.log')) -Wait | Select-String '中央缴费机'
若登录失败,再查看同日期的 warn.log。通过项目管理脚本以 split 模式启动时,标准输出还会同步写入 .run\backend.stdout.log。
代码库还提供不依赖真实数据库或硬件的 HTTP 联调回归测试。它以内存 SQLite 建立一条在场订单,并按模拟桩顺序验证 login -> queryprice -> paysuccess -> paystatus -> 重试 paysuccess -> heartbeat,确保状态查询可确认支付结果且重复支付通知不会产生第二笔支付记录:
$env:GOCACHE = (Resolve-Path '.gocache').Path
go test ./internal/modules/central-payment/... -run TestPOFSimulatorHTTPFlow -count=1
以下内容未在当前实现范围内,需在真机到位前向厂商确认后再扩展:
/api/checkpassword 仅给出 Data.Password,没有业务语义,当前未实现。/api/ticket 的优惠券时机、抵扣规则与本系统收费规则尚未定义,当前未实现。/api/paylist 投币/找零明细的 VoucherNo 唯一性、补传重试和对账口径未定义,当前未实现。/api/payfail 的 CarNo 字段说明写为“凭证编号”,字段语义冲突,当前未实现。/api/devstatus 中 Payment.CurrencyInfo 的数据结构和设备故障处置规则未定义,当前未实现。Data 中补充稳定且唯一的 VoucherNo 或 SerialNo,以支持跨订单、跨重试窗口的精确幂等和财务对账。/api/pof-login 和 /api/pof-querymoney,但没有定义交班时段/班次边界,也没有说明 QueryTime 是查询时点还是统计区间。当前未实现,待现场交班和对账口径确认后扩展。| 编号 | 资料 |
|---|---|
| [1] | 停车系统缴费接口说明补全polan(4) |
| [2] | 自助缴费机集成网络协议(英文版 2025) |
| [4] | POF 停车缴费机硬件规格 |
| [6] | 智慧停车系统 — 测试用例报告 |
| [7] | 缴费机 API 接口文档 |
| [9] | 缴费机支付流程 |
| [16] | 自助缴费机集成协议 |
| [17] | SmartParking 集成协议 |
| [19] | 交班对账机制 |