<?php
namespace App\Web;
use App\Entity\Branch;
use App\Entity\MpesaAuth;
use App\Entity\MpesaManual;
use App\Entity\MpesaTransaction;
use App\Entity\MpesaTransactionVerification;
use App\Entity\User;
use App\Entity\UserBranch;
use App\Form\MpesaManualIDType;
use App\Form\MpesaManualTransactionType;
use App\Form\MpesaManualType;
use App\Service\MpesaVerifyService;
use DateTime;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\ObjectManager;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerBuilder;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpClient\Exception\ClientException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class MpesaHomeController extends AbstractController
{
private ObjectManager $em;
private MpesaVerifyService $verifyService;
private LoggerInterface $logger;
private HttpClientInterface $client;
public function __construct(ManagerRegistry $managerRegistry, MpesaVerifyService $verifyService, LoggerInterface $logger, HttpClientInterface $client)
{
$this->em = $managerRegistry->getManager();
$this->verifyService = $verifyService;
$this->logger = $logger;
$this->client = $client;
}
/**
* @Route("/mpesa", name="mpesaHomeRoute")
* @param Request $request
* @return Response
*/
public function mpesaHomeAction(Request $request)
{
return $this->render('mpesa/mpesa_home.html.twig', [
]);
}
/**
* @Route("/mpesa/testing", name="mpesaHomeRoute0")
* @param Request $request
*/
public function mpesaTestingAction(Request $request): Response
{
/* $jsonData = $request->getContent();
$result = $jsonData['Result'];
$resultCode = $result['ResultCode'];
if ($resultCode == '0') {
$resultParameters = $result['ResultParameters']['ResultParameter'];
$firstName = null;
$middleName = null;
$lastName = null;
$mpesaTransaction = new MpesaTransaction();
foreach ($resultParameters as $index => $resultParameter) {
if ($index == 0) {
$phoneName = $resultParameter['Value'];
if ($phoneName) {
$phoneNameArray = explode('-', $phoneName);
$phoneNumber = trim($phoneNameArray[0]);
$name = $phoneNameArray[1];
$namesArray = explode(" ", trim($name));
foreach ($namesArray as $index => $item) {
if ($index == 0) {
$firstName = trim($item);
} elseif ($index == 1) {
$middleName = trim($item);
} elseif ($index >= 2) {
$lastName .= trim($item);
}
}
$mpesaTransaction->setMsisdn($phoneNumber);
$mpesaTransaction->setFirstName($firstName);
$mpesaTransaction->setMiddleName($middleName ? $middleName : '-');
$mpesaTransaction->setLastName($lastName ? $lastName : '-');
}
} else if ($index == 1) {
$values = explode('-', $resultParameter['Value']);
$mpesaTransaction->setShortCode($values[0]);
} else if ($index == 3) {
$transactionTime = explode('-', $resultParameter['Value']);
$from = \DateTime::createFromFormat('YmdHis', $transactionTime[0]);
$mpesaTransaction->setTransactionTime($from);
} else if ($index == 10) {
$amount = $resultParameter['Value'];
$mpesaTransaction->setTransactionAmount($amount);
} else if ($index == 12) {
$transactionID = $resultParameter['Value'];
$mpesaTransaction->setTransactionId($transactionID);
}
}
//
$mpesaTransaction->setTransactionType("Paybill");
$mpesaTransaction->setIsUsed(false);
$mpesaTransaction->setIsValidated(false);
$mpesaTransaction->setCreatedAt(new DateTime());
$mpesaTransaction->setIsUsed(false);
}*/
$j = $this->verifyService->encryptPassword(base64_encode('Id@23098240'));
return new Response($j, Response::HTTP_OK);
}
/**
* @Route("/mpesa/manual", name="mpesaManualRoute")
* @param Request $request
* @return Response
*/
public function mpesaManualAction(Request $request)
{
return $this->render('mpesa/manual_mpesa.html.twig', []);
}
/**
* @Route("/mpesa/update/{id}", name="mpesaUpdateDateRoute")
* @param Request $request
* @param $id
* @return Response
*/
public function mpesaUpdateCreatedAtDate(Request $request, $id)
{
$em = $this->em;
$mpesaTransaction = $em->getRepository(MpesaTransaction::class)->findOneBy([
'id' => $id
]);
if ($mpesaTransaction) {
$mpesaTransaction->setCreatedAt(new \DateTime());
}
$em->flush();
return new JsonResponse('success');
}
/**
* @Route("/mpesa/manual/new/transaction", name="mpesaManualNewTransactionRoute")
* @param Request $request
* @return Response
*/
public function mpesaManualNewAction(Request $request): Response
{
$em = $this->em;
if (!in_array('ROLE_MPESA_ADMIN', $this->getUser()->getRoles())) {
$this->addFlash('warning', 'You ARE NOT AUTHORIZED TO DO THIS - Contact ADMIN');
$route = $request->headers->get('referer');
return $this->redirect($route);
}
$mpesaTransaction = new MpesaTransaction();
// $mpesaTransaction->setCreatedAt(new \DateTime());
$mpesaTransaction->setTransactionType('NA');
$mpesaTransaction->setIsComplete(true);
$mpesaTransaction->setBillReferenceNumber('');
$mpesaTransaction->setAccountBalance(0);
$mpesaTransaction->setIsUsed(false);
$mpesaTransaction->setIsSeen(false);
$mpesaTransaction->setIsValidated(false);
$mpesaTransaction->setTransactionTime(new \DateTime());
$mpesaManual = new MpesaManual();
$mpesaManual->setMpesaTransaction($mpesaTransaction);
$mpesaManual->setCreatedAt(new \DateTime());
$form = $this->createForm(MpesaManualIDType::class, $mpesaManual, [
'validation_groups' => [
'Default'
]
]);
$form->handleRequest($request);
if ($form->isSubmitted()) {
$mpesaT = $em->getRepository(MpesaTransaction::class)->findOneBy([
'transactionId' => $mpesaTransaction->getTransactionId()
]);
if ($mpesaT) {
$form->get('MpesaTransaction')->get('transactionId')->addError(new FormError('Transaction Available ...'));
}
if ($form->isValid()) {
$mpesaTransactionVerification = $em->getRepository(MpesaTransactionVerification::class)->findOneBy([
'transactionId' => $mpesaTransaction->getTransactionId()
]);
/* $mpesaAuth = $this->em->getRepository(MpesaAuth::class)->findOneBy([
'branch' => $mpesaManual->getBranch()
]);*/
if ($mpesaTransactionVerification) {
$mpesaAuth = $this->em->getRepository(MpesaAuth::class)->findOneBy([
'tillNumber' => $mpesaTransactionVerification->getShortCode()
]);
$mpesa = new MpesaTransaction();
$mpesa->setTransactionId($mpesaTransactionVerification->getTransactionId());
$mpesa->setTransactionType($mpesaTransactionVerification->getTransactionType());
$mpesa->setTransactionTime($mpesaTransactionVerification->getTransactionTime());
$mpesa->setTransactionAmount($mpesaTransactionVerification->getTransactionAmount());
$mpesa->setShortCode($mpesaTransactionVerification->getShortCode());
$mpesa->setBillReferenceNumber($mpesaTransactionVerification->getBillReferenceNumber());
$mpesa->setAccountBalance($mpesaTransactionVerification->getAccountBalance());
$mpesa->setThirdPartyTransactionId($mpesaTransactionVerification->getThirdPartyTransactionId());
$mpesa->setMsisdn($mpesaTransactionVerification->getMsisdn());
$mpesa->setFirstName($mpesaTransactionVerification->getFirstName());
$mpesa->setMiddleName($mpesaTransactionVerification->getMiddleName());
$mpesa->setLastName($mpesaTransactionVerification->getLastName());
$mpesa->setIsComplete(true);
$mpesa->setCreatedAt(new DateTime());
$mpesa->setIsValidated(true);
$mpesa->setIsSeen(false);
$mpesa->setIsUsed(false);
$mpesa->setCompletedMpesaFromIp($request->getClientIp());
$mpesaManual = new MpesaManual();
$mpesaManual->setMpesaTransaction($mpesa);
$mpesaManual->setCreatedAt(new \DateTime());
$mpesaManual->setCreatedBy($this->getUser());
$mpesaManual->setBranch($mpesaAuth->getBranch());
$this->em->persist($mpesaManual);
try {
$em->persist($mpesa);
$em->flush();
return $this->redirectToRoute('mpesaManualNewTransactionRoute');
} catch (\PDOException $exception) {
return $this->render('mpesa/manual_new_mpesa_transaction.html.twig', [
'form' => $form->createView()
]);
}
} /*else {
$transactionId = $mpesaTransaction->getTransactionId();
try {
$this->getMpesaTransaction($transactionId, $mpesaManual->getBranch());
$this->addFlash("info", "Gotten from mpesa verify");
return $this->redirectToRoute('mpesaManualNewTransactionRoute');
} catch (\Exception $e) {
if ($e->getCode() == 404) {
try {
$this->getMpesaAuthentication($mpesaAuth);
$this->getMpesaTransaction($mpesaTransaction->getTransactionId(), $mpesaManual->getBranch());
} catch (TransportExceptionInterface|ClientExceptionInterface|RedirectionExceptionInterface|ServerExceptionInterface $e) {
$this->addFlash("error", "Exception occurred during mpesa verify 2 - {$e->getCode()} -" . $e->getMessage());
}
}
// $this->addFlash("error", "Exception occurred during mpesa verify - {$e->getCode()} -" . $e->getMessage());
return $this->render('mpesa/manual_new_mpesa_transaction.html.twig', [
'form' => $form->createView()
]);
}
}*/
}
}
return $this->render('mpesa/manual_new_mpesa_transaction.html.twig', [
'form' => $form->createView()
]);
}
/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
*/
function getMpesaTransaction($transactionId, Branch $branch){
$response = $this->verifyService->getTransaction(
$transactionId,
$branch);
}
/**
* @Route("/mpesa/manual/new", name="mpesaManualNewRoute")
* @param Request $request
* @return Response
*/
public function mpesaManualNewActionk(Request $request)
{
$em = $this->em;
if (!in_array('ROLE_ADMIN_WEB', $this->getUser()->getRoles())) {
$this->addFlash('warning', 'You ARE NOT AUTHORIZED TO DO THIS - Contact ADMIN');
$route = $request->headers->get('referer');
return $this->redirect($route);
}
$mpesaTransaction = new MpesaTransaction();
// $mpesaTransaction->setCreatedAt(new \DateTime());
$mpesaTransaction->setTransactionType('NA');
$mpesaTransaction->setIsComplete(true);
$mpesaTransaction->setBillReferenceNumber('');
$mpesaTransaction->setAccountBalance(0);
$mpesaTransaction->setIsUsed(false);
$mpesaTransaction->setIsSeen(false);
$mpesaTransaction->setIsValidated(false);
$mpesaTransaction->setTransactionTime(new \DateTime());
$mpesaManual = new MpesaManual();
$mpesaManual->setMpesaTransaction($mpesaTransaction);
$mpesaManual->setCreatedAt(new \DateTime());
$form = $this->createForm(MpesaManualType::class, $mpesaManual, [
'validation_groups' => [
'Default'
]
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$mpesaAuth = $em->getRepository(MpesaAuth::class)->findOneBy([
'branch' => $mpesaManual->getBranch()
]);
$user = $em->getRepository(User::class)->findOneBy([
'id' => 1
]);
if ($mpesaAuth) {
try {
$mpesaTransaction->setShortCode($mpesaAuth->getTillNumber());
$mpesaManual->setCreatedBy($user);
$em->persist($mpesaTransaction);
$em->persist($mpesaManual);
$em->flush();
return $this->redirectToRoute('mpesaManualNewRoute');
} catch (\Exception $e) {
dump($e);
}
}
}
return $this->render('mpesa/manual_new_mpesa.html.twig', [
'form' => $form->createView()
]);
}
/**
* @Route("/mpesa/manual/edit/{id}", name="mpesaManualEditRoute")
* @param Request $request
* @param $id
* @return Response
*/
public function mpesaManualNewEditActionk(Request $request, $id)
{
$em = $this->em;
if (!in_array('ROLE_ADMIN_WEB', $this->getUser()->getRoles())) {
$this->addFlash('warning', 'You ARE NOT AUTHORIZED TO DO THIS - Contact ADMIN');
$route = $request->headers->get('referer');
return $this->redirect($route);
}
$mpesaTransaction = $this->em->getRepository(MpesaTransaction::class)->findOneBy([
'transactionId' => $id
]);
$mpesaManual = $this->em->getRepository(MpesaManual::class)->findOneBy([
'mpesaTransaction' => $mpesaTransaction
]);
if (!$mpesaManual) {
return $this->redirectToRoute('mpesaManualNewRoute');
}
$mpesaTransaction = $mpesaManual->getMpesaTransaction();
$form = $this->createForm(MpesaManualType::class, $mpesaManual, [
'validation_groups' => [
'Default'
]
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$mpesaAuth = $em->getRepository(MpesaAuth::class)->findOneBy([
'branch' => $mpesaManual->getBranch()
]);
$user = $em->getRepository(User::class)->findOneBy([
'id' => 1
]);
if ($mpesaAuth) {
try {
$mpesaTransaction->setShortCode($mpesaAuth->getTillNumber());
$mpesaManual->setCreatedBy($user);
$em->flush();
return $this->redirectToRoute('mpesaManualNewRoute');
} catch (\Exception $e) {
dump($e);
}
}
}
return $this->render('mpesa/manual_new_mpesa.html.twig', [
'form' => $form->createView()
]);
}
/**
* @Route("/mpesa/json", name="mpesaJSONRoute")
* @return Response
*/
public function mpesaTransactionsJSON(Request $request)
{
$context = new SerializationContext();
$context->setSerializeNull(true);
$branchId = $request->getSession()->get('branch') ?: null;
$serializer = SerializerBuilder::create()->build();
$page = $request->request->get('page') > 1 ? $request->request->get('page') : 1;
$rows = $request->request->get('rows') > 1 ? $request->request->get('rows') : 20;
$offset = ($page - 1) * $rows;
$fromDate = $request->request->get("from_date");
$toDate = $request->request->get("to_date");
// dump($fromDate);
$fDate = null;
$date = new \DateTime('+1 day');
$tDate = null;
$fromDate = empty($fromDate) ? $fDate : $fromDate;
$toDate = empty($toDate) ? $tDate : $toDate;
$filterRules = $request->request->get('filterRules');
dump($filterRules);
/*
* If the @filterRules is empty set the @fromDate & @toDate to today's date
*/
if (!$fromDate && !$toDate) {
$date = new DateTime();
$d = $date->format('Y-m-d');
dump($d);
$fromDate = $d;
$toDate = $d;
}
if ($fromDate && $toDate) {
$filterRules = json_decode($filterRules, true);
if (!$filterRules) $filterRules = [];
$dates = [
'field' => 'a.transaction_time',
'op' => 'between',
'value' => [
'from' => str_replace(" ", "", $fromDate),
'to' => str_replace(" ", "", $toDate)
],
];
array_push($filterRules, $dates);
$filterRules = json_encode($filterRules);
}
$userBranches = $this->em->getRepository(UserBranch::class)->findBy([
'user' => $this->getUser()
]);
if ($branchId) {
$multipleBranches = ' AND (';
$count = count($userBranches);
foreach ($userBranches as $index => $userBranch) {
dump($index, $count);
if ($index < ($count - 1)) {
$multipleBranches .= " c.id = {$userBranch->getBranch()->getId()} or ";
} else {
$multipleBranches .= " c.id ={$userBranch->getBranch()->getId()})";
}
}
$filterRules = json_decode($filterRules, true);
if (!$filterRules) $filterRules = [];
$branch = [
'field' => 'c.id',
'op' => 'multi',
'value' => $multipleBranches,
];
array_push($filterRules, $branch);
$filterRules = json_encode($filterRules);
}
$transactions = $this->em->getRepository(MpesaTransaction::class)->getAllTransactions($filterRules, $offset, $rows);
$count = $this->em->getRepository(MpesaTransaction::class)->getAllTransactionsCounter($filterRules);
dump($count);
$data = [
'total' => $count['total'],
'rows' => $transactions,
'amounts' => number_format($count['amount'])
];
$data = $serializer->serialize($data, 'json', $context);
// $data = json_encode($data, false);
return new Response($data, Response::HTTP_OK, [
'ContentType' => 'application/json'
]);
}
/**
* @Route("/mpesa/manual/json", name="mpesaManualJSONRoute")
* @return Response
*/
public function mpesaManualTransactionsJSON(Request $request)
{
$context = new SerializationContext();
$context->setSerializeNull(true);
$serializer = SerializerBuilder::create()->build();
$branchId = $request->getSession()->get('branch') ?: null;
$page = $request->request->get('page') > 1 ? $request->request->get('page') : 1;
$rows = $request->request->get('rows') > 1 ? $request->request->get('rows') : 20;
$offset = ($page - 1) * $rows;
$filterRules = $request->request->get('filterRules');
if ($branchId) {
$filterRules = json_decode($filterRules, true);
if (!$filterRules) $filterRules = [];
$branch = [
'field' => 'c.id',
'op' => 'equal',
'value' => $branchId,
];
array_push($filterRules, $branch);
$filterRules = json_encode($filterRules);
}
$transactions = $this->em->getRepository(MpesaTransaction::class)->getAllManualTransactions($filterRules, $offset, $rows);
$count = $this->em->getRepository(MpesaTransaction::class)->getAllManualTransactionsCounter($filterRules);
$data = [
'total' => $count,
'rows' => $transactions,
];
$data = $serializer->serialize($data, 'json', $context);
// $data = json_encode($data, false);
return new Response($data);
/*return new JsonResponse($data, Response::HTTP_OK, [
'ContentType' => 'application/json'
]);*/
}
/**
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
* @throws ServerExceptionInterface
*/
function getMpesaAuthentication(MpesaAuth $credential)
{
$host = 'api.safaricom.co.ke';
$tokenRequest = '/oauth/v1/generate?grant_type=client_credentials';
$em = $this->em;
$date = new \DateTime();
$date = date_format($date, 'YmdHis');
$url = "https://{$host}{$tokenRequest}";
$password = base64_encode("{$credential->getConsumerKey()}:{$credential->getConsumerSecret()}");
try {
$response = $this->client->request(
"GET",
$url,
[
'headers' => [
"Content-Type:application/json",
"Authorization:Basic {$password}"
]
]
);
$responseData = $response->getContent();
// dump($responseData); die;
$responseDataArray = json_decode($responseData, true);
$credential->setToken($responseDataArray['access_token']);
$credential->setTokenUpdatedAt(new \DateTime());
$em->flush();
$this->logger->debug("ok - {$responseData}_");
return new Response($response->getContent(), Response::HTTP_OK);
} catch (ClientExceptionInterface|ClientException|RedirectionExceptionInterface|ServerExceptionInterface|TransportExceptionInterface $e) {
$this->logger->debug($e->getMessage());
return new Response($e->getMessage(), Response::HTTP_OK);
}
}
}