前端对接分销开票
分销开票调整优化
09-24 调整需求:费用类型勾选分批开票、30/60/90 时间筛选、申请单维度记录与撤销、逾期赔付标识;含核心口径与页面-接口对应
Markdown 原文(给 AI 用):https://doc.xfun.fun/partner-invoice-adjust-api.md
对应 2026-09-24《繁花/优花速达开票调整优化》9 条需求的后端实现。全部为新增接口 + 既有接口加可选参数,旧版小程序不受影响。所有接口 POST + JSON,沿用花店登录态,前缀 /invoice。通用约定(响应结构、分页、时间与金额格式)与 上一版文档 完全一致,此处不重复。
接口一览
| 模块 | 路径 | 名称 | 状态 |
|---|---|---|---|
| 发票中心(新版) | /invoice/partner/type/list | 可开票类型汇总 | 新增 |
| 发票中心(新版) | /invoice/partner/flower/supplier/list | 花材款供应商汇总 | 新增 |
| 发票中心(新版) | /invoice/partner/apply/preview | 一键开票预览 | 变更 +invoiceItemTypes、timeRange |
| 发票中心(新版) | /invoice/partner/apply/submit | 一键开票提交 | 变更 +invoiceItemTypes、timeRange |
| 开票记录(申请单维度) | /invoice/partner/application/list | 记录列表 | 新增 |
| 开票记录(申请单维度) | /invoice/partner/application/detail | 申请单详情 | 新增 |
| 开票记录(申请单维度) | /invoice/partner/application/flower | 花材款发票明细 | 新增 |
| 开票记录(申请单维度) | /invoice/partner/application/cancel | 撤销申请单 | 新增 |
| 既有接口 | /invoice/partner/group/list | 可开票分组列表 | 变更 +timeRange(可选) |
| 既有接口 | /invoice/partner/group/order/list | 组内订单列表 | 变更 +timeRange(可选) |
本版变化(相对 2026-09-07 版)
- 发票中心改「按费用类型」展示:4 类各一行(供应链服务费 / 干线物流费 / 平台服务费 / 花材款),花材款聚合展示供应商家数与合计,不再按供应商平铺分组。数据源换成 类型汇总接口。
- 支持勾选费用类型分批开票:预览 / 提交新增
invoiceItemTypes。金额按全量拆分固定,勾选只决定本次开哪些类型(见 核心口径)。 - 新增时间筛选
timeRange:30 / 60 / 90 天,按 确认收货时间。页面默认选中 30 天并 显式传 30;不传为「近 3 个月」旧口径(仅作旧版兼容,新版页面别用)。传其他值报错「时间筛选仅支持30/60/90天」。 - 开票记录改申请单维度:一次申请一条记录,汇总状态新增「部分开票」。旧的按票据(request)平铺的记录列表不再是记录页数据源。
- 撤销改申请单级:全部票据未开才可撤,任一已开(或已被百望受理)整单不可撤。不再提供单张票据撤销入口。
- 逾期补开标识:逾期后商家补开的发票,已开票区仍带逾期标识与「已赔付百分之二」文案(赔付指花店已收到申请金额 2% 的寻梦币补偿)。
- 收据流程本次 无变化:收据不参与类型勾选,applyType=2 的「去开收据」流程照旧。
核心口径:勾选与金额(产品 2026-09-24 拍板)
金额永远按全量拆分固定,勾选费用类型只决定本次开哪些类型的票,分批开总和不变。
- 一笔订单的实付被拆成 4 项(花材款 / 供应链服务费 / 干线物流费 / 平台服务费),各项金额由后端全量算法一次算死,相互独立、勾选不重算。
- 例:可开票池共 100 元 = 花材款 70 + 物流 10 + 供应链 5 + 平台 15。只勾「花材款」提交 → 本次开 70 元;剩下 30 元留在池子里,下次勾其余类型再开,两次合计仍是 100。
- 所以前端 底部合计 = 勾选行的
amount直接相加,不需要再调预览接口算勾选组合的金额(预览接口也支持传勾选,返回值一致)。 - 花材款只能 整体勾选,不能只选其中部分供应商。供应商汇总页是纯查看的下钻页,与勾选状态无关。
- 未勾选任何类型时禁用提交按钮;全不勾传给后端会报「所选费用类型没有可开票金额」。
页面与接口对应(按原型)
| 原型页面 | 用到的接口 |
|---|---|
| 发票中心(类型勾选列表) | 类型汇总渲染 4 行 + 勾选框;切时间筛选重新请求;底部合计前端累加勾选行 amount |
| 平台项行(供应链 / 物流 / 平台服务费)→ 订单列表 | 旧接口 /partner/group/order/list:传 invoiceItemType + statusTab: 2 + 与列表页相同的 timeRange;不传 supplierId(更不能传字符串 "undefined",会报消息解析错误)。返回订单数与金额和类型汇总行一致 |
| 花材款 → 供应商汇总页 | 点花材款行进入,供应商汇总(带同样的 timeRange);纯展示,返回不改变勾选 |
| 申请开票(勾选页直接提交,无确认页) | 选抬头 → 提交(invoiceItemTypes + timeRange + invoiceTitleId)。预览在新版发票流程 可不调(已选金额=勾选行 amount 相加即准确值),想做提交前金额校验再调;收据流程(applyType=2)仍用预览 |
| 开票记录列表 | 记录列表(分页);行上展示汇总状态、逾期角标(hasOverdue) |
| 申请详情 | 申请单详情;平台三项行直接给 requestNo / invoiceUrl,花材款行进花材款明细 |
| 花材款发票明细 | 花材款明细三区(待开 / 已开 / 已逾期);单张票所含订单用旧接口 /partner/request/detail(传 requestNo) |
| 撤销 | 列表 / 详情 canCancel=true 时展示按钮 → 撤销申请单 |
枚举
timeRange 时间筛选,按确认收货时间
| 值 | 含义 |
|---|---|
| 30 | 近 30 天(页面默认,显式传) |
| 60 | 近 60 天 |
| 90 | 近 90 天 |
| 不传 | 近 3 个月(仅旧版兼容) |
| 其他值 | 报错 |
invoiceItemType 费用类型,同旧版
0 花材款 · 1 供应链服务费 · 2 干线物流费 · 3 平台服务费
申请单汇总状态 status 记录列表 / 详情头部
| 值 | 文案 | 含义 |
|---|---|---|
| 1 | 待商家开票 | 所有票据都还没开 |
| 2 | 已开发票 | 所有票据都已开出 |
| 3 | 部分开票 | 已开了一部分,其余待开或逾期 |
| 4 | 已撤销 | 整单撤销 |
详情内类型行状态 typeItems[].status
| 值 | 文案 | 说明 |
|---|---|---|
| 1 | 未开发票 | — |
| 2 | 已开发票 | 平台项此时 invoiceUrl 非空 |
| 3 | 部分开票 | 仅花材款可能出现(部分供应商已开) |
| 4 | 已逾期 | 该类型票据全部逾期未开 |
逾期与赔付标识
hasOverdue(列表 / 详情):申请单里存在逾期票据,含「逾期后又补开」的。overdueFlag(花材款明细行):已逾期区恒 true;已开票区为 true 表示逾期补开,行上要同时展示逾期标识与compensateDesc。compensateDesc:逾期时固定「已赔付百分之二」,直接展示后端文案;未逾期为空串。
发票中心(新版) · 前缀 /invoice
POST/invoice/partner/type/list可开票类型汇总
新增
新版发票中心的数据源。返回 4 类费用各一行(固定顺序:供应链服务费 → 干线物流费 → 平台服务费 → 花材款),金额为 0 的类型不返回。每行对应一个勾选框,勾选状态由前端维护。
请求
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
timeRange | int | 可选 | 30 / 60 / 90;页面默认选 30 并显式传 30 |
响应 data 为数组,可能为空(无可开票订单)
| 字段 | 类型 | 说明 |
|---|---|---|
invoiceItemType | int | 0 花材款 · 1 供应链服务费 · 2 干线物流费 · 3 平台服务费 |
typeName | string | 类型名,直接展示 |
amount | decimal | 该类型可开票金额合计。勾选后底部合计 = 勾选行 amount 相加 |
orderCount | int | 关联订单数(同类型跨供应商去重) |
supplierCount | int | 可开票供应商家数;仅花材款 > 0(如「共5家供应商」),平台项为 0 |
示例
// 请求
{ "timeRange": 30 }
// 响应
{
"code": 0, "msg": "success",
"data": [
{ "invoiceItemType": 1, "typeName": "供应链服务费", "amount": 48.00, "orderCount": 12, "supplierCount": 0 },
{ "invoiceItemType": 2, "typeName": "干线物流费", "amount": 96.50, "orderCount": 10, "supplierCount": 0 },
{ "invoiceItemType": 3, "typeName": "平台服务费", "amount": 63.50, "orderCount": 12, "supplierCount": 0 },
{ "invoiceItemType": 0, "typeName": "花材款", "amount": 1356.00, "orderCount": 12, "supplierCount": 5 }
]
}POST/invoice/partner/flower/supplier/list花材款供应商汇总
新增
点花材款行进入的下钻页:按供应商展示可开票金额与订单数。纯查看,返回列表页不改变勾选状态;花材款只能整体勾选,此页没有勾选框。传与列表页相同的 timeRange。
请求
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
timeRange | int | 可选 | 与类型汇总页保持一致 |
响应 data 为数组
| 字段 | 类型 | 说明 |
|---|---|---|
supplierId | long | 供应商 id |
supplierName | string | 供应商名称 |
amount | decimal | 该供应商可开票金额 |
orderCount | int | 关联订单数 |
示例
// 请求
{ "timeRange": 30 }
// 响应
{ "code": 0, "msg": "success",
"data": [
{ "supplierId": 1021, "supplierName": "云南甲花卉", "amount": 656.00, "orderCount": 6 },
{ "supplierId": 1088, "supplierName": "斗南乙鲜花", "amount": 700.00, "orderCount": 7 }
] }POST/invoice/partner/apply/preview一键开票预览
变更:+invoiceItemTypes、timeRange
既有接口加两个可选参数,响应结构不变(见旧文档)。新版发票流程没有确认页,可以不调此接口(勾选合计前端累加即可);保留给旧版一键流程、收据流程(applyType=2)、以及可选的提交前金额校验。
请求 新增字段,其余不变
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
applyType | int | 可选 | 新版发票中心传 1(仅发票);收据流程照旧传 2 |
invoiceItemTypes | int[] | 可选 | 新增 勾选的费用类型,如 [0, 2];不传 = 全部(旧版行为) |
timeRange | int | 可选 | 新增 30 / 60 / 90,与列表页一致;不传 = 近 3 个月旧口径 |
响应
- 结构同旧版:
totalAmount(勾选类型合计)、orderCount(勾选类型去重订单数)、supplierBreakdown(只含勾选类型的行)。 - 勾选的类型都没有可开票金额时报错:「所选费用类型没有可开票金额」。
示例
// 请求:只勾了花材款和干线物流费,近30天
{ "applyType": 1, "invoiceItemTypes": [0, 2], "timeRange": 30 }POST/invoice/partner/apply/submit一键开票提交
变更:+invoiceItemTypes、timeRange
既有接口加同样两个可选参数。一次提交生成 一个申请单(applicationId),内部按勾选类型生成多张票据、各自独立开票。未勾的类型金额留在可开票池,之后可再次勾选提交(新申请单)。
请求 新增字段,其余不变
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
invoiceTitleId | long | 必填 | 发票抬头 ID(同旧版) |
applyType | int | 可选 | 新版发票中心传 1;收据流程照旧传 2(收据不受勾选影响) |
invoiceItemTypes | int[] | 可选 | 新增 与预览一致,务必传同一份勾选 |
timeRange | int | 可选 | 新增 与预览一致 |
响应 同旧版
// 请求
{ "invoiceTitleId": 88, "applyType": 1, "invoiceItemTypes": [0, 2], "timeRange": 30 }
// 响应
{ "code": 0, "msg": "success", "data": { "applicationId": 3301, "receiptIds": [] } }开票记录(申请单维度) · 前缀 /invoice
POST/invoice/partner/application/list记录列表
新增
新版开票记录页数据源:一次申请一条记录,按申请时间倒序,分页。替代旧的按票据平铺的 /partner/request/list。
请求
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
pageIndex | int | 必填 | 从 1 起 |
pageSize | int | 必填 | 建议 10 |
statusTab | int | 可选 | 新增 三 Tab 方案:1 开票中(汇总状态为待商家开票或部分开票)2 已完成(已开发票)3 已逾期(存在逾期未开票据);不传返回全部(含已撤销)。已逾期 Tab 下记录的 status 仍是 1 或 3,卡片上的逾期标识用 hasOverdue;逾期没开完的单同时出现在 Tab 1 和 3 |
响应 data.records 每行
| 字段 | 类型 | 说明 |
|---|---|---|
id | long | 申请单 ID,后续详情 / 明细 / 撤销都传它 |
applicationNo | string | 申请编号 |
createTime | datetime | 申请时间 |
titleName | string | 发票抬头,卡片直接展示 |
taxNumber | string | 税号,个人抬头可能为空 |
totalAmount | decimal | 汇总金额(撤销的申请单也保留原金额) |
status | int | 1 待商家开票 2 已开发票 3 部分开票 4 已撤销 |
statusDesc | string | 状态文案,直接展示 |
hasOverdue | boolean | 存在逾期票据(含逾期补开),行上展示逾期角标 |
canCancel | boolean | 可撤销:全部票据未开时 true |
示例
// 请求
{ "pageIndex": 1, "pageSize": 10, "statusTab": 1 }
// 响应
{ "code": 0, "msg": "success",
"data": { "total": 2, "current": 1, "pages": 1, "records": [
{ "id": 3301, "applicationNo": "FP20260927001", "createTime": "2026-09-27 10:00:00",
"totalAmount": 1452.50, "status": 3, "statusDesc": "部分开票", "hasOverdue": false, "canCancel": false },
{ "id": 3288, "applicationNo": "FP20260920007", "createTime": "2026-09-20 15:20:00",
"totalAmount": 800.00, "status": 2, "statusDesc": "已开发票", "hasOverdue": true, "canCancel": false }
] } }POST/invoice/partner/application/detail申请单详情
新增
票据信息(抬头 / 税号 / 金额 / 时间)+ 按费用类型的发票明细行。平台三项每行就是一张票,直接给票据编号和发票 URL;花材款是聚合行(张数 = 供应商数),点击进花材款明细页。
请求
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
applicationId | long | 必填 | 记录列表的 id |
响应
| 字段 | 类型 | 说明 |
|---|---|---|
id / applicationNo / createTime / totalAmount / status / statusDesc / hasOverdue / canCancel | — | 同记录列表行 |
titleName | string | 发票抬头 |
taxNumber | string | 税号 |
typeItems | array | 发票明细,按费用类型一行 |
invoiceItemType | int | 0 花材款 · 1 供应链服务费 · 2 干线物流费 · 3 平台服务费 |
typeName | string | 类型名 |
amount | decimal | 该类型申请金额 |
orderCount | int | 关联订单数 |
status | int | 1 未开发票 2 已开发票 3 部分开票 4 已逾期 |
statusDesc | string | 状态文案 |
pendingCount | int | 待开票张数。花材款 = 待开供应商数;平台项 0 或 1 |
invoicedCount | int | 已开票张数,口径同上 |
requestNo | string | 票据编号。平台项用它调旧接口 /partner/request/detail 看所含订单;花材款为空,走花材款明细页 |
invoiceUrl | string | 发票文件 URL,平台项已开票时有值,预览 / 下载直接用 |
示例
// 请求
{ "applicationId": 3301 }
// 响应(截取)
{ "code": 0, "msg": "success",
"data": {
"id": 3301, "applicationNo": "FP20260927001", "titleName": "昆明某某花店", "taxNumber": "91530100XXXX",
"createTime": "2026-09-27 10:00:00", "totalAmount": 1452.50,
"status": 3, "statusDesc": "部分开票", "canCancel": false, "hasOverdue": false,
"typeItems": [
{ "invoiceItemType": 2, "typeName": "干线物流费", "amount": 96.50, "orderCount": 10,
"status": 2, "statusDesc": "已开发票", "pendingCount": 0, "invoicedCount": 1,
"requestNo": "RQ20260927002", "invoiceUrl": "https://…/rq2.pdf" },
{ "invoiceItemType": 0, "typeName": "花材款", "amount": 1356.00, "orderCount": 12,
"status": 3, "statusDesc": "部分开票", "pendingCount": 3, "invoicedCount": 2,
"requestNo": null, "invoiceUrl": null }
] } }POST/invoice/partner/application/flower花材款发票明细
新增
申请详情里点花材款行进入。按供应商一张票,分三区:待开票 / 已开票(含逾期补开)/ 已逾期。单张票所含订单用旧接口 /partner/request/detail 传 requestNo。
请求
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
applicationId | long | 必填 | 同详情 |
响应
| 字段 | 类型 | 说明 |
|---|---|---|
totalAmount | decimal | 花材款合计金额 |
supplierCount | int | 供应商家数(= 票据张数) |
pendingList / invoicedList / overdueList | array | 三个分区,行结构相同: |
requestNo | string | 票据编号,下钻票据详情用 |
supplierId / supplierName | — | 供应商 |
amount | decimal | 该票金额 |
orderCount | int | 关联订单数 |
invoiceUrl | string | 发票文件 URL,已开票区有值 |
overdueFlag | boolean | 已逾期区恒 true;已开票区 true = 逾期补开,行上带逾期标识 |
compensateDesc | string | 逾期时「已赔付百分之二」,直接展示;未逾期为空串 |
示例
// 请求
{ "applicationId": 3301 }
// 响应(截取)
{ "code": 0, "msg": "success",
"data": { "totalAmount": 1356.00, "supplierCount": 5,
"pendingList": [
{ "requestNo": "RQ20260927005", "supplierId": 1090, "supplierName": "丙花卉", "amount": 300.00,
"orderCount": 3, "invoiceUrl": null, "overdueFlag": false, "compensateDesc": "" } ],
"invoicedList": [
{ "requestNo": "RQ20260927003", "supplierId": 1021, "supplierName": "云南甲花卉", "amount": 656.00,
"orderCount": 6, "invoiceUrl": "https://…/rq3.pdf", "overdueFlag": false, "compensateDesc": "" },
{ "requestNo": "RQ20260910001", "supplierId": 1088, "supplierName": "斗南乙鲜花", "amount": 400.00,
"orderCount": 4, "invoiceUrl": "https://…/rq1.pdf", "overdueFlag": true, "compensateDesc": "已赔付百分之二" } ],
"overdueList": [
{ "requestNo": "RQ20260901009", "supplierId": 1105, "supplierName": "丁园艺", "amount": 0.00,
"orderCount": 1, "invoiceUrl": null, "overdueFlag": true, "compensateDesc": "已赔付百分之二" } ] } }POST/invoice/partner/application/cancel撤销申请单
新增
申请单级撤销:整单所有票据都未开(且未被开票平台受理)才可撤,任一已开整单不可撤。前端只在 canCancel=true 时展示按钮,仍需处理并发导致的报错。撤销后金额回到可开票池,可重新勾选申请。
请求
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
applicationId | long | 必填 | — |
响应与错误文案
- 成功:
{ "code": 0, "data": true },刷新列表即可(该单变「已撤销」,金额保留展示)。 - 「申请单不存在」——id 错误或不属于当前花店。
- 「当前状态不可撤销」——已撤销 / 已完成的单。
- 「已有票据开出或逾期,无法撤销申请」「已有票据发起开票,无法撤销申请」——期间商家开了票或百望已受理,提示后刷新详情。
- 「票据状态已变化,请刷新后重试」——并发冲突,重试即可。
旧接口的去留
| 旧接口 | 新版怎么用 |
|---|---|
/partner/group/list、/partner/group/order/list | 保留并支持 timeRange(可选)。新版里 group/order/list 就是平台项行的订单下钻:invoiceItemType + statusTab: 2 + timeRange,不传 supplierId。timeRange 必须与列表页一致,不传会落到近 3 个月旧口径,订单数对不上 |
/partner/request/detail | 继续使用:单张票据的所含订单与每单金额,从申请详情(平台项 requestNo)或花材款明细(每行 requestNo)下钻 |
/partner/request/list | 保留但新版记录页不再使用,改用 /partner/application/list |
/partner/request/cancel | 保留但新版不再暴露单张撤销入口,撤销一律走 /partner/application/cancel |
收据三接口 /receipt/application/*、可开收据 /partner/receipt/order/list | 不变,见旧文档 |
联调环境:测试服已部署(bulky-test/purchaser)。所有新接口未登录统一返回 { "code": 1, "msg": "当前未登录" },请带花店登录态调试;接口行为与文档不符时以 knife4j 在线文档为准并反馈后端。
对应后端分支 xiaofun/xm-bulky-mall-suppiler · 2026-09-24 需求,09-24 已上测(bulky-test/purchaser)。旧版对接文档见 partner-invoice-api。