响应账单接入指南
协议版本:v1。更新日期:2026-09-06。
在模型请求中添加以下 HTTP Header,即可请求返回本次调用的账单信息:
X-Billing-Metadata: v1
按 Token 计费的模型可返回最终结算金额和 Token 用量;其他计费方式返回最终结算金额。不添加此 Header,响应保持原有格式,收费规则不变。
charged_amount 是本次请求按照当前账户实际生效计费规则得到的最终结算总额。客户端应直接展示或记录该字段,不要根据模型公开单价、生成参数、Token 数或其他响应字段自行反算金额。
1. 快速接入
1.1 添加 Header
-
保留原有 API Key 鉴权,只额外添加
X-Billing-Metadata: v1。 -
值使用小写
v1,每次需要账单的请求都要携带,且只发送一次。其他值或重复值不启用账单返回。 -
此字段是 HTTP 请求头,不放入 JSON 请求体或 URL 参数。移除该 Header 即可停止请求账单信息。
使用 Postman、Apifox 时,在 Headers 页添加一行 X-Billing-Metadata / v1 即可。
以下域名、模型名和金额仅为示例,请替换为您的 API 地址、可用模型和 API Key。金额示例不是模型报价,执行请求会按正常规则计费。
1.2 cURL 示例:普通文本请求
以下为 Bash 命令。通过环境变量设置 PLATFORM_API_BASE 和 PLATFORM_API_KEY;PLATFORM_API_BASE 为不含 /v1 的平台地址,例如 https://api.example.com。
curl --include --max-time 240 \
"${PLATFORM_API_BASE}/v1/chat/completions" \
-H "Authorization: Bearer ${PLATFORM_API_KEY}" \
-H "Content-Type: application/json" \
-H "X-Billing-Metadata: v1" \
-d '{
"model": "gpt-5.5",
"messages": [{"role": "user", "content": "hello"}],
"stream": false,
"max_completion_tokens": 1024
}'
读取非流式响应时,先检查响应头。以下值表示账单在 JSON 正文中:
X-Billing-Delivery: body
Content-Type: application/json
然后读取 JSON 顶层 _billing,不从 choices 或模型生成的文本中读取:
{
"id": "chatcmpl_example",
"object": "chat.completion",
"created": 1788652800,
"model": "gpt-5.5",
"choices": [
{
"index": 0,
"message": {"role": "assistant", "content": "Hello!"},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 1200,
"completion_tokens": 300,
"total_tokens": 1500
},
"_billing": {
"version": "v1",
"request_id": "req_example_001",
"model": "gpt-5.5",
"pricing_mode": "token",
"charged_quota": 2000,
"charged_amount": "0.004000",
"currency": "CNY",
"settlement_status": "settled",
"usage": {
"input_tokens": 1200,
"output_tokens": 300,
"total_tokens": 1500,
"cached_input_tokens": 0,
"cache_creation_input_tokens": 0,
"image_input_tokens": 0,
"audio_input_tokens": 0,
"audio_output_tokens": 0,
"reasoning_output_tokens": 0,
"source": "upstream"
}
}
}
1.3 PowerShell 示例
PowerShell 可在原有请求头集合中增加该字段:
$requestHeaders = @{
Authorization = "Bearer $env:PLATFORM_API_KEY"
"X-Billing-Metadata" = "v1"
}
$requestBody = @{
model = "gpt-5.5"
messages = @(@{ role = "user"; content = "hello" })
stream = $false
max_completion_tokens = 1024
} | ConvertTo-Json -Depth 5
Invoke-WebRequest -Method Post -Uri "$env:PLATFORM_API_BASE/v1/chat/completions" -Headers $requestHeaders -ContentType "application/json" -Body $requestBody
检查响应头和 JSON 原文,不要只查看工具提取出的模型文本。
2. 账单字段
2.1 基础字段
| 字段 | 类型 | 含义 |
| --- | --- | --- |
| version | string | 账单协议版本,当前为 v1 |
| request_id | string | 本次请求标识,用于核对账单 |
| model | string | 本次请求的模型名称 |
| pricing_mode | string | 本次请求的计费模式 |
| settlement_status | string | 结算状态,见下表 |
| charged_quota | integer,可缺省 | 本次请求最终结算的额度,不是 Token 数或剩余余额 |
| charged_amount | string,可缺省 | 本次请求最终结算的扣费总金额,不是单价、预估金额或剩余余额 |
| currency | string,可缺省 | 金额对应的币种或单位 |
| usage | object,可缺省 | 仅按 Token 计费且用量可用时返回 |
展示扣费时读取 charged_amount 和 currency,不要根据 Token 数自行反算金额。使用十进制类型或原字符串保存金额,不同币种不要直接相加,重复处理响应时按 request_id 去重。
currency 为 CNY、USD 或 CUSTOM 时,金额字符串使用 6 位小数;为 QUOTA 时,金额为额度的整数字符串。CUSTOM 的具体单位请向服务方确认。不要固定假设币种为人民币,也不要把额度当作 Token 用量。
2.2 计费模式
| pricing_mode | 含义 | 是否返回 _billing.usage |
| --- | --- | --- |
| token | 按 Token 计费 | 用量可用时返回,也可能缺省 |
| per_request | 按次计费 | 不返回 |
| image_resolution | 图片按分辨率档位计费 | 不返回 |
| video_second | 视频按秒计费 | 不返回 |
| task | 按任务计费 | 不返回 |
| free | 免费模型 | 不返回 |
以响应中的 pricing_mode 为准,不按模型名称判断。非 Token 计费不返回 _billing.usage,但原协议的 usage 或 usageMetadata 仍可能存在。
2.3 结算状态
| settlement_status | 含义 | 客户端处理 |
| --- | --- | --- |
| settled | 服务端已完成最终结算 | 读取 charged_quota、charged_amount 和 currency |
| pending | 异步任务账单尚未结算 | 保存任务 ID,后续查询任务时再次携带 Header |
| pending_reconciliation | 账单待确认 | 不返回金额、额度、币种和扩展用量;保留请求标识核对 |
待核对的返回示例:
{
"_billing": {
"version": "v1",
"request_id": "req_example_002",
"model": "gpt-5.5",
"pricing_mode": "token",
"settlement_status": "pending_reconciliation"
}
}
仅在 version: "v1"、settlement_status: "settled" 且金额字段完整时读取扣费金额。其他状态、账单缺失或字段不完整时,标记为“账单未获取/待确认”,不要记为零元。
HTTP 200、错误响应、超时或流式中断,都不能替代账单状态判断。需要核对时保留 request_id,查看消费记录或联系支持人员;不要为了获取账单重新发送生成请求,以免再次产生费用。
2.4 Token 用量
| _billing.usage 字段 | 含义 |
| --- | --- |
| input_tokens | 输入 Token 数 |
| output_tokens | 输出 Token 数 |
| total_tokens | 总 Token 数,缓存计数的包含关系因模型协议而异 |
| cached_input_tokens | 缓存读取/命中的输入 Token 数 |
| cache_creation_input_tokens | 缓存写入的输入 Token 数 |
| image_input_tokens | 图片输入 Token 明细 |
| audio_input_tokens | 音频输入 Token 明细 |
| audio_output_tokens | 音频输出 Token 明细 |
| reasoning_output_tokens | 推理输出 Token 明细 |
| source | 当前为 upstream,表示来自模型服务返回的用量 |
不要将所有明细直接相加,缓存及多模态计数可能与输入、输出计数重叠。明细为 0 也可能表示该项未提供。usage 缺省表示用量未提供,不等于零用量,不影响单独读取已结算金额。
3. 流式请求
流式请求也添加 X-Billing-Metadata: v1。使用 SSE 解析器读取完整事件,账单位于结束阶段的 JSON 事件中,不会随每段文字重复返回。
| 请求接口 | _billing 读取位置 | 结束标志 |
| --- | --- | --- |
| /v1/chat/completions、/v1/completions | [DONE] 前最后一个合法 JSON chunk 的顶层 | [DONE] |
| /v1/messages | 最终 message_delta 数据对象的顶层 | message_stop |
| /v1/responses | response.completed 或 response.incomplete 数据对象的顶层 | 对应结束事件 |
SSE 不依赖 X-Billing-Delivery 响应头。不要在收到最后一段文字或第一个 finish_reason 后立刻断开,应继续读取到协议结束标志。
3.1 Chat Completions
Header 与普通请求相同,请求体改为:
{
"model": "gpt-5.5",
"messages": [{"role": "user", "content": "hello"}],
"stream": true,
"max_completion_tokens": 1024,
"stream_options": {"include_usage": true}
}
使用 cURL 时可增加 --no-buffer。stream_options.include_usage 用于请求原协议的流式用量,不能替代账单 Header;该参数须由所选模型接口支持。
读取 [DONE] 之前最后一个合法 JSON chunk 顶层的 _billing。该 chunk 的 choices 可能为空。以下仅展示终态示例,前面的文本事件已省略:
data: {"id":"chatcmpl_example","object":"chat.completion.chunk","created":1788652800,"model":"gpt-5.5","choices":[],"usage":{"prompt_tokens":1200,"completion_tokens":300,"total_tokens":1500},"_billing":{"version":"v1","request_id":"req_example_003","model":"gpt-5.5","pricing_mode":"token","charged_quota":2000,"charged_amount":"0.004000","currency":"CNY","settlement_status":"settled","usage":{"input_tokens":1200,"output_tokens":300,"total_tokens":1500,"cached_input_tokens":0,"cache_creation_input_tokens":0,"image_input_tokens":0,"audio_input_tokens":0,"audio_output_tokens":0,"reasoning_output_tokens":0,"source":"upstream"}}}
data: [DONE]
[DONE] 本身不是 JSON,不会携带账单。/v1/completions 的账单终态位置相同,业务字段仍使用 Completions 协议。
3.2 Claude Messages
请求地址为 /v1/messages。沿用原有鉴权和版本 Header,增加账单 Header:
curl --include --no-buffer --max-time 240 \
"${PLATFORM_API_BASE}/v1/messages" \
-H "x-api-key: ${PLATFORM_API_KEY}" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-H "X-Billing-Metadata: v1" \
-d '{
"model": "claude-opus-5",
"messages": [{"role": "user", "content": "hello"}],
"max_tokens": 1024,
"stream": true
}'
账单位于最终 message_delta 事件的数据对象顶层,不在 delta、message_start 或 message_stop 中:
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":300},"_billing":{"version":"v1","request_id":"req_example_004","model":"claude-opus-5","pricing_mode":"token","charged_quota":2000,"charged_amount":"0.004000","currency":"CNY","settlement_status":"settled","usage":{"input_tokens":1200,"output_tokens":300,"total_tokens":1500,"cached_input_tokens":0,"cache_creation_input_tokens":0,"image_input_tokens":0,"audio_input_tokens":0,"audio_output_tokens":0,"reasoning_output_tokens":0,"source":"upstream"}}}
event: message_stop
data: {"type":"message_stop"}
3.3 Responses
请求地址为 /v1/responses,在原有请求中增加同一个 Header。非流式读取响应顶层 _billing;流式读取 response.completed 或 response.incomplete 事件数据对象的顶层 _billing。
即读取 eventData._billing,不是 eventData.response._billing。以下为终态关键字段示意,其他业务字段已省略:
event: response.completed
data: {"type":"response.completed","response":{"id":"resp_example","status":"completed"},"_billing":{"version":"v1","request_id":"req_example_005","model":"gpt-5.5","pricing_mode":"token","charged_quota":2000,"charged_amount":"0.004000","currency":"CNY","settlement_status":"settled","usage":{"input_tokens":1200,"output_tokens":300,"total_tokens":1500,"cached_input_tokens":0,"cache_creation_input_tokens":0,"image_input_tokens":0,"audio_input_tokens":0,"audio_output_tokens":0,"reasoning_output_tokens":0,"source":"upstream"}}}
response.incomplete 仍需按原协议判断业务结果,例如输出达到限制;是否结算则独立检查 _billing.settlement_status。
3.4 SDK 读取注意事项
使用能保留完整 JSON 事件及扩展字段的接口,不要只使用文本迭代器。若 SDK 不暴露 _billing,请读取原始 HTTP/SSE 响应。一个网络数据块不一定对应一条完整 SSE 事件。
遇到连接中断、错误事件或没有收到完整账单时,按“账单未获取”处理,不从普通 usage 推算金额,不自动重发生成请求。
4. 图片及其他非 Token 计费模型
添加 Header 的方式不变,例如:
curl --include --max-time 240 \
"${PLATFORM_API_BASE}/v1/images/generations" \
-H "Authorization: Bearer ${PLATFORM_API_KEY}" \
-H "Content-Type: application/json" \
-H "X-Billing-Metadata: v1" \
-d '{
"model": "gpt-image-2-count",
"prompt": "Blue square.",
"n": 1,
"size": "1024x1024",
"quality": "low"
}'
图片尺寸和质量仍按所选模型的接口要求填写。
按分辨率计费时,账单示例为:
{
"_billing": {
"version": "v1",
"request_id": "req_example_006",
"model": "gpt-image-2-count",
"pricing_mode": "image_resolution",
"charged_quota": 200000,
"charged_amount": "0.400000",
"currency": "CNY",
"settlement_status": "settled"
}
}
以上仅展示账单部分。金额为本次请求总额,不是每张单价;非 Token 模式没有 _billing.usage。图片响应也可能通过下一节的 Trailer 返回账单。
5. 非流式响应的读取位置
非流式客户端必须根据 X-Billing-Delivery 决定读取位置,不能只看正文是否存在 _billing:
| X-Billing-Delivery | 账单来源 | 处理要求 |
| --- | --- | --- |
| body | JSON 顶层 _billing | 检查对象版本、状态与必要字段 |
| trailer | HTTP 响应结束后的 X-Billing-* Trailer | 忽略正文中的同名 _billing,不要回退读取正文 |
| none、缺失、未知或冲突值 | 未确认交付 | 记录账单未获取,不按零金额处理 |
较大的 JSON、纯文本、字幕和音频等响应可能使用 trailer。始终根据响应头选择读取方式,不按模型类型猜测。
HTTP Trailer 是正文结束后的尾部字段,不是最初收到的响应头。完整读取响应后,通过客户端的 Trailer 接口获取以下值:
| Trailer 字段 | 对应账单字段 |
| --- | --- |
| X-Billing-Version | version |
| X-Billing-Request-Id | request_id |
| X-Billing-Model | model |
| X-Billing-Pricing-Mode | pricing_mode |
| X-Billing-Status | settlement_status |
| X-Billing-Charged-Quota | charged_quota,读取后解析为整数 |
| X-Billing-Amount | charged_amount |
| X-Billing-Currency | currency |
| X-Billing-Input-Tokens | usage.input_tokens |
| X-Billing-Output-Tokens | usage.output_tokens |
| X-Billing-Total-Tokens | usage.total_tokens |
请求标识和模型名需按 URL 百分号规则解码一次,保留 + 原义。Trailer 用量只有三个基础计数;非 Token 模式没有 Token 值,未确认状态没有金额值。
浏览器 Fetch 和部分 SDK 无法读取 Trailer。使用此类响应前,请确认客户端及 API 地址支持 Trailer;无法取得尾部字段时按账单未获取处理,不回退读取正文中的 _billing。
6. Python 非流式读取示例
本示例使用 Python 标准库,无自动重试,也不自动跟随重定向。通过环境变量提供平台地址与 Key,可通过 PLATFORM_MODEL 修改模型名。示例只读取 body 账单,不实现 Trailer 或 SSE 解析。
import json
import os
from decimal import Decimal
from urllib.error import HTTPError
from urllib.request import HTTPRedirectHandler, Request, build_opener
class NoRedirect(HTTPRedirectHandler):
def redirect_request(self, req, fp, code, msg, headers, newurl):
return None
base_url = os.environ["PLATFORM_API_BASE"].rstrip("/")
api_key = os.environ["PLATFORM_API_KEY"]
payload = {
"model": os.environ.get("PLATFORM_MODEL", "gpt-5.5"),
"messages": [{"role": "user", "content": "hello"}],
"stream": False,
"max_completion_tokens": 1024,
}
request = Request(
base_url + "/v1/chat/completions",
data=json.dumps(payload).encode("utf-8"),
headers={
"Authorization": "Bearer " + api_key,
"Content-Type": "application/json",
"X-Billing-Metadata": "v1",
},
method="POST",
)
try:
response = build_opener(NoRedirect()).open(request, timeout=240)
except HTTPError as error:
response = error # An error response may still carry billing metadata.
with response:
http_status = response.status
delivery_values = response.headers.get_all("X-Billing-Delivery", [])
body = response.read()
print("HTTP:", http_status)
if delivery_values != ["body"]:
print("Billing not read from body:", delivery_values)
else:
data = json.loads(body)
billing = data.get("_billing") if isinstance(data, dict) else None
if not isinstance(billing, dict) or billing.get("version") != "v1":
print("Billing unavailable; this does not mean zero charge.")
else:
print("Request ID:", billing.get("request_id"))
status = billing.get("settlement_status")
required = ("charged_amount", "charged_quota", "currency")
if status == "settled" and all(k in billing for k in required):
amount = Decimal(billing["charged_amount"])
print("Charged:", amount, billing["currency"])
if billing.get("pricing_mode") == "token":
print("Usage:", billing.get("usage", "unavailable"))
else:
print("Billing not confirmed:", status)
实际应用还应处理网络异常、响应解析失败和流式中断,保留已有请求标识用于核对,避免因账单读取失败触发生成请求重试。妥善保护 API Key,不写入客户端公开页面、共享日志或代码仓库。
7. 支持范围
| 接口或场景 | 账单读取方式 |
| --- | --- |
| Chat Completions / Completions | 非流式 JSON;流式最后一个合法 JSON chunk |
| Claude Messages | 非流式 JSON;流式最终 message_delta |
| Responses | 非流式 JSON;流式 response.completed / response.incomplete |
| 同步 Images 生成、编辑 | JSON 或 Trailer |
| Gemini 原生同步 generateContent,包括同步生图 | JSON 或大响应 Trailer |
| 同步 Embeddings、Rerank、音频转写/翻译等 | JSON 或 Trailer;用量可能缺省 |
| Speech 等二进制响应 | Trailer |
| Seedance 等视频异步任务、Midjourney、Suno 的提交和单任务查询 | 提交读取 pending;单任务查询读取最终账单,见第 8 节 |
Gemini 原生 streamGenerateContent 和 Realtime WebSocket 当前暂不支持账单返回。异步任务的列表、批量查询、回调、取消、删除和媒体下载接口不返回任务账单,请使用单任务查询接口。
按您调用的接口协议选择读取方式,不按模型厂商判断。例如通过 /v1/chat/completions 调用其他厂商模型,也按 Chat 的格式读取账单。
8. 异步任务账单
8.1 提交与查询分别添加 Header
在每一次需要读取账单的请求中添加 X-Billing-Metadata: v1,提交与查询互相独立:
| 提交请求 | 单任务查询请求 | 查询响应 |
| --- | --- | --- |
| 带 Header | 带 Header | 可读取账单 |
| 带 Header | 不带 Header | 原有任务响应,不返回账单 |
| 不带 Header | 带 Header | 仍可读取该任务的可用账单 |
| 不带 Header | 不带 Header | 原有任务响应,不返回账单 |
Header 不改变任务的计费规则或收费方式。提交成功时的 _billing.settlement_status 为 pending,不返回预估金额。任务完成并结算后,通过同一任务 ID 查询到 settled 和最终金额;不要重复提交生成任务。
异步账单的 request_id 标识原始提交请求,不是每次查询的新请求标识。同一任务多次返回的已结算金额是该任务的总额,不是每次查询新增的费用;客户端应更新同一条账单,不能把多次查询的金额累加。
8.2 平台视频接口示例
提交一个 5 秒、480p 的视频任务:
curl --include --max-time 240 \
"${PLATFORM_API_BASE}/v1/video/generations" \
-H "Authorization: Bearer ${PLATFORM_API_KEY}" \
-H "Content-Type: application/json" \
-H "X-Billing-Metadata: v1" \
-d '{
"model": "doubao-seedance-2-5-260628",
"prompt": "A blue balloon floating in the sky.",
"duration": 5,
"size": "480p",
"metadata": {
"resolution": "480p",
"ratio": "16:9",
"generate_audio": false
}
}'
提交成功时返回任务 ID,账单仍在等待结算:
{
"id": "task_example_001",
"task_id": "task_example_001",
"object": "video",
"model": "doubao-seedance-2-5-260628",
"status": "queued",
"_billing": {
"version": "v1",
"request_id": "req_async_001",
"model": "doubao-seedance-2-5-260628",
"pricing_mode": "video_second",
"settlement_status": "pending"
}
}
使用返回的 task_id 查询同一任务:
curl --include --max-time 240 \
"${PLATFORM_API_BASE}/v1/video/generations/task_example_001" \
-H "Authorization: Bearer ${PLATFORM_API_KEY}" \
-H "X-Billing-Metadata: v1"
任务完成后的响应示意如下。业务任务位于 data,账单仍位于整个响应的顶层 _billing:
{
"code": "success",
"data": {
"task_id": "task_example_001",
"status": "SUCCESS",
"progress": "100%"
},
"_billing": {
"version": "v1",
"request_id": "req_async_001",
"model": "doubao-seedance-2-5-260628",
"pricing_mode": "video_second",
"charged_quota": 2310000,
"charged_amount": "4.620000",
"currency": "CNY",
"settlement_status": "settled"
}
}
8.3 火山兼容 Seedance 示例
原有提交请求中增加 Header:
curl --include --max-time 240 \
"${PLATFORM_API_BASE}/api/v3/contents/generations/tasks" \
-H "Authorization: Bearer ${PLATFORM_API_KEY}" \
-H "Content-Type: application/json" \
-H "X-Billing-Metadata: v1" \
-d '{
"model": "doubao-seedance-2-5-260628",
"content": [{"type": "text", "text": "A blue balloon floating in the sky."}],
"duration": 5,
"resolution": "480p",
"ratio": "16:9",
"generate_audio": false
}'
模型和生成参数请按您的可用模型配置填写。以下为提交响应示意:
{
"id": "task_example_002",
"_billing": {
"version": "v1",
"request_id": "req_async_002",
"model": "doubao-seedance-2-5-260628",
"pricing_mode": "video_second",
"settlement_status": "pending"
}
}
后续查询仍要添加 Header:
curl --include --max-time 240 \
"${PLATFORM_API_BASE}/api/v3/contents/generations/tasks/task_example_002" \
-H "Authorization: Bearer ${PLATFORM_API_KEY}" \
-H "X-Billing-Metadata: v1"
检查 X-Billing-Delivery 后读取 JSON 顶层 _billing,不是 content._billing 或 data._billing。最终账单示意如下,任务的其他字段已省略:
{
"id": "task_example_002",
"model": "doubao-seedance-2-5-260628",
"status": "succeeded",
"resolution": "480p",
"ratio": "16:9",
"duration": 5,
"generate_audio": false,
"_billing": {
"version": "v1",
"request_id": "req_async_002",
"model": "doubao-seedance-2-5-260628",
"pricing_mode": "video_second",
"charged_quota": 2310000,
"charged_amount": "4.620000",
"currency": "CNY",
"settlement_status": "settled"
}
}
以上两个视频示例中的金额仅用于说明响应格式,不代表固定报价。实际金额以每次响应中 settlement_status: "settled" 时返回的 charged_amount 和 currency 为准。按 Token 计费的任务会返回 pricing_mode: "token";用量可用时还会带 _billing.usage。用量缺省不影响读取已结算金额。
8.4 其他异步接口
沿用所选协议的提交参数及鉴权,仅增加同一个 Header。常用单任务查询接口如下:
| 任务协议 | 单任务查询 |
| --- | --- |
| Seedance | GET /api/v3/contents/generations/tasks/{task_id};也支持 /seedance 前缀别名 |
| OpenAI 兼容视频 | GET /v1/videos/{task_id} |
| 通用视频生成 | GET /v1/video/generations/{task_id} |
账单在整个响应 JSON 的顶层。即使业务任务位于 data 中,也应读取 response._billing,而不是 response.data._billing。大响应仍按第 5 节的来源头选择正文或 Trailer。
8.5 等待中、失败和旧任务
-
pending:沿用任务接口的合理轮询间隔继续查询,不要高频轮询。 -
settled:金额字段完整时记录最终总额。已确认全额退款的账单可能为零;不能仅凭任务失败认定已全额退款。 -
pending_reconciliation:金额暂不可确认,保留任务 ID 和request_id核对。任务成功也可能出现此状态,不保证持续查询会自动变为settled。 -
没有
_billing:部分历史任务或暂不可提供账单的任务可能没有账单,不能记为免费。
任务状态和账单状态应分开处理。不要因为账单缺失、待确认或查询超时,重新提交生成任务。