payted / payted-php
Official PHP SDK for Payted Payment Gateway - M-Pesa, Emola & Visa payments in Mozambique
dev-main
2026-02-02 06:49 UTC
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.0
Requires (Dev)
- mockery/mockery: ^1.5
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.0
This package is auto-updated.
Last update: 2026-03-02 07:01:32 UTC
README
SDK oficial PHP para integração com o gateway de pagamentos Payted - M-Pesa, Emola e Visa em Moçambique.
Instalação
composer require payted/payted-php
Configuração
Uso Directo
use Payted\Payted; $client = Payted::client('seu-api-token', [ 'base_url' => 'https://pay.ted.co.mz/api', // opcional 'timeout' => 60, // opcional, em segundos ]);
Laravel
O SDK inclui auto-discovery para Laravel. Após instalar, publique a configuração:
php artisan vendor:publish --tag=payted-config
Configure no seu .env:
PAYTED_API_TOKEN=seu-api-token PAYTED_WEBHOOK_SECRET=seu-webhook-secret PAYTED_APP_ID=1
Uso
Checkout (Redirect)
Para pagamentos onde o cliente é redirecionado para uma página de checkout:
use Payted\Payted; $client = Payted::client('seu-api-token'); $checkout = $client->checkout()->create([ 'app_id' => 1, 'valor_total' => 500.00, 'referencia_externa' => 'PEDIDO-123', 'itens' => [ [ 'nome' => 'Curso de PHP', 'quantidade' => 1, 'preco_unitario' => 500.00, ], ], 'return_url' => 'https://meusite.com/sucesso', 'cancel_url' => 'https://meusite.com/cancelado', ]); // Redirecionar o cliente header('Location: ' . $checkout->checkoutUrl); exit;
Débito Directo (Síncrono)
Para pagamentos sem redirect (ex: POS, subscrições):
$debit = $client->debit()->process([ 'app_id' => 1, 'valor_total' => 100.00, 'referencia_externa' => 'POS-456', 'metodo' => 'mpesa', // ou 'emola' 'numero_cliente' => '841234567', ]); if ($debit->isPaid()) { echo "Pagamento confirmado! ID: " . $debit->transacaoId; } else { echo "Pagamento falhou: " . $debit->erro; }
Consultar Status
// Por ID do pagamento $status = $client->debit()->status('TED12345678'); // Por referência externa $status = $client->debit()->statusByReference('PEDIDO-123'); if ($status->isPaid) { echo "Pagamento confirmado!"; } elseif ($status->isPending()) { echo "Aguardando confirmação..."; } else { echo "Pagamento falhou."; }
Webhooks
Valide webhooks recebidos do Payted:
use Payted\Webhook\WebhookValidator; $validator = new WebhookValidator('seu-webhook-secret'); try { $event = $validator->constructEvent( file_get_contents('php://input'), $_SERVER['HTTP_X_PAYTED_SIGNATURE'] ); if ($event->isPaymentCompleted()) { $referenciaExterna = $event->getReferenciaExterna(); $pagamentoId = $event->getPagamentoId(); // Processar pagamento confirmado // Actualizar pedido no banco de dados } if ($event->isPaymentFailed()) { // Processar falha de pagamento } http_response_code(200); echo json_encode(['received' => true]); } catch (\Payted\Exceptions\WebhookException $e) { http_response_code(400); echo json_encode(['error' => $e->getMessage()]); }
Laravel
Usando a Facade
use Payted\Laravel\PaytedFacade as Payted; // Checkout $checkout = Payted::checkout()->create([ 'app_id' => config('payted.app_id'), 'valor_total' => 500.00, 'referencia_externa' => 'PEDIDO-123', ]); return redirect($checkout->checkoutUrl);
Injeção de Dependência
use Payted\PaytedClient; class PaymentController extends Controller { public function __construct( private PaytedClient $payted ) {} public function checkout(Request $request) { $checkout = $this->payted->checkout()->create([ 'app_id' => config('payted.app_id'), 'valor_total' => $request->total, 'referencia_externa' => $request->order_id, ]); return redirect($checkout->checkoutUrl); } }
Webhook Controller
use Illuminate\Http\Request; use Payted\Webhook\WebhookValidator; use Payted\Exceptions\WebhookException; class WebhookController extends Controller { public function __construct( private WebhookValidator $validator ) {} public function handle(Request $request) { try { $event = $this->validator->constructEvent( $request->getContent(), $request->header('X-Payted-Signature') ); if ($event->isPaymentCompleted()) { // Marcar pedido como pago Order::where('reference', $event->getReferenciaExterna()) ->update(['status' => 'paid']); } return response()->json(['received' => true]); } catch (WebhookException $e) { return response()->json(['error' => $e->getMessage()], 400); } } }
Transações C2B (com Parceiro)
Para pagamentos com divisão entre a aplicação e um parceiro:
$checkout = $client->checkout()->create([ 'app_id' => 1, 'valor_total' => 1000.00, 'referencia_externa' => 'VENDA-789', // Dados do parceiro 'parceiro_nome' => 'Loja do João', 'parceiro_email' => 'joao@loja.com', 'parceiro_contacto' => '841234567', 'parceiro_tipo' => 'comerciante', // Divisão de receita 'percentagem_app' => 10, // 10% para a plataforma 'percentagem_parceiro' => 90, // 90% para o parceiro ]); echo "Tipo: " . $checkout->tipoTransacao; // C2B echo "Parceiro ID: " . $checkout->parceiroId;
Tratamento de Erros
use Payted\Exceptions\AuthenticationException; use Payted\Exceptions\ValidationException; use Payted\Exceptions\RateLimitException; use Payted\Exceptions\ApiException; try { $debit = $client->debit()->process([...]); } catch (AuthenticationException $e) { // Token inválido (401) echo "Erro de autenticação: " . $e->getMessage(); } catch (ValidationException $e) { // Dados inválidos (422) echo "Erros de validação:"; foreach ($e->getErrors() as $field => $errors) { echo "$field: " . implode(', ', $errors); } } catch (RateLimitException $e) { // Limite excedido (429) echo "Limite excedido. Tente novamente em " . $e->getRetryAfter() . " segundos."; } catch (ApiException $e) { // Erro do servidor echo "Erro da API: " . $e->getMessage(); }
Métodos de Pagamento
| Método | Código | Descrição |
|---|---|---|
| M-Pesa | mpesa |
Pagamento via M-Pesa |
| Emola | emola |
Pagamento via Emola |
| Visa | visa |
Pagamento via cartão Visa (apenas checkout) |
Requisitos
- PHP 8.1+
- Guzzle HTTP 7.0+
Suporte
- Email: dev@payted.co.mz
- Documentação: https://docs.payted.co.mz
Licença
MIT