# POSTBACK automático

Depois de a fatura ser confirmada com sucesso, é enviada uma solicitação POST com as informações de pagamento para o URL de notificação especificado nas configurações do projeto.

O sistema suporta dois formatos de POSTBACK:

1. JSON
2. application/x-www-form-urlencoded

Para configurar o formato de POSTBACK, vá às configurações do seu projeto e abra a secção «Integration & API».

Após a execução bem-sucedida do pagamento, é enviada uma requisição POST com informações sobre o pagamento para o URL de notificação especificado nas definições do projeto.

### O que o método permite fazer

* Envia automaticamente uma solicitação POST para o URL que você especificou após a fatura ser confirmada pelo sistema.
* O formato de POSTBACK pode ser configurado.

### Parâmetros do postback

| Nome           | Tipo   | Exemplo                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | Descrição                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| -------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| estado         | string | sucesso                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | Estado de execução da requisição                                                                                                                                                                                                                                                                                                                                                                                                                        |
| invoice\_id    | string | 89UX09KA                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | Identificador único do pagamento sem o prefixo INV                                                                                                                                                                                                                                                                                                                                                                                                      |
| amount\_crypto | float  | 0.000113                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | Montante do pagamento em criptomoeda                                                                                                                                                                                                                                                                                                                                                                                                                    |
| currency       | string | BNB                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | <p>Código da moeda<br><br>BTC, LTC, TRX, SOL, TON, BNB, ETH, ETH\_ARB, ETH\_BASE, ETH\_OPT, USDT\_ARB, USDT\_BSC, USDT\_ERC20, USDT\_OPT, USDT\_SOL, USDT\_TON, USDT\_TRC20, USDC\_ARB, USDC\_BASE, USDC\_BSC, USDC\_ERC20, USDC\_OPT, USDC\_SOL, DAI\_ARB, DAI\_BASE, DAI\_BSC, DAI\_ERC20, DAI\_OPT, USDD\_TRC20, PYUSD\_ERC20, PYUSD\_SOL, XAUT\_ERC20, XAUT\_TON, ARB\_ARB, OP\_OPT, PEPE\_BSC, PEPE\_ERC20, SHIB\_BSC, SHIB\_ERC20, TRUMP\_SOL</p> |
| order\_id      | string | ORDER\_93223                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | Número personalizado da fatura no sistema externo                                                                                                                                                                                                                                                                                                                                                                                                       |
| token          | string | eyJ0eXAiOiJKV1QiLCJhbGciOiJIAcI1NiJ9.eyJpZCI6MTMsImV4cCI6MTYzMTc4NjQyNn0.HQavV3z8dFnk56bX3MSY5X9lR6qVa9YhAoeTEHkaAzs                                                                                                                                                                                                                                                                                                                                                                                                                                                            | Token JWT — assinatura da resposta do servidor                                                                                                                                                                                                                                                                                                                                                                                                          |
| invoice\_info  | dict   | <p>"invoice\_info": {</p><p>        "uuid": "INV-ILRAJE1Q",</p><p>        "created": "2026-01-01 10:20:04.222439",</p><p>        "address": "0x635DBa<...>2Ec029fc555af05d2",</p><p>        "currency": {</p><p>            "id": 20,</p><p>            "code": "BNB",</p><p>            "fullcode": "BNB",</p><p>            "network": {</p><p>                "code": "BSC",</p><p>                "id": 20,</p><p>                "icon": "<https://cdn.cryptocloud.plus/img/network/BSC.svg>",</p><p>                "fullname": "BNB Smart Chain"</p><p>            }</p> | Informações detalhadas da fatura. Disponível apenas em JSON.                                                                                                                                                                                                                                                                                                                                                                                            |

{% hint style="info" %}
Token JWT — uma assinatura da resposta do servidor. É assinado com a chave secreta (SECRET KEY) gerada nas configurações do projeto. O token é válido por 5 minutos após a criação da notificação. Um novo token é gerado sempre que uma notificação de pagamento é enviada.

Algoritmo de criptografia — HS256.
{% endhint %}

### Exemplo de postback em JSON

{% tabs %}
{% tab title="POSTBACK JSON" %}

```json
{
    "estado": "sucesso",
    "invoice_id": "ILRAJE1Q",
    "amount_crypto": 0.000113,
    "currency": "BNB",
    "order_id": null,
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJ<...>hPirF9kHCx3ZXEspVfGNGuK7cZ8",
    "invoice_info": {
        "uuid": "INV-ILRAJE1Q",
        "created": "2026-01-27 10:20:04.222439",
        "address": "0x635DBa9c6e5E9<...>6f8Bed2Ec029fc555af05d2",
        "currency": {
            "id": 20,
            "code": "BNB",
            "fullcode": "BNB",
            "network": {
                "code": "BSC",
                "id": 20,
                "icon": "https://cdn.cryptocloud.plus/img/network/BSC.svg",
                "fullname": "BNB Smart Chain"
            },
            "name": "BNB",
            "is_email_required": false,
            "stablecoin": false,
            "icon_base": "https://cdn.cryptocloud.plus/img/currency/BNB.svg",
            "icon_network": "https://cdn.cryptocloud.plus/img/currency/BNB.svg",
            "icon_qr": "https://cdn.cryptocloud.plus/img/stroke/BNB_STROKE.svg",
            "order": 13
        },
        "date_finished": "2026-01-01 10:23:14.000940",
        "expiry_date": "2026-01-02 10:20:04.197389",
        "side_commission": "client",
        "type_payments": "crypto",
        "amount": 0.000113,
        "amount_": 0.000113,
        "status": "paid",
        "invoice_status": "success",
        "is_email_required": false,
        "project": {
            "id": 1,
            "name": "Test",
            "fail": "https://test.com/failed-payment",
            "success": "https://test.com/successful-payment",
            "logo": ""
        },
        "tx_list": [
            "0x12fb777c41b58b8304278416e5a<...>c1e7708b2160745af56403641522"
        ],
        "amount_in_crypto": null,
        "amount_in_fiat": 0.1,
        "amount_usd": 0.1,
        "amount_to_pay": 0.000113,
        "amount_to_pay_usd": 0.1,
        "amount_paid": 0.000113,
        "amount_paid_usd": 0.1,
        "fee": 0,
        "fee_usd": 0,
        "service_fee": 0.000002,
        "service_fee_usd": 0,
        "received": 0.000111,
        "received_usd": 0.1,
        "to_surcharge": 0,
        "to_surcharge_usd": 0,
        "total_rub": 0,
        "step": 3,
        "test_mode": false,
        "type": "up",
        "aml_enabled": false,
        "aml_side": "merchant",
        "aml_checks": [],
        "links_invoice": null
    }
}
```

{% endtab %}

{% tab title="POSTBACK application/x-www-form-urlencoded" %}

```php
{
    "estado": "sucesso",
    "invoice_id": "ILRAJE1Q",
    "amount_crypto": 0.000113,
    "currency": "BNB",
    "order_id": null,
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJ<...>hPirF9kHCx3ZXEspVfGNGuK7cZ8",
}
```

{% endtab %}
{% endtabs %}

### Exemplos de manipulador de postback em JSON

Estes exemplos mostram como você pode lidar com notificações de POSTBACK em formato JSON no lado do seu projeto.

{% tabs %}
{% tab title="Python" %}

```python
from flask import Flask, request, jsonify
import os
import jwt  # pip install PyJWT

app = Flask(__name__)

JWT_SECRET = os.getenv("JWT_SECRET", "super-secret")
JWT_ALGORITHMS = ["HS256"]


def validate_token(token: str) -> bool:
    """
    Valida apenas JWT HS256 se o token estiver presente e não estiver vazio.
    Espera-se que o token seja uma string JWT bruta (sem o prefixo "Bearer ").
    """
    if token is None:
        return True
    if not isinstance(token, str):
        return False

    token = token.strip()
    if token == "":
        return True

    try:
        jwt.decode(token, JWT_SECRET, algorithms=JWT_ALGORITHMS)
        return True
    except jwt.PyJWTError:
        return False


@app.route("/postback", methods=["POST"])

def handle_postback():
    # 1) Ler o corpo JSON
    data = request.get_json(silent=True)
    if not isinstance(data, dict):
        return jsonify({"error": "JSON inválido"}), 400

    # 2) Campos de nível superior
    status = data.get("status")
    invoice_id = data.get("invoice_id")
    amount_crypto = data.get("amount_crypto")
    currency = data.get("currency")
    order_id = data.get("order_id")
    token = data.get("token")

    # Validação básica
    if not invoice_id or not order_id:
        return jsonify({"error": "Falta invoice_id ou order_id"}), 400

    # 3) Validar o token JWT (apenas se fornecido)
    if not validate_token(token):
        return jsonify({"error": "Token inválido"}), 401

    # 4) Objeto aninhado invoice_info
    invoice_info = data.get("invoice_info") or {}

    uuid = invoice_info.get("uuid")
    created = invoice_info.get("created")
    address = invoice_info.get("address")

    invoice_status = invoice_info.get("invoice_status")
    invoice_amount = invoice_info.get("amount")
    amount_paid = invoice_info.get("amount_paid")
    fee = invoice_info.get("fee")

    # 5) Aninhamento mais profundo: invoice_info.currency.network
    inv_currency = invoice_info.get("currency") or {}
    network = inv_currency.get("network") or {}
    network_code = network.get("code")

    # 6) Informações do projeto
    project = invoice_info.get("project") or {}
    project_name = project.get("name")

    # 7) A lógica de negócio deve ser implementada aqui:
    # - idempotência por invoice_id / uuid
    # - atualizar o status da fatura no banco de dados
    # - validação de valor / moeda
    # - registo (evite registrar o token)

    return jsonify({"message": "Postback recebido"}), 200


if __name__ == "__main__":
    app.run(port=5000, debug=True)
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const express = require("express");
const jwt = require("jsonwebtoken");

const app = express();
app.use(express.json());

// Segredo HS256 (armazene em ENV em produção)
const JWT_SECRET = process.env.JWT_SECRET || "super-secret";

/**
 * Valida o token JWT HS256 apenas se ele estiver presente e não estiver vazio.
 * Espera-se que o token seja uma string JWT bruta (sem o prefixo "Bearer ").
 */
function validateToken(token) {
  // O token é opcional
  if (token === undefined || token === null) return true;
  if (typeof token !== "string") return false;

  const t = token.trim();
  if (t === "") return true;

  try {
    jwt.verify(t, JWT_SECRET, { algorithms: ["HS256"] });
    return true;
  } catch (err) {
    return false;
  }
}

app.post("/postback", (req, res) => {
  // 1) Ler o corpo JSON
  const data = req.body;
  if (!data || typeof data !== "object" || Array.isArray(data)) {
    return res.status(400).json({ error: "JSON inválido" });
  }

  // 2) Campos obrigatórios básicos (ajuste conforme necessário)
  const invoice_id = data.invoice_id;
  const order_id = data.order_id;

  if (!invoice_id || !order_id) {
    return res.status(400).json({ error: "Falta invoice_id ou order_id" });
  }

  // 3) Validar o token JWT (apenas se fornecido)
  const token = data.token;
  if (!validateToken(token)) {
    return res.status(401).json({ error: "Token inválido" });
  }

  // 4) Objeto aninhado invoice_info
  const invoice_info = data.invoice_info || {};

  const uuid = invoice_info.uuid;
  const created = invoice_info.created;
  const address = invoice_info.address;

  const invoice_status = invoice_info.invoice_status;
  const invoice_amount = invoice_info.amount;
  const amount_paid = invoice_info.amount_paid;
  const fee = invoice_info.fee;

  // 5) Aninhamento mais profundo: invoice_info.currency.network
  const inv_currency = invoice_info.currency || {};
  const network = inv_currency.network || {};
  const network_code = network.code;

  // 6) Informações do projeto
  const project = invoice_info.project || {};
  const project_name = project.name;

  // 7) A lógica de negócio vai aqui (exemplos):
  // - idempotência por invoice_id / uuid
  // - atualizar o status da fatura no BD
  // - validar valores/moeda
  // - registo (evite registrar o token)
  //
  // Exemplo (pseudo):
  // await db.invoices.upsert({ invoice_id, order_id, uuid, invoice_status, amount_paid, fee, network_code, project_name, created, address })

  // 8) Resposta mínima (conforme solicitado)
  return res.status(200).json({ message: "Postback recebido" });
});

app.listen(5000, () => {
  console.log("Servidor em execução em http://127.0.0.1:5000");
});
```

{% endtab %}

{% tab title="PHP 7.4 +" %}

```php
<?php
// postback.php

header('Content-Type: application/json; charset=utf-8');

$JWT_SECRET = getenv('JWT_SECRET') ?: 'super-secret';

/**
 * Decodificação Base64URL (JWT usa base64url sem preenchimento)
 */
function base64url_decode($data) {
    $remainder = strlen($data) % 4;
    if ($remainder) {
        $data .= str_repeat('=', 4 - $remainder);
    }
    $data = strtr($data, '-_', '+/');
    return base64_decode($data);
}

/**
 * Valida o JWT HS256 apenas se o token estiver presente e não estiver vazio.
 * Espera-se que o token seja uma string JWT bruta (sem o prefixo "Bearer ").
 */
function validateToken($token, $secret) {
    // O token é opcional
    if (!isset($token)) return true;
    if (!is_string($token)) return false;

    $t = trim($token);
    if ($t === '') return true;

    $parts = explode('.', $t);
    if (count($parts) !== 3) return false;

    [$headerB64, $payloadB64, $sigB64] = $parts;

    $headerJson = base64url_decode($headerB64);
    $payloadJson = base64url_decode($payloadB64);
    if ($headerJson === false || $payloadJson === false) return false;

    $header = json_decode($headerJson, true);
    $payload = json_decode($payloadJson, true);
    if (!is_array($header) || !is_array($payload)) return false;

    // Garantir HS256
    if (($header['alg'] ?? null) !== 'HS256') return false;

    // Verificar assinatura
    $dataToSign = $headerB64 . '.' . $payloadB64;
    $expectedSigRaw = hash_hmac('sha256', $dataToSign, $secret, true);
    $sigRaw = base64url_decode($sigB64);
    if ($sigRaw === false) return false;

    if (!hash_equals($expectedSigRaw, $sigRaw)) return false;

    // Opcional: validar exp/nbf se presentes
    $now = time();
    if (isset($payload['nbf']) && is_numeric($payload['nbf']) && $now < (int)$payload['nbf']) {
        return false;
    }
    if (isset($payload['exp']) && is_numeric($payload['exp']) && $now >= (int)$payload['exp']) {
        return false;
    }

    return true;
}

// 1) Ler o corpo JSON bruto
$raw = file_get_contents('php://input');
$data = json_decode($raw, true);

if (!is_array($data)) {
    http_response_code(400);
    echo json_encode(['error' => 'JSON inválido'], JSON_UNESCAPED_UNICODE);
    exit;
}

// 2) Campos obrigatórios básicos
$invoice_id = $data['invoice_id'] ?? null;
$order_id   = $data['order_id'] ?? null;

if (!$invoice_id || !$order_id) {
    http_response_code(400);
    echo json_encode(['error' => 'Falta invoice_id ou order_id'], JSON_UNESCAPED_UNICODE);
    exit;
}

// 3) Validar o token JWT (apenas se fornecido)
$token = $data['token'] ?? null;
if (!validateToken($token, $JWT_SECRET)) {
    http_response_code(401);
    echo json_encode(['error' => 'Token inválido'], JSON_UNESCAPED_UNICODE);
    exit;
}

// 4) Objeto aninhado invoice_info
$invoice_info = $data['invoice_info'] ?? [];

$uuid    = $invoice_info['uuid'] ?? null;
$created = $invoice_info['created'] ?? null;
$address = $invoice_info['address'] ?? null;

$invoice_status = $invoice_info['invoice_status'] ?? null;
$invoice_amount = $invoice_info['amount'] ?? null;
$amount_paid    = $invoice_info['amount_paid'] ?? null;
$fee            = $invoice_info['fee'] ?? null;

// 5) Aninhamento mais profundo: invoice_info.currency.network
$inv_currency = $invoice_info['currency'] ?? [];
$network      = $inv_currency['network'] ?? [];
$network_code = $network['code'] ?? null;

// 6) Informações do projeto
$project      = $invoice_info['project'] ?? [];
$project_name = $project['name'] ?? null;

// 7) A lógica de negócio vai aqui (exemplos):
// - idempotência por invoice_id / uuid
// - atualizar o status da fatura no BD
// - validar valores/moeda
// - registo (evite registrar o token)
//
// Exemplo (pseudo):
// save_postback($invoice_id, $order_id, $uuid, $invoice_status, $amount_paid, $fee, $network_code, $project_name, $created, $address);

// 8) Resposta mínima
http_response_code(200);
echo json_encode(['message' => 'Postback recebido'], JSON_UNESCAPED_UNICODE);
```

{% endtab %}
{% endtabs %}

### Exemplo de um manipulador de POSTBACK para `application/x-www-form-urlencoded`:

Estes exemplos mostram como você pode lidar com notificações de POSTBACK em `application/x-www-form-urlencoded` formato no lado do seu projeto.

{% tabs %}
{% tab title="Python" %}

```python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/postback', methods=['POST'])
def handle_postback():
    # Alterado para request.form para processar dados no formato x-www-form-urlencoded
    status = request.form.get('status')
    invoice_id = request.form.get('invoice_id')
    amount_crypto = request.form.get('amount_crypto')
    currency = request.form.get('currency')
    order_id = request.form.get('order_id')
    token = request.form.get('token')
    
    # ... o seu código para lidar com o postback ...
    
    return jsonify({'message': 'Postback recebido'}), 200

if __name__ == '__main__':
    app.run(port=5000)
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
const express = require('express');
const app = express();

// Adicionar middleware para processar JSON
app.use(express.json());

// Adicionar middleware para processar dados x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));

app.post('/postback', (req, res) => {
    const { status, invoice_id, amount_crypto, currency, order_id, token } = req.body;
    
    // ... o seu código para lidar com o postback ...
    
    res.json({ message: 'Postback recebido' });
});

app.listen(3000, () => {
    console.log('O servidor está a correr na porta 3000');
});

```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$body = file_get_contents('php://input');
$data = [];
parse_str($body, $data);

$status = $data['status'] ?? null;
$invoice_id = $data['invoice_id'] ?? null;
$amount_crypto = $data['amount_crypto'] ?? null;
$currency = $data['currency'] ?? null;
$order_id = $data['order_id'] ?? null;
$token = $data['token'] ?? null;

// ... o seu código para processar o postback ...

echo json_encode(['message' => 'Postback recebido']);
?>
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.cryptocloud.plus/pt/referencia-da-api-v2/postback.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
