动态 QR Code 指南
本指南说明如何使用动态 QR Code 生成 PIX 收款。
概述
动态 QR Code 允许您创建具有指定金额、过期时间和付款人信息的唯一收款。适用于以下场景:
- 电子商务 - 订单付款
- 账单 - 发票和账单
- 服务 - 服务费用支付
如果需要可重复使用、可接受多笔付款且不会过期的代码——柜台上的牌子、捐赠、月费 ——请参见静态二维码指南。
集成流程
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Create │ │ Customer │ │ Webhook │
│ Charge │ ───► │ Pays QR │ ───► │ Received │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
▼ ▼
Returns EMV Confirms
and payload Payment
第一步:创建收款(动态 QR Code)
请求
curl -X POST "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/qr-code/dynamic" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-12345" \
-d '{
"pixKey": "your-pix-key-here",
"value": 150.75,
"expirationDate": "2026-02-10T15:30:00Z",
"identifier": "order-12345",
"message": "Payment for order #12345"
}'
请求体参数
| 字段 | 类型 | 必填 | 描述 |
|---|---|---|---|
pixKey | string | 是 | 收款账户的 PIX 密钥(必须已注册) |
value | number | 是 | 收款金额(BRL),必须大于零。最多 2 位小数(例如 150.75) |
expirationDate | datetime | 推荐 | 过期日期/时间(RFC3339 格式,例如 2026-02-10T15:30:00Z)。未提供时采用清算行默认值(MT:1 天) |
identifier | string | 推荐 | 唯一的收款标识符(最多 38 个字符,字符集 [A-Za-z0-9._-])。若省略,API 会生成一个不含连字符的 UUID |
message | string | 否 | 向付款人显示的消息(最多 140 个字符) |
allowedPayerTaxNumber | string | 否 | 授权付款的特定 CPF/CNPJ |
重要请求头
| 请求头 | 描述 |
|---|---|
Idempotency-Key | 唯一标识符,用于防止重复创建收款 |
成功响应 (201 Created)
{
"txid": "88a38a908a92441a98dac228ee1d9507",
"emv": "00020101021226790014br.gov.bcb.pix2557brcode.starkinfra.com/v2/88a38a908a92441a98dac228ee1d95075204000053039865802BR5912iDez Digital6004Lins62070503***63040BFF",
"type": "dynamic",
"status": "ACTIVE",
"value": 150.75,
"message": "Payment for order #12345",
"description": "Payment for order #12345",
"identifier": "order-12345",
"accountId": "{accountId}",
"pixKey": "8026ff12-cb4a-4d19-9638-08bb15d450e2",
"allowChange": false,
"createdAt": "2026-02-10T12:00:00Z",
"expiresAt": "2026-02-10T15:30:00Z"
}
data 信封响应是一个扁平对象(字段在顶层)。没有 data 信封,也没有
statusCode/title/message 字段。复制粘贴代码在 emv(不是
data.payload),密钥在 pixKey(不是 data.chave)。
| 字段 | 描述 |
|---|---|
emv | PIX 复制粘贴代码(EMV 字符串)。渲染为 QR code。 |
txid | 内部交易 ID |
identifier | 唯一的收款 ID(用于查询) |
status | 收款状态(ACTIVE = 有效) |
pixKey | 用于收款的 PIX 密钥 |
value | 收款金额(BRL) |
expiresAt | 过期时间(RFC3339) |
第二步:显示 QR Code
使用 PIX 复制粘贴
将 emv 字段展示给客户进行复制:
<input type="text"
value="00020101021226790014br.gov.bcb.pix..."
readonly />
<button onclick="navigator.clipboard.writeText(this.previousElementSibling.value)">
Copy
</button>
您可以使用任何 QR code 库(例如 qrcode.js、python-qrcode)从 emv 字符串生成 QR code 图片。
第三步:查询收款状态
通过 identifier 轮询收款状态:
qrcode.manage 范围同时涵盖创建、取消和查询 QR:专用于收款的凭证无需通用查询
范围(read,同时可访问余额与流水)即可确认 QR 是否已付款。参见
身份验证指南。
请求
curl -X GET "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/qr-code/lookup?identifier=order-12345" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}"
可能的状态
| 状态 | 描述 |
|---|---|
ACTIVE | 已创建 / 等待中 |
AWAITING-PAYMENT | 等待付款 |
PAID | 付款已确认 |
CANCELLED | 已取消 / 被拒绝 |
EXPIRED | 已过期,未收到付款 |
UNKNOWN | 合作方状态超出已知映射 |
status 以大写(规范化)返回。PIX 退款不会将 QR 状态改为
"refunded" —— QR 保持 PAID,退款通过交易/账单跟踪。
各状态的响应示例
有效(等待付款)
{
"txid": "88a38a908a92441a98dac228ee1d9507",
"emv": "00020101021226790014br.gov.bcb.pix2557brcode.starkinfra.com/v2/88a38a90...",
"type": "dynamic",
"status": "ACTIVE",
"value": 150.75,
"description": "Payment for order #12345",
"identifier": "order-12345",
"accountId": "6ff57bc1-e4a9-403b-be62-42378b8aafd7",
"pixKey": "8026ff12-cb4a-4d19-9638-08bb15d450e2",
"createdAt": "2026-02-09T01:50:36Z",
"expiresAt": "2026-02-09T02:50:34Z"
}
已支付(付款已确认)
{
"txid": "b091da7bba6a45d1a9f709daaba04e30",
"emv": "00020101021226790014br.gov.bcb.pix...",
"type": "dynamic",
"status": "PAID",
"value": 150.75,
"message": "Payment for order #12345",
"description": "Payment for order #12345",
"identifier": "order-12345",
"accountId": "6ff57bc1-e4a9-403b-be62-42378b8aafd7",
"pixKey": "8026ff12-cb4a-4d19-9638-08bb15d450e2",
"allowChange": false,
"createdAt": "2026-02-05T22:08:02Z",
"expiresAt": "2026-02-05T23:08:00Z",
"paidAt": "2026-02-05T22:10:25Z",
"paidAmount": 150.75,
"endToEndId": "E303062942026020522100000005EXVX",
"payer": {
"name": "John Smith",
"document": "12345678901",
"bankIspb": "30306294",
"bankName": "BANCO EXEMPLO",
"branch": "0020",
"account": "004912314"
},
"payee": {
"name": "iDez Digital",
"document": "12345678000190",
"bankIspb": "50871921",
"bankCode": "681"
}
}
退款后
PIX 退款(POST /v1/accounts/{accountId}/pix/out/refund)不会将 QR 状态
改为 "refunded" —— QR 保持 PAID。退款是独立交易;请通过账单
(GET .../statement)或付款查询(GET .../pix/payments/lookup)跟踪。QR
查询不会返回退款字段。
已过期(收款已过期)
{
"txid": "c1234567890abcdef1234567890abcde",
"emv": "00020101021226790014br.gov.bcb.pix...",
"type": "dynamic",
"status": "EXPIRED",
"value": 50.00,
"identifier": "order-99999",
"accountId": "6ff57bc1-e4a9-403b-be62-42378b8aafd7",
"pixKey": "8026ff12-cb4a-4d19-9638-08bb15d450e2",
"createdAt": "2026-02-01T10:00:00Z",
"expiresAt": "2026-02-01T10:30:00Z"
}
字段参考
| 字段 | 何时出现 | 描述 |
|---|---|---|
txid | 始终 | 内部 QR code 交易 ID |
emv | 始终 | PIX 复制粘贴代码(BR Code) |
type | 始终 | QR code 类型(dynamic 或 static) |
status | 始终 | 当前状态(ACTIVE、AWAITING-PAYMENT、PAID、CANCELLED、EXPIRED、UNKNOWN) |
value | 始终 | 收款金额(BRL) |
identifier | 始终 | 您的唯一收款标识符 |
accountId | 始终 | 收款所属账户 |
pixKey | 可用时 | 收款使用的 PIX 密钥 |
createdAt | 可用时 | 创建时间戳 |
expiresAt | 可用时 | 过期日期(动态 QR) |
paidAt | 已支付时 | 付款时间戳 |
paidAmount | 已支付时 | 实际支付金额(BRL) |
endToEndId | 已支付时 | PIX E2E 标识符 |
payer | 已支付时 | 付款人信息(name、document、bankIspb、bankName、branch、account、pixKey) |
payee | 可用时 | 收款人(您的账户)信息 |
查询端点
通过 identifier 查询(向后兼容别名:txid):
curl -X GET "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/qr-code/lookup?identifier=order-12345" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}"
查询在合作方端实时解析,返回扁平的 QR 对象(status、value、emv,以及
付款后返回 payer/payee/endToEndId)。此端点不接受
qrcodeId/endToEndId,且不返回交易/手续费/退款数据。
第四步:接收付款 Webhook
当客户完成付款时,您会收到一个采用规范信封(id、type、occurredAt、
schemaVersion、data)的 qrcode.paid webhook:
{
"id": "evt_987654321",
"type": "qrcode.paid",
"occurredAt": "2026-02-05T22:10:25.000Z",
"schemaVersion": "1.0",
"environment": "production",
"tenantId": "tenant-yourcompany",
"accountId": "{accountId}",
"data": {
"endToEnd": "E303062942026020522100000005EXVX",
"type": "dynamic",
"identifier": "order-12345",
"qrcodeId": "b091da7bba6a45d1a9f709daaba04e30",
"amount": 150.75,
"payer": {
"name": "John Smith",
"document": "12345678901",
"bankCode": "033",
"branch": "0001",
"accountNumber": "54321-0"
},
"payee": {
"name": "iDez Digital",
"document": "12345678000190"
},
"receivedAt": "2026-02-05T22:10:25.000Z"
}
}
通过 POST /v1/webhooks 配置 webhooks,事件类型为 qrcode.paid。参见 Webhooks 指南。
第五步:取消收款(可选)
在收款被支付之前取消待处理的收款:
curl -X DELETE "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/qr-code?identifier=order-12345" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}"
响应(200 OK):
{
"identifier": "order-12345",
"status": "CANCELLED"
}
第六步:QR Code 指标(可选)
QR code 没有列表端点 —— 查询始终通过 identifier。如需按天聚合的指标
(生成/支付/退款/金额),请使用:
curl -X GET "https://tenant.api.corpx.com/v1/accounts/{accountId}/pix/qr-codes/stats?days=30" \
-H "Authorization: Bearer {token}" \
-H "X-Tenant-Id: {tenant_id}"
完整示例:电子商务集成
#!/bin/bash
# Configuration
API_URL="https://tenant.api.corpx.com"
TOKEN="your_token_here"
TENANT_ID="tenant-yourcompany"
ACCOUNT_ID="your-account-id"
PIX_KEY="your-pix-key"
# 1. Create charge for order
ORDER_ID="order-$(date +%s)"
AMOUNT=299.90
EXPIRATION=$(date -u -v+30M +"%Y-%m-%dT%H:%M:%SZ") # 30 minutes
echo "Creating charge: $ORDER_ID for R\$$AMOUNT..."
response=$(curl -s -X POST "$API_URL/v1/accounts/$ACCOUNT_ID/pix/qr-code/dynamic" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Tenant-Id: $TENANT_ID" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $ORDER_ID" \
-d "{
\"pixKey\": \"$PIX_KEY\",
\"value\": $AMOUNT,
\"expirationDate\": \"$EXPIRATION\",
\"identifier\": \"$ORDER_ID\",
\"message\": \"Store Purchase - $ORDER_ID\"
}")
# 2. Extract information
IDENTIFIER=$(echo $response | jq -r '.identifier')
EMV=$(echo $response | jq -r '.emv')
echo "Charge created!"
echo "ID: $IDENTIFIER"
echo "PIX Copy and Paste: $EMV"
# 3. Poll for payment (alternative to webhook)
while true; do
sleep 10
status_response=$(curl -s "$API_URL/v1/accounts/$ACCOUNT_ID/pix/qr-code/lookup?identifier=$IDENTIFIER" \
-H "Authorization: Bearer $TOKEN" \
-H "X-Tenant-Id: $TENANT_ID")
current_status=$(echo $status_response | jq -r '.status')
if [ "$current_status" = "PAID" ]; then
paid_amount=$(echo $status_response | jq -r '.paidAmount')
e2e=$(echo $status_response | jq -r '.endToEndId')
echo "Payment confirmed! Amount: R\$$paid_amount, E2E: $e2e"
break
elif [ "$current_status" = "EXPIRED" ]; then
echo "Charge expired"
break
fi
echo "Awaiting payment... Status: $current_status"
done
最佳实践
- 使用 Idempotency Key - 每笔收款始终发送唯一标识符以防止重复
- 设置合适的过期时间 - 结账页面设置 30 分钟,发票设置 24 小时
- 配置 webhooks - 不要仅依赖轮询,使用
qrcode.paid事件 - 所有金额使用 BRL - 最多 2 位小数(例如
150.75表示 R$150,75) - 处理过期情况 - 当收款过期时通知客户
- 保存 identifier - 用于查询状态和对账
常见错误
错误采用 { "errorCode": "...", "message": "..." } 格式:
errorCode | HTTP | 原因 | 解决方案 |
|---|---|---|---|
missing_field | 400 | 缺少 pixKey,或 value 小于等于零 | 提供已注册的密钥和正数 BRL 金额 |
invalid_identifier | 400 | identifier 超出字符集 [A-Za-z0-9._-] 或超过 38 个字符 | 调整标识符 |
invalid_field | 400 | message 超过 140 个字符或含不支持的字符 | 缩短消息 |
invalid_payload | 400 | JSON 格式错误、expirationDate 不符合 RFC3339 或已过期 | 修正请求体 |
missing_param | 400 | 查询/取消时未在 query 中提供 identifier | 提供 ?identifier=(别名:txid) |
not_found | 404 | 未找到收款 | 检查 identifier 和 accountId |
policy_denied | 422 | 策略规则拒绝了该收款的创建 | 查看响应体中的 violations —— 策略与规则 |
示例:
{
"errorCode": "missing_field",
"message": "pixKey and positive value are required"
}
后续步骤
- Cash Out 指南 - 发起 PIX 转账
- 退款指南 - 撤销已收到的付款
- Webhooks - 配置通知