To accept Paystack payments in Symfony, inject the HttpClientInterface, create a PaystackService that wraps API calls, and build controllers for initialization and callback handling. Use environment variables for your secret key and verify every transaction server-side.
Add your Paystack keys to .env:
PAYSTACK_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxx
Bind it as a parameter in config/services.yaml:
parameters:
paystack_secret_key: '%env(PAYSTACK_SECRET_KEY)%'
// src/Service/PaystackService.php
namespace App\Service;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class PaystackService
{
private HttpClientInterface $client;
private string $secretKey;
public function __construct(HttpClientInterface $client, string $paystackSecretKey)
{
$this->client = $client;
$this->secretKey = $paystackSecretKey;
}
public function initializeTransaction(string $email, int $amountKobo, string $reference, string $callbackUrl): array
{
$response = $this->client->request('POST', 'https://api.paystack.co/transaction/initialize', [
'headers' => [
'Authorization' => 'Bearer ' . $this->secretKey,
'Content-Type' => 'application/json',
],
'json' => [
'email' => $email,
'amount' => $amountKobo,
'reference' => $reference,
'callback_url' => $callbackUrl,
],
]);
return $response->toArray();
}
public function verifyTransaction(string $reference): array
{
$response = $this->client->request('GET', 'https://api.paystack.co/transaction/verify/' . $reference, [
'headers' => [
'Authorization' => 'Bearer ' . $this->secretKey,
],
]);
return $response->toArray();
}
}
Get weekly developer tips
Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.
No spam. Unsubscribe anytime.
// src/Controller/PaymentController.php
namespace App\Controller;
use App\Service\PaystackService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Uid\Uuid;
class PaymentController extends AbstractController
{
#[Route('/pay', methods: ['POST'])]
public function initialize(Request $request, PaystackService $paystack): Response
{
$email = $request->request->get('email');
$amount = (int) ($request->request->get('amount', 5000) * 100);
$reference = 'order_' . Uuid::v4()->toRfc4122();
// TODO: Save order to database
$result = $paystack->initializeTransaction(
$email, $amount, $reference,
$this->generateUrl('payment_callback', [], 0)
);
if ($result['status'] ?? false) {
return $this->redirect($result['data']['authorization_url']);
}
return new Response('Failed: ' . ($result['message'] ?? 'Unknown'), 400);
}
#[Route('/payment/callback', name: 'payment_callback')]
public function callback(Request $request, PaystackService $paystack): Response
{
$reference = $request->query->get('reference') ?? $request->query->get('trxref');
if (!$reference) {
return new Response('Missing reference', 400);
}
$result = $paystack->verifyTransaction($reference);
if (($result['status'] ?? false) && $result['data']['status'] === 'success') {
// TODO: Verify amount, mark order as paid
return $this->render('payment/success.html.twig', ['reference' => $reference]);
}
return $this->render('payment/failed.html.twig');
}
}
# config/services.yaml
services:
App\Service\PaystackService:
arguments:
$paystackSecretKey: '%paystack_secret_key%'
KES 2,999
The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.
Start Paystack Course