PHP 8.3 · Type-safe · MIT License

Pagamentos PHP
sem dor de cabeça

Uma interface, 15+ gateways. Integre PIX, cartão, boleto e muito mais — troque de gateway mudando apenas 1 linha de código.

15+
gateways prontos
1
linha para trocar
0
setup sem API
100%
type-safe
payment.php
// ① Comece SEM precisar de API real
$hub = new PaymentHub(new FakeBankGateway());

// ② Crie o pagamento
$pix = $hub->createPixPayment(
    PixPaymentRequest::create(
        amount: 149.90,
        customerEmail: 'cliente@email.com',
        description: 'Pedido #1234'
    )
);

// ③ Troque para produção — só isso
$hub = new PaymentHub(new AsaasGateway($config));
// ↑ Todo o resto continua igual ✓
// gateways suportados

15+ gateways prontos para usar

Brasileiros e internacionais. PIX, boleto, cartão, assinaturas, split — cada gateway com documentação própria.

🧪 FakeBank dev
🟣 Asaas
🟡 Pagar.me
🟣 C6 Bank
💚 MercadoPago
🟠 PagSeguro
🔴 Adyen
🔵 Stripe
💙 PayPal
🌎 EBANX 7 países
🏦 Banco do Brasil
🏦 Itaú
🟣 NuBank
🏦 BofA CashPro
🟢 EtherGlobal PIX

FakeBankGateway
Desenvolva offline

Incluso na biblioteca. Simula todos os gateways sem internet, sem credenciais, sem sandbox. Desenvolva toda sua lógica localmente e conecte na API real só quando estiver pronto.

Offline
Sem API keys
Persistência JSON
PIX, Cartão, Boleto
Split & Escrow
Assinaturas
Sub-contas & Wallets
Testes automatizados
dev → produção
// DESENVOLVIMENTO (offline, sem credenciais)
$hub = new PaymentHub(new FakeBankGateway());

// PRODUÇÃO — mesma interface, só troca o gateway
$hub = new PaymentHub(new PagarMeGateway([
    'api_key' => $_ENV['PAGARME_KEY'],
]));

// O resto do código? Não muda nada. ✓
$pix = $hub->createPixPayment($request);
$sub = $hub->createSubscription($request);
$spl = $hub->createSplitPayment($request);
// funcionalidades

Tudo que você precisa,
nada que você não precisa

ValueObjects validados, events, webhooks, antifraude — estrutura sólida sem abstrações desnecessárias.

💰
ValueObjects Type-safe
Money, CPF, CNPJ, Email e CardNumber com validação automática. Zero string mágica perdida no código.
🔄
Split de Pagamento
Divida recebimentos entre múltiplos destinatários com regras customizáveis. Marketplace nativo.
🔁
Assinaturas & Recorrência
Criar, cancelar, suspender e reativar. Cobranças automáticas nos intervalos que você definir.
🔒
Escrow (Custódia)
Retenha fundos, libere parcial ou totalmente conforme regras de negócio. Cancelamento sem custo.
👛
Wallets & Sub-contas
Carteiras digitais, saldo, transferências entre wallets e gestão completa de sub-contas.
🛡️
Antifraude & Webhooks
Blacklist/whitelist, análise de risco, e webhooks padronizados com processor por gateway.
Events System
PaymentCreated, PaymentCompleted, PaymentFailed, PaymentRefunded — hooks para cada etapa.
🌎
Multi-país
EBANX cobre 7 países da América Latina. BofA CashPro para operações nos EUA via Zelle/ACH/Wire.
🎯
Pre-auth & Capture
Reserve o valor, capture depois. Suportado nos principais gateways de cartão.
// por que payment hub?

Integração direta vs Payment Hub

Característica Payment Hub Integração direta Outra lib
Trocar gateway 1 linha de código Reescrever tudo Parcial
Testar sem API ✓ FakeBankGateway
PHP 8.3 + Type hints ✓ 100% Depende Parcial
ValueObjects validados ✓ CPF, Money, Card…
Split nativo Por gateway
PIX + Boleto + Cartão ✓ Interface única APIs diferentes Parcial
Gateways bancários (BB, Itaú) Muito complexo

⚙️ Configuração

configuração básica
use IsraelNogueira\PaymentHub\PaymentHub;
use IsraelNogueira\PaymentHub\Gateways\FakeBank\FakeBankGateway;

// Sem persistência (memória)
$gateway = new FakeBankGateway();
$hub     = new PaymentHub($gateway);

// Com caminho customizado de storage
$gateway = new FakeBankGateway(storagePath: '/tmp/meus-testes');
💡 Use o FakeBankGateway durante o desenvolvimento e troque apenas o gateway ao ir para produção — toda a lógica de negócio permanece igual.

💾 Persistência de Dados

O FakeBankGateway persiste tudo em arquivos JSON locais. Estrutura gerada automaticamente:

estrutura de diretórios
/storage/fakebank/
├── transactions.json
├── customers.json
├── tokens.json
├── wallets.json
├── subscriptions.json
├── sub_accounts.json
├── escrows.json
├── payment_links.json
├── refunds.json
└── transfers.json
acesso direto ao storage
$storage = $gateway->getStorage();

$tx       = $storage->get('transactions', 'FAKE_PIX_abc');
$all      = $storage->getAll('customers');
$approved = $storage->find('transactions', ['status' => 'approved']);

$storage->clear('transactions'); // limpa um tipo
$storage->clearAll();             // limpa tudo

Em gateways reais (ex: EtherGlobalAssetsGateway) não existe storage local — os dados vêm direto do rawResponse de cada chamada.

rawResponse — PIX
$response = $hub->createPixPayment($pixRequest);

$qrCodeId = $response->rawResponse['qrCodeId'] ?? null;
$pixKey   = $response->rawResponse['pixKey']   ?? null; // copia e cola
$expireAt = $response->rawResponse['expireAt'] ?? null;
rawResponse — saldo e transferência
$balance = $hub->getBalance();
echo $balance->balance;          // saldo total
echo $balance->availableBalance; // disponível
echo $balance->pendingBalance;   // pendente

$transfer = $hub->transfer($transferRequest);

$pixId      = $transfer->rawResponse['pixId']      ?? null;
$e2e        = $transfer->rawResponse['e2e']        ?? null; // ID end-to-end do Bacen
$executedAt = $transfer->rawResponse['executedAt'] ?? null;
💡 rawResponse varia por gateway — sempre use ?? pra acessar campos que não são padronizados na interface comum.

💳 PIX

criar pagamento PIX
use IsraelNogueira\PaymentHub\DataObjects\Requests\PixPaymentRequest;

$request = PixPaymentRequest::create(
    amount:           100.00,
    customerName:     'João Silva',
    customerEmail:    'joao@teste.com',
    customerDocument: '12345678900',
    description:      'Pedido #1234'
);

$response = $hub->createPixPayment($request);

echo $response->transactionId; // FAKE_PIX_xyz789
echo $response->status->value; // 'approved'

// QR Code e Copia e Cola
$qr  = $hub->getPixQrCode($response->transactionId);
$txt = $hub->getPixCopyPaste($response->transactionId);

💳 Cartão de Crédito

criar pagamento
use IsraelNogueira\PaymentHub\DataObjects\Requests\CreditCardPaymentRequest;

$request = CreditCardPaymentRequest::create(
    amount:           250.00,
    installments:     3,
    cardNumber:       '4111111111111111',
    cardHolderName:   'JOAO SILVA',
    cardExpiryMonth:  '12',
    cardExpiryYear:   '2028',
    cardCvv:          '123',
    customerEmail:    'joao@teste.com',
    customerDocument: '12345678900'
);

$response = $hub->createCreditCardPayment($request);

// Tokenizar cartão
$token = $hub->tokenizeCard(['number' => '4111...', 'holderName' => 'JOAO', ...]);

// Pre-autorização
$hub->capturePreAuthorization($transactionId);         // total
$hub->capturePreAuthorization($transactionId, 100.00); // parcial
$hub->cancelPreAuthorization($transactionId);

💳 Cartão de Débito

criar pagamento
use IsraelNogueira\PaymentHub\DataObjects\Requests\DebitCardPaymentRequest;

$request = DebitCardPaymentRequest::create(
    amount:           89.90,
    cardNumber:       '5555555555554444',
    cardHolderName:   'MARIA SILVA',
    cardExpiryMonth:  '08',
    cardExpiryYear:   '2027',
    cardCvv:          '321',
    customerEmail:    'maria@teste.com',
    customerDocument: '12345678900'
);

$response = $hub->createDebitCardPayment($request);

echo $response->transactionId; // FAKE_DC_xyz789
echo $response->rawResponse['card_brand']; // mastercard
💡 Sem parcelamento — DebitCardPaymentRequest não aceita installments, diferente do cartão de crédito.

🧾 Boleto

criar boleto
use IsraelNogueira\PaymentHub\DataObjects\Requests\BoletoPaymentRequest;

$request = BoletoPaymentRequest::create(
    amount:           150.00,
    customerName:     'João Silva',
    customerDocument: '12345678900',
    customerEmail:    'joao@teste.com',
    dueDate:          '2025-03-15',
    description:      'Mensalidade março'
);

$response = $hub->createBoleto($request);

$url = $hub->getBoletoUrl($response->transactionId);
$hub->cancelBoleto($response->transactionId);

🔀 Split de Pagamento

dividir recebimento
use IsraelNogueira\PaymentHub\DataObjects\Requests\SplitPaymentRequest;

$request = new SplitPaymentRequest(
    amount: 1000.00,
    splits: [
        ['account_id' => 'FAKE_ACC_1', 'percentage' => 70],
        ['account_id' => 'FAKE_ACC_2', 'percentage' => 30],
    ]
);

$response = $hub->createSplitPayment($request);

👥 Clientes

CRUD de clientes
use IsraelNogueira\PaymentHub\DataObjects\Requests\CustomerRequest;

$customer = $hub->createCustomer(new CustomerRequest(
    name:           'João Silva',
    email:          'joao@teste.com',
    documentNumber: '12345678900',
    phone:          '11999999999'
));

$hub->getCustomer($customer->customerId);
$hub->updateCustomer($customer->customerId, ['email' => 'novo@teste.com']);
$hub->listCustomers(); // array com todos

🔁 Assinaturas

gerenciar assinaturas
use IsraelNogueira\PaymentHub\DataObjects\Requests\SubscriptionRequest;

$request = SubscriptionRequest::create(
    amount:      49.90,
    interval:    'monthly',
    customerId:  'FAKE_CUSTOMER_abc',
    cardToken:   'FAKE_TOKEN_xyz',
    description: 'Plano Premium'
);

$sub = $hub->createSubscription($request);

$hub->cancelSubscription($sub->subscriptionId);
$hub->suspendSubscription($sub->subscriptionId);
$hub->reactivateSubscription($sub->subscriptionId);
$hub->updateSubscription($sub->subscriptionId, ['value' => 59.90]);

📊 Transações

consultar e listar
$status = $hub->getTransactionStatus('FAKE_PIX_abc');
echo $status->status->label();

// Lista todas as transações
$transactions = $hub->listTransactions();

foreach ($transactions as $txn) {
    echo $txn['id'] . ' - ' . $txn['status'];
}

💰 Estornos

estorno total e parcial
use IsraelNogueira\PaymentHub\DataObjects\Requests\RefundRequest;

// Estorno total
$request  = RefundRequest::create(transactionId: 'FAKE_CC_abc', reason: 'Solicitado');
$response = $hub->refund($request);

// Estorno parcial
$response = $hub->partialRefund('FAKE_CC_abc', 50.00);

// Chargeback
$hub->getChargebacks(['status' => 'pending']);
$hub->disputeChargeback('FAKE_CB_abc', ['evidence' => ['nota.pdf']]);

👛 Wallets

carteiras digitais
use IsraelNogueira\PaymentHub\DataObjects\Requests\WalletRequest;

$wallet = $hub->createWallet(new WalletRequest(customerId: 'FAKE_CUST_abc'));
$id     = $wallet->walletId; // FAKE_WALLET_xyz

$hub->addBalance($id, 100.00);
$hub->deductBalance($id, 30.00);

$balance = $hub->getWalletBalance($id);
echo "R$ " . $balance->balance;

// Transferência entre wallets
$hub->transferBetweenWallets('FAKE_WALLET_1', 'FAKE_WALLET_2', 75.00);

🏢 Sub-contas

marketplace / multi-tenant
use IsraelNogueira\PaymentHub\DataObjects\Requests\SubAccountRequest;

$sub = $hub->createSubAccount(new SubAccountRequest(
    name:           'Vendedor Teste',
    email:          'vendedor@teste.com',
    documentNumber: '12345678900'
));

$hub->getSubAccount($sub->subAccountId);
$hub->updateSubAccount($sub->subAccountId, ['email' => 'novo@teste.com']);
$hub->activateSubAccount($sub->subAccountId);
$hub->deactivateSubAccount($sub->subAccountId);

🔒 Escrow (Custódia)

custódia de fundos
use IsraelNogueira\PaymentHub\DataObjects\Requests\EscrowRequest;

$escrow = $hub->holdInEscrow(new EscrowRequest(
    transactionId: 'FAKE_CC_abc', amount: 500.00
));

$hub->releaseEscrow($escrow->escrowId);
$hub->partialReleaseEscrow($escrow->escrowId, 200.00);
$hub->cancelEscrow($escrow->escrowId);

💸 Transferências

transferir fundos
use IsraelNogueira\PaymentHub\DataObjects\Requests\TransferRequest;
use IsraelNogueira\PaymentHub\ValueObjects\Money;
use IsraelNogueira\PaymentHub\Enums\Currency;

$request = new TransferRequest(
    money:       Money::from(500.00, Currency::BRL),
    description: 'Repasse marketplace',
    metadata:    ['pix_key' => 'cnpj@empresa.com']
);

$hub->transfer($request);
$hub->scheduleTransfer($request, '2025-03-15');
$hub->cancelScheduledTransfer('FAKE_TRANSFER_abc');

💰 Saldo e Conciliação

consultar saldo
$balance = $hub->getBalance();
echo "R$ " . $balance->balance;          // 10000.00 padrão
echo "R$ " . $balance->availableBalance;

// Agenda de liquidação
$schedule = $hub->getSettlementSchedule(['date_from' => '2025-01-01']);

// Antecipação de recebíveis
$hub->anticipateReceivables(['FAKE_PIX_abc', 'FAKE_CC_xyz']);

🛡️ Antifraude

análise e blacklist
// Análise retorna risk_score aleatório (1-100)
$analysis = $hub->analyzeTransaction('FAKE_CC_abc');
// ['risk_score' => 42, 'status' => 'approved', 'recommendation' => 'approve']

$hub->addToBlacklist('12345678900', 'cpf');
$hub->removeFromBlacklist('12345678900', 'cpf');

🔔 Webhooks

registrar e gerenciar webhooks
$wh = $hub->registerWebhook(
    url:    'https://meusite.com/webhook',
    events: ['payment.approved', 'payment.refunded']
);

$hub->listWebhooks();
$hub->deleteWebhook($wh['webhook_id']);

🎲 Cartões de Teste

Use estes números no FakeBankGateway para simular aprovação ou recusa:

Número Status Bandeira Motivo
4111 1111 1111 1111 ✓ Aprovado Visa Cartão válido padrão
4111 1111 1111 1112 ✕ Recusado Visa Saldo insuficiente
5555 5555 5555 4444 ✕ Recusado Mastercard Cartão bloqueado
0000 0000 0000 0000 ✕ Recusado Cartão inválido
⚠️ O FakeBankGateway é apenas para testes. Nunca use em produção. Não valida CPF, cartões reais ou envia webhooks de verdade.

📮 Postman Collection

O repositório inclui uma collection completa do Postman cobrindo todos os endpoints da API, mais 2 environments prontos (Dev/Prod) e 5 exemplos de webhooks recebidos. Não é necessária para usar a lib — instale via Composer normalmente — mas ajuda a explorar o contrato de cada gateway antes de integrar.

Grupo Endpoints Exemplos
PIX 3 criar, QR Code, copia e cola
Cartão de Crédito 5 criar, tokenizar, pré-autorização, captura, cancelamento
Boleto 3 criar, obter URL, cancelar
Assinaturas 4 criar, cancelar, suspender, reativar
Estornos 2 total, parcial
Transações 2 consultar status, listar
Split de Pagamento 1 dividir recebimento
Sub-contas 4 criar, obter, ativar, desativar
Wallets 5 criar, saldo, add/subtrair, transferir entre wallets
Escrow 4 reter, liberar total/parcial, cancelar
Links de Pagamento 3 criar, obter, expirar
Clientes 4 criar, obter, atualizar, listar
Webhooks 3 registrar, listar, remover
Saldo 1 consultar saldo
Webhook Samples (Incoming) 5 payment.approved, declined, refund, subscription, chargeback
environments disponíveis
// Development
BASE_URL     = 'http://localhost:8000/api/v1'
API_KEY      = 'your-dev-api-key-here'

// Production
BASE_URL     = 'https://api.payment-hub.com/v1'
API_KEY      = 'your-production-api-key-here'

// Variáveis compartilhadas: TRANSACTION_ID, CUSTOMER_ID, CARD_TOKEN,
// SUBSCRIPTION_ID, WALLET_ID, YOUR_WEBHOOK_URL

🔔 Webhook Handlers

A seção Webhooks mostra como registrar uma URL via API. Já os Webhook Handlers abaixo são classes dedicadas para processar os eventos recebidos de bancos específicos — cada um com o próprio esquema de autenticação e formato de payload.

BancoDoBrasilWebhookHandler — token fixo
// BB não usa HMAC. Autentica via token fixo no header
// x-webhook-token (PIX) ou Authorization: Bearer (Cobrança)
$handler = new BancoDoBrasilWebhookHandler(
    webhookToken:  $_ENV['BB_WEBHOOK_TOKEN'],
    validateToken: true
);

$handler->onPixRecebido(function (array $event) {
    // $event['txid'], $event['endToEndId'], $event['valor'], $event['pagador']
    Orders::confirm($event['txid'], $event['valor']);
});

$handler->onBoletoLiquidado(function (array $event) {
    Orders::markPaid($event['nossoNumero']);
});

$handler->onUnknownEvent(fn($e) => Log::warning('BB evento desconhecido', $e));

// Endpoint do webhook:
$result = $handler->handle(); // lê php://input + getallheaders()
$handler->respondOk($result); // HTTP 200 rápido (fastcgi_finish_request)
BofACashProWebhookHandler — HMAC-SHA256 + IP whitelist
// BofA assina o body bruto com HMAC-SHA256 (header X-BofA-Signature)
// e pode validar IP de origem como camada extra
$handler = new BofACashProWebhookHandler(
    webhookSecret: $_ENV['BOFA_WEBHOOK_SECRET'],
    validateIp:    true,
    allowedIps:    ['198.51.100.10', '198.51.100.11']
);

$handler->onPaymentReceived(function (array $event) {
    // $event['paymentType']: ZELLE | ACH_SAME_DAY | ACH_STANDARD | WIRE
    // $event['amount'], $event['senderEmail'], $event['memo']...
    Ledger::credit($event['accountId'], $event['amount']);
});

$handler->on(BofACashProWebhookHandler::EVENT_PAYMENT_FAILED, fn($e) =>
    Log::warning('Pagamento falhou', ['id' => $e['paymentId']]));

$result = $handler->handle();
$handler->respondOk($result);
Handler Autenticação Eventos Idempotência
BancoDoBrasilWebhookHandler Token fixo (header, hash_equals) PIX recebido/devolvido, Boleto liquidado/vencido/baixado txid / nossoNumero
BofACashProWebhookHandler HMAC-SHA256 + IP whitelist opcional Payment received/sent/failed/returned/cancelled, saldo baixo, extrato eventId
⚠️ Ambos os handlers esperam responder HTTP 200 em até 10s. Use respondOk() logo após handle() e processe lógica pesada de forma assíncrona (fila/job) para evitar reenvios do banco.

🧪 Testes Automatizados

150+ testes unitários e de integração garantindo qualidade em cada gateway.

Gateway Testes Cobertura
Banco do Brasil 50+ ⭐⭐⭐⭐⭐
BofA CashPro 40+ ⭐⭐⭐⭐⭐
Itaú 30+ ⭐⭐⭐⭐

🔐 Certificados mTLS

Banco do Brasil e Itaú exigem certificados ICP-Brasil em produção.

$gateway = new ItauGateway(
    clientId:     $_ENV['ITAU_CLIENT_ID'],
    clientSecret: $_ENV['ITAU_CLIENT_SECRET'],
    sandbox:      false,
    certPath:     '/certs/itau-prod.pfx',
    certPassword: $_ENV['ITAU_CERT_PASSWORD']
);

🚨 Exceções Específicas

InvalidAmountException
InvalidCardNumberException
InvalidDocumentException
InvalidEmailException
GatewayException

Pronto em 30 segundos

Um composer install e você já tem acesso a todos os gateways.

01Instalar via Composer
# terminal
composer require
  israel-nogueira/payment-hub
02Teste sem API real
$hub = new PaymentHub(
  new FakeBankGateway()
);

$pix = $hub->createPixPayment(
  PixPaymentRequest::create(
    amount: 99.90,
    customerEmail:
      'dev@local.com'
  )
);
03Vai para produção
// Só troca o gateway
$hub = new PaymentHub(
  new AsaasGateway([
    'api_key' =>
      $_ENV['ASAAS_KEY'],
    'sandbox' => false,
  ])
);
// O resto? Igual. ✓

Sua próxima integração
de pagamento já deveria estar pronta

Código aberto, MIT License, documentação completa em português.