Installation Add the bundle via Composer:
composer require dbp/relay-mono-bundle
Enable it in config/bundles.php:
return [
// ...
DigitalBlueprint\RelayMonoBundle\RelayMonoBundle::class => ['all' => true],
];
Configuration Publish the default config:
php bin/console dbp:relay-mono:config:init
Update config/packages/relay_mono.yaml with your Relay API credentials (e.g., relay_mono.api_key, relay_mono.endpoint).
First Use Case Trigger a payment via a Symfony controller:
use DigitalBlueprint\RelayMonoBundle\Service\PaymentService;
class PaymentController extends AbstractController
{
public function createPayment(PaymentService $paymentService): Response
{
$payment = $paymentService->createPayment([
'amount' => 1000, // cents
'currency' => 'EUR',
'description' => 'Order #123',
'customer_email' => 'user@example.com',
]);
return $this->json($payment);
}
}
Payment Processing
PaymentService for one-time or subscription payments.
$payment = $paymentService->createPayment($data);
RelayMonoWebhookSubscriber to listen for async events:
use DigitalBlueprint\RelayMonoBundle\Event\WebhookEvent;
public function onWebhook(WebhookEvent $event) {
$payload = $event->getPayload();
// Process payment status updates (e.g., 'paid', 'failed')
}
Register in services.yaml:
services:
App\EventListener\RelayWebhookListener:
tags:
- { name: kernel.event_subscriber }
Refunds and Captures
Use RefundService and CaptureService:
$refund = $refundService->createRefund($paymentId, ['amount' => 500]);
$capture = $captureService->capturePayment($paymentId);
Idempotency
Leverage the idempotency_key in API calls to avoid duplicate processing:
$paymentService->createPayment($data, 'unique-key-123');
$builder->add('amount', MoneyType::class, [
'currency' => 'EUR',
'scale' => 2,
]);
/**
* @ORM\Entity
*/
class Order {
#[ORM\Column(type: 'string', unique: true)]
private string $relayPaymentId;
}
RelayMonoClient mock in tests:
$client = $this->createMock(RelayMonoClient::class);
$client->method('createPayment')->willReturn(['id' => 'test-payment']);
$this->container->set(RelayMonoClient::class, $client);
API Key Management
parameter_bag for secrets:
# config/packages/relay_mono.yaml
relay_mono:
api_key: '%env(RELAY_MONO_API_KEY)%'
dbp:relay-mono:config:update after generation.Webhook Verification
WebhookEvent:
if (!$event->isSignatureValid()) {
throw new \RuntimeException('Invalid webhook signature');
}
Idempotency Keys
$key = Str::uuid()->toString();
Currency/Amount Handling
if ($data['amount'] % 1 !== 0) {
throw new \InvalidArgumentException('Amount must be in cents');
}
Logs: Enable debug mode in relay_mono.yaml:
relay_mono:
debug: true
Logs will appear in var/log/dev.log.
HTTP Client: Inspect raw API calls with:
bin/console debug:container | grep relay_mono.http_client
Override the client in tests to mock responses.
Custom Payment Methods
Extend RelayMonoBundle\Service\PaymentService to add logic (e.g., fraud checks):
class CustomPaymentService extends PaymentService {
public function createPayment(array $data, ?string $idempotencyKey = null): array {
$this->validateForFraud($data);
return parent::createPayment($data, $idempotencyKey);
}
}
Event Dispatching Trigger Symfony events for Relay callbacks:
$dispatcher->dispatch(new PaymentEvent($paymentData));
Database Sync Use Doctrine lifecycle callbacks to sync Relay data:
#[ORM\PrePersist]
public function setRelayPaymentId(): void {
$this->relayPaymentId = $this->paymentService->getPaymentId();
}
relay_mono:
endpoint: '%env(RELAY_MONO_ENDPOINT)%' # e.g., 'https://api.relay-staging.com'
config/packages/relay_mono.yaml:
relay_mono:
http_client:
timeout: 30
How can I help you explore Laravel packages today?