提要:用服务端中转 +简道云 v5 文件事务 + systemd 常驻与 journald日志,稳定实现单位/个人会员证书自动生成与回填。
搭建背景
你已有证书生成页面(PHP端点)与简道云表单审批流程,原流程需人工在网页填信息再生成证书。目标是把“审核通过后自动生成证书并回填到表单附件”,同时兼容单位会员与个人会员两类证书模板,减少人工操作与重复。
目的
- 在简道云的“审核通过/数据修改”触发时,自动生成电子证书并将图片作为附件写回该记录。
- 对单位/个人会员分支自动识别与处理。
- 将服务端改为稳定常驻运行,并具备安全(签名)、日志与维护能力。
逻辑思路
- 用服务端中转:Webhook接收审批通过,服务端读取表单字段,调用既有PHP端点生成证书(Base64),再按简道云 v5 文件接口的“事务上传”流程上传并回填附件。
- 单位会员分支:直接把姓名、编号、有效期以 x-www-form-urlencoded 传给单位端点生成。
- 个人会员分支:根据“会员类型=个人”,先按“编号”查询会员基本信息表补齐字段与照片,再以 multipart/form-data 传给个人端点生成。
- 为防止平台5秒超时重试:Webhook“快速ACK”,整条链路在后台异步执行;加幂等锁与看门狗防并发与异常残留。
- 安全与可观测:启用 x-jdy-signature 验签(SHA1),并用 systemd+journald常驻与日志管理。
总体数据流
实现要点(关键节点)
- 证书生成端点:
- 单位:CERT_URL_DANWEI(name、number、exp)。
- 个人:CERT_URL_GEREN(gerenname、gerennumber、gerenexp、gerensex、gerencard、gerencoltd、gerenwork、gerenphoto)。
单位会员时序
个人会员时序(信息补齐与数组清洗)
-
简道云 v5 文件事务:
- 先 POST 获取上传凭证与地址(token+url)与 transaction_id。
- 用 multipart/form-data 上传文件得到 key。
- 用同一 transaction_id 调用 data/update,将附件字段写入 { value: [key] }。
-
字段来源:
- 主表提供 full_name(或 name)、number、exp、member_type。
- 个人会员需补齐:gender、id_card_number、employer、title、photo(“查询多条数据接口”按 number eq筛选,fields传别名;将 title 数组 join 为字符串、photo取第1张url)。
-
Webhook执行模型:
- 顶部做签名校验与来源IP白名单(可选)。
- 立即返回 200(ACK),后台 setImmediate 执行“查询→生成→上传→回填”。
- 幂等锁 processing + 看门狗(超时自动释放)。
签名校验
异步ACK与幂等控制
实现结果
- 单位会员:审批通过或编辑修改触发一次生成并回填,表单附件字段出现 certificate_编号.jpg。
- 个人会员:自动查询会员基本信息表补齐字段与照片,生成并回填证书图片。
- 简道云“数据推送”不再超时重试,数据修改日志仅记录一次更新。
- 启用 systemd 后后台常驻运行、崩溃自动重启;日志由 journald管理,带时间戳与自动轮转。
部署结构
注意事项
- 事务一致性:获取上传凭证与 data/update 必须使用同一 transaction_id;有效期约1小时。
- **字段****ID/**别名:查询多条接口 fields 与 filter.field可用你自定义的别名(number、gender等);如租户要求内部ID,需用 _widget_XXXX。
- 个人字段数组:title/photo常为数组,提交前需处理为字符串与URL。
- 签名校验:仅对 POST 正式推送验签;GET /webhook(连接测试)放行。验签必须对原始请求体(req.rawBody)做 HMAC-SHA1。
- 反向代理:Apache需为 /webhook 配置 ProxyPass/ProxyPassReverse 到 127.0.0.1:3000/webhook,并在 443(HTTPS)虚拟主机同样配置。
- CentOS 7 环境:系统 glibc 为 2.17,不支持 Node 20 的RPM包;采用 nvm 的 Node 16 直接跑 systemd(ExecStart指向绝对路径)。
维护
-
日志:用 journald 查看(带时间戳、自动轮转)。
- journalctl -u vip-card-bridge -f
- journalctl -u vip-card-bridge –since today
-
签名与安全:
- .env 里 JIANDC_WEBHOOK_SIGNATURE_KEY 是密钥,日志仅打印 hasWebhookSecret: true,不打印密钥本身。
-
Webhook****稳定性:
- 保持“快速ACK + 后台处理 + 幂等锁 + 看门狗”,避免超时与并发重复。
-
字段与模板变更:
- 若证书版式或字段变更,同步调整PHP端点与字段映射;给模板版本与生成时间做记录更利于审计。
待优化项
- 容器化:将服务迁移到 Docker(node:20-alpine)以获得更新环境与更易移植的部署。
- 结构化日志:可引入 pino/winston 输出JSON结构化日志,便于检索与汇总。
- 队列与重试:高并发场景可加队列(Redis + BullMQ),统一控制并发与失败重试。
- 版本化证书:文件名加入时间戳/版本号(certificate_编号_YYYYMMDD.jpg),避免覆盖历史。
常用命令速查
- Node 与依赖
- which node / type -a node
- npm install(在 /opt/vip-card-bridge)
- systemd 服务(nvm Node 16 路径)
- 编辑 /etc/systemd/system/vip-card-bridge.service:
- ExecStart=/root/.nvm/versions/node/v16.20.2/bin/node /opt/vip-card-bridge/server.cjs
- Environment=“PATH=/root/.nvm/versions/node/v16.20.2/bin:/usr/bin:/bin”
- EnvironmentFile=/opt/vip-card-bridge/.env
- sudo systemctl daemon-reload
- sudo systemctl enable vip-card-bridge
- sudo systemctl restart vip-card-bridge
- journalctl -u vip-card-bridge -f
- journald 持久化与上限(可选)
- sudo mkdir -p /var/log/journal
- sudo chown root:systemd-journal /var/log/journal
- sudo systemctl restart systemd-journald
- /etc/systemd/journald.conf:
- SystemMaxUse=200M
- SystemMaxFileSize=50M
- Apache 反向代理(443虚拟主机中)
- ProxyRequests Off
- ProxyPreserveHost On
- ProxyPass “/webhook” “http://127.0.0.1:3000/webhook”
- ProxyPassReverse “/webhook” “http://127.0.0.1:3000/webhook”
- 健康检查
- curl http://127.0.0.1:3000/health
- curl https://bjhearing.cn/health