Callbacks
Process webhook notifications with built-in signature verification.
The Callbacks facade handles webhook signature verification and payload processing.
Overview​
When a payment status changes, Paysera sends a webhook to your callback URL. The SDK provides tools to:
- Verify the webhook signature
- Parse the payload into typed objects
- Extract payment information
Recommended Usage​
Use processPaymentCallback() for combined verification and parsing:
<?php
use Paysera\CheckoutSdk\SdkFacadeBuilder;
use Paysera\CheckoutSdk\Exception\IntegrationException;
use Psr\Http\Message\ServerRequestInterface;
// Your webhook endpoint
function handleWebhook(ServerRequestInterface $request): void
{
$sdk = (new SdkFacadeBuilder())->build();
$callbacksFacade = $sdk->getCallbacksFacade();
try {
// Verify signature and parse payload
$callback = $callbacksFacade->processPaymentCallback($request);
// Extract event information
$eventName = $callback->getEvent()->getName();
$eventType = $callback->getEvent()->getType();
// Extract order information
$order = $callback->getOrder();
$orderId = $order->getId();
$status = $order->getOrderInfo()->getStatus();
$amount = $order->getOrderInfo()->getAmount();
$currency = $order->getOrderInfo()->getCurrency();
// Get your reference
$reference = $order->getMerchantData()['reference'];
// Process based on order status
$status = $order->getOrderInfo()->getStatus();
if ($order->getOrderInfo()->isPaid()) {
handlePaymentCompleted($reference, $order);
} else {
handleOrderUpdated($reference, $order, $status);
}
// Return success response
http_response_code(200);
echo $callbacksFacade->getCallbackResponseSuccessMessage();
} catch (IntegrationException $e) {
// Signature verification failed
error_log('Webhook verification failed: ' . $e->getMessage());
http_response_code(401);
}
}
Callback Object Structure​
$callback = $callbacksFacade->processPaymentCallback($request);
// Event information
$event = $callback->getEvent();
$eventName = $event->getName(); // e.g., 'order.amount_paid_updated'
$eventType = $event->getType(); // e.g., 'order'
// Order information
$order = $callback->getOrder();
$orderId = $order->getId();
// Order info (status, amount)
$orderInfo = $order->getOrderInfo();
$status = $orderInfo->getStatus(); // e.g., 'paid'
$amount = $orderInfo->getAmount(); // int (cents), e.g., 2500
$amountPaid = $orderInfo->getAmountPaid(); // int (cents)
$currency = $orderInfo->getCurrency(); // 'EUR'
$isPaid = $orderInfo->isPaid(); // bool - checks if status is 'paid'
// Merchant data (your reference) - MerchantData implements ArrayAccess
$merchantData = $order->getMerchantData();
$reference = $merchantData['reference']; // 'ORDER-12345'
// Payment links used
$paymentLinks = $order->getPaymentLinkCollection();
foreach ($paymentLinks as $link) {
$linkId = $link->getId();
$linkName = $link->getName();
$payerInfo = $link->getPayerInfo();
$payments = $link->getPayments(); // PaymentCollection
}
Manual Verification (Advanced)​
For more control, verify and parse separately:
Step 1: Verify Signature​
try {
$callbacksFacade->verifyCallbackRequest($request);
// Signature is valid
} catch (IntegrationException $e) {
// Signature verification failed
http_response_code(401);
exit;
}
Step 2: Parse Payload​
// After verification
$callback = $callbacksFacade->buildPaymentCallback($request);
// Process callback...
Step 3: Extract Headers (Optional)​
$headers = $callbacksFacade->getCallbackRequestHeaders($request);
// Access custom header information
Response Codes​
The SDK provides constants for response codes:
// Success code (200)
$successCode = $callbacksFacade->getCallbackResponseSuccessCode();
// Verification failed code (401)
$failedCode = $callbacksFacade->getCallbackResponseVerificationFailedCode();
// Success message
$successMessage = $callbacksFacade->getCallbackResponseSuccessMessage();
Complete Handler Example​
<?php
namespace App\Http\Controllers;
use Paysera\CheckoutSdk\SdkFacade;
use Paysera\CheckoutSdk\Exception\IntegrationException;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
class PayseraWebhookController
{
private SdkFacade $sdk;
private OrderRepository $orders;
public function __construct(SdkFacade $sdk, OrderRepository $orders)
{
$this->sdk = $sdk;
$this->orders = $orders;
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$callbacksFacade = $this->sdk->getCallbacksFacade();
try {
$callback = $callbacksFacade->processPaymentCallback($request);
$eventName = $callback->getEvent()->getName();
$reference = $callback->getOrder()->getMerchantData()['reference'];
$status = $callback->getOrder()->getOrderInfo()->getStatus();
// Find local order
$order = $this->orders->findByReference($reference);
if (!$order) {
error_log("Order not found: $reference");
return $this->successResponse($callbacksFacade);
}
// Idempotency check
if ($order->paysera_status === $status) {
return $this->successResponse($callbacksFacade);
}
// Handle based on order status
if ($callback->getOrder()->getOrderInfo()->isPaid()) {
$this->handleCompleted($order, $callback);
} else {
$this->handleStatusUpdate($order, $callback);
}
return $this->successResponse($callbacksFacade);
} catch (IntegrationException $e) {
error_log('Webhook verification failed: ' . $e->getMessage());
return response('Verification failed', 401);
}
}
private function handleCompleted($order, $callback): void
{
$order->status = 'paid';
$order->paysera_status = 'completed';
$order->paid_at = now();
$order->save();
// Trigger fulfillment
event(new OrderPaid($order));
}
private function handleStatusUpdate($order, $callback): void
{
$status = $callback->getOrder()->getOrderInfo()->getStatus();
$order->paysera_status = $status;
$order->save();
}
private function successResponse($callbacksFacade): ResponseInterface
{
return response(
$callbacksFacade->getCallbackResponseSuccessMessage(),
$callbacksFacade->getCallbackResponseSuccessCode()
);
}
}