12goyuriyr/symfony-mono-acquiring-bundle
Installation:
composer require 12goyuriyr/symfony-mono-acquiring-bundle
Ensure MonobankAcquiring\MonobankAcquiringBundle is registered in config/bundles.php.
Configuration:
Add your Monobank token to .env:
MONO_API_TOKEN=your_merchant_token_here
Create config/packages/monobank_acquiring.yaml:
monobank_acquiring:
api_token: '%env(MONO_API_TOKEN)%'
First Use Case:
Inject the MonobankAcquiringClientInterface into a service/controller:
use MonobankAcquiring\Client\MonobankAcquiringClientInterface;
class PaymentController {
public function __construct(
private MonobankAcquiringClientInterface $client
) {}
public function createInvoice(): void
{
$invoice = $this->client->createInvoice(
amount: 100.00,
currency: 'UAH',
description: 'Test payment',
orderId: 'order_123'
);
// Handle response (DTO object)
}
}
Payment Invoice Creation:
Use createInvoice() with required parameters (amount, currency, description, orderId).
$invoice = $client->createInvoice(
amount: 100.50,
currency: 'USD',
description: 'Product purchase',
orderId: 'order_456',
successUrl: '/payment/success',
failureUrl: '/payment/failure'
);
Invoice DTO with id, status, and other metadata.Status Checks:
Poll invoice status with getInvoice():
$invoice = $client->getInvoice('invoice_id_123');
if ($invoice->getStatus() === 'PAID') {
// Process payment
}
Currency Exchange Rates:
Fetch rates via getExchangeRates():
$rates = $client->getExchangeRates(['USD', 'EUR']);
// $rates['USD'] = 38.50 (example)
$client->getInvoice('invoice_id')->then(
fn(Invoice $invoice) => $bus->dispatch(new ProcessPayment($invoice))
);
$constraints = new Assert\Collection([
'amount' => new Assert\NotBlank(),
'currency' => new Assert\Choice(['UAH', 'USD', 'EUR']),
]);
$validator->validate($data, $constraints);
PAYMENT_PENDING):
use Symfony\Component\Retry\Retry;
Retry::create()
->withMaxAttempts(3)
->withDelay(1000)
->execute(fn() => $client->getInvoice($invoiceId));
Token Security:
MONO_API_TOKEN in config files. Use .env and restrict file permissions.Idempotency:
orderId for the same amount. Use UUIDs or timestamps for uniqueness:
$orderId = 'order_' . Str::uuid()->toString();
Rate Limits:
getExchangeRates() responses:
$cache = $container->get('monobank_acquiring.cache.exchange_rates');
$rates = $cache->get('rates', fn() => $client->getExchangeRates(['USD']));
Webhook Validation:
$signature = $_SERVER['HTTP_X_MONO_SIGNATURE'];
$expected = hash_hmac('sha256', $payload, $apiToken);
if (!hash_equals($signature, $expected)) {
throw new \RuntimeException('Invalid signature');
}
MONO_API_DEBUG=true in .env to log raw requests/responses to var/log/monobank_api.log.namespace App\DTO;
use MonobankAcquiring\DTO\Invoice as BaseInvoice;
class Invoice extends BaseInvoice {
public function getNewField(): ?string {
return $this->data['new_field'] ?? null;
}
}
Override the service in config/services.yaml:
MonobankAcquiring\Client\MonobankAcquiringClientInterface: '@app.monobank_acquiring.client'
Custom HTTP Client: Replace the default client by binding an interface:
# config/services.yaml
MonobankAcquiring\Client\MonobankAcquiringClientInterface: '@app.custom_monobank_client'
Example implementation:
class CustomMonobankClient implements MonobankAcquiringClientInterface {
public function createInvoice(float $amount, string $currency, string $description, string $orderId): Invoice {
// Add logging, retry logic, etc.
return $this->delegate->createInvoice($amount, $currency, $description, $orderId);
}
}
Event Listeners:
Dispatch events for critical actions (e.g., InvoiceCreatedEvent):
$event = new InvoiceCreatedEvent($invoice);
$dispatcher->dispatch($event);
Register in config/services.yaml:
services:
App\EventListener\MonobankListener:
tags:
- { name: kernel.event_listener, event: invoice.created, method: onInvoiceCreated }
How can I help you explore Laravel packages today?