* SZEP card poller implementation added
* new tags for sms parsing
This commit is contained in:
parent
d73a24b1d6
commit
8b22f1d663
@ -13,6 +13,7 @@
|
||||
"php": "^7.1",
|
||||
"dasprid/container-interop-doctrine": "^1.0",
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
"http-interop/http-middleware": "^0.4.1",
|
||||
"roave/security-advisories": "dev-master",
|
||||
"zendframework/zend-component-installer": "^1.0",
|
||||
"zendframework/zend-config-aggregator": "^1.0",
|
||||
|
||||
988
composer.lock
generated
988
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -5,11 +5,13 @@ return [
|
||||
'invokables' => [],
|
||||
'factories' => [
|
||||
App\Command\KoinImportCommand::class => App\Command\KoinImportCommandFactory::class,
|
||||
App\Command\PeriodicSZEPCommand::class => App\Command\PeriodicSZEPCommandFactory::class,
|
||||
],
|
||||
],
|
||||
'console' => [
|
||||
'commands' => [
|
||||
App\Command\KoinImportCommand::class,
|
||||
App\Command\PeriodicSZEPCommand::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@ -10,4 +10,7 @@
|
||||
return [
|
||||
'koin.user' => '',
|
||||
'koin.pass' => '',
|
||||
|
||||
'szep.card' => '',
|
||||
'szep.key' => '',
|
||||
];
|
||||
|
||||
1
data/.gitignore
vendored
1
data/.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
*
|
||||
!soap-xmls/*
|
||||
!.gitignore
|
||||
|
||||
36
src/App/Command/PeriodicSZEPCommand.php
Normal file
36
src/App/Command/PeriodicSZEPCommand.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Service\SZEPManagerService;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class PeriodicSZEPCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @var SZEPManagerService
|
||||
*/
|
||||
private $szepManager;
|
||||
|
||||
public function __construct(SZEPManagerService $szepManager)
|
||||
{
|
||||
$this->szepManager = $szepManager;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('szep:cron')
|
||||
->setDescription('Parse SZEP card');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$result = $this->szepManager->pollRecent();
|
||||
$output->writeln($result);
|
||||
}
|
||||
}
|
||||
22
src/App/Command/PeriodicSZEPCommandFactory.php
Normal file
22
src/App/Command/PeriodicSZEPCommandFactory.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Service\SZEPManagerService;
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class PeriodicSZEPCommandFactory
|
||||
{
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
* @return PeriodicSZEPCommand
|
||||
* @throws \Psr\Container\ContainerExceptionInterface
|
||||
* @throws \Psr\Container\NotFoundExceptionInterface
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
/** @var SZEPManagerService $szepManager */
|
||||
$szepManager = $container->get(SZEPManagerService::class);
|
||||
return new PeriodicSZEPCommand($szepManager);
|
||||
}
|
||||
}
|
||||
@ -45,6 +45,7 @@ class ConfigProvider
|
||||
|
||||
Service\SmsStoreService::class => Service\SmsStoreServiceFactory::class,
|
||||
Service\KoinService::class => Service\KoinServiceFactory::class,
|
||||
Service\SZEPManagerService::class => Service\SZEPManagerServiceFactory::class,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
159
src/App/Entity/SZEPCardEntry.php
Normal file
159
src/App/Entity/SZEPCardEntry.php
Normal file
@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(
|
||||
* name="szep_card_entries",
|
||||
* indexes={
|
||||
* @ORM\Index(name="amount", columns={"amount"}),
|
||||
* @ORM\Index(name="merchant", columns={"merchant"}),
|
||||
* @ORM\Index(name="pocket", columns={"pocket"}),
|
||||
* @ORM\Index(name="entry_date", columns={"entry_date"})
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class SZEPCardEntry implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(name="hash", type="string", length=100, nullable=false)
|
||||
* @var string
|
||||
*/
|
||||
private $hash;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="amount", type="integer", length=200, nullable=false)
|
||||
* @var int
|
||||
*/
|
||||
private $amount;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="merchant", type="string", length=250, nullable=false)
|
||||
* @var string
|
||||
*/
|
||||
private $merchant;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="pocket", type="string", length=50, nullable=true)
|
||||
* @var string
|
||||
*/
|
||||
private $pocket;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="entry_date", type="date_immutable", nullable=false)
|
||||
* @var \DateTimeImmutable
|
||||
*/
|
||||
private $date;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHash(): string
|
||||
{
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $hash
|
||||
* @return SZEPCardEntry
|
||||
*/
|
||||
public function setHash(string $hash): SZEPCardEntry
|
||||
{
|
||||
$this->hash = $hash;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getAmount(): int
|
||||
{
|
||||
return $this->amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $amount
|
||||
* @return SZEPCardEntry
|
||||
*/
|
||||
public function setAmount(int $amount): SZEPCardEntry
|
||||
{
|
||||
$this->amount = $amount;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMerchant(): string
|
||||
{
|
||||
return $this->merchant;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $merchant
|
||||
* @return SZEPCardEntry
|
||||
*/
|
||||
public function setMerchant(string $merchant): SZEPCardEntry
|
||||
{
|
||||
$this->merchant = $merchant;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPocket(): string
|
||||
{
|
||||
return $this->pocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $pocket
|
||||
* @return SZEPCardEntry
|
||||
*/
|
||||
public function setPocket(string $pocket): SZEPCardEntry
|
||||
{
|
||||
$this->pocket = $pocket;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTimeImmutable
|
||||
*/
|
||||
public function getDate(): \DateTimeImmutable
|
||||
{
|
||||
return $this->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DateTimeImmutable $date
|
||||
* @return SZEPCardEntry
|
||||
*/
|
||||
public function setDate(\DateTimeImmutable $date): SZEPCardEntry
|
||||
{
|
||||
$this->date = $date;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify data which should be serialized to JSON
|
||||
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
|
||||
* @return mixed data which can be serialized by <b>json_encode</b>,
|
||||
* which is a value of any type other than a resource.
|
||||
* @since 5.4.0
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'hash' => $this->getHash(),
|
||||
'amount' => $this->getAmount(),
|
||||
'merchant' => $this->getMerchant(),
|
||||
'pocket' => $this->getPocket(),
|
||||
'date' => $this->getDate()->format("Y.m.d"),
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
@ -20,7 +19,6 @@ use Doctrine\ORM\Mapping as ORM;
|
||||
*/
|
||||
class Sms implements \JsonSerializable
|
||||
{
|
||||
|
||||
const DIRECTION_SENT = 0;
|
||||
const DIRECTION_RECEIVED = 1;
|
||||
|
||||
|
||||
@ -128,7 +128,8 @@ class User implements \JsonSerializable
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeSmsMessage(Sms $sms): User{
|
||||
public function removeSmsMessage(Sms $sms): User
|
||||
{
|
||||
if ($this->smsMessages->contains($sms)) {
|
||||
$this->smsMessages->removeElement($sms);
|
||||
}
|
||||
|
||||
@ -15,6 +15,10 @@ class KoinService
|
||||
const BASE_URI = 'https://www.koin.hu';
|
||||
const DEFAULT_EXPENSE = 'Egyéb kiadás';
|
||||
|
||||
const CATEGORY_PAYMENT = 'Fizetés';
|
||||
const CATEGORY_FOOD = 'Étel';
|
||||
const CATEGORY_SPORT = '';
|
||||
|
||||
/**
|
||||
* 1 - date
|
||||
* 2 - time
|
||||
@ -92,6 +96,18 @@ class KoinService
|
||||
*/
|
||||
private function getExpenseCategory(string $posInfo): string
|
||||
{
|
||||
if (false !== strpos($posInfo, "ERICSSON HàZ ÉTTEREM")) {
|
||||
return 'Étel';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "ERICSSON HàZ BÜFÉ")) {
|
||||
return 'Kávé';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "SCIENCE PARK ÉTTEREM")) {
|
||||
return 'Étel';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "STOCZEK ETTEREM")) {
|
||||
return 'Étel';
|
||||
}
|
||||
@ -104,7 +120,7 @@ class KoinService
|
||||
return 'Bevásárlás';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "SPAR MAGYARORSZAG")) {
|
||||
if (false !== strpos($posInfo, "SPAR")) {
|
||||
return 'Étel';
|
||||
}
|
||||
|
||||
@ -116,7 +132,11 @@ class KoinService
|
||||
return 'Étel';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "OSMANI DÖNER KEBAB")) {
|
||||
if (false !== strpos($posInfo, "MCDONALDSETTE")) {
|
||||
return 'Étel';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "DÖNER KEBAB")) {
|
||||
return 'Étel';
|
||||
}
|
||||
|
||||
@ -144,6 +164,17 @@ class KoinService
|
||||
return 'Szórakozás';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "DECATHLON")) {
|
||||
return 'Sport';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "MOL TÖLTÖàLL")) {
|
||||
return 'Autó';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "AMAZON SERVICES-KINDLE")) {
|
||||
return 'Szórakozás';
|
||||
}
|
||||
|
||||
return self::DEFAULT_EXPENSE;
|
||||
}
|
||||
@ -156,66 +187,60 @@ class KoinService
|
||||
{
|
||||
$tags = [];
|
||||
|
||||
if (false !== strpos($posInfo, "SCIENCE PARK ÉTTEREM")) {
|
||||
if (false !== strpos($posInfo, "ERICSSON HàZ ÉTTEREM")) {
|
||||
$tags[] = 'Ericsson Ház';
|
||||
$tags[] = 'Menza';
|
||||
} elseif (false !== strpos($posInfo, "ERICSSON HàZ BÜFÉ")) {
|
||||
$tags[] = 'Ericsson Ház';
|
||||
$tags[] = 'Büfé';
|
||||
} elseif (false !== strpos($posInfo, "SCIENCE PARK ÉTTEREM")) {
|
||||
$tags[] = 'Science Park';
|
||||
$tags[] = 'Menza';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "STOCZEK ETTEREM")) {
|
||||
} elseif (false !== strpos($posInfo, "STOCZEK ETTEREM")) {
|
||||
$tags[] = "Stoczek";
|
||||
$tags[] = "Menza";
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "BKK AUTOMATA")) {
|
||||
} elseif (false !== strpos($posInfo, "BKK AUTOMATA")) {
|
||||
$tags[] = "Bérlet";
|
||||
$tags[] = "BKV";
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "SPAR MAGYARORSZAG")) {
|
||||
} elseif (false !== strpos($posInfo, "SPAR")) {
|
||||
$tags[] = 'Spar';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "TESCO")) {
|
||||
} elseif (false !== strpos($posInfo, "TESCO")) {
|
||||
$tags[] = 'Tesco';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "SZLOVàK ABC")) {
|
||||
} elseif (false !== strpos($posInfo, "SZLOVàK ABC")) {
|
||||
$tags[] = 'Szlovák ABC';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "MCDHU")) {
|
||||
} elseif (false !== strpos($posInfo, "BURGER KING")) {
|
||||
$tags[] = 'Burger King';
|
||||
$tags[] = 'Junk food';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "OSMANI DÖNER KEBAB")) {
|
||||
} elseif (false !== strpos($posInfo, "MCDHU")) {
|
||||
$tags[] = 'McDonald\'s';
|
||||
$tags[] = 'Junk food';
|
||||
} elseif (false !== strpos($posInfo, "MCDONALDSETTE")) {
|
||||
$tags[] = 'McDonald\'s';
|
||||
$tags[] = 'Junk food';
|
||||
} elseif (false !== strpos($posInfo, "DÖNER KEBAB")) {
|
||||
$tags[] = 'Kebab';
|
||||
$tags[] = 'Junk food';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "Princess Bakery")) {
|
||||
$tags[] = 'Pricess Bakery';
|
||||
} elseif (false !== strpos($posInfo, "Princess Bakery")) {
|
||||
$tags[] = 'Princess Bakery';
|
||||
$tags[] = 'Junk food';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "PIROG-DA")) {
|
||||
} elseif (false !== strpos($posInfo, "PIROG-DA")) {
|
||||
$tags[] = 'Pirog-da';
|
||||
$tags[] = 'Junk food';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "GYOGYSZER")) {
|
||||
} elseif (false !== strpos($posInfo, "GYOGYSZER")) {
|
||||
$tags[] = 'Gyógyszer';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "GOOGLE *Google Music")) {
|
||||
} elseif (false !== strpos($posInfo, "GOOGLE *Google Music")) {
|
||||
$tags[] = 'Google play';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "DIGI ")) {
|
||||
} elseif (false !== strpos($posInfo, "DIGI ")) {
|
||||
$tags[] = 'Digi';
|
||||
}
|
||||
|
||||
if (false !== strpos($posInfo, "Aqua Electromax")) {
|
||||
} elseif (false !== strpos($posInfo, "Aqua Electromax")) {
|
||||
$tags[] = 'Aqua';
|
||||
} elseif (false !== strpos($posInfo, "DECATHLON")) {
|
||||
$tags[] = 'Decathlon';
|
||||
} elseif (false !== strpos($posInfo, "MOL TÖLTÖàLL")) {
|
||||
$tags[] = 'MOL';
|
||||
} elseif (false !== strpos($posInfo, "AMAZON SERVICES-KINDLE")) {
|
||||
$tags[] = 'Kindle';
|
||||
$tags[] = 'Amazon';
|
||||
}
|
||||
|
||||
$tags[] = 'Auto';
|
||||
|
||||
255
src/App/Service/SZEPManagerService.php
Normal file
255
src/App/Service/SZEPManagerService.php
Normal file
@ -0,0 +1,255 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\SZEPCardEntry;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use GuzzleHttp\Client;
|
||||
|
||||
class SZEPManagerService
|
||||
{
|
||||
const TEMPLATE_WORKFLOW_START = "data/soap-xmls/SZEP_startWorkflow.xml";
|
||||
const TEMPLATE_WORKFLOW_STATE = "data/soap-xmls/SZEP_getWorkflowState.xml";
|
||||
const TEMPLATE_QUERY_CARD = "data/soap-xmls/SZEP_queryCard.xml";
|
||||
|
||||
const CERTIFICATE_WEB_PATH = "https://www.otpbankdirekt.hu/homebank/mobilalkalmazas/certificate";
|
||||
const CERTIFICATE_CACHED_PATH = "data/cache/SZEP_cert.pem";
|
||||
|
||||
const SOAP_ENDPOINT = "https://www.otpbankdirekt.hu/mwaccesspublic/mwaccess";
|
||||
|
||||
const POCKET_FOOD = 'Vendéglátás';
|
||||
const POCKET_SPORT = 'Szabadidő';
|
||||
|
||||
const TAG_POCKET_FOOD = 'SZÉP kártya';
|
||||
const TAG_POCKET_SPORT = 'SZÉP kártya - szabadidő';
|
||||
|
||||
/** @var array */
|
||||
private $config;
|
||||
|
||||
/** @var Client */
|
||||
private $httpClient;
|
||||
|
||||
/** @var EntityManager */
|
||||
private $em;
|
||||
|
||||
/** @var KoinService */
|
||||
private $koinService;
|
||||
|
||||
public function __construct(Client $httpClient,
|
||||
array $config,
|
||||
EntityManager $em,
|
||||
KoinService $koinService)
|
||||
{
|
||||
$this->httpClient = $httpClient;
|
||||
$this->config = $config;
|
||||
$this->em = $em;
|
||||
$this->koinService = $koinService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Doctrine\ORM\ORMException
|
||||
* @throws \Doctrine\ORM\OptimisticLockException
|
||||
* @throws \Doctrine\ORM\TransactionRequiredException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function pollRecent()
|
||||
{
|
||||
$workflowResult = $this->startWorkflow();
|
||||
$pollResult = $this->pollResult($workflowResult);
|
||||
$this->parseResult($pollResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the soap workflow
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function startWorkflow(): string
|
||||
{
|
||||
$certificate = $this->getCertificate();
|
||||
openssl_public_encrypt($this->config['szep.card'], $cryptCardId, $certificate, OPENSSL_PKCS1_PADDING);
|
||||
openssl_public_encrypt($this->config['szep.key'], $cryptCardKey, $certificate, OPENSSL_PKCS1_PADDING);
|
||||
|
||||
$endDate = new \DateTimeImmutable();
|
||||
$startDate = $endDate->sub(new \DateInterval('P4D'));
|
||||
|
||||
$gueryTemplate = file_get_contents(self::TEMPLATE_QUERY_CARD);
|
||||
$query = sprintf($gueryTemplate,
|
||||
"X" . base64_encode($cryptCardId),
|
||||
base64_encode($cryptCardKey),
|
||||
$startDate->format("Y.m.d"),
|
||||
$endDate->format("Y.m.d")
|
||||
);
|
||||
|
||||
$soapXml = sprintf(file_get_contents(self::TEMPLATE_WORKFLOW_START), $query);
|
||||
$soapResponseXml = $this->doSoapRequest($soapXml);
|
||||
|
||||
$domDocument = new \DOMDocument();
|
||||
$domDocument->loadXML($soapResponseXml);
|
||||
|
||||
$documentXpath = new \DOMXPath($domDocument);
|
||||
/** @var \DOMElement $returnElement */
|
||||
$returnElement = $documentXpath->query('//return')->item(0);
|
||||
return $returnElement->textContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll until the result is ready
|
||||
* @param string $workflowResult
|
||||
* @return string
|
||||
*/
|
||||
private function pollResult(string $workflowResult): string
|
||||
{
|
||||
$soapXml = sprintf(file_get_contents(self::TEMPLATE_WORKFLOW_STATE), $workflowResult);
|
||||
do {
|
||||
sleep(1);
|
||||
$soapResponseXml = $this->doSoapRequest($soapXml);
|
||||
|
||||
$domDocument = new \DOMDocument();
|
||||
$domDocument->loadXML($soapResponseXml);
|
||||
|
||||
$documentXpath = new \DOMXPath($domDocument);
|
||||
/** @var \DOMElement $completedElement */
|
||||
$completedElement = $documentXpath->query('//completed')->item(0);
|
||||
} while ($completedElement->textContent != "true");
|
||||
|
||||
/** @var \DOMElement $resultElement */
|
||||
$resultElement = $documentXpath->query('//result')->item(0);
|
||||
return base64_decode($resultElement->textContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the decoded payload
|
||||
* @param string $resultXml
|
||||
* @throws \Doctrine\ORM\ORMException
|
||||
* @throws \Doctrine\ORM\OptimisticLockException
|
||||
* @throws \Doctrine\ORM\TransactionRequiredException
|
||||
*/
|
||||
private function parseResult(string $resultXml)
|
||||
{
|
||||
$domDocument = new \DOMDocument();
|
||||
$domDocument->loadXML($resultXml);
|
||||
|
||||
$documentXpath = new \DOMXPath($domDocument);
|
||||
/** @var \DOMElement[] $returnElements */
|
||||
$recordElements = $documentXpath->query('/answer/resultset/record');
|
||||
|
||||
$newRecords = [];
|
||||
|
||||
/** @var \DOMElement $element */
|
||||
foreach ($recordElements as $element) {
|
||||
$date = trim($documentXpath->query('./datum', $element)->item(0)->textContent);
|
||||
$amount = trim($documentXpath->query('./osszeg', $element)->item(0)->textContent);
|
||||
$merchant = trim($documentXpath->query('./ellenoldali_nev', $element)->item(0)->textContent);
|
||||
$pocket = trim($documentXpath->query('./alszamla', $element)->item(0)->textContent);
|
||||
|
||||
$hash = md5("$date#$amount#$merchant#$pocket");
|
||||
if (null != $this->em->find(SZEPCardEntry::class, $hash)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$szepCardEntity = new SZEPCardEntry();
|
||||
$szepCardEntity->setHash($hash)
|
||||
->setAmount($amount)
|
||||
->setMerchant($merchant)
|
||||
->setPocket($pocket)
|
||||
->setDate(new \DateTimeImmutable(str_replace(".", "-", $date)));
|
||||
$newRecords[] = $szepCardEntity;
|
||||
}
|
||||
|
||||
/** @var SZEPCardEntry $newRecord */
|
||||
foreach ($newRecords as $newRecord) {
|
||||
$resultCode = $this->koinService->saveTransaction(
|
||||
abs($newRecord->getAmount()),
|
||||
'HUF',
|
||||
$newRecord->getDate()->format("Y-m-d"),
|
||||
$this->getCategory($newRecord),
|
||||
$this->getTags($newRecord)
|
||||
);
|
||||
if ($resultCode > 199 && $resultCode < 300) {
|
||||
$this->em->persist($newRecord);
|
||||
}
|
||||
}
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
private function getCategory(SZEPCardEntry $SZEPCardEntry): string
|
||||
{
|
||||
return ($SZEPCardEntry->getAmount() > 0)
|
||||
? KoinService::CATEGORY_PAYMENT
|
||||
: (
|
||||
$SZEPCardEntry->getPocket() == self::POCKET_FOOD
|
||||
? KoinService::CATEGORY_FOOD
|
||||
: KoinService::DEFAULT_EXPENSE
|
||||
);
|
||||
}
|
||||
|
||||
private function getTags(SZEPCardEntry $SZEPCardEntry): array
|
||||
{
|
||||
$tags = [];
|
||||
|
||||
if (false !== strpos($SZEPCardEntry->getMerchant(), "Sigma Technology")) {
|
||||
$tags[] = 'Sigma';
|
||||
$tags[] = 'Cafeteria';
|
||||
} elseif (false !== strpos($SZEPCardEntry->getMerchant(), "Ericsson Ház Étterem")) {
|
||||
$tags[] = 'Ericsson Ház';
|
||||
$tags[] = 'Menza';
|
||||
} elseif (false !== strpos($SZEPCardEntry->getMerchant(), "Planet Sushi Alle")) {
|
||||
$tags[] = 'Planet Sushi';
|
||||
$tags[] = 'Sushi';
|
||||
} elseif (false !== strpos($SZEPCardEntry->getMerchant(), "Stoczek utcai Étterem")) {
|
||||
$tags[] = 'Stoczek';
|
||||
$tags[] = 'Street Food';
|
||||
} elseif (false !== strpos($SZEPCardEntry->getMerchant(), "Stoczek")) {
|
||||
$tags[] = 'Stoczek';
|
||||
} elseif (false !== strpos($SZEPCardEntry->getMerchant(), "Science Park")) {
|
||||
$tags[] = 'Science Park';
|
||||
$tags[] = 'Menza';
|
||||
} elseif (false !== strpos($SZEPCardEntry->getMerchant(), "Cafe Park")) {
|
||||
$tags[] = 'Cafe Park';
|
||||
$tags[] = 'Menza';
|
||||
} elseif (false !== strpos($SZEPCardEntry->getMerchant(), "Wikinger Gyorsétterem")) {
|
||||
$tags[] = 'Wikinger';
|
||||
} elseif (false !== strpos($SZEPCardEntry->getMerchant(), "Wasabi Étterem")) {
|
||||
$tags[] = 'Wasabi';
|
||||
$tags[] = 'Sushi';
|
||||
} elseif (false !== strpos($SZEPCardEntry->getMerchant(), "Szentmihályi Uszoda")) {
|
||||
$tags[] = 'Tope';
|
||||
}
|
||||
|
||||
switch ($SZEPCardEntry->getPocket()) {
|
||||
case self::POCKET_FOOD: $tags[] = self::TAG_POCKET_FOOD; break;
|
||||
case self::POCKET_SPORT: $tags[] = self::TAG_POCKET_SPORT; break;
|
||||
}
|
||||
|
||||
$tags[] = 'Auto';
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $soapXml
|
||||
* @return string
|
||||
*/
|
||||
private function doSoapRequest(string $soapXml): string
|
||||
{
|
||||
$response = $this->httpClient->post(self::SOAP_ENDPOINT, [
|
||||
'body' => $soapXml,
|
||||
]);
|
||||
return $response->getBody()->getContents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cached public certificate
|
||||
* @return string
|
||||
*/
|
||||
private function getCertificate(): string
|
||||
{
|
||||
if (file_exists(self::CERTIFICATE_CACHED_PATH)) {
|
||||
return file_get_contents(self::CERTIFICATE_CACHED_PATH);
|
||||
}
|
||||
|
||||
$cert = file_get_contents(self::CERTIFICATE_WEB_PATH);
|
||||
file_put_contents(self::CERTIFICATE_CACHED_PATH, $cert);
|
||||
return $cert;
|
||||
}
|
||||
}
|
||||
33
src/App/Service/SZEPManagerServiceFactory.php
Normal file
33
src/App/Service/SZEPManagerServiceFactory.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use GuzzleHttp\Client;
|
||||
use Interop\Container\ContainerInterface;
|
||||
|
||||
class SZEPManagerServiceFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
* @return SZEPManagerService
|
||||
* @throws \Psr\Container\ContainerExceptionInterface
|
||||
* @throws \Psr\Container\NotFoundExceptionInterface
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container)
|
||||
{
|
||||
$httpClient = new Client([
|
||||
'cookies' => true,
|
||||
'headers' => [
|
||||
'Content-Type' => 'text/xml; charset=UTF-8',
|
||||
]
|
||||
]);
|
||||
$config = $container->get('config');
|
||||
/** @var EntityManager $em */
|
||||
$em = $container->get('doctrine.entity_manager.orm_default');
|
||||
/** @var KoinService $koinService */
|
||||
$koinService = $container->get(KoinService::class);
|
||||
return new SZEPManagerService($httpClient, $config, $em, $koinService);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user