Skip to content

按 ID 查询 Cash-Out

通过 transaction_id 查询 PIX 交易的详情和状态。

端点

GET /api/external/transactions/:id

请求头

类型必填描述
AuthorizationStringApiKey {client_id}:{client_secret}

路径参数

参数类型必填描述
idString交易 ID(transaction_id

示例

bash
curl -X GET https://api.owem.com.br/api/external/transactions/PIXOUT20260309a1b2c3d4e5f6 \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"

响应根据交易状态而不同。此端点按以下优先级顺序在以下源中搜索:

  1. 已结算交易transactionstransaction_id,或按内部十六进制 UUID — Base.decode16
  2. 进行中的 PIX OUToutbound_requests stage 1 或 2)按 transaction_id
  3. QR Codeqrcodestx_id)— 如果有 paid_at + payment_end_to_end_id,通过 E2E 解析 transactions 中链接的实际交易;否则返回 "未付款 QR Code" 结构

如果在任何源中都没有匹配,返回 404

transaction_id 查询不会返回被拒绝的交易

同步 BACEN 拒绝(PACS.002 RJCT)和 force-voids 持久化在 failed_transactions 中,当您按 transaction_id 查询时此端点找不到它们。使用替代端点:

输入验证拒绝(立即 400/422)不经过此流程 — 它们已在 POST 中返回同步错误。


响应 -- 已结算交易 (200)

json
{
  "worked": true,
  "data": {
    "id": "c7f3a8b12d4e4f6a9c1b3e5f7a9b1d3e",
    "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
    "end_to_end_id": "E37839059202603091530abcdef01",
    "external_id": "order-9876",
    "type": "pix",
    "direction": "outbound",
    "status": "settled",
    "amount": 300000,
    "fee_amount": 350,
    "net_amount": 300350,
    "description": "Pagamento fornecedor",
    "counterparty_name": "Joao Silva",
    "recipient_key": "12345678901",
    "created_at": "2026-03-09T15:30:00Z",
    "completed_at": "2026-03-09T15:30:02Z"
  }
}
字段类型描述
data.idString交易内部 UUID,带连字符的规范格式,36 个字符(例:"c7f3a8b1-2d4e-4f6a-9c1b-3e5f7a9b1d3e")。控制器在序列化之前通过 Ecto.UUID.load/1 传递 16 字节二进制 — 格式不是 32 字符十六进制小写无连字符
data.transaction_idString交易唯一标识(出款常见前缀 PIXOUT,入款 PIXIN,但不保证 — 始终读取字段,不要从前缀派生)
data.end_to_end_idStringSPI/BACEN 的 End-to-End 标识
data.external_idString您系统中的标识符。未提供时为 null
data.typeString交易类型。常见值:pixpix_return。后端对字段 t.type 执行 passthrough — 遗留记录可能返回其他值
data.directionStringoutbound(cash-out)、inbound(cash-in)、creditdebit。后两者在字段 t.direction 未持久化且后端通过 Helpers.infer_direction/2 基于 account_id × to_account_id 推断时出现
data.statusString归一化状态(见下表)
data.amountInteger值,以基础单位(÷ 10.000 得到雷亚尔)。300000 = R$ 30,00
data.fee_amountInteger收取的手续费,以基础单位
data.net_amountInteger净额,以基础单位
data.descriptionString创建时填写的描述
data.counterparty_nameString对手方姓名(付款方或收款方)
data.recipient_keyString收款方 PIX 密钥(仅出款)
data.created_atString创建日期(ISO 8601)
data.completed_atString完成日期(ISO 8601),待处理时为 null

响应 -- 进行中的 PIX OUT (200)

当交易仍在处理时(BACEN 确认之前)返回。

json
{
  "worked": true,
  "data": {
    "status": "processing",
    "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
    "end_to_end_id": "E37839059202603091530abcdef01",
    "amount": 300000,
    "fee_amount": 350,
    "net_amount": 300350,
    "external_id": "order-9876",
    "pix_key": "12345678901",
    "description": "Pagamento fornecedor",
    "type": "pix",
    "direction": "outbound",
    "payment_status": "processing",
    "started_at": "2026-03-09T15:30:00Z",
    "recipient": {
      "name": "Joao Silva",
      "key": "12345678901",
      "key_type": "cpf"
    }
  }
}
附加字段类型描述
data.recipientObject通过 DICT 解析的收款方数据
data.recipient.nameString密钥持有人姓名
data.recipient.keyString使用的 PIX 密钥
data.recipient.key_typeString密钥类型(cpfcnpjemailphoneevp
data.started_atString处理开始日期(ISO 8601)

响应 -- 被拒绝的交易 (200)

由端点 /transactions/e2e/:e2e_idGET /transactions/ref/:external_id 在 PIX 被 SPI 拒绝或处理期间失败时返回。GET /transactions/:id 不返回(见上文关于 failed_transactions 的警告)。

json
{
  "worked": true,
  "data": {
    "status": "failed",
    "transaction_id": "PIXOUT20260309a1b2c3d4e5f6",
    "end_to_end_id": "E37839059202603091530abcdef01",
    "amount": 300000,
    "fee_amount": 350,
    "external_id": "order-9876",
    "type": "pix",
    "direction": "outbound",
    "payment_status": "failed",
    "failure_reason": "rejected: AB03",
    "reason_code": "AB03",
    "reason_description": "Aborted by PSP of creditor",
    "started_at": "2026-03-09T15:30:00Z",
    "failed_at": "2026-03-09T15:30:05Z",
    "recipient": {
      "name": "Joao Silva",
      "key": "12345678901"
    }
  }
}
附加字段类型描述
data.failure_reasonString拒绝的原始原因(格式:BACEN 代码为 "rejected: {CODE}",或集成描述如 "dict_key_not_found""ambiguous key""insufficient balance"
data.reason_codeStringfailure_reason 提取的结构化代码。对于 BACEN 拒绝,遵循 ISO 20022(AC03AB03ED05DUPL 等)。当 failure_reason 不包含结构化代码时为 null
data.reason_descriptionStringreason_code 的人类描述,英文(在 Fluxiq.UseCases.Pix.ReasonCodes 中集中)。示例:"Invalid creditor account number"(AC03)、"Aborted by PSP of creditor"(AB03)、"Settlement failed"(ED05)。代码未识别时为 null
data.recipientObject收款方数据(可用时)。在非常早期的故障中可能省略
data.failed_atString拒绝日期/时间(ISO 8601)

拒绝代码的结构

字段 reason_codereason_description 派生自集中在 Fluxiq.UseCases.Pix.ReasonCodes 中的字典。用于程序化错误路由。仅将 failure_reason 用于日志和诊断。完整代码表见 PIX Cash-Out 按密钥 -- 错误代码


响应 -- 未付款 QR Code (200)

当 ID 对应于尚未付款的 QR Code 时返回。

json
{
  "worked": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "transaction_id": "7popu57v6us7p6pcicgq12345",
    "end_to_end_id": null,
    "external_id": "order-9876",
    "type": "pix_qrcode",
    "status": "pending",
    "amount": 300000,
    "fee_amount": 0,
    "net_amount": 300000,
    "description": "Cobrança PIX",
    "direction": "credit",
    "counterparty_name": null,
    "recipient_key": "12345678901",
    "created_at": "2026-03-09T15:30:00Z",
    "completed_at": null
  }
}
QR 状态描述
pendingQR Code 激活,等待付款
settledQR Code 填充了 paid_at,但控制器无法通过 payment_end_to_end_id 解析 transactions 中的真实交易。在 Phase 1 ACSP(ACK to BACEN)和 Phase 2 ACCC(PG MERGE 完成)之间的窗口中,或当 QR↔TX 链接因其他原因失败时发生。活跃代码路径show_transaction_controller.ex:83)— 不要当作错误处理;几秒钟后重新查询,后端应正常返回 "已结算交易" 结构
expiredQR Code 已过期(默认 TTL 60 分钟 — 可通过 account.qrcode_expiration_seconds 按账户配置)
cancelledQR Code 手动取消(或在 2026-04 静态→动态迁移期间批量取消)

:当 QR 已付款且后端可以通过 E2E 查找真实交易时,响应是上面的 "已结算交易" 结构(status: "settled" 和真实的 transaction_id,而不是 QR 的 tx_id)。仅当查找返回 nil 时,才会回到 "未付款 QR Code" 结构,status: "settled"


status 字段的值

GET 的状态取决于源

GET /transactions/:id4 个不同的表中搜索,并根据找到交易的源返回不同的状态。所有源之间没有统一的词汇。

状态含义
processingoutbound_requests(stage 12已发送 PACS.008,等待 BACEN 确认。余额处于 hold
processingoutbound_requests(stage 4 — 重试队列)ClientLimiter / DictBucket.Guard 限制,等待自动重试(Oban PixOutRetryWorker,TTL 120min)。返回的结构与 stage 1/2 相同 — 通过入队时触发的 webhook pix.payout.queued 区分
settledtransactions(内部状态 1BACEN 已确认结算,余额已移动。最终成功状态
pendingtransactions(内部状态 2罕见情况 — 在提升为 settled 之前的中间状态的交易
failedtransactions(内部状态 3)或 failed_transactions最终失败状态。由 BACEN 拒绝(PACS.002 RJCT)、孤儿 force-voided(>30min 在 hold 中)、重试队列过期(DICT_QUEUE_TIMEOUT)或内部错误

兼容性说明:遗留记录(在词汇统一之前)可能显示 status: "completed"status: "accepted"。将它们视为等同于 "settled"

与 webhook 的对应

  • pix.payout.queued 在请求处于 outbound_requests.stage=4 时对应于 GET 中的 status: "processing"
  • pix.payout.confirmed 始终对应于 GET 中的 status: "settled"
  • pix.payout.failedpix.payout.rejected 始终对应于 GET 中的 status: "failed"

对于 QR Code(cash-in,超出 PIX OUT 范围),qrcodes 表添加 4 个值:pendingsettledexpiredcancelled — 在上面的 "未付款 QR Code" 部分描述。

错误响应 -- 404

json
{
  "worked": false,
  "detail": "Transação não encontrada"
}

Owem Pay Instituição de Pagamento — ISPB 37839059