① 开票
开一张数电发票。所有业务共用这一个接口——普通商品直接调,属于税局认定的特定业务时在基础字段之外多传一块即可。开票是异步的:本接口只返回受理号,票要用②查结果拿。
属「正向开票 · 腾讯联用」——开票通道的签名与加密全在开灵中台,你只调这一个。
接口
POST https://openapi.kailingteck.com/api/v1/invoice/forward/create
鉴权:X-App-Key + X-Timestamp(Unix 秒) + X-Sign(= sha256(appKey + 时间戳 + 报文原文 + appSecret) 小写十六进制)。与开灵其它接口完全一致。
请求参数
⚠️
开票数据真实性与税务责任
- 发票的全部票面要素——购销方名称与纳税人识别号、商品名称与税收分类编码、数量金额与税率、 支付流水号等——必须真实,并与实际发生的业务一致。
- 开灵仅提供接口通道与报文转发,不对报文内容做真实性核验,也无从判断一笔业务是否真实发生。
- 若因填报虚假、编造或与实际业务不符的数据(例如编造的支付流水号、不实的购方税号、 与真实交易不符的商品名称或税收分类编码)导致发票异常、被税务机关核查或稽查,相关法律责任与后果由开票方(销方)自行承担。
- 两点建议:没有真实线上支付环节就不要传
pay_info, 留空即可;税收分类编码拿不准时,先与主管税务机关或开灵确认后再开,不要试错。
| 字段 | 必填 | 大白话说明 |
|---|---|---|
order_id | 必填 | 你侧订单号,全局唯一。查结果、红冲都用它,不要复用 |
seller_taxpayer_num | 必填 | 销方税号(开票方,即贵司税号)。★须与实际业务一致,虚假填报引发的税务责任由开票方承担。 |
terminal_code | 必填 | 数电票规则:传销方税号,不是传统税盘号 |
invoice_type_code | 必填 | 082 全电电子普票 / 081 全电电子专票 |
title_type | 必填 | 抬头类型:1 个人或政府事业单位 / 2 企业 |
buyer_title | 必填 | 购方名称。title_type=2 时 buyer_taxpayer_num 也必填。★须为真实购买方,不得虚构或代填他人抬头。 |
buyer_taxpayer_num | 条件 | 购方税号,抬头类型为企业时必填。★须与实际业务一致,虚假填报引发的税务责任由开票方承担。 |
drawer | 必填 | 开票人姓名,需与电子税务局登记一致。★不得填写他人姓名。 |
amount_has_tax | 必填 | 含税总金额,元,两位小数。★须等于实际成交金额,★须与实际业务一致,虚假填报引发的税务责任由开票方承担。 |
amount_without_tax | 必填 | 不含税总金额 |
tax_amount | 必填 | 总税额。★须与金额、税率自洽(不含税金额+税额=含税金额),不得凑数。 |
items[].name | 必填 | 商品名称,50 字内。不含 < > / & 等特殊符号。部分特定业务对名称写法另有要求,见下方对应的业务块。★须如实反映所售商品或服务,不得以其他品名替代。 |
items[].tax_code | 必填 | 税收分类编码,见税局分类编码表。★须与商品或服务的实际属性匹配;拿不准的先与主管税务机关或开灵确认,不要试错。编码错配引发的税务责任由开票方承担。 |
items[].total_price | 必填 | 该行不含税金额 = 含税金额 ÷(1+税率),两位小数 |
items[].tax_rate | 必填 | 税率,最多三位小数。★须为该商品或服务适用的法定税率,不得自行调整。 |
items[].tax_amount | 必填 | 该行税额 = 不含税金额 × 税率,两位小数 |
items[].total | 条件 | 数量,最多 8 位小数。传了 price 就必填 |
items[].price | 条件 | 不含税单价 = 不含税金额 ÷ 数量。传了 total 就必填 |
items[].unit | 选填 | 商品单位,显示在票面「单位」栏,可填「个」「次」等。部分特定业务对单位取值有强制要求,见下方对应的业务块 |
items[].models | 选填 | 规格型号,显示在票面「规格型号」栏 |
items[].discount | 选填 | 含税折扣总金额,必须是负数 |
items[].preferential_policy_flag | 选填 | 优惠政策标志 |
items[].zero_tax_flag | 选填 | 零税率标识 |
pay_info[] | 选填 | 支付信息集合。★开灵实测:不传也能开出票。但如果你的业务有真实线上支付环节(尤其成品油「支付即开票」),建议如实传——通道文档要求乐企联用传真实渠道流水号,编造的流水号在支付与发票匹配核验时有风险 |
pay_info[].pay_num | 选填 | ★真实的渠道交易流水号(微信支付流水号以 420 开头)。没有线上支付环节就留空,不要编一个填进去——虚构流水号引发的税务风险由开票方承担 |
pay_info[].pay_channel_code | 选填 | 交易渠道代码:001 现金 / 002 银行转账 / 003 票据 / 004 借记卡 / 005 信用卡 / 006 购物卡券 / 007 优惠券 / 008 商场积分 / 009 支付宝 / 010 微信支付 / 011 云闪付 / 012 Apple Pay / 013 Samsung Pay / 099 其他。★通道文档写明乐企联用只支持微信支付(010);实测传 001 现金也能开,但以真实支付方式为准 |
callback_url | 必填 | ★开票结果回传地址——回调不用另外配置,就是随这个请求送过去的。开票状态一变,平台会 POST 推到这个地址;推送字段见下方「开票结果回调」块。不想轮询就靠它。红冲的回传地址在 ③ 的 invoices[].callback_url 里单独传 |
specific_business_code | 特定业务必填 | ★特定业务代码——这是通往「特定业务」的入口。普通开票不填;做税局认定的特定业务时填对应代码,并在请求体顶层加上该代码对应的字段块。取值:01 成品油 / 03 建筑服务 / 04 货物运输 / 05 不动产销售 / 06 不动产经营租赁 / 09 旅客运输 / 13 拖拉机和联合收割机 / 15 数电二手车 / 51、52 二手车销售统一发票。★农产品收购(16)、自产农产品(12)、报废产品收购(24)不在本产品范围——这三类是收购方开给出售方的票,属于反向开票,请用平台的「反向开票」产品 |
special_invoice_kind | 选填 | 特殊票种标识,普通开票传空或 00。做特定业务时按业务取值,具体取值见下方对应的业务块 |
e_extra_info | 选填 | 特殊行业扩展信息,传 JSON 字符串(不是对象)。医疗服务住院(specific_business_code=10)/门诊(=11)时传病人信息;乐企微信支付拆分金额时传支付订单数据 |
请求示例(基础字段,特定业务的完整报文见下方各业务块)
{
"order_id": "REG1788017096448",
"invoice_type_code": "082",
"seller_taxpayer_num": "91110119MABQDU249D",
"seller_name": "北京湛露科技有限公司",
"seller_address": "北京市",
"seller_tel": "01000000000",
"seller_bank_name": "测试银行",
"seller_bank_account": "1234567890",
"title_type": 1,
"buyer_title": "个人",
"terminal_code": "91110119MABQDU249D",
"drawer": "开灵测试",
"callback_url": "https://你们的域名/invoice/callback",
"template": 1,
"amount_has_tax": "1.00",
"amount_without_tax": "0.88",
"tax_amount": "0.12",
"taxpayer_confirmation": {
"draw_with_nobuyer_flag": 1
},
"items": [
{
"name": "办公用品",
"tax_code": "1080118000000000000",
"unit": "个",
"total": "1",
"price": "0.88",
"total_price": "0.88",
"tax_rate": "0.13",
"tax_amount": "0.12",
"amount_has_tax": "1.00"
}
]
}上面那张是基础字段,所有票都要填。做税局认定的特定业务(运输、建筑、租赁、成品油…)时, 在同一个请求体里还要补两样:
- 把
specific_business_code填成你这行的业务代码; - 在请求体顶层(和
items平级,不是塞进 items 里)加上该业务对应的那一块对象。
{
"order_id": "...",
"specific_business_code": "06", ← ① 填业务代码(这里以不动产租赁为例)
"items": [ ... ],
"real_static_rent": { ← ② 与 items 平级,加在顶层
"property_num": "无",
"location": "北京市大兴区",
...
},
"pay_info": [ ... ]
}每一块都写清楚了什么时候触发、加在哪里, 并附一份已经把基础字段合并好的完整报文,不用自己拼。 每块只列额外要传的字段,基础字段看上面那张表。
⚠ 有 4 块不是由 specific_business_code 触发的(差额征税、销方/购方证件信息、冠名发票), 各自的触发条件写在块里,别照着业务代码找。
一、特定业务(由 specific_business_code 决定)
填了哪个业务代码,就在顶层加上对应的这一块。不做这行就都不用管。
二、按场景补充(和业务代码无关)
这几块不看业务代码,看的是主体性质、票种或模板—— 比如开给自然人要带证件信息、走差额征税要带扣除额。别照着 specific_business_code 找它们。
返回
统一信封 code/msg/requestId/timestamp/data,业务字段都在 data 里。code 为 CYT_00000 表示调用成功。
返回参数(data)
| 字段 | 大白话说明 |
|---|---|
state | 受理状态,1 表示已受理、开票中 |
order_sn | 通道受理号。★查结果时可以用它,也可以用你自己的 order_id |
invoice_id | 同 order_sn(值一样) |
mock | true=演示数据,未真实开票 |
返回示例(成功)
{
"code": "CYT_00000",
"msg": "success",
"data": {
"state": 1,
"order_sn": "7499487274632001743",
"invoice_id": "7499487274632001743",
"mock": false
}
}返回示例(失败)
{
"code": "CYT_50200",
"data": {
"upstreamCode": 1014,
"upstreamMessage": "第1项商品明细中,开票明细金额校验失败"
}
}异常与报错
| 情形 | 含义与处理 |
|---|---|
| 开票明细金额校验失败 | ★最常见。要求 price × total 精确等于 total_price,且 total_price + tax_amount = amount_has_tax。用能整除的数字,别让小数除不尽 |
| 无法映射到「成品油单位」枚举 | ★成品油的 unit 只能填 LITER 或 TON(英文大写)。填中文「升」「吨」会报这个错 |
| 企业开具成品油发票必须有成品油经销、生产资质 | 销方企业没有成品油经营资质。这是税务资质问题,不是接口问题,需企业向主管税务机关办理 |
| tax_code 不对 | 税收分类编码要按油品/商品准确填,汽油为 1070101010100000000 |
| order_id 重复 | 同一个订单号不能重复开票 |
前端怎么用
const r = await post('/api/v1/invoice/forward/create', payload);
save(r.data.order_sn); // 存下来,查结果要用
// 开票是异步的,接着轮询②查结果所有业务共用这一个开票接口,区别只在于「除了基础字段,还要不要多传一块特定业务字段」。选你的场景,照那一块的完整报文改值即可。
