File: //var/www/payments-gateway/src/Service/PaymentService.php
<?php
// src/Service/PaymentService.php
namespace App\Service;
use App\Entity\Payment;
use App\Repository\PaymentRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class PaymentService
{
public function __construct(
private HttpClientInterface $httpClient,
private EntityManagerInterface $em,
private PaymentRepository $paymentRepository,
private string $apiUsername,
private string $apiSecret,
private string $accountName,
private string $apiUrl,
private string $hmacKey,
private string $notificationUrl
) {}
public function initiatePayment(array $data): array
{
$existing = $this->paymentRepository->find($data['order_reference']);
if ($existing && $existing->getStatus() !== 'completed') {
return ['payment_link' => $existing->getPaymentLink()];
}
$payload = [
'account_name' => $this->accountName,
'nonce' => uniqid('', true),
'timestamp' => gmdate('Y-m-d\TH:i:sO'),
'amount' => $data['amount'],
'order_reference' => $data['order_reference'],
'customer_url' => 'https://127.0.0.1',
'api_username' => $this->apiUsername,
];
$res = $this->httpClient->request('POST', $this->apiUrl, [
'headers' => [
'Authorization' => 'Basic ' . base64_encode($this->apiUsername . ':' . $this->apiSecret),
'Content-Type' => 'application/json'
],
'json' => $payload
]);
$result = $res->toArray();
$payment = new Payment();
$payment->setOrderReference($data['order_reference']);
$payment->setStudentId($data['student_id']);
$payment->setAmount($data['amount']);
$payment->setPaymentLink($result['payment_link']);
$payment->setStatus('pending');
$payment->setCreatedAt(new \DateTimeImmutable());
$this->em->persist($payment);
$this->em->flush();
return ['payment_link' => $result['payment_link']];
}
public function verifyHmac(string $body, ?string $signature): bool
{
if (!$signature) return false;
$expected = 'HMAC ' . base64_encode(hash_hmac('sha1', $body, $this->hmacKey, true));
return hash_equals($expected, $signature);
}
public function processWebhook(array $data): void
{
$orderRef = $data['payment_reference'] ?? null;
$status = $data['payment_state'] ?? null;
if (!$orderRef || !$status) return;
$payment = $this->paymentRepository->find($orderRef);
if ($payment) {
$payment->setStatus($status);
$payment->setPaidAt(new \DateTimeImmutable());
$this->em->flush();
}
}
public function getPaymentRepository(): PaymentRepository
{
return $this->paymentRepository;
}
}