短链服务 — 迭代需求

对应需求:待同步飞书需求池。目标是在 FCS 生成还款链接后,将长链压缩为可追踪、可过期、可高效访问的短链,并将短链作为短信模板参数传给短信服务发送。还款长链生成需求详见 13-还款链接生成

1. 第一性原理

还款短信的核心目标不是“发出链接”,而是让客户低成本、可信地进入正确还款页面,并让业务能追踪触达后的访问和还款转化。长链直接进入短信会带来三类问题:

  • 短信内容过长,影响模板变量长度、短信计费和客户阅读。
  • 长链暴露过多业务参数,不利于安全控制和后续失效。
  • FCS 只能知道短信是否提交,无法直接知道客户是否点击还款链接。

短链服务需要把“链接压缩、访问跳转、点击追踪、有效期控制”沉淀为通用能力,FCS 只关心还款场景的业务参数和发送结果。

2. 业务目标

  • 支持 FCS 在生成还款长链后调用短链服务创建短链。
  • 支持 FCS 将短链作为短信模板变量调用短信发送服务。
  • 支持客户点击短链后快速跳转到原始还款长链。
  • 支持按业务场景追踪短链生成、短信发送、短链访问、跳转结果和后续还款转化。
  • 支持短链有效期,到期后不能继续跳转到还款页面。
  • 支持高并发访问,避免还款提醒批量发送后短链跳转成为瓶颈。

3. 范围

3.1 本期包含

能力范围
短链生成调用方传入长链、业务场景、业务对象、有效期和扩展追踪字段,短链服务返回短链
批量短链支持 FCS 批量传入还款长链并批量返回短链,满足还款提醒批量短信发送
短链访问客户访问短链后,短链服务校验状态并跳转到原始长链
有效期控制默认有效期 90 天;调用方传 expireDays=-1 时永久有效
访问追踪记录访问时间、访问结果、业务标识、设备和来源信息
唯一性校验校验短码唯一、requestId 幂等唯一,短链不按业务对象复用
异常页短链不存在、已过期或目标链接异常时,按 bizCode 展示对应兜底 H5 页面
运维查询支持按短码、借据、客户、业务订单查询生成和访问记录

3.2 本期不包含

  • 面向运营人员手工创建营销短链。
  • 自定义短链域名管理后台。
  • A/B 测试、渠道分流、深度归因等营销能力。
  • 短链内容编辑;已生成短链默认不允许改目标长链。
  • 人工禁用短链能力;本期不提供运营或客服手工禁用入口。
  • 用短链替代 App 内账单、还款计划和还款入口展示。

4. 业务流程

FCS 生成还款长链
  -> 调用短链服务创建短链
  -> 短链服务写入映射、有效期和业务追踪字段
  -> 返回短链 URL
  -> FCS 将短链作为短信模板变量调用短信服务
  -> 客户收到短信并点击短链
  -> 短链服务校验短码状态和有效期
  -> 记录访问日志
  -> 302 跳转到原始还款长链
  -> 客户完成还款
  -> FCS/支付侧按原还款链路入账

5. 链路边界

模块职责
FCS生成还款长链;决定是否需要短链;传入业务标识、有效期和短信变量;记录短信业务发送结果
短链服务生成短码;按 bizCode 选择短链域名;保存长短链映射;校验有效期;记录访问;执行跳转;提供查询能力
CRS / 短信服务按模板 ID 和变量发送短信;记录短信供应商请求和返回结果
还款 H5 / App承接原始还款长链,完成还款展示、支付发起和结果处理
数据分析关联短信发送、短链访问和还款结果,形成转化漏斗

6. 前置依赖:还款链接生成

短链服务不负责初始化还款页面。FCS 需先按 13-还款链接生成 生成可访问的还款长链,再调用短链服务创建短链。

短链服务只要求 longUrl 满足以下条件:

  • longUrl 已由 FCS / 支付中台生成,能被还款 H5 正常承接。
  • 短链触达场景对应的还款长链应能被识别为 scene=3 来源。
  • longUrl 协议、格式和必要业务参数符合基础安全校验;本期暂不按域名白名单限制还款长链。
  • 生成还款长链失败时,FCS 不应继续调用短链服务。

边界口径:

  • sceneCode 是业务触达场景字段,FCS 生成还款长链和调用短链服务时使用同一字段名。
  • scene=3 是还款长链中的支付入口来源标识,由 FCS / 支付中台负责生成和识别;短链服务不解析 scene=3,也不基于 scene=3 做业务分支。
  • 短链服务接收的 longUrl 是可直接跳转的最终 URL,不理解 Plutus token 机制,也不维护 token 有效期。
  • Plutus / 支付中台不是本期短链服务调用方;本期由 FCS 生成还款长链后调用短链服务。
  • repayAmountpartialRepay 等还款业务字段由 FCS 和还款页负责校验;如需追踪,可由 FCS 放入 metadata,短链服务只存储不参与计算。

7. 短链生成规则

7.1 生成入口

短链服务按统一标准模式创建短链。FCS 还款短信是首个接入场景,后续同一接口可扩展到合同、绑卡、活动、运营通知等其他业务链接。

FCS 还款短信可先接入以下场景:

场景sceneCode说明
还款日前提醒repayment_due_reminder到期日前提醒客户还款
到期日提醒repayment_due_today借据应还日当天提醒客户还款
逾期提醒repayment_overdue_reminder逾期后提醒客户还款
还款失败后引导repayment_failed_retry扣款失败后引导客户重新还款
客服手动触达repayment_customer_service_notice客服处理来电、在线咨询、投诉时手动发送还款入口
催收触达repayment_collection_notice催收系统或催收人员触达逾期客户时发送还款入口

FCS 侧还款链接生成和短链服务统一使用 sceneCode 表示业务触达场景。还款长链中的 scene=3 只表示支付入口来源为短链触达,短链服务不按 scene=3 做业务分支,本期只做 URL 基础合法性校验并按短码映射跳转。

7.2 请求字段

短链创建统一采用标准模式:调用方必须传 longUrl 和结构化字段。短链服务不解析长链 query 作为核心数据契约,避免 URL 编码、参数加密、H5 路由变化或参数名变化导致追踪失效。

字段设计原则:

  • 通用字段不绑定 FCS、借据或客户模型,保证短链服务可被其他业务复用。
  • 业务字段通过 businessKeysubjectTypesubjectIdmetadata 承载,避免为每类业务无限增加一级字段。
  • 还款场景常用字段可以显式保留,便于 FCS、客服、催收和数据分析快速查询。
  • 长链中的加密参数只作为跳转载体,短链服务不依赖其明文内容。

7.2.1 通用必填字段

字段必填说明
longUrl原始长链;短链服务只负责保存和跳转,不解析其中加密参数作为核心契约
sceneCode业务场景编码,如 repayment_due_reminderrepayment_collection_notice
bizCode租户/业务线/App 标识,用于短链域名选择、异常兜底 H5 页面和统计隔离
requestId调用方幂等号;同一 requestId 重试必须返回同一短链结果
caller调用方系统编码,如 fcscrsops,用于权限、审计和排查

7.2.2 通用可选字段

字段必填说明
expireDays短链有效天数;为空默认 90 天;传 -1 表示永久有效
expireTime指定失效时间;与 expireDays 二选一。若同时传入,以 expireTime 为准
subjectType业务主体类型,如 customerloanordercontractcampaign
subjectId业务主体 ID;与 subjectType 配合做通用查询
batchNo批次号;用于批量短信、催收批次、运营触达批次统计
channel触达渠道,如 smswhatsapppushmanual
templateCode短信或触达模板编码,用于关联触达模板效果
recipientMasked脱敏接收方,如脱敏手机号;仅用于排查和展示
businessKey调用方业务对象键;用于业务查询和统计归因。还款场景建议使用 FCS 业务单号或 loanId + sceneCode + batchNo
metadata扩展追踪字段,只放非敏感业务属性,如金额、期次、产品、外部订单号

7.3 建议接口形式

POST /api/short-links
Content-Type: application/json
{
  "longUrl": "https://app.example.com/repayment?loanId=LN123&source=sms",
  "sceneCode": "repayment_due_reminder",
  "bizCode": "cashloan",
  "caller": "fcs",
  "requestId": "fcs-remind-20260714-LN123-001",
  "businessKey": "LN123:repayment_due_reminder:repay-remind-20260714",
  "subjectType": "loan",
  "subjectId": "LN123",
  "batchNo": "repay-remind-20260714",
  "channel": "sms",
  "templateCode": "REPAYMENT_DUE_REMINDER",
  "custId": "C10001",
  "loanId": "LN123",
  "orderId": null,
  "recipientMasked": "080****0000",
  "expireDays": 90,
  "metadata": {
    "amount": "12000",
    "periodNo": "3",
    "productName": "Cash Loan"
  }
}

响应:

{
  "shortCode": "a8K3mQ",
  "shortDomain": "s.example.com",
  "shortUrl": "s.example.com/a8K3mQ",
  "expireTime": "2026-10-13T23:59:59+08:00",
  "permanent": false,
  "traceId": "sl-20260714-000001"
}

7.4 批量创建接口

批量创建用于还款提醒、逾期提醒等批量短信场景。批量接口与单条接口使用相同字段语义,每个元素独立校验、独立生成短链、独立返回结果。

POST /api/short-links/batch
Content-Type: application/json
{
  "batchNo": "repay-remind-20260714",
  "caller": "fcs",
  "bizCode": "cashloan",
  "sceneCode": "repayment_due_reminder",
  "expireDays": 90,
  "items": [
    {
      "requestId": "fcs-remind-20260714-LN123-001",
      "businessKey": "LN123:repayment_due_reminder:repay-remind-20260714",
      "longUrl": "https://app.example.com/repayment?loanId=LN123&source=sms",
      "subjectType": "loan",
      "subjectId": "LN123",
      "custId": "C10001",
      "loanId": "LN123",
      "recipientMasked": "080****0000",
      "metadata": {
        "amount": "12000",
        "periodNo": "3"
      }
    }
  ]
}

响应:

{
  "batchNo": "repay-remind-20260714",
  "total": 1,
  "success": 1,
  "failed": 0,
  "items": [
    {
      "requestId": "fcs-remind-20260714-LN123-001",
      "shortCode": "a8K3mQ",
      "shortDomain": "s.example.com",
      "shortUrl": "s.example.com/a8K3mQ",
      "expireTime": "2026-10-13T23:59:59+08:00",
      "permanent": false,
      "traceId": "sl-20260714-000001",
      "success": true
    }
  ]
}

批量规则:

  • 批量接口不要求全量成功;单条失败不影响同批次其他短链生成。
  • 同一批次内 requestId 必须唯一。
  • 建议单批次上限由短链服务配置,例如 500 或 1000 条,避免单次请求过大影响服务稳定性。

7.5 返回字段

字段说明
shortCode短码
shortDomainbizCode 匹配的短链域名,不带 https://
shortUrl可放入短信模板的完整短链,不带 https://,格式为 shortDomain/shortCode
expireTime短链失效时间
permanent是否永久有效
traceId短链服务追踪 ID

7.6 唯一性校验

  • 短链不复用:除同一 requestId 幂等重试外,每次创建请求都生成新的 shortCode
  • shortCode 全局唯一;生成后必须做唯一性校验,发生碰撞时自动重新生成。
  • requestIdcaller + bizCode 范围内唯一;同一 requestId 重试返回第一次创建结果,不新建短链。
  • 批量接口内 requestId 不允许重复;重复项返回参数错误。
  • businessKey 只用于业务查询和统计,不用于短链复用。

8. 短链访问规则

8.1 跳转规则

  • 有效短链访问成功后返回 HTTP 302,跳转到原始 longUrl
  • 短链不存在、已过期或目标链接异常时,不跳转到还款页,展示异常兜底 H5 页面。
  • 提示页需引导客户回到 App 或联系官方客服,不展示内部错误原因。
  • 短链访问不改变借据状态,不发起还款,不替代还款页自身的身份和金额校验。

8.2 异常兜底页

  • 每个已注册 bizCode 必须配置一个异常情况下的兜底 H5 页面,例如链接不存在、链接已过期、目标链接异常等场景均进入该页面。
  • 兜底 H5 页面由 bizCode 决定,便于不同 App / 业务线展示对应品牌、客服电话、App 下载或返回 App 引导。
  • 兜底 H5 页面配置值应为完整可访问 URL,并纳入短链服务配置管理。
  • 如果短链记录存在,则按短链记录中的 bizCode 选择兜底 H5 页面;如果短码不存在导致无法识别 bizCode,使用短链服务全局默认兜底页。
  • 兜底 H5 页面不展示借据号、手机号、客户姓名、内部错误码等敏感或技术信息。

8.3 有效期

默认有效期:

  • expireDays 为空时,默认有效期为 90 天。
  • expireDays = -1 表示永久有效,短链服务不生成 expireTime
  • expireDays > 0 时,短链服务按创建时间计算 expireTime
  • 若调用方传入 expireTime,短链服务按该时间失效;expireTimeexpireDays 同时传入时,以 expireTime 为准。

规则:

  • 本期不设置场景最长有效期上限。
  • 到期后访问必须失效,不能继续跳转到原始还款链接。
  • 永久有效短链仍需遵守长链自身的业务校验;如果原始还款链接已不可用,由还款页或原业务系统拦截。

9. 数据追踪

9.1 短链主记录

字段说明
shortCode短码,唯一
shortDomain短链域名,不带协议
shortUrl完整短链,不带协议
longUrlHash原始长链哈希,避免明文长链参与索引
longUrlEncrypted加密存储的原始长链
sceneCode业务场景
bizCode租户/业务线
caller调用方系统
businessKey调用方业务对象键
subjectType业务主体类型
subjectId业务主体 ID
batchNo批次号
channel触达渠道
templateCode触达模板编码
custId客户 ID
loanId借据 ID
orderId还款订单号
recipientMasked脱敏接收方
requestId调用方幂等号
status有效、已过期
expireTime失效时间
permanent是否永久有效
metadata扩展追踪字段快照
createTime创建时间
createdBy创建人或系统账号

9.2 访问日志

字段说明
shortCode短码
accessTime访问时间
accessResult成功跳转、已过期、不存在、目标异常
sceneCode业务场景
bizCode租户/业务线
caller调用方系统
businessKey调用方业务对象键
subjectType业务主体类型
subjectId业务主体 ID
custId客户 ID,还款场景使用
loanId借据 ID,还款场景使用
ipHashIP 哈希
userAgent浏览器 / 设备信息
referer来源
traceId请求追踪 ID

9.3 转化统计

至少支持以下漏斗:

短链生成数
  -> 短信提交成功数
  -> 短链访问 UV / PV
  -> 成功跳转数
  -> 还款成功数

关联口径:

  • 短信发送:优先通过 requestIdbatchNo 关联;如调用方传入 businessKey,可同时使用 businessKey 关联。还款场景可使用 sceneCode + loanId + custId 交叉校验。
  • 短链访问:通过 shortCode 关联。
  • 还款成功:通过 loanIdcustId、还款时间窗口和场景批次关联;如 FCS 能传 orderId,优先按 orderId 关联。

10. 访问效率与稳定性

10.1 性能要求

指标要求
短链生成接口P95 < 200ms,不包含跨服务网络异常
短链跳转接口P95 < 100ms
可用性不低于短信触达主链路可用性要求
批量提醒支持还款提醒批量发送后集中点击访问

10.2 技术约束

  • 短码映射需支持缓存读取,访问跳转不应每次强依赖数据库查询。
  • 缓存 TTL 不能超过短链有效期。
  • 永久有效短链的缓存 TTL 由短链服务统一配置,例如按小时或天级过期后回源数据库刷新,不能因为业务永久有效就让缓存永久不失效。
  • 缓存未命中时可回源数据库;回源成功后重新写入缓存。
  • 访问日志写入不应阻塞跳转主流程;可异步落库或队列化。
  • 短码生成需避免可枚举规律,不能使用连续自增 ID 直接暴露。
  • 原始长链需加密存储,日志中不得打印完整还款链接。

11. 安全与风控

  • 短链域名按 bizCode 配置差异化域名,配置值不带 https://,如 s.example.com
  • 对外返回的 shortUrl 不带 https://,短信模板中直接使用 shortDomain/shortCode
  • 创建短链时必须校验 bizCode 是否已注册并启用;未注册、未启用或未配置短链域名、异常兜底 H5 页的 bizCode,直接拒绝创建短链。
  • 本期短链域名暂不考虑白名单逻辑,创建短链时不因 longUrl 域名未登记而拒绝请求;后续如需开放给更多调用方,再补充按 bizCode 配置长链域名白名单的能力。
  • 创建短链时仍需校验 longUrl 协议、格式和必要业务参数;只允许 http / https 链接,不允许空链接、非法 URL 或明显不可跳转的值。
  • 短链访问不做客户敏感信息展示,敏感校验仍由还款页负责。
  • 短链异常页不展示借据号、手机号、客户姓名等敏感信息。
  • 短链服务保存的 longUrl 不得在业务日志中明文打印。

12. 监控告警

监控项告警条件
短链生成失败率连续 5 分钟超过阈值
短链跳转失败率连续 5 分钟超过阈值
跳转接口耗时P95 超过阈值
过期访问激增同一场景异常升高
短信成功但短链访问为 0批次级异常,用于排查模板、域名或链路问题
缓存回源比例回源比例异常升高

13. 验收标准

13.1 生成与发送

  • FCS 生成还款长链后能成功换取短链。
  • FCS 能将短链作为短信模板变量传给短信服务。
  • 传入未注册、未启用或配置不完整的 bizCode 时,短链服务拒绝创建短链。
  • 同一 requestId 重试不会生成多个短链。
  • 标准创建接口必须传入 longUrlsceneCodebizCodecallerrequestId
  • 不同 requestId 即使业务字段相同,也应生成不同短链。
  • 批量创建接口能返回每条请求的成功或失败结果。

13.2 访问与有效期

  • 客户点击有效短链后能快速跳转到原始还款页。
  • 未传有效期时,短链默认 90 天有效。
  • 上游传 expireDays=-1 时,短链永久有效。
  • 过期短链不能继续跳转到还款页。
  • 短链不存在、已过期或目标链接异常时,进入对应 bizCode 的异常兜底 H5 页面。

13.3 追踪与统计

  • 能查询单个短链的生成记录、业务对象和失效时间。
  • 能查询短链访问日志和访问结果。
  • 能按批次或场景统计短信发送、短链访问和还款转化。
  • 能按通用字段 businessKeysubjectType + subjectId 查询,也能按还款字段 custIdloanId 查询;未传 businessKey 时不影响短链生成和跳转。
  • 访问日志不包含完整手机号、完整 IP 和明文敏感长链。

13.4 性能与稳定性

  • 短链跳转 P95 满足性能要求。
  • 访问日志写入异常不影响客户跳转。
  • 缓存失效或未命中时能回源数据库完成跳转。
  • 短链服务异常时,FCS 应记录失败并按业务配置决定是否降级为长链短信或跳过发送。

14. 上线清单

  • 确认各 bizCode 对应短链域名,配置值不带 https://
  • 确认各 bizCode 已配置异常兜底 H5 页面。
  • 确认 FCS 创建短链接口字段和幂等规则。
  • 确认默认有效期 90 天和永久有效 expireDays=-1 的处理规则。
  • 确认批量创建接口单批次上限、部分失败返回格式和重试规则。
  • 确认短链生成、访问、跳转失败、缓存回源等监控告警。
  • 确认短链数据保留周期和敏感字段脱敏/加密策略。