hl-api-changelog/changelogs/2026-04/24_fix_order-v2_policy-pdf-view-and-retry.md

3.2 KiB

保单 PDF 上传链路修复 + 新增重试接口

日期: 2026-04-24 PR: #1369 (dev) Issue: #1367 类型: fix + feat 服务: hl-order-service-v2


摘要

订单详情 → 合同保险 tab → 保险保障 → 点击「查看保单」之前对很多已承保订单会弹「暂无保单文件」。根因是测试服 Nacos hl-order-service-v2-test.yml 未配置 oss: 段,承保成功后的异步保单 PDF 上传被 PolicyPdfUploadService.init()configured=false 静默跳过,insurance_order.policy_pdf_url 永远为 NULL。

本次修复三件事:

  1. 配置侧: Nacos 已补齐 oss: 配置
  2. 代码侧: AsyncConfig 新增 insuranceTaskExecutor bean(之前悬空 qualifier),PolicyPdfUploadService self-injection 修 @Async 自调用陷阱
  3. 体验侧: 新增单订单重试接口 + 空 URL 时自动异步补传 + 友好文案

受影响接口

接口 方法 变化
GET /admin/insurance/policy/{id}/download GET 行为增强: policy_pdf_url 为空时 fire-and-forget 异步补传一次 + 抛文案「保单生成中,约 30 秒后可重试」(原文案「保单PDF尚未上传,请稍后再试或手动触发上传」)
POST /admin/insurance/policy/{id}/retry-upload POST 新增: 同步触发单个保单 PDF 补传, 成功返回 OSS URL, 失败抛 BusinessException
POST /admin/insurance/upload-missing-pdfs POST 行为修正: 原先同类自调用导致 @Async 退化为串行, 现改走代理真异步, 返回的 data 是「提交的任务数」不是「已完成数」

前端需要的改动

  • 无强制改动。原「查看保单」接口路径、签名、成功路径返回都不变。
  • 文案建议同步: 当接口返回 code=500 message="保单生成中,约 30 秒后可重试" 时, 建议前端把 toast 从「暂无保单文件」改成「保单生成中,约 30 秒后可重试」, 并可在 30 秒后再次点击自动重试。
  • 可选接入: 新接口 POST /admin/insurance/policy/{id}/retry-upload 可以做成订单详情「查看保单」旁的「手动重试」按钮; 响应结构 Result<String>, data 是 PDF 的 OSS URL。同步耗时 ≈ 保游网下载 PDF + OSS 上传, 一般 5-10 秒。

请求/响应示例

GET /admin/insurance/policy/{id}/download

保单已生成(happy path):

{
  "code": 200,
  "message": "成功",
  "data": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/insurance/policy/2026/04/24/policy_2047591721386098690.pdf",
  "success": true
}

保单刚承保、PDF 还没来得及上传:

{
  "code": 500,
  "message": "保单生成中,约 30 秒后可重试",
  "data": null,
  "success": false
}

后端已异步补传,前端 30 秒后重试即可拿到 URL。

POST /admin/insurance/policy/{id}/retry-upload

成功:

{
  "code": 200,
  "message": "成功",
  "data": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/insurance/policy/2026/04/24/policy_xxx.pdf",
  "success": true
}

失败(订单状态不对 / 外部保单号缺失 / 保游网还没生成 / OSS 未配置):

{
  "code": 500,
  "message": "保单PDF暂不可补传,请稍后再试或检查保险订单状态",
  "data": null,
  "success": false
}