andrepayone/payone-symfony-bundle
Install the Bundle
composer require andrepayone/payone-symfony-bundle
Enable the bundle in config/bundles.php:
return [
// ...
Andrepayone\PayoneBundle\PayoneBundle::class => ['all' => true],
];
Configure PAYONE
Add your credentials to config/packages/payone.yaml:
payone:
merchant_id: '%env(PAYONE_MERCHANT_ID)%'
secret_key: '%env(PAYONE_SECRET_KEY)%'
endpoint: '%env(PAYONE_ENDPOINT)%' # e.g., 'https://payone.com/api/v1'
First Use Case: Create a Payment
Use the PayoneClient service to initiate a payment:
use Andrepayone\PayoneBundle\Service\PayoneClient;
class PaymentController extends AbstractController
{
public function createPayment(PayoneClient $payoneClient): Response
{
$payment = $payoneClient->createPayment([
'amount' => 10.00,
'currency' => 'EUR',
'order_id' => 'order_123',
'description' => 'Test payment',
'success_url' => $this->generateUrl('payment_success'),
'fail_url' => $this->generateUrl('payment_fail'),
]);
return $this->redirect($payment->getRedirectUrl());
}
}
Verify Callback Handling
Ensure your payment_success and payment_fail routes handle the PAYONE callback parameters (e.g., payone_transaction_id, payone_status).
Initiate Payment
Use PayoneClient::createPayment() to generate a payment request. The SDK returns a redirect URL for the customer.
Handle Callback
After payment, PAYONE redirects to your success_url or fail_url. Validate the callback using:
$payoneClient->validateCallback($request);
This ensures the request is legitimate (e.g., checks payone_signature).
Process Asynchronous Notifications PAYONE sends webhook notifications for status updates. Create a route to handle these:
# config/routes.yaml
payone_webhook:
path: /payone/webhook
controller: App\Controller\PayoneWebhookController::handleWebhook
Validate and process the notification:
public function handleWebhook(Request $request, PayoneClient $payoneClient): Response
{
if ($payoneClient->validateWebhook($request)) {
$notification = $payoneClient->processWebhook($request);
// Update your database or trigger logic based on $notification.
}
return new Response('OK');
}
HttpFoundation components via Laravel’s Symfony\Contracts\HttpClient or Guzzle for HTTP requests if needed.payone_transaction_id in your orders table to link payments to orders.\Monolog\Logger::getInstance()->info('PAYONE Webhook', ['data' => $request->getContent()]);
endpoint: 'https://sandbox.payone.com/api/v1') and mock the PayoneClient in tests:
$this->mock(PayoneClient::class)->shouldReceive('createPayment')->andReturn(new PaymentResponse('https://sandbox.payone.com/redirect'));
Callback Validation
validateCallback() or validateWebhook() exposes your app to fraudulent requests.Idempotency
payone_transaction_id exists in your DB before acting).Endpoint Configuration
payone:
endpoint: '%env(PAYONE_ENDPOINT)%'
Ensure PAYONE_ENDPOINT is set correctly in .env.Currency/Amount Formatting
1000 for €10.00). Passing floats (e.g., 10.00) may fail.$amount = 1000; // Not 10.00
Timeouts
$client = new \GuzzleHttp\Client(['timeout' => 30]);
payone-sdk to log requests/responses:
payone:
debug: true # Adds logging to Symfony's logger
Content-Type: application/json is set for API calls.Custom Payment Methods
Extend the bundle by creating a custom service that wraps PayoneClient for your business logic:
class CustomPayoneService
{
public function __construct(private PayoneClient $payoneClient) {}
public function createSubscription(float $amount, string $customerId): PaymentResponse
{
return $this->payoneClient->createPayment([
'amount' => $amount * 100,
'currency' => 'EUR',
'order_id' => "sub_$customerId",
'subscription' => true,
// ...
]);
}
}
Event Dispatching
Trigger Symfony events (e.g., kernel.event_dispatcher) after successful payments:
$dispatcher->dispatch(new PaymentSucceededEvent($notification));
Listen to events in your controllers or services.
Queue Webhooks Offload webhook processing to a queue (e.g., Laravel Queues) to avoid timeouts:
public function handleWebhook(Request $request): Response
{
if ($payoneClient->validateWebhook($request)) {
ProcessWebhookJob::dispatch($request->getContent());
}
return new Response('OK');
}
How can I help you explore Laravel packages today?