Skip to content

PIX Cash-Out 复制粘贴码

使用从 PIX QR Code 中提取的 EMV 代码(复制粘贴码)执行 PIX 转账。

端点

POST /api/external/pix/cash-out

请求头

类型必填描述
AuthorizationStringApiKey {client_id}:{client_secret}
Content-TypeStringapplication/json
hmacStringbody 的 HMAC-SHA512 签名(十六进制)
Idempotency-KeyString避免重复处理的唯一键(最大 256 字符)。行为与 PIX Cash-Out 按密钥 中记录的相同

必需权限

API Key 必须具有 transfer:write 权限才能发送 PIX。没有该权限,请求返回 403 Forbidden。参见 如何配置权限

请求体

字段类型必填描述
amountInteger金额,以**分(centavos)**为单位。R$ 30,00 = 3000在动态 QR 中,此值会被 QR URL 的查询覆盖 — 见下文
emvStringPIX QR Code 的 EMV 复制粘贴码。别名 codigo_copia_cola 也被接受,但 emv 是规范的 — 请优先使用
descriptionString转账描述(最多 140 个字符)
external_idString您系统中的标识符,用于追踪。trim 后最多 128 字符。仅 a-zA-Z0-9._:- 字符。在响应和 webhook 中返回。无效值会被静默丢弃(交易继续,external_id: null)。详见 PIX Cash-Out 按密钥
end_to_end_idStringBACEN 格式的 End-to-End ID。建议省略 — 后端会确定性生成。仅在协调的重新处理场景中发送

复制粘贴码

emv 字段接受从 PIX QR Code 复制的完整 EMV 代码。API 自动从 EMV 载荷中提取 PIX 密钥、收款方数据和收款的原始值。后端在继续之前验证 CRC-16/CCITT-FFFF 和 TLV 结构。

静态 QR vs 动态 QR

API 以不同方式处理这两种类型:

静态 QR(PoIM=11,无 URL):

  • PIX 密钥和 metadata 来自 EMV 载荷本身
  • 请求中发送的 amount直接使用作为转账值
  • 无外部查询 — DICT 验证后立即结算

动态 QR(PoIM=12,tag 26/25 中有 URL):

  • 后端对嵌入 EMV 载荷中的 URL 执行 Provider.consult_qrcode 并接收 JWS(BACEN Manual 2.9.0)
  • 权威值来自 JWS 响应(valor.original)并覆盖客户端发送的 amount
  • 如果 URL 查询失败(超时、JWS 无效、QR 在发行方已过期),返回 HTTP 422 及 detail: "QR Code dinamico nao pode ser resolvido"
  • 使用覆盖值作为真相来源 — 响应中的 net_amount 反映实际收取的值

动态 QR 不要依赖发送的值

在动态 QR 中,始终查询 POST 响应以获得有效的 amount。后端会忽略发送值与 QR 发行方返回值之间的任何差异 — 这是 BACEN 的要求。

货币值

输入值以分为单位(R$ 1,00 = 100)。响应值以基础单位为单位(R$ 1,00 = 10000)。要将响应转换为雷亚尔,请除以 10.000。绝不使用浮点数。

示例

bash
curl -X POST https://api.owem.com.br/api/external/pix/cash-out \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "hmac: $HMAC" \
  -d '{
    "amount": 3000,
    "emv": "00020126580014br.gov.bcb.pix0136a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d5204000053039865802BR5913NOME RECEBEDOR6008BRASILIA62070503***6304ABCD",
    "description": "Pagamento via QR Code",
    "external_id": "invoice-4521"
  }'

成功响应 -- 200 / 202

json
{
  "worked": true,
  "final": false,
  "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
  "end_to_end_id": "E37839059202603091530abcdef01",
  "external_id": "invoice-4521",
  "amount": 300000,
  "fee_amount": 350,
  "net_amount": 300350,
  "status": "accepted",
  "detail": "PIX enviado para processamento"
}

HTTP 200 vs 202

  • HTTP 200:交易已结算(final: true,status: "settled")。
  • HTTP 202:交易已被接受处理(final: false)。status 可能为 "accepted"(正常流程)、"queued"(DICT rate-limit — 每 3 秒自动重试最多 120 分钟,session 155)或 "pending_approval"(等待批准)。通过轮询或 webhook 跟踪状态。
字段类型描述
workedBooleantrue 表示请求已被接受
finalBoolean当交易达到终止状态(已结算或已拒绝)时为 true。仍在处理中时为 false
transaction_idString交易唯一标识
end_to_end_idStringSPI/BACEN 的 End-to-End 标识
external_idString您的标识符,按发送原样返回。未提供时为 null
amountInteger转账值,以基础单位(÷ 10.000 得到雷亚尔)。300000 = R$ 30,00。在动态 QR 中,反映 JWS 查询返回的权威值 — 可能与 request 中发送的 amount 不同
fee_amountInteger收取的手续费,以基础单位(÷ 10.000 得到雷亚尔)
net_amountInteger付款账户总借记值(amount + fee_amount)— 不是收款方收到的值。参见 PIX Cash-Out 按密钥 了解 cash-out 和 cash-in 之间的语义不对称性
statusString其中之一:acceptedsettledqueuedpending_approval。详见 PIX Cash-Out 按密钥
detailString描述消息

拒绝代码

EMV 的 cash-out 拒绝遵循与 PIX Cash-Out 按密钥 完全相同的标准 — 两种 body 格式(格式 A {status: "failed", errors: [...]} 和格式 B {errors: {bad_request: "..."}})、三类错误(验证 / 集成 / rate-limit 已入队)以及相同的 UPPERCASE × lowercase 词汇。下面的项目仅突出显示EMV 路径特有的代码。

EMV 特有的验证错误(HTTP 400 / 422)

HTTP格式带代码的字段含义
400Berrors.bad_request: "invalid emv payload"EMV 载荷格式错误(CRC-16 无效、TLV 不完整、缺少必需 tag)— 在 Orchestrator 之前由 parser 检测
400Berrors.bad_request: "invalid or missing amount"amount 缺失、零、负数或非整数(静态 QR)
422Aerrors[0].code: "same_institution_transfer"QR 由 Owem 账户生成 — 不支持同机构 PIX(使用 TEF)。:HTTP 422(非 400),结构 {status: "failed", errors: [{code: "same_institution_transfer", params: []}]}
422detail: "QR Code dinamico nao pode ser resolvido"查询动态 QR 的 URL 失败(超时、JWS 无效、QR 在发行方已过期)— 此路径在控制器中由 Orchestrator 之前处理,返回遗留结构 {errors: {unprocessable_entity: "..."}}
422Aerrors[0].code: "insufficient_balance"可用余额小于 amount + fee_amount

其他错误

对于代码 dict_key_not_founddict_key_blockeddict_rate_limited(同步)、dict_bucket_exhausted(同步)、dict_lookup_failedprovider_rejectedprovider_schema_errorprovider_unknown_error全部以格式 A 返回 HTTP 400(不是 429 或 503)。详见 PIX Cash-Out 按密钥 — 与 DICT provider 的集成错误

带自动重试的 rate-limit(HTTP 202 queued

当每 merchant 的 ClientLimiter(默认 DICT_CLIENT_MAX_PER_MIN=120)或全局的 DictBucket.Guard(refill DICT_BUCKET_REFILL_RATE=18/min,capacity 250)在到达 OnZ 之前检测到超限时,cash-out 会被加入 Fluxiq.Workers.PixOutRetryWorker 队列并返回 HTTP 202,status: "queued"。flag pix_out_retry_queue_enabled 自 session 155 起在 PRD 中为 ON。详见 PIX Cash-Out 按密钥 — 带自动重试的 rate-limit

异步 BACEN 拒绝

初始接受(HTTP 202)后,SPI/BACEN 可能通过 PACS.002 RJCT 拒绝。此拒绝:

  • 不会改变原始 HTTP 响应(已作为 202 发送)
  • 通过 GET /transactions/:idstatus: "failed" + reason_code(AC03、AB03、ED05 等)+ reason_description(英文)显示
  • 触发 webhook pix.payout.rejected,带相同的结构化字段

参见 按 ID 查询 Cash-Out 获取完整的 BACEN 代码列表。

下一步

创建转账后,通过以下方式跟踪状态:

或通过 Webhook 自动接收确认。

Owem Pay Instituição de Pagamento — ISPB 37839059