Kill Bill 0.24.22 API 使用详解
curl 直连 Kill Bill 0.24.22 REST API 实测计费全生命周期:租户/目录/账户/支付方式/订阅/发票/收款/Credit/取消全链路带真实回显,认证三件套、分页响应头约定、错误体结构与 415/400/401/404 排障实录。
Kill Bill 0.24.22 API 使用详解
目标:以 curl 直连 Kill Bill 0.24.22 REST API,完整实测一条计费生命周期链路——创建租户、上传定价目录、建立账户与支付方式、开通订阅、生成发票、收款、账户 Credit 到订阅取消,每个命令带真实回显与错误排障实录;并覆盖认证三件套、分页约定与错误体结构。Kill Bill 无活跃维护的 CLI 工具(官方 kb-cli 已多年未更新),REST API 就是其运维与集成的主接口,故本篇以 API 为主线。
一、环境信息
- 操作系统:Ubuntu 22.04.4 LTS(内核 6.8.0-138-generic)
- Kill Bill:0.24.22(API 服务地址
http://<服务器IP>:8146,端口与部署见 《Kill Bill 0.24.22 Docker Compose 部署指南》) - KAUI 管理界面:4.0.31(
http://<服务器IP>:8147,本文命令均可与 KAUI 界面操作互相印证) - 数据库:killbill/mariadb 0.24
- 演示凭据:API 管理员
admin,口令q1w2e3r4(由部署时KB_ADMIN_PASSWORD注入);租户密钥bob/lazar(本文实测创建的演示租户) - 实测日期:2026-10-23;Swagger 描述文件
http://<服务器IP>:8146/swagger可获取全部端点定义
二、前置条件
- Kill Bill 服务已就绪(Swagger 描述文件返回 200):
实测回显:
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8146/swagger200 - 具备 curl(或 Postman 等任意 HTTP 客户端);
- 理解 Kill Bill API 的认证模型(见第三节):每个请求需要 HTTP Basic 管理员凭据 + 租户密钥双头,缺一个都是 401。
三、认证方式
Kill Bill API 认证由两层构成(每请求必须同时携带):
| 层 | 形式 | 说明 |
|---|---|---|
| 管理员凭据 | HTTP Basic(-u admin:q1w2e3r4) | 认证「操作者」,由 shiro 配置决定(见配置篇 3.4) |
| 租户密钥 | X-Killbill-ApiKey + X-Killbill-ApiSecret 头 | 认证「业务租户」,多租户隔离的凭证 |
审计头(可选但推荐):X-Killbill-CreatedBy: admin 标记操作来源,会写入每条资源的审计日志。
认证失败的实测表现(缺租户密钥或密钥错误均返回 401):
curl -s -o /dev/null -w '%{http_code}\n' -u admin:q1w2e3r4 http://127.0.0.1:8146/1.0/kb/catalog
实测回显:
401
补齐三件套后:
curl -s -o /dev/null -w '%{http_code}\n' -u admin:q1w2e3r4 -H 'X-Killbill-ApiKey: bob' -H 'X-Killbill-ApiSecret: lazar' http://127.0.0.1:8146/1.0/kb/catalog
实测回显:
200
💡 说明:本文为便于复制,示例统一以
http://127.0.0.1:8146为基地址、演示租户bob/lazar、管理员admin/q1w2e3r4。生产环境请替换为自有地址与强凭据。
四、快速开始:首次部署的初始化三步
全新部署的数据库没有任何租户与目录,先完成初始化(顺序固定):
4.1 创建租户
curl -s -X POST 'http://127.0.0.1:8146/1.0/kb/tenants' \
-u admin:q1w2e3r4 \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'X-Killbill-CreatedBy: admin' \
--data '{}'
实测回显(HTTP 201,响应体为空,新租户的 ApiKey/ApiSecret 取自请求头):
http=201
重复执行同一命令的实测回显(排障点:幂等报错,说明已存在):
{"className":"org.killbill.billing.tenant.api.TenantApiException","code":20000,"message":"Tenant already exists for key null","causeClassName":null,"causeMessage":null,"stackTrace":[]}
4.2 上传定价目录
目录是 XML 文件(官方示例 SpyCarAdvanced.xml 包含 Standard/Gold 等产品与 standard-monthly 等计划)。以 text/xml 方式上传(排障实录:用 application/xml 会得到 415 Unsupported Media Type,0.24.22 该端点仅接受 text/xml):
curl -s -X POST 'http://127.0.0.1:8146/1.0/kb/catalog' \
-u admin:q1w2e3r4 \
-H 'Content-Type: text/xml' \
-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'X-Killbill-CreatedBy: admin' \
--data-binary @SpyCarAdvanced.xml
实测回显(HTTP 201,响应体为空):
http=201
4.3 验证目录
curl -s -u admin:q1w2e3r4 -H 'X-Killbill-ApiKey: bob' -H 'X-Killbill-ApiSecret: lazar' http://127.0.0.1:8146/1.0/kb/catalog
实测回显(输出节选,目录版本已生效,含产品与计划):
[
{
"versionDate": "2024-01-02T00:00:00Z",
"products": [
{
"name": "Standard",
"category": "BASE"
},
{
"name": "Gold",
"category": "BASE"
}
],
"plans": [
{
"name": "standard-monthly",
"billingPeriod": "MONTHLY"
}
]
}
]
💡 说明:GET 同一端点带
Accept: application/xml头可取回原始 XML;JSON 形态适合脚本比对。上传后版本化生效,订阅请求里的planName必须与目录中的计划名精确一致。
五、核心 API 分类详解
5.1 账户管理(/1.0/kb/accounts)
创建账户:
curl -s -X POST 'http://127.0.0.1:8146/1.0/kb/accounts' \
-u admin:q1w2e3r4 \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'X-Killbill-CreatedBy: admin' \
--data '{"name":"测试客户A","email":"custa@example.com","currency":"USD"}' \
-D - -o /dev/null
实测回显(HTTP 201,Location 头返回新账户地址):
HTTP/1.1 201 Created
Location: http://127.0.0.1:8146/1.0/kb/accounts/8fd8790e-44eb-41e1-8202-bcef9c3c8c20
查询账户(余额字段内置在账户对象中,无需单独端点):
curl -s -u admin:q1w2e3r4 -H 'X-Killbill-ApiKey: bob' -H 'X-Killbill-ApiSecret: lazar' \
http://127.0.0.1:8146/1.0/kb/accounts/8fd8790e-44eb-41e1-8202-bcef9c3c8c20
实测回显(输出节选):
{
"accountId": "8fd8790e-44eb-41e1-8202-bcef9c3c8c20",
"name": "测试客户A",
"externalKey": "8fd8790e-44eb-41e1-8202-bcef9c3c8c20",
"email": "custa@example.com",
"currency": "USD",
"accountBalance": 0.0,
"accountCBA": 0.0,
"invoiceBalance": 0.0,
"referenceTime": "2026-10-23T17:22:13.000Z"
}
关键字段解读:externalKey 是外部系统(你的业务库)与 Kill Bill 账户的关联键,创建时可自定、之后可用 GET /1.0/kb/accounts?externalKey=<key> 检索;accountBalance(账户总欠/余)、accountCBA(账户 Credit 余额)、invoiceBalance(未清发票合计)三值在对账时用途不同。
按外部键检索:
curl -s -u admin:q1w2e3r4 -H 'X-Killbill-ApiKey: bob' -H 'X-Killbill-ApiSecret: lazar' \
'http://127.0.0.1:8146/1.0/kb/accounts?externalKey=8fd8790e-44eb-41e1-8202-bcef9c3c8c20'
实测回显(数组返回单个账户,同上节选)。
5.2 支付方式(/1.0/kb/accounts/{id}/paymentMethods)
无真实网关时用内置的 __EXTERNAL_PAYMENT__ 插件(标记账户为外部收款,用于演示与线下转账场景):
curl -s -X POST 'http://127.0.0.1:8146/1.0/kb/accounts/8fd8790e-44eb-41e1-8202-bcef9c3c8c20/paymentMethods' \
-u admin:q1w2e3r4 \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'X-Killbill-CreatedBy: admin' \
--data '{"pluginName":"__EXTERNAL_PAYMENT__","pluginInfo":{"externalPaymentMethodId":"custa-cc-001","isDefaultPaymentMethod":true}}' \
-D - -o /dev/null
实测回显:
HTTP/1.1 201 Created
Location: http://127.0.0.1:8146/1.0/kb/paymentMethods/231f2bd7-5047-4157-bfec-45720b940fb5
⚠️ 排障实录:字段名写错会得到 400 并回显合法字段清单——本文实测把
externalPaymentMethodId误写为externalKey时,错误体列出PaymentMethodPluginDetailJson仅接受isDefaultPaymentMethod、properties、externalPaymentMethodId三个字段,按清单修正即通过。这种「错误体自带字段白名单」的行为在 0.24.22 各写接口一致,是排除字段拼错的利器。
5.3 订阅管理(/1.0/kb/subscriptions)
开通订阅(planName 必须是目录中存在的计划):
curl -s -X POST 'http://127.0.0.1:8146/1.0/kb/subscriptions' \
-u admin:q1w2e3r4 \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'X-Killbill-CreatedBy: admin' \
--data '{"accountId":"8fd8790e-44eb-41e1-8202-bcef9c3c8c20","planName":"standard-monthly"}' \
-D - -o /dev/null
实测回显:
HTTP/1.1 201 Created
Location: http://127.0.0.1:8146/1.0/kb/subscriptions/bf0a2058-0747-4fb0-98c3-bae618842927
查询订阅状态:
curl -s -u admin:q1w2e3r4 -H 'X-Killbill-ApiKey: bob' -H 'X-Killbill-ApiSecret: lazar' \
http://127.0.0.1:8146/1.0/kb/subscriptions/bf0a2058-0747-4fb0-98c3-bae618842927
实测回显(输出节选):
{
"subscriptionId": "bf0a2058-0747-4fb0-98c3-bae618842927",
"productId": "ca05c725-36d8-4152-8c2e-6ba1a375d556",
"planName": "standard-monthly",
"state": "ACTIVE",
"phaseType": "TRIAL",
"billingPeriod": "MONTHLY",
"priceList": "DEFAULT",
"startDate": "2026-10-23T17:33:22.000Z"
}
standard-monthly 计划定义了 30 天试用期(TRIAL)+ 长期月费(EVERGREEN),刚开通处于 TRIAL 阶段,试用期结束自动转入 EVERGREEN 并按月出账。
取消订阅(DELETE,可选 JSON 控制即时/期末生效):
curl -s -X DELETE 'http://127.0.0.1:8146/1.0/kb/subscriptions/bf0a2058-0747-4fb0-98c3-bae618842927' \
-u admin:q1w2e3r4 \
-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'X-Killbill-CreatedBy: admin' \
-H 'Content-Type: application/json' \
--data '{}'
实测回显(HTTP 204,再次查询状态):
HTTP/1.1 204 No Content
{"subscriptionId": "bf0a2058-0747-4fb0-98c3-bae618842927", "state": "CANCELLED", "cancelledDate": "2026-10-23T17:35:58.000Z"}
状态 CANCELLED 确认取消生效。请求体中带 "entitlementPolicyOverride":"IMMEDIATE" 可立即终止权益(默认按策略在计费周期末生效)。
5.4 发票管理(/1.0/kb/invoices 与 /1.0/kb/accounts/{id}/invoices)
查询账户全部发票:
curl -s -u admin:q1w2e3r4 -H 'X-Killbill-ApiKey: bob' -H 'X-Killbill-ApiSecret: lazar' \
http://127.0.0.1:8146/1.0/kb/accounts/8fd8790e-44eb-41e1-8202-bcef9c3c8c20/invoices
实测回显(输出节选,订阅开通即生成的试用期发票):
[
{
"invoiceId": "8991d4c4-5fab-4d32-afb3-50fae84a2c13",
"invoiceNumber": "1",
"status": "COMMITTED",
"amount": 0.0,
"balance": 0.0,
"currency": "USD",
"targetDate": "2026-10-23"
}
]
账户 Credit(充值抵扣)(排障实录:端点是顶层 POST /1.0/kb/credits,请求体是数组,字段为 amount 而非 creditAmount):
curl -s -X POST 'http://127.0.0.1:8146/1.0/kb/credits' \
-u admin:q1w2e3r4 \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'X-Killbill-CreatedBy: admin' \
--data '[{"accountId":"8fd8790e-44eb-41e1-8202-bcef9c3c8c20","amount": 100.00, "currency":"USD", "description":"预存赠送额度"}]'
实测回显(HTTP 200,返回生成的发票条目;CREDIT_ADJ 负项 + CBA_ADJ 正项记入一张草稿发票):
[
{
"invoiceId": "d7ae832d-381f-4aab-9164-9d01718c98de",
"itemType": "CREDIT_ADJ",
"amount": -100.0,
"description": "预存赠送额度",
"currency": "USD"
}
]
该发票状态为 DRAFT(草稿),草稿发票不参与余额计算,需提交(POST /1.0/kb/invoices/{id}/commitInvoice)后生效——这是对账时「明明加了 Credit 但余额没变」的经典成因。
5.5 支付管理(/1.0/kb/invoices/{id}/payments)
对发票发起外部支付(账户已绑 __EXTERNAL_PAYMENT__ 支付方式时):
curl -s -X POST 'http://127.0.0.1:8146/1.0/kb/invoices/8991d4c4-5fab-4d32-afb3-50fae84a2c13/payments' \
-u admin:q1w2e3r4 \
-H 'Content-Type: application/json' \
-H 'X-Killbill-ApiKey: bob' \
-H 'X-Killbill-ApiSecret: lazar' \
-H 'X-Killbill-CreatedBy: admin' \
--data '{"accountId":"8fd8790e-44eb-41e1-8202-bcef9c3c8c20","purchasedAmount": 0.00, "paymentExternalKey": "inv1-pay-001"}'
实测回显(HTTP 204;Location 头返回支付记录地址):
HTTP/1.1 204 No Content
查询账户支付记录:
curl -s -u admin:q1w2e3r4 -H 'X-Killbill-ApiKey: bob' -H 'X-Killbill-ApiSecret: lazar' \
http://127.0.0.1:8146/1.0/kb/accounts/8fd8790e-44eb-41e1-8202-bcef9c3c8c20/payments
实测回显($0 试用期发票不产生实质支付记录,返回空数组;非零金额发票支付后会返回 purchasedAmount、status、transactions 等完整支付对象):
[]
💡 说明:真实网关场景下换装支付插件(Stripe/PayPal 等,经 OSGi 插件目录部署),同样的支付接口会路由到真实网关执行扣款;
paymentExternalKey是对账用的幂等键,请按业务生成唯一值。
5.6 租户与目录的其他常用端点
| 端点 | 方法 | 用途 |
|---|---|---|
/1.0/kb/tenants | POST | 创建租户(4.1 实测 201) |
/1.0/kb/catalog | POST/GET | 上传/查询目录(4.2/4.3 实测 201/200) |
/1.0/kb/catalog/xml | GET | 取目录原始 XML |
/1.0/kb/accounts/{id}/bundles | GET | 查账户契约包与订阅树 |
/1.0/kb/accounts/{id}/invoices | GET | 查账户发票(5.4 实测) |
/1.0/kb/accounts/{id}/payments | GET | 查账户支付(5.5 实测) |
/1.0/kb/accounts/{id}/auditLogs | GET | 查账户全量审计日志 |
/1.0/kb/invoices/{id} | GET | 按发票 ID 查详情 |
/1.0/kb/invoices/{id}/commitInvoice | POST | 提交草稿发票 |
/1.0/kb/invoices/{id}/payments | POST | 发票收款(5.5 实测 204) |
/1.0/kb/subscriptions | POST | 开通订阅(5.3 实测 201) |
/1.0/kb/subscriptions/{id} | GET/DELETE | 查询/取消订阅(5.3 实测 200/204) |
/1.0/kb/credits | POST | 账户 Credit(5.4 实测 200) |
六、分页与错误处理
6.1 分页约定(实测)
列表型接口支持 offset/limit 查询参数,分页元数据在响应头(不在响应体):
curl -s -D - -o /dev/null -u admin:q1w2e3r4 -H 'X-Killbill-ApiKey: bob' -H 'X-Killbill-ApiSecret: lazar' \
'http://127.0.0.1:8146/1.0/kb/accounts/pagination?offset=0&limit=5'
实测回显(分页相关响应头):
X-Killbill-Pagination-CurrentOffset: 0
X-Killbill-Pagination-TotalNbRecords: 1
X-Killbill-Pagination-MaxNbRecords: 1
体里是当前页数据数组;翻页用 offset 递增,TotalNbRecords 判断是否取完。同构分页面还有 /1.0/kb/invoices/pagination、/1.0/kb/payments/pagination 等。
6.2 错误体结构与常见码(实测)
错误响应是统一 JSON 结构(className/code/message):
查询不存在的账户(实测):
curl -s -u admin:q1w2e3r4 -H 'X-Killbill-ApiKey: bob' -H 'X-Killbill-ApiSecret: lazar' \
http://127.0.0.1:8146/1.0/kb/accounts/00000000-0000-0000-0000-000000000000
实测回显:
{"className":"org.killbill.billing.util.callcontext.InternalCallContextFactory$ObjectDoesNotExist","code":null,"message":"Object id=00000000-0000-0000-0000-000000000000 type=ACCOUNT doesn't exist!","causeClassName":null,"causeMessage":null,"stackTrace":[]}
HTTP 状态码速查(全部为本文实测值):
| 状态码 | 场景 | 实测案例 |
|---|---|---|
| 200 | 读接口/部分写接口成功 | GET catalog;POST credits |
| 201 | 资源创建成功 | 创建账户/租户/订阅/支付方式 |
| 204 | 成功且无返回体 | 发票收款、取消订阅 |
| 400 | 请求体字段非法 | 支付方式字段拼写错误(错误体带合法字段清单) |
| 401 | 认证三件套缺失或错误 | 缺 ApiKey 头 |
| 404 | 资源不存在或端点不存在 | 查询不存在的账户 ID;端点路径写错 |
| 415 | Content-Type 不符 | 上传目录用 application/xml |
七、常见问题
Q1:401 了,Basic 账号密码明明是对的? 认证三件套缺一不可(见第三节):Basic + ApiKey + ApiSecret。新部署还必须先创建租户(4.1),否则密钥头传什么都 401。
Q2:怎么判断订阅当前处于什么阶段?
GET 订阅详情看 phaseType(TRIAL/DISCOUNT/FIXEDTERM/EVERGREEN)与 state(ACTIVE/CANCELLED/PENDING 等);阶段切换由目录定义与计费引擎自动推进,订阅变更走 POST /1.0/kb/subscriptions/{id}/changePlan。
Q3:调支付接口 400,提示 unknown properties?
错误体会列出该接口的合法字段白名单(本文 5.2/5.4 实测两次),对照修正字段名即可;注意 0.24.22 中支付请求需要 accountId + purchasedAmount。
Q4:加了 Credit 但账户余额没变?
Credit 生成的是草稿发票(DRAFT),不参与余额计算,需提交(commitInvoice)生效;或者创建 Credit 时直接在账户上转余额(transferCredit 端点)。余额三值(accountBalance/invoiceBalance/accountCBA)的口径差异见 5.1 字段解读。
Q5:有没有命令行客户端? 官方早期有 kb-cli(Ruby gem),已多年未维护、未覆盖 0.24.x 新特性,不建议作为运维入口;REST API 是唯一覆盖全部能力的接口(本文即全部用 curl 实测),日常运营可配合 KAUI 界面与 Swagger 调试页。
Q6:哪里能看到全部端点与参数定义?
服务内置 Swagger 描述文件 http://<IP>:8146/swagger(OpenAPI 规范,可导入 Postman 生成客户端);本文表格收录的是运维高频端点,全部端点以 Swagger 为准。
八、参考链接
- 官方 API 文档(端点/参数定义):
https://killbill.io/docs/ - Swagger 描述文件(服务内置):
http://<服务器IP>:8146/swagger - 官方 Getting Started(租户初始化与认证说明来源):
https://docs.killbill.io/latest/getting_started.html - 本平台同组件文档:《Kill Bill 0.24.22 介绍与选型指南》、《Kill Bill 0.24.22 Docker Compose 部署指南》、《Kill Bill 0.24.22 配置参数详解》