Exemplo em PHP

Este documento contém um exemplo completo de implementação da API Flowbiz em PHP.

Código Completo

<?php
// Exemplo de implementação em PHP seguindo o manual MBUNI-4708
// Endpoints: /api/v2/healthz, /api/v2/categories, /api/v2/brands, /api/v2/products, /api/v2/orders
// Autenticação: header X-Impulse-Key em todos, exceto /healthz

// Configuração
$API_KEY = 'sua_api_key_aqui'; // Em produção, use variáveis de ambiente

header('Content-Type: application/json');

// Verificar método HTTP (somente GET)
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
    http_response_code(405);
    echo json_encode(['error' => 'method_not_allowed', 'message' => 'Only GET is supported']);
    exit;
}

// Obter caminho da URL
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);

// Healthz não requer autenticação
if ($path === '/api/v2/healthz') {
    echo json_encode(['status' => 'ok']);
    exit;
}

// Validar API Key para os demais endpoints
$headers = function_exists('getallheaders') ? getallheaders() : [];
$apiKey = $headers['X-Impulse-Key'] ?? ($headers['x-impulse-key'] ?? '');
if ($apiKey !== $API_KEY) {
    http_response_code(401);
    echo json_encode(['error' => 'unauthorized', 'message' => 'X-Impulse-Key is missing or invalid']);
    exit;
}

// Obter parâmetros de paginação (padrão 50, máximo 100)
$offset = isset($_GET['offset']) ? max(0, intval($_GET['offset'])) : 0;
$limit = isset($_GET['limit']) ? intval($_GET['limit']) : 50;
if ($limit <= 0) { $limit = 50; }
if ($limit > 100) { $limit = 100; }

// Função para responder com envelope de paginação
function respondPaginated(array $items, int $offset, int $limit) {
    $total = count($items);
    $page = array_slice($items, $offset, $limit);
    $count = count($page);
    $hasNext = ($offset + $count) < $total;
    $response = [
        'data' => $page,
        'total' => $total,
        'offset' => $offset,
        'limit' => $limit,
        'count' => $count,
        'hasNext' => $hasNext
    ];
    if ($hasNext) {
        $response['nextOffset'] = $offset + $count;
    }
    echo json_encode($response);
}

// Dados simulados
$ALL_CATEGORIES = [
    ['id' => '1', 'name' => 'Eletrônicos'],
    ['id' => '2', 'name' => 'Roupas'],
    ['id' => '3', 'name' => 'Acessórios']
];

$ALL_BRANDS = [
    ['id' => '1', 'name' => 'Samsung'],
    ['id' => '2', 'name' => 'Apple'],
    ['id' => '3', 'name' => 'Nike']
];

$ALL_PRODUCTS = [
    [
        'productId' => '1',
        'url' => 'https://exemplo.com/produto/1',
        'brand' => ['id' => '1', 'name' => 'Samsung'],
        'category' => [['id' => '1', 'name' => 'Eletrônicos']],
        'variants' => [
            ['sku' => 'SKU-1A', 'name' => 'Produto 1 - Variante A', 'price' => 50.0, 'available' => true]
        ]
    ],
    [
        'productId' => '2',
        'url' => 'https://exemplo.com/produto/2',
        'brand' => ['id' => '2', 'name' => 'Apple'],
        'category' => [['id' => '1', 'name' => 'Eletrônicos']],
        'variants' => [
            ['sku' => 'SKU-2A', 'name' => 'Produto 2 - Variante A', 'price' => 75.0, 'available' => true]
        ]
    ]
];

$ALL_ORDERS = [
    [
        'platform' => 'SuaPlataforma',
        'orderId' => '12345',
        'date' => '2023-06-01T10:00:00Z',
        'subtotal' => 100.0,
        'freight' => 10.0,
        'discounts' => 5.0,
        'total' => 105.0,
        'currency' => 'BRL',
        'rawPaymentStatus' => 'Pago',
        'isPaid' => true,
        'customerId' => '1',
        'customerEmail' => '[email protected]',
        'optIn' => true,
        'items' => [
            [
                'productId' => '1',
                'categories' => [['id' => '1', 'name' => 'Eletrônicos']],
                'sku' => 'SKU-1A',
                'name' => 'Produto 1 - Variante A',
                'brand' => 'Samsung',
                'price' => 50.0,
                'quantity' => 2,
                'url' => 'https://exemplo.com/produto/1',
                'imageUrl' => 'https://exemplo.com/img/1.jpg'
            ]
        ],
        'paymentMethods' => [
            ['type' => 'credit_card', 'amount' => 105.0]
        ],
        'deliveryMethods' => [
            ['type' => 'standard', 'amount' => 10.0]
        ],
        'deliveryAddress' => [
            'city' => 'São Paulo',
            'addressLine2' => 'Apto 101',
            'neighborhood' => 'Centro',
            'addressNumber' => '123',
            'state' => 'SP',
            'addressLine1' => 'Rua Principal',
            'postalCode' => '01000-000',
            'country' => 'BR'
        ]
    ]
];

// Roteamento
switch ($path) {
    case '/api/v2/categories':
        respondPaginated($ALL_CATEGORIES, $offset, $limit);
        break;
    case '/api/v2/brands':
        respondPaginated($ALL_BRANDS, $offset, $limit);
        break;
    case '/api/v2/products':
        respondPaginated($ALL_PRODUCTS, $offset, $limit);
        break;
    case '/api/v2/orders':
        handleOrders($offset, $limit, $ALL_ORDERS);
        break;
    default:
        http_response_code(404);
        echo json_encode(['error' => 'not_found', 'message' => 'Endpoint não encontrado']);
}

// Handler de pedidos com validação de data e envelope de paginação
function handleOrders(int $offset, int $limit, array $allOrders) {
    // Validar presença de start_date e end_date (YYYY-MM-DD)
    $start = $_GET['start_date'] ?? null;
    $end = $_GET['end_date'] ?? null;
    if (!$start || !$end) {
        http_response_code(400);
        echo json_encode(['error' => 'bad_request', 'message' => 'start_date and end_date are required in YYYY-MM-DD format']);
        return;
    }
    if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $start) || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $end)) {
        http_response_code(400);
        echo json_encode(['error' => 'bad_request', 'message' => 'start_date and end_date must be in YYYY-MM-DD format']);
        return;
    }

    $startTs = strtotime($start . 'T00:00:00Z');
    $endTs = strtotime($end . 'T23:59:59Z');
    if ($startTs === false || $endTs === false) {
        http_response_code(400);
        echo json_encode(['error' => 'bad_request', 'message' => 'Invalid date range']);
        return;
    }

    // Filtrar por intervalo inclusivo
    $filtered = array_values(array_filter($allOrders, function($o) use ($startTs, $endTs) {
        $ts = strtotime($o['date']);
        return $ts !== false && $ts >= $startTs && $ts <= $endTs;
    }));

    // Responder paginado
    respondPaginated($filtered, $offset, $limit);
}

Explicação

Este exemplo implementa uma API REST em PHP que atende aos requisitos do padrão Flowbiz. A implementação inclui:

  1. Validação da API Key em todas as requisições
  2. Endpoints para listar categorias, marcas, produtos e pedidos
  3. Suporte à paginação em todos os endpoints
  4. Filtro de data no endpoint de pedidos

Para usar este exemplo, você precisará:

  1. Substituir sua_api_key_aqui pela sua chave de API real
  2. Implementar a lógica para buscar dados do seu banco de dados ou sistema de armazenamento
  3. Adaptar as estruturas de dados conforme necessário para seu caso de uso específico

Estrutura de Arquivos

Para implementar este exemplo, você pode criar um único arquivo index.php com o código acima ou dividir em múltiplos arquivos para melhor organização:

/api
  /v2
    index.php       # Arquivo principal com roteamento
    config.php      # Configurações (API_KEY, etc.)
    categories.php  # Handler para categorias
    brands.php      # Handler para marcas
    products.php    # Handler para produtos
    orders.php      # Handler para pedidos

Configuração do Servidor Web

Apache

Se estiver usando Apache, você pode configurar o redirecionamento de URLs com um arquivo .htaccess:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]

Nginx

Se estiver usando Nginx, adicione a seguinte configuração:

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

Executando o Exemplo

Para executar este exemplo:

  1. Salve o código em um arquivo index.php
  2. Coloque o arquivo em um servidor web com suporte a PHP (Apache, Nginx, etc.)
  3. Acesse os endpoints através do navegador ou ferramentas como Postman ou cURL

Testando a API

Você pode testar a API usando ferramentas como Postman, cURL ou qualquer cliente HTTP. Lembre-se de incluir o header X-Impulse-Key com o valor correto em todas as requisições.

Exemplo de requisição:

curl -X GET "http://seu-servidor.com/api/v2/categories" \
     -H "X-Impulse-Key: sua_api_key_aqui"