编辑 | blame | 历史 | 原始文档

智能电表 — 联调验签与充值记录对接说明

一、数据库脚本执行顺序

在业务库(如 funingyunwei)依次执行:

顺序 脚本 说明
1 yw_electrical_actions.sql 异步操作记录表
2 business.yw_electrical.permissions.sql business:ywelectrical:device
3 business.yw_electrical_charge.permissions.sql 充值记录查询/导出
4 business.yw_electrical_param.permissions.sql 电表参数(若未执行过)
5 business.yw_electrical.menu.sql 智能电表、充值记录、参数设置菜单 + admin 授权
6 business.yw_electrical_warning.* 报警记录(若未执行过)

执行后请 重新登录 或刷新权限缓存,侧栏才会出现新菜单。


二、异步回调 electricalNotify 联调验签

2.1 回调地址

  • 路径POST {服务根地址}/electronic/electricalNotify
  • Content-Typeapplication/x-www-form-urlencoded(表单字段)
  • 字段response_contenttimestampsign
  • 配置ElectronicConstant.notify_url 必须与三方平台后台配置的 完整公网 URL 一致(含路径)。

示例:

https://your-domain.com/electronic/electricalNotify

2.2 验签算法(与出站 ElectronicToolUtil.getSign 一致)

  1. 取参与签名字段,组成 Map<String,String>(**推荐**):
  • auth_code = ElectronicConstant.auth_code
  • response_content = 原始 JSON 字符串(与 POST 参数完全一致,不要二次格式化)
  • timestamp = 平台 POST 的 timestamp 字符串
  1. 将 Map 的 key 按字典序排序,依次拼接各 key 对应的 value(只拼 value,不含 key 名)。
  2. 在拼接结果末尾追加 ElectronicConstant.nonce
  3. 对最终字符串做 UTF-8 MD5,得到 32 位小写十六进制(比较时忽略大小写)。

若上述验签失败,代码会 再尝试 仅使用 response_content + timestamp 两个字段(不含 auth_code),以兼容部分平台版本。

2.3 本地自测 sign(Java)

Map<String, String> data = new HashMap<>();
data.put("auth_code", ElectronicConstant.auth_code);
data.put("response_content", responseContent); // 与 POST 一致
data.put("timestamp", timestamp);
String sign = ElectronicToolUtil.getSign(data);

2.4 响应约定

场景 HTTP 状态 响应体 平台行为
验签通过且处理完成 200 SUCCESS 停止重试
验签失败 400 FAIL 按策略重试

| 非 200 或 FAIL | - | - | 间隔重试直至成功或达上限 |

2.5 response_content 单条结构

{
  "opr_id": "与提交异步任务时一致",
  "status": "SUCCESS",
  "cid": "采集器号",
  "address": "表地址",
  "error_msg": "失败时的错误码或说明"
}

status 与本地 yw_electrical_actions.status 映射:

平台 status actions.status 说明
ACCEPTED / QUEUE / PROCESSING 0 处理中
SUCCESS / DELIVERED 1 成功
FAIL / TIMEOUT / NOTSUPPORT / CANCELED / RESPONSE_TIMEOUT / RESPONSE_FAIL / NOTFOUND 2 失败

2.6 联调检查清单

  • [ ] dmvisit_admin 已启动,Shiro 已放行 /electronic/electricalNotify
  • [ ] 公网/NAT 能访问回调 URL(内网需端口映射或穿透)
  • [ ] auth_codenonce 与三方后台一致
  • [ ] 提交远程操作后 yw_electrical_actionsopr_idstatus=0
  • [ ] 模拟 POST 回调后 status 更新,拉闸/合闸/开户/充值副作用正确
  • [ ] yw_electrical_logtype=1 的推送记录

2.7 常见问题

验签一直失败

  • 核对 response_content 是否与平台发送字节级一致(URL 编码、空格、转义)。
  • 确认 timestamp 为字符串而非带小数。
  • 用平台文档确认是否包含 auth_code 参与签名。

回调成功但 actions 不更新

  • opr_id 是否与 yw_electrical_actions.opr_id 完全一致(提交时本地生成的 UUID)。

三、充值记录页对接

3.1 数据流

用户「确认充值」
  → operate(recharge) → 三方 recharger(异步)
  → 写入 yw_electrical_charge(status=0 充值中,opr_id=任务ID)
  → 写入 yw_electrical_actions + yw_electrical_log

平台回调 electricalNotify(status=SUCCESS)
  → 更新 yw_electrical_actions.status=1
  → 按 opr_id 更新 yw_electrical_charge.status=1,statusTime/statusInfo
  → 刷新 yw_electrical 余额(refreshBalanceFromData)

回调 FAIL
  → actions.status=2,charge.status=2

3.2 表字段对应

yw_electrical_charge 来源
obj_id 电表 id
address / name / c_id 电表档案
money 充值金额
remark 充值备注
opr_id 异步任务 opr_id
status 0充值中 / 1成功 / 2失败
banlance 充值前账户余额(电表 balance)
room_names 绑定房间展示名

3.3 前端页面

  • 菜单路径/business/ywelectricalcharge
  • 页面admin/src/views/business/ywelectricalcharge.vue
  • 接口/visitsAdmin/cloudService/business/ywElectricalCharge/page
  • 权限business:ywelectricalcharge:query

用户在智能电表远程控制提交充值后,提示「请到充值记录查看结果」,即在列表按表名/地址、opr_id、状态筛选查看。

3.4 与「商户充值」区别

侧栏「商户充值 / 充值记录」若为 yw_top_up_log 等业务,与 电表充值记录yw_electrical_charge)为不同数据源;日常用电下「充值记录」菜单指向电表专用页面。


四、相关配置项汇总

配置项 位置 说明
auth_code ElectronicConstant 三方授权码
nonce ElectronicConstant 签名随机串
notify_url ElectronicConstant 异步通知完整 URL
api_url / api2_url ElectronicConstant 三方 API 根地址

五、定时任务(system_timer + quartz_job)

system_timer 读取 quartz_job 表,通过 visitServiceJob Bean 反射调用 VisitServiceFegin 对应方法,HTTP 落到 admin_timerYwTimerController

配置脚本:server/db/quartz_job.yw_timer.sql(执行后需在作业调度平台重启/恢复任务以加载 Cron)。

任务 Cron module(Feign 方法) HTTP(admin_timer)
采集器状态 0 */5 * * * ? getElectricalStatus GET /timer/yw/getElectricalStatus
批量抄表 30 0 * * * ? syncElectricalMeterData GET /timer/yw/syncElectricalMeterData
日志清理 0 30 2 * * ? cleanElectricalLog GET /timer/yw/cleanElectricalLog
空调网关状态 0 */5 * * * ? syncConditionerGatewayStatus GET /timer/yw/syncConditionerGatewayStatus
空调内机状态 0 */10 * * * ? syncConditionerIndoorUnits GET /timer/yw/syncConditionerIndoorUnits