Uma interface, 15+ gateways. Integre PIX, cartão, boleto e muito mais — troque de gateway mudando apenas 1 linha de código.
// ① 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 ✓
Brasileiros e internacionais. PIX, boleto, cartão, assinaturas, split — cada gateway com documentação própria.
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.
// 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);
ValueObjects validados, events, webhooks, antifraude — estrutura sólida sem abstrações desnecessárias.
| 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 | ✕ |
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');
FakeBankGateway durante o desenvolvimento e troque apenas o gateway ao ir para produção — toda a lógica de negócio permanece igual.O FakeBankGateway persiste tudo em arquivos JSON locais. Estrutura gerada automaticamente:
/storage/fakebank/
├── transactions.json
├── customers.json
├── tokens.json
├── wallets.json
├── subscriptions.json
├── sub_accounts.json
├── escrows.json
├── payment_links.json
├── refunds.json
└── transfers.json
$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.
$response = $hub->createPixPayment($pixRequest); $qrCodeId = $response->rawResponse['qrCodeId'] ?? null; $pixKey = $response->rawResponse['pixKey'] ?? null; // copia e cola $expireAt = $response->rawResponse['expireAt'] ?? null;
$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.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);
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);
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
DebitCardPaymentRequest não aceita installments, diferente do cartão de crédito.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);
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);
use IsraelNogueira\PaymentHub\DataObjects\Requests\PaymentLinkRequest; $request = new PaymentLinkRequest( amount: 99.90, description: 'Produto XYZ' ); $link = $hub->createPaymentLink($request); echo $link->linkId; // FAKE_LINK_abc echo $link->url; // URL pronta pra compartilhar echo $link->status;
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
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]);
$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']; }
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']]);
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);
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);
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);
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');
$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']);
// 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');
$wh = $hub->registerWebhook( url: 'https://meusite.com/webhook', events: ['payment.approved', 'payment.refunded'] ); $hub->listWebhooks(); $hub->deleteWebhook($wh['webhook_id']);
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 |
Um composer install e você já tem acesso a todos os gateways.
# terminal composer require israel-nogueira/payment-hub
$hub = new PaymentHub( new FakeBankGateway() ); $pix = $hub->createPixPayment( PixPaymentRequest::create( amount: 99.90, customerEmail: 'dev@local.com' ) );
// Só troca o gateway $hub = new PaymentHub( new AsaasGateway([ 'api_key' => $_ENV['ASAAS_KEY'], 'sandbox' => false, ]) ); // O resto? Igual. ✓
Código aberto, MIT License, documentação completa em português.