揽月 · 接口接入

备用金归还接口说明

本地实现契约 · 2026-09-19 · 面向财务前台与内部接入维护人员

1. 适用范围

本文描述当前揽月内部 /api/finance/ 路由,使用登录会话。旧商户订单 V1 / V2 的商户号、MD5 / RSA2 签名不能替代这里的登录、公司范围和权限。

当前验收使用本地 Mock 数据。本文不是开放第三方生产调用的承诺。读取任务、展示二维码、返回本地支付状态,都不证明已经获得支付宝产品权益、发生真实到账或完成真实宜搭回写。

资金方向为员工向公司归还备用金。财务创建任务并交付一任务一码;员工认领、制单授权、本人付款确认、支付结果、到账和核销分别记录。财务查看二维码不会发起资金交易。

依据:src/application.js、src/finance-workbench.js、src/group-payment-service.js、src/finance-materials-router.js、src/finance-materials.js,以及本次对应回归测试。代码变更时应同步核对本说明。

2. 登录、权限与公司范围

  1. 在已配置的公司财务域名登录。服务端依据请求 Host 解析公司,登录账号的 company_id 必须与该公司一致。平台管理员角色也不能绕过财务域名与账号的绑定要求。
  2. 已登录页面通过 GET /api/session 取得当前会话及 csrfToken。使用同源 Cookie;不在 URL、日志或文档里放 Cookie、密码或令牌。
  3. 读取需要 orders:read;写入需要 orders:create,并发送 x-csrf-token。JSON 写入使用 Content-Type: application/json。
  4. 请求里的 companyId 只能声明当前公司,不能用来切换公司。列表参数不提供跨公司查询;任务 ID、材料 ID 仍在服务端核对归属。
  5. 页面只展示服务端 availableActions 允许的操作;点击后服务端会再次校验。隐藏按钮不是权限保障。

下面示例里的 ID 都是占位值,必须来自当前登录公司真实返回的选项。不要把演示 ID、令牌或地址复制到生产环境。

3. 先读取可用选项与任务

GET 路径结果与用途
/api/finance/options当前公司、收款账户、可用归还义务、合同模板、历史名称及页面操作权限。材料开关为 materialUploadsAvailable。
/api/finance/pending-scan-tasks{tasks:[...]};过滤字段:batchNo、taskNo、status、createdFrom、createdTo。批次和任务号精确匹配;status 使用下列 flowStage;时间建议带明确时区。当前接口没有分页参数。
/api/finance/pending-scan-tasks/:id{task:{...}};单任务当前状态、收款方、材料摘要及 availableActions。
/api/finance/workbench公司归还余额、任务与查询/回写/异常信息的本地投影;不是调用支付机构查单。
/api/finance/repayment-obligations{obligations:[...]},公司内归还义务。
/api/finance/pending-scan-tasks/:id/integration接入检查与流程事件;读取不保存配置、不执行付款或主动查单。

任务关键字段:id / taskNo / batchNo / companyId / companyName / receiptAccountId / receiptAccountName / amountCents / availableActions。amountCents 为整数分;amount 为两位小数字符串元。身份信息仅使用接口提供的脱敏投影。

materialSummary 是附件登记数量与是否选过模板:{attachmentCount:2,templateSelected:true}。未开启材料功能时为 null,不能解释为“零附件”。登记摘要不是文件完整性、签署、归档或审批通过的证明;完整材料仍通过材料接口核对。

当前可过滤的 flowStage

DRAFT, PENDING_APPROVAL, APPROVED, REJECTED, LEGACY_REVIEW, WRITTEN_BACK, PAY_SUCCESS, PAY_FAILED, RISK_REVIEW, PAYMENT_RESULT_PENDING, PAYMENT_CONFIRMING, PAYMENT_CONFIRMED, TRANSFER_AUTHORIZED, TRANSFER_AUTHORIZING, DOCUMENT_EVIDENCED, DOCUMENT_SIGNED, DOCUMENT_SIGNING, DOCUMENT_GENERATING, DOCUMENT_EXCEPTION, IDENTITY_BOUND, QR_EXPIRED, QR_VOID, QR_READY, READY_TO_BUILD

4. 创建一批独立任务

POST /api/finance/pending-scan-task-batches

{
  "companyId": 1,
  "authorizationName": "TEST 备用金归还",
  "idempotencyKey": "TEST-return-20260919-001",
  "items": [{
    "repaymentObligationId": 11,
    "receiptAccountId": 21,
    "amount": "10.00"
  }]
}

创建结果应再读取任务投影。创建任务不等于审批完成、二维码已生成或付款成功。旧单任务创建接口仍存在,但当前前台使用本批次入口承载创建与幂等恢复。

5. 材料、政策与员工资料

附件功能目前仅在 mode=mock && allowMockTools=true 开启,其他情况下材料路由返回 404。上传 PDF、PNG、JPEG,单文件最多 5 MiB、每行最多 5 个。服务端检查文件头尾、大小、名称、类型并计算摘要;这不等于文件内容获得法律效力或经过病毒扫描。

方法 / 路径请求 / 结果
POST /api/finance/material-uploadsJSON:requestId(UUID v4)、name、contentType、contentBase64。成功返回登记元数据;新文件 201、幂等重放 200。同一 requestId 改内容冲突。
GET / DELETE /api/finance/material-uploads/:idGET 下载有权访问的文件;DELETE 只移除自己可移除的未绑定草稿。已绑定材料不能按草稿删除。
GET / POST /api/finance/pending-scan-tasks/:id/materialsGET 返回 template、files、frozen、documentMethod、documentStatus、archiveReference 等,校验材料快照;POST 用 materialIds、contractTemplateId 绑定,既有集合冻结,不能换内容。
POST /api/finance/pending-scan-tasks/:id/materials/:fileId/archiveJSON {};显式归档当前任务已关联的文件。只有政策允许 MANUAL_ARCHIVE 才可走此路径,不能冒充 ESIGN。
POST /api/finance/pending-scan-tasks/:id/document-policyrequirement、method、basis、version;其他批准方式另需 methodIdentifier。决定政策后冻结,需符合任务当前可操作状态。
POST /api/finance/employee-profiles/:id/supplementsname、employeeRef、evidenceRef、eventRef;仅 Mock 工具且有写权限时可补录。须使用任务返回的 profileId。员工扫码绑定后补录,不在发码前强制指定钉钉身份;补录不是支付宝实名核验。

材料政策组合:REQUIRED 配 MANUAL_ARCHIVE / ESIGN / OTHER_APPROVED_METHOD;NOT_REQUIRED 配 NOT_APPLICABLE,并提供真实制度依据与版本。上传≠签署,模板≠签署文件,材料满足≠审批通过。归还任务的管理审批由既有后台流程完成。

6. 建码、查看、取消和重建

方法 / 路径语义
POST /api/finance/pending-scan-tasks/:id/build-qrJSON {},生成该任务二维码,返回 {task}。需管理证据、审批、材料政策、归还义务/余额、来源及身份/支付状态等全部满足;接入运行时存在时还检查该运行时配置。
GET /api/finance/pending-scan-tasks/:id/qr.svg?generation=N返回受登录/公司/状态保护的 SVG,禁止缓存。generation 可选;提供时必须为单个安全正整数且与当前代次一致,否则返回 400 / 409。无参数保留旧读取方式。页面始终携带当前代次;查看前先读取任务与其 qrGeneration、qrExpiresAt、view-qr 权限。
POST /api/finance/pending-scan-tasks/:id/voidJSON {};按服务端状态控制作废/取消。已扫码或进入付款的任务不可绕过限制。
POST /api/finance/pending-scan-tasks/:id/rebuildJSON {};允许时更换二维码代次,旧码失效。不是重复付款入口。
POST /api/finance/pending-scan-tasks/clear-voided按现有服务端规则归档本公司可清理的作废任务,不表示删除支付审计。

有效期以 qrExpiresAt 为准;常规旧 Mock 建码默认 30 分钟,授权接入运行时可采用单独设置的分钟数,不应在客户端写死。

“本批建码”是客户端先精确查批次、冻结合格任务 ID,再顺序调用单任务建码;不存在新增的批量资金支付接口。“查看本批二维码”只读取已有可查看任务,不自动建码、重建、认领或付款。逐张交付仍是一任务一码。

批内查看以开始查看时的任务集合为准,每次切换重新核对;读取时已过期、已认领或已作废的任务不展示二维码。显示期间到达过期时间会清除图片;其他人的操作不会实时推送到已打开窗口,最终可用性仍由扫码时的服务端校验决定。关闭后刷新可重新整理本批清单。

7. 支付结果与核销如何判断

  1. GET 任务 / workbench 只读取当前记录,不会向支付宝发送主动查单。
  2. 制单授权、员工确认、PAY_SUCCESS、查询证据、公司到账、回单、核销与业务回写分别核对。页面回跳、二维码生成、跳转成功不能作为付款成功证据。
  3. 任务投影含 paymentAttempt、query、writeback、reconciliation、closure 和 timeline。当前 reconciliation.providerBillVerified=false 明示尚未验证真实机构账单;LOCAL_QUERY_VERIFIED 仅为本地验证结果。
  4. 需补查时,使用既有管理后台的查询操作及其权限/环境限制。财务侧本文不提供越权激活、生产查单或直接触发付款指令。

禁止用于本归还方向:POST .../:id/submit-transfer 与 POST .../:id/query-transfer 为旧主动转账路径,当前返回 409 FUNDING_DIRECTION_MISMATCH,不能用它们实现员工还款。

8. 失败恢复与排查

情况处理
401 AUTH_REQUIRED清除页面私有信息,重新登录;不要用旧会话自动提交资金或建码写请求。
403 / CSRF_REJECTED核对当前公司域名、账号绑定与权限;CSRF 失效重新读取会话。不能改 companyId 绕过。
409 IDEMPOTENCY_CONFLICT恢复原请求核对;新业务意图才使用新幂等键,不覆盖原批次。
409 FINANCE_QR_UNAVAILABLE二维码已不满足当前查看条件;清除图片,刷新核对任务状态。
409 FINANCE_QR_GENERATION_MISMATCH任务读取与图片读取之间发生了重建;清除图片并重新读取当前任务,不能把新码配上旧说明。
404 材料路由先检查材料功能是否开放及当前环境;不为通过测试擅自开启生产 Mock 工具。
400 参数/状态拒绝根据 error、message 与排错编号核对。建码路由可能在事务完成后的审计环节报错,不能仅凭 400 认定“没有出码”。
超时、断网、非预期响应或 500写入结果可能未知。停止本批后续操作,先精确读取原批次/任务与代次,再决定下一步;禁止直接重复写入或批量补发。

排查记录保留请求时间、公司、任务/批次号、动作、HTTP 状态、业务 error 和 x-request-id。不要记录明文 Cookie、CSRF、二维码令牌、付款参数、密钥或完整员工身份信息。

本文不包含实际凭据、不执行示例请求、不改变接口权限。真实支付宝联调、到账与回单闭环须单独授权并依据官方契约验收。