PIX Cash-In -- 生成 QR Code
生成带 QR Code 的 PIX 收款请求,将资金收入与您 API Key 关联的账户。
端点
POST /api/external/pix/cash-in请求头
| 头 | 类型 | 必填 | 描述 |
|---|---|---|---|
Authorization | String | 是 | ApiKey {client_id}:{client_secret} |
Content-Type | String | 是 | application/json |
hmac | String | 是 | body 的 HMAC-SHA512 签名(了解详情) |
Idempotency-Key | String | 否 | 避免重复处理的唯一键(最多 256 字符) |
X-Key-Case | String | 否 | 设为 camelCase 以使用 camelCase 接收响应字段(默认 snake_case) |
请求体
| 字段 | 类型 | 必填 | 描述 | 示例 |
|---|---|---|---|---|
amount | Integer | 是 | 金额,以**分(centavos)**为单位(R$ 30,00 = 3000) | 3000 |
description | String | 否 | 收款描述。如省略,默认为 "Cobranca PIX"。 | "Pedido #1234" |
external_id | String | 否 | 您系统中的标识符,用于追踪。最多 128 字符。仅 a-zA-Z0-9._:-(超出标准的值会被静默丢弃,字段返回 null -- 见下方警告)。在响应和 webhook 中返回。 | "order-9876" |
pix_key | String | 否 | 用于生成 QR Code 的特定 PIX 密钥。如省略,使用账户最新的活跃密钥(按 inserted_at DESC 排序)。 | "12345678901" |
city | String | 否 | 收款人在 QR Code 中的城市。默认:SAO PAULO。自动截断为 15 个字符。 | "RIO DE JANEIRO" |
amount 始终以整数(分)发送
字段 amount 必须是以分为单位的整数。绝不发送 float/decimal 值:
- ✅
"amount": 3000→ R$ 30,00 - ❌
"amount": 30.00→ 解释为30分 = R$ 0,30(金额小 100 倍) - ❌
"amount": 30→ R$ 0,30(也不正确)
在 JavaScript 中,始终使用 Math.round 转换后再发送:
const valorEmReais = 30.0;
const amount = Math.round(valorEmReais * 100); // 3000Python: amount = round(valor_em_reais * 100)。Go: amount := int(math.Round(valorEmReais * 100))。
货币值(输入 × 响应)
输入值以分(centavos)为单位(R$ 1,00 = 100)。响应值以基础单位为单位(R$ 1,00 = 10000)。要将响应转换为雷亚尔,请除以 10.000。切勿在任何方向使用浮点数。
无效的 external_id = 静默丢弃
如果 external_id 包含 a-zA-Z0-9._:- 之外的字符、超过 128 字节或仅为空白,服务器会静默丢弃该值,响应中返回 "external_id": null(不返回错误)。在用于对账之前始终检查响应中的 external_id -- 如果返回 null,您的标识符被验证拒绝了。
示例
BODY='{"amount":3000,"description":"Pedido #1234","external_id":"order-9876"}'
HMAC=$(echo -n "$BODY" | openssl dgst -sha512 -hmac "$CLIENT_SECRET" | awk '{print $2}')
curl -X POST https://api.owem.com.br/api/external/pix/cash-in \
-H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-H "hmac: $HMAC" \
-d "$BODY"成功响应 (200)
{
"worked": true,
"transaction_id": "7popu57v6us7p6pcicgq12345",
"qr_code": "00020126580014br.gov.bcb.pix...",
"qr_code_image": "data:image/png;base64,iVBORw0KGgo...",
"external_id": "order-9876",
"amount": 300000,
"status": "active",
"type": "dynamic",
"location_url": "https://qrcode.owem.com.br/pix/v2/a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"expires_at": "2026-03-07T16:30:00Z"
}| 字段 | 类型 | 描述 |
|---|---|---|
worked | Boolean | true 表示操作成功 |
transaction_id | String | null | 收款唯一标识(QR Code 的 tx_id,按 BACEN spec 最多 35 个字母数字字符)。仅在罕见的内部持久化故障中为 null |
qr_code | String | null | 用于支付的 EMV 复制粘贴码。仅在罕见的内部持久化故障中为 null(JSON 字面值,不是字符串 "null") |
qr_code_image | String | Base64 编码的 QR Code 图像(PNG,前缀 data:image/png;base64,)。在罕见的内部故障中为空字符串("") |
external_id | String | null | 您的标识符,按发送时原样返回。未提供时、无效时(见上方警告)或被清理丢弃时为 null |
amount | Integer | 收款金额,以基础单位(÷ 10.000 得到雷亚尔)。300000 = R$ 30,00 |
status | String | 初始状态始终为 active(QR Code 已激活可收款)。后续演变(paid/expired/cancelled)可通过查询和 webhook 查看(见 QR Code 生命周期) |
type | String | null | QR Code 类型:dynamic(2026 年 4 月起的默认)或 static。Dynamic 要求付款方银行查询 location_url 并验证 JWS |
location_url | String | null | BACEN 动态载荷查询 URL(例:https://qrcode.owem.com.br/pix/v2/{uuid})。不是 JWS 本身 -- 付款方银行对此端点执行 GET 以接收签名的 ISO 20022 载荷(JWS PS256)。仅在动态 QR 中出现;静态 QR 为 null |
expires_at | String | null | QR Code 过期日期/时间,ISO 8601 UTC 带 Z 后缀(例:2026-03-07T16:30:00Z)。无过期时为 null |
动态 QR 是默认
所有生产账户自 2026 年 4 月起默认使用动态 QR。动态 QR 包含 URL(location_url),付款方银行通过 JWS 查询该 URL 获取签名载荷 -- 最大化与 BACEN-strict 银行的兼容性。
错误响应 (400)
{
"worked": false,
"detail": "O campo amount é obrigatório"
}错误响应 (401)
{
"error": {
"status": 401,
"message": "Missing API key credentials. Use Authorization: ApiKey <client_id>:<client_secret>"
}
}错误响应 (422)
{
"worked": false,
"detail": "Invalid HMAC signature"
}推荐流程
QR Code 有效期
生成的 QR Code 默认有效期 1 小时。有效期可按账户配置(字段 qrcode_expiration_seconds);始终检查响应中返回的 expires_at 获取确切日期/时间。
过期后,状态自动变为 expired(通过内部 worker,每 5 分钟运行一次)。对于 merchant 手动取消的收款,状态为 cancelled。参见 按 ID 查询 Cash-In 中的完整状态列表。
QR Code 生命周期
QR Code 在创建后经历这些状态:
| 状态 | 来源 | 描述 |
|---|---|---|
active | 初始 | QR 生成成功,准备被扫描/支付 |
paid | 收到付款 | BACEN 付款已确认并关联到 QR(通过 ACCC 后的内部 worker) |
expired | Worker QrExpirationChecker | TTL 达到 expires_at。Worker 每 5 分钟运行,标记过期的 active QR 并触发 webhook pix.charge.expired |
cancelled | 手动或批量 | 由 merchant 取消(通过门户)或在管理操作中(例:2026 年 4 月静态→动态迁移取消了带值的活跃静态 QR) |
used | 遗留 | 旧 pipeline 的瞬时中间状态。新客户端应将其视为等同于 paid |
在查询中,paid 可能显示为 settled
端点 GET /transactions/:id 及等效项从交易(非 QR)视角返回 status 字段。已付款的 QR 在查询中显示为 status: "settled",type: "pix"(或结算后短期窗口内 type: "pix_qrcode",此时 transactions 中的最终行仍在持久化)。参见 按 ID 查询 Cash-In 中的完整表格。