⑦ 红冲 / 取消
开错了、要撤单时用。红冲=已出票后开一张红票对冲(页面类,要人确认);取消=付款前直接取消这单(数据类),撤单/换单场景用它。红冲后个税、手续费由工行自动冲退,散户不吃亏。
属「工商银行 · 业务型接口」——底层编排 乐企直联原子接口,你只调这一个。
红冲
接口 · 红冲(页面类)
POST https://openapi.kailingteck.com/api/v1/rinv/invoice/red
鉴权:X-App-Key + X-Timestamp + X-Sign(= sha256(appKey + 时间戳 + 报文 + appSecret))。
请求参数
| 字段 | 必填 | 大白话说明 |
|---|---|---|
orderId | 必填 | 要冲红的原订单号 |
amount | 选填 | 冲红金额,不传为全额 |
projectName | 选填 | 项目 / 货物名称 |
请求示例
{
"orderId": "ORD1",
"amount": "100",
"projectName": "废纸"
}返回
所有接口都用同一层信封:code/msg/requestId/timestamp/data。业务字段都在 data 里,下表列的就是 data 的内容。code 为 CYT_00000 表示调用成功。
返回参数(data)
| 字段 | 大白话说明 |
|---|---|
orderId | 回显原订单号 |
pageUrl | 工行红冲确认页地址,跳过去人工确认 |
mock | true=演示数据 |
返回示例(成功)
{
"code": "CYT_00000",
"data": {
"orderId": "ORD1",
"pageUrl": "https://openapi.kailingteck.com/api/v1/icbc/redirect/rxxx",
"mock": false
}
}前端怎么用
location.href = res.data.pageUrl; // 跳工行红冲确认页
红冲要开红字确认单,是页面类流程。冲完可再用⑤查结果确认。
取消开票(推荐)
接口 · 取消开票(推荐)(数据类)
POST https://openapi.kailingteck.com/api/v1/rinv/invoice/cancel
鉴权:X-App-Key + X-Timestamp + X-Sign(= sha256(appKey + 时间戳 + 报文 + appSecret))。
请求参数
| 字段 | 必填 | 大白话说明 |
|---|---|---|
orderId | 必填 | 要取消的订单号(与④下单一致) |
offlineRefund | 选填 | 是否已线下退款:1=是 / 0=否(默认不上送)。仅特殊场景需要:已支付但缴税失败、或开票失败且线下已把货款退还的单子,传 1 才能取消关闭;付款前的普通撤单不用传 |
请求示例
{
"orderId": "ORD1"
}返回
所有接口都用同一层信封:code/msg/requestId/timestamp/data。业务字段都在 data 里,下表列的就是 data 的内容。code 为 CYT_00000 表示调用成功。
返回参数(data)
| 字段 | 大白话说明 |
|---|---|
cancelled | ★true=取消成功(或这单先前已取消过);false=没取消成,看 reason |
alreadyCancelled | true=这单先前已经取消过,本次按成功处理——接口幂等,重试安全 |
reason | cancelled=false 时,工行给的原始说法 |
raw | 工行原始返回(reversal_status:00 取消成功 / 01 取消失败) |
返回示例(成功)
{
"code": "CYT_00000",
"msg": "success",
"data": {
"orderId": "ORD1",
"cancelled": true,
"reason": null,
"mock": false
}
}前端怎么用
const r = await post('/api/v1/rinv/invoice/cancel', { orderId });
if (!r.data.cancelled) alert(r.data.reason); // 没取消成,按工行的说法处理主场景:预开票成功、散户已确认、但还没付款的订单——撤单/换单时先取消这单,再重新下单。取消成功后用⑤查开票结果确认状态。与「作废」是同一个工行接口(《发票取消接口》),cancel 是推荐入口、返回结构更直白;旧路径 /api/v1/rinv/invoice/void 继续可用,返回结构为旧版(result/status)。
作废(旧入口)
接口 · 作废(旧入口)(数据类)
POST https://openapi.kailingteck.com/api/v1/rinv/invoice/void
鉴权:X-App-Key + X-Timestamp + X-Sign(= sha256(appKey + 时间戳 + 报文 + appSecret))。
请求参数
| 字段 | 必填 | 大白话说明 |
|---|---|---|
orderId | 必填 | 要作废的原订单号 |
offlineRefund | 选填 | 是否已线下退款:1=是 / 0=否(默认)。工行 2026-07 起支持:已支付但缴税失败、或开票失败且线下已完成退款的单子,传 1 才能取消关闭;普通未支付订单不用传 |
请求示例
{
"orderId": "ORD1"
}返回
所有接口都用同一层信封:code/msg/requestId/timestamp/data。业务字段都在 data 里,下表列的就是 data 的内容。code 为 CYT_00000 表示调用成功。
返回参数(data)
| 字段 | 大白话说明 |
|---|---|
orderId | 回显原订单号 |
status | 工行给的作废状态 |
result | 工行给的处理结果说明 |
raw | 工行原始全字段 |
返回示例(成功)
{
"code": "CYT_00000",
"data": {
"orderId": "ORD1",
"status": "02",
"result": "成功",
"mock": false,
"raw": { }
}
}异常与报错
| 情形 | 含义与处理 |
|---|---|
| 提示未查询到订单数据 | 订单号不对,或该单还没到可作废的阶段 |
| 已开票的单作废失败 | 票已经开出去了就只能走红冲,不能作废 |
前端怎么用
// 直接作废,拿 data.status / data.result
所有接口通用的报错(平台层)
| HTTP / code | 含义与处理 |
|---|---|
400 · CYT_40001 | 必填参数没传,data.hint 里写了缺哪个 |
401 · CYT_40100 / 40102 | 缺鉴权头,或签名算错。签名 = sha256(appKey + 时间戳 + 报文原文 + appSecret),参与签名的报文必须与实际发送的逐字节一致 |
401 · CYT_40103 | 时间戳与服务器相差超过 300 秒,校准本机时间后重试 |
403 · CYT_40301 | 这把密钥的产品或渠道不对(工行接口需要「反向开票」产品 + 「工商银行」渠道) |
429 · CYT_42901 | 超过每分钟 120 次限流,稍后重试 |
502 · CYT_50200 | 工行侧暂时不可达。注意工行测试环境每晚 19:00 后关闭、次日恢复,联调请排在工作时间 |
200 · data.mock=true | 尚未配置工行凭据,返回的是演示数据、并未真调工行 |
