短链服务 — 迭代需求
对应需求:待同步飞书需求池。目标是在 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 生成还款长链后调用短链服务。
repayAmount、partialRepay等还款业务字段由 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、借据或客户模型,保证短链服务可被其他业务复用。
- 业务字段通过
businessKey、subjectType、subjectId、metadata承载,避免为每类业务无限增加一级字段。 - 还款场景常用字段可以显式保留,便于 FCS、客服、催收和数据分析快速查询。
- 长链中的加密参数只作为跳转载体,短链服务不依赖其明文内容。
7.2.1 通用必填字段
| 字段 | 必填 | 说明 |
|---|---|---|
longUrl | 是 | 原始长链;短链服务只负责保存和跳转,不解析其中加密参数作为核心契约 |
sceneCode | 是 | 业务场景编码,如 repayment_due_reminder、repayment_collection_notice |
bizCode | 是 | 租户/业务线/App 标识,用于短链域名选择、异常兜底 H5 页面和统计隔离 |
requestId | 是 | 调用方幂等号;同一 requestId 重试必须返回同一短链结果 |
caller | 是 | 调用方系统编码,如 fcs、crs、ops,用于权限、审计和排查 |
7.2.2 通用可选字段
| 字段 | 必填 | 说明 |
|---|---|---|
expireDays | 否 | 短链有效天数;为空默认 90 天;传 -1 表示永久有效 |
expireTime | 否 | 指定失效时间;与 expireDays 二选一。若同时传入,以 expireTime 为准 |
subjectType | 否 | 业务主体类型,如 customer、loan、order、contract、campaign |
subjectId | 否 | 业务主体 ID;与 subjectType 配合做通用查询 |
batchNo | 否 | 批次号;用于批量短信、催收批次、运营触达批次统计 |
channel | 否 | 触达渠道,如 sms、whatsapp、push、manual |
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 | 短码 |
shortDomain | 按 bizCode 匹配的短链域名,不带 https:// |
shortUrl | 可放入短信模板的完整短链,不带 https://,格式为 shortDomain/shortCode |
expireTime | 短链失效时间 |
permanent | 是否永久有效 |
traceId | 短链服务追踪 ID |
7.6 唯一性校验
- 短链不复用:除同一
requestId幂等重试外,每次创建请求都生成新的shortCode。 shortCode全局唯一;生成后必须做唯一性校验,发生碰撞时自动重新生成。requestId在caller + 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,短链服务按该时间失效;expireTime与expireDays同时传入时,以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,还款场景使用 |
ipHash | IP 哈希 |
userAgent | 浏览器 / 设备信息 |
referer | 来源 |
traceId | 请求追踪 ID |
9.3 转化统计
至少支持以下漏斗:
短链生成数
-> 短信提交成功数
-> 短链访问 UV / PV
-> 成功跳转数
-> 还款成功数关联口径:
- 短信发送:优先通过
requestId、batchNo关联;如调用方传入businessKey,可同时使用businessKey关联。还款场景可使用sceneCode + loanId + custId交叉校验。 - 短链访问:通过
shortCode关联。 - 还款成功:通过
loanId、custId、还款时间窗口和场景批次关联;如 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重试不会生成多个短链。 - 标准创建接口必须传入
longUrl、sceneCode、bizCode、caller、requestId。 - 不同
requestId即使业务字段相同,也应生成不同短链。 - 批量创建接口能返回每条请求的成功或失败结果。
13.2 访问与有效期
- 客户点击有效短链后能快速跳转到原始还款页。
- 未传有效期时,短链默认 90 天有效。
- 上游传
expireDays=-1时,短链永久有效。 - 过期短链不能继续跳转到还款页。
- 短链不存在、已过期或目标链接异常时,进入对应
bizCode的异常兜底 H5 页面。
13.3 追踪与统计
- 能查询单个短链的生成记录、业务对象和失效时间。
- 能查询短链访问日志和访问结果。
- 能按批次或场景统计短信发送、短链访问和还款转化。
- 能按通用字段
businessKey、subjectType + subjectId查询,也能按还款字段custId、loanId查询;未传businessKey时不影响短链生成和跳转。 - 访问日志不包含完整手机号、完整 IP 和明文敏感长链。
13.4 性能与稳定性
- 短链跳转 P95 满足性能要求。
- 访问日志写入异常不影响客户跳转。
- 缓存失效或未命中时能回源数据库完成跳转。
- 短链服务异常时,FCS 应记录失败并按业务配置决定是否降级为长链短信或跳过发送。
14. 上线清单
- 确认各
bizCode对应短链域名,配置值不带https://。 - 确认各
bizCode已配置异常兜底 H5 页面。 - 确认 FCS 创建短链接口字段和幂等规则。
- 确认默认有效期 90 天和永久有效
expireDays=-1的处理规则。 - 确认批量创建接口单批次上限、部分失败返回格式和重试规则。
- 确认短链生成、访问、跳转失败、缓存回源等监控告警。
- 确认短链数据保留周期和敏感字段脱敏/加密策略。