src/Diplix/KMGBundle/Service/TaMiConnector.php line 87

Open in your IDE?
  1. <?php
  2. namespace Diplix\KMGBundle\Service;
  3. use Diplix\Commons\DataHandlingBundle\Entity\SysLogEntry;
  4. use Diplix\Commons\DataHandlingBundle\Repository\SysLogRepository;
  5. use Diplix\KMGBundle\Entity\Accounting\CoopMember;
  6. use Diplix\KMGBundle\Entity\Address;
  7. use Diplix\KMGBundle\Entity\Availability;
  8. use Diplix\KMGBundle\Entity\Order;
  9. use Diplix\KMGBundle\Entity\OrderStatus;
  10. use Diplix\KMGBundle\Entity\PriceList;
  11. use Diplix\KMGBundle\Util\XmlCapable;
  12. use Doctrine\DBAL\Driver\Connection;
  13. use Doctrine\ORM\EntityManager;
  14. use Doctrine\ORM\EntityManagerInterface;
  15. use DOMDocument;
  16. use GuzzleHttp;
  17. use SimpleXMLElement;
  18. use Symfony\Component\HttpFoundation\JsonResponse;
  19. use Symfony\Component\HttpFoundation\Request;
  20. use Symfony\Component\HttpFoundation\Response;
  21. class TaMiConnector extends XmlCapable
  22. {
  23.     const TAMI_OK 1// ErgebnisCode für OK
  24.     const TAMI_ERR 2// ErgebnisCode !=1 = nicht ok
  25.     public static $tamiStatusMap = [
  26.         => 'Offen',
  27.         => 'Vermittelt',
  28.         => 'Erfolgreich',
  29.         => 'Fehlfahrt',
  30.         => 'Storniert',
  31.         11 => 'Angebot'
  32.     ];
  33.     const LogRequest 101;
  34.     const LogResponse 102;
  35.     const LogCallback 103;
  36.     const TimestampFormat "Y-m-d\TH:i:sP";
  37.     public static $connectionSettings = array(
  38.                 'connect_timeout' => "5"// abort if no response after X seconds
  39.                 'verify' => false// we do not care if the cert is valid or not
  40.     );
  41.     /**
  42.      * @var GuzzleHttp\Client
  43.      */
  44.     protected $client;
  45.     /**
  46.      * @var EntityManager
  47.      */
  48.     protected $em;
  49.     /**
  50.      * @var Connection
  51.      */
  52.     protected $db;
  53.     protected $statusCache = array();
  54.     protected $serverAddress "http://localhost/KMG/Web/web/app_dev.php/kmg/server-mock/";
  55.     protected $clientID "KMGONLINE";
  56.     protected $logPath;
  57.     protected $additionalSyslogging true;
  58.     protected $trace false;
  59.     protected $tamiEnabled true;
  60.     public function enableTami($enableTami)
  61.     {
  62.         $this->tamiEnabled $enableTami;
  63.     }
  64.     public function __construct(EntityManagerInterface $em)
  65.     {
  66.         parent::__construct();
  67.         $this->logPath =  __DIR__ "/../../../../app/logs/tami.log";
  68.         $this->em $em;
  69.         $this->db $this->em->getConnection();
  70.         // init http client (guzzle 6.x)
  71.         $this->client = new GuzzleHttp\Client($this::$connectionSettings);
  72.         // cache status entities
  73.         $rep $this->em->getRepository(OrderStatus::class);
  74.         $all $rep->findAll();
  75.         /** @var OrderStatus $a */
  76.         foreach ($all as $a)
  77.         {
  78.             $this->statusCache[$a->getTamiStatus()] = $a;
  79.         }
  80.     }
  81.     public function setServerAddress($url)
  82.     {
  83.         $this->serverAddress $url;
  84.     }
  85.     public function enableAdditionalSyslogging($enable)
  86.     {
  87.         $this->additionalSyslogging $enable;
  88.     }
  89.     protected function logData($dir=0,$data)
  90.     {
  91.         $msg "[".date("Y-m-d H:i:s")."]".($dir == ">>>\n" : ($dir == ?  "<<<\n"  "(trace)" ) );
  92.         $msg .= $data "\n";
  93.         file_put_contents($this->logPath$msgFILE_APPEND);
  94.     }
  95.     protected function formatXml($simpleXml)
  96.     {
  97.         $xml parent::formatXml($simpleXml);
  98.         if ($this->trace)
  99.         {
  100.             $this->logData(2,"formatXml()\n".$xml);
  101.         }
  102.         return $xml;
  103.     }
  104.     /**
  105.      * Used to remove the <?xml> tag since LIBXML_NOXMLDECL is not working properly
  106.      * @param $text
  107.      * @return string
  108.      */
  109.     protected function stripFirstLine($text)
  110.     {
  111.         $stripped =  substr$textstrpos($text"\n")+);
  112.         if ($this->trace)
  113.         {
  114.             $this->logData(2,"stripFirstLine()\n".$text);
  115.         }
  116.         return $stripped;
  117.     }
  118.     /**
  119.      * @param array|SimpleXMLElement $attributeArray
  120.      * @return mixed
  121.      * @throws \Exception
  122.      */
  123.     protected function aid($attributeArray$throwException=true)
  124.     {
  125.         if ($attributeArray instanceof SimpleXMLElement )
  126.         {
  127.             // no idea why ->attributes() is not working here. we use this workaround instead
  128.             $attributeArray = (array) $attributeArray;
  129.             $attributeArray $attributeArray["@attributes"];
  130.         }
  131.         // The documentation differs from the live data, so we support both cases
  132.         if (array_key_exists("AuftragID",$attributeArray))
  133.             return $attributeArray["AuftragID"];
  134.         else
  135.         if (array_key_exists("AuftragId",$attributeArray))
  136.             return $attributeArray["AuftragId"];
  137.         else
  138.         {
  139.             if ($throwException) throw new \Exception("No AuftragId/AuftragID in node attributes !");
  140.         }
  141.     }
  142.     /**
  143.      * @param Order $order
  144.      * @return SimpleXMLElement
  145.      */
  146.     protected function createOrderXml(Order $order)
  147.     {
  148.         $now = new \DateTime();
  149.         $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><VermAuftrag/>',LIBXML_NOEMPTYTAG);
  150.         $xml->addAttribute("Sender",$this->clientID);
  151.         $fa $xml->addChild("FahrAuftrag");
  152.         $fa->addAttribute("AuftragID",$order->getRemoteOrderId()); // created by remote server if empty, else handled as update
  153.         $fa->addAttribute("ZSt",$now->format($this::TimestampFormat));
  154.         $fa->addChild("Personen",$order->getPersonCount());
  155.         $fa->addChild("Zahlart",$order->getPaymentType()->getTamiCode());
  156.         // Preis soll nicht im Auftag erscheinen, nur als Info :: $fa->addChild("Preis",$order->getLastEstimatedPrice());
  157.         $best $fa->addChild("Besteller");
  158.         // this name is used by tami. use customer company name instead of orderer's name
  159.         $customerNameForTami $order->getCustomer()->getName();
  160.         if (
  161.             ($order->getPriceList()!==null)
  162.             &&
  163.             ($order->getPriceList()->getOverwriteCustomerNameForTamiWithThis()!==null)
  164.             &&
  165.             (strlen(trim($order->getPriceList()->getOverwriteCustomerNameForTamiWithThis()))>0)
  166.         )
  167.         {
  168.             $customerNameForTami $order->getPriceList()->getOverwriteCustomerNameForTamiWithThis();
  169.         }
  170.         $best->addChild("Name",  trim($customerNameForTami) );
  171.         $best->addChild("Telefon",$order->getOrdererPhone());
  172.         $comment "";
  173.         if ($order->getAlreadyPaid())
  174.         {
  175.             $comment.="BEZAHLT;";
  176.         }
  177.         $comment.= "P: ".number_format($order->getLastEstimatedPrice(),2,',',".").";";
  178.         if ($order->getIsVip())
  179.         {
  180.             $comment.= "VIP;";
  181.         }
  182.         if ($order->getLastEstimatedDistance()>0)
  183.         {
  184.             $comment.= ceil($order->getLastEstimatedDistance())."KM;";
  185.         }
  186.         if ($order->getCostCenter()!="")
  187.         {
  188.             $comment.= sprintf("KoSt: %s;",$order->getCostCenter());
  189.         }
  190.         if ($order->getChildSeatCount()>0)
  191.         {
  192.             $comment.= sprintf("Kindersitze: %d (%s);",$order->getChildSeatCount(),$order->getChildSeatInfo());
  193.         }
  194.         /* do not submit flightno in comment anymore, moved to first address
  195.         if ($order->getFlightNo()!="")
  196.         {
  197.             $comment.= sprintf("FlugNr: %s;",$order->getFlightNo());
  198.         }
  199.         */
  200.         if ($order->getCarType()!="")
  201.         {
  202.             $comment.= sprintf("Fhzg: %s;",$order->getCarType());
  203.         }
  204.         if ($order->getCreditCardNo()!="")
  205.         {
  206.             $comment .= sprintf("KK:%s,%s/%s;",$order->getCreditCardNo(),$order->getCreditCardMonth(),$order->getCreditCardYear());
  207.         }
  208.         $idx 0;
  209.         /** @var Address $address */
  210.         foreach ($order->getAddressList() as $address)
  211.         {
  212.             if ($address->getBeDeleted()) continue; // maybe deleted already but still available in the current instance
  213.             $comment .= /*sprintf("Quick%d:",$idx+1) .*/ $address->getName();
  214.             if ($address->getPassenger()!=""$comment .= sprintf("(%s)",$address->getPassenger());
  215.             if ($address->getCreditCardNo()!=""$comment .= sprintf("(KK:%s,%s/%s)",$address->getCreditCardNo(),$address->getCreditCardMonth(),$address->getCreditCardYear());
  216.             if ($address->getMobileNumber()!=""$comment.= sprintf("(Tel:%s)",$address->getMobileNumber());
  217.             if ($idx $order->getAddressList()->count()-1$comment.=">";
  218.             /** @var SimpleXMLElement $wp */
  219.             $wp $fa->addChild("Wegpunkt");
  220.             $einaus = ($idx $order->getAddressList()->count()-"Einstieg" "Ausstieg"); // only last waypoint is exit
  221.             $wp->addAttribute("Typ",$einaus);
  222.             if ($idx == 0$wp->addChild("Zeit",$order->getOrderTime()->format($this::TimestampFormat)); // Timestamp only relevant for first address
  223.             $a $wp->addChild("Adresse");
  224.             $a->addChild("Quick",htmlspecialchars($address->getName()));
  225.             $a->addChild("Ort",$address->getCity());
  226.             $a->addChild("PLZ",$address->getZipCode());
  227.             $street $address->getStreet();
  228.             // insert flight-no for first address if available
  229.             if (($idx==0)&&($order->getFlightNo()!=""))
  230.             {
  231.                 $street sprintf("%s; %s",$order->getFlightNo(),$street);
  232.             }
  233.             $a->addChild("Strasse",$street);
  234.             $a->addChild("HNr",$address->getNumber());
  235.             $idx++;
  236.             if ($this->trace)
  237.             {
  238.                  $this->logData(2,"createOrderXml():address".($idx-1).": ".$address->getName()."\n" );
  239.             }
  240.         }
  241.         $opt $fa->addChild("Optionen" implode(' '$order->getCustomer()->getTamiOptions()));
  242.         $comment .= ";;".$order->getComment();
  243.         $comment str_replace(";",",",$comment);
  244.         $comment str_replace("|",",",$comment);
  245.         $fa->addChild("Information"htmlspecialchars($comment));
  246.         if ($this->trace)
  247.         {
  248.             $this->logData(2,"createOrderXml()\n".$xml->asXML());
  249.         }
  250.         return $xml;
  251.     }
  252.     protected function processOrderConfirmation($responseTextOrder $order)
  253.     {
  254.         $root simplexml_load_string($responseText);
  255.         /** @var SimpleXMLElement $fab */
  256.         $faba $root->{"FahrAuftragBestaetigen"}->attributes();
  257.         $resultCode $faba["Ergebniscode"];
  258.         $resultMsg $faba["Ergebnistext"];
  259.         if ($resultCode==1)
  260.         {
  261.             $order->setRemoteOrderId(  $this->aid($faba));
  262.             $order->setRemoteOrderSubmittedTime(  new \DateTime() );
  263.             $order->setRemoteStatus(Order::REMOTE_SUCCESS);
  264.         }
  265.         else
  266.         {
  267.             $order->setRemoteStatus(Order::REMOTE_ERROR);
  268.         }
  269.         $order->setRemoteResult($resultCode);
  270.         $order->setRemoteResultText($resultMsg);
  271.         if ($this->additionalSysloggingSysLogRepository::logEntityOperation($this->db,self::LogResponse,"Order",$order->getId(),[],
  272.             sprintf("TaMi:FahrAuftragBestaetigen:%d:%s:%s",$resultCode,$resultMsg,$this->aid($faba,false)));
  273.         return ($order->getRemoteStatus()==Order::REMOTE_SUCCESS);
  274.     }
  275.     /**
  276.      * @param SimpleXMLElement $fasNode
  277.      * @return true|string true on success, else error message as string
  278.      */
  279.     protected function processStatusUpdateCallbackNode($fasNode)
  280.     {
  281.         $oid $this->aid($fasNode);
  282.         $status $fasNode->{"AuftragStatus"};
  283.         $rep $this->em->getRepository(Order::class);
  284.         /** @var Order $order */
  285.         $order $rep->findOneBy(array("remoteOrderId"=>$oid));
  286.         if (!is_object($order))
  287.         {
  288.             return "Unbekannte AuftragID";
  289.         }
  290.         $order->setOrderStatus($this->statusCache[(int)$status]);
  291.         return true;
  292.     }
  293.     /**
  294.      * @param $results array( AuftragID=>(true|string)
  295.      * @return SimpleXMLElement
  296.      */
  297.     protected function createStatusUpdateCallbackReponseXml($results)
  298.     {
  299.         $now = new \DateTime();
  300.         $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><VermAuftrag/>');
  301.         $xml->addAttribute("Sender",$this->clientID);
  302.         foreach ($results as $oid=>$status)
  303.         {
  304.             $fa $xml->addChild("FahrAuftragStatusBestaetigen");
  305.             $fa->addAttribute("AuftragID",$oid);
  306.             $fa->addAttribute("ZSt",$now->format($this::TimestampFormat));
  307.             $fa->addAttribute("Ergebniscode", ($status===trueself::TAMI_OK self::TAMI_ERR));
  308.             $fa->addAttribute("Ergebnistext", ($status!==true$status "OK"));
  309.         }
  310.         return $xml;
  311.     }
  312.     protected function VermAuftrag($xml)
  313.     {
  314.         $body $this->stripFirstLine$this->formatXml$xml ) );
  315.         $this->logData(0,$body);
  316.         $res $this->client->post($this->serverAddress "VermAuftrag" ,array(
  317.             'headers'   =>['Content-Type' => 'text/xml' ],
  318.             "body"      =>$body));
  319.         $resultXml $res->getBody()->getContents();
  320.         $this->logData(1,$resultXml);
  321.         if ($res->getStatusCode() != 200// actually on error status codes, guzzle itsself throws an exception beforehand
  322.         {
  323.             throw new \Exception(sprintf("HTTP %d: %s",$res->getStatusCode(),$res->getReasonPhrase()));
  324.         }
  325.         return $resultXml;
  326.     }
  327.     /**
  328.      * Create or update an order on remote TaMi Server
  329.      * TODO: directly link pricelist via entity, remove separate parameter
  330.      * @param Order $order
  331.      * @return bool
  332.      */
  333.     public function submitOrder(Order $order)
  334.     {
  335.         if ($this->additionalSysloggingSysLogRepository::logEntityOperation($this->db,self::LogRequest,"Order",$order->getId(),[],sprintf("TaMi:FahrAuftrag"));
  336.         try
  337.         {
  338.             $resultXml $this->VermAuftrag(  $this->createOrderXml($order) );
  339.             $ok $this->processOrderConfirmation($resultXml,$order);
  340.             $this->em->flush($order);
  341.             return $ok;
  342.         }
  343.         catch (\Exception $ex)
  344.         {
  345.             $order->setRemoteStatus(Order::REMOTE_ERROR);
  346.             $xtra "";
  347.             if ($ex instanceof GuzzleHttp\Exception\RequestException)
  348.             {
  349.                 $r $ex->getResponse();
  350.                 if (is_object($r)) $xtra $r->getBody();
  351.             }
  352.             else
  353.             {
  354.                 $xtra $ex->getTraceAsString();
  355.             }
  356.             SysLogRepository::logEntityOperation($this->db,self::LogResponse,"Order",$order->getId(),[],
  357.                 sprintf("TaMi:EXCEPTION:%s:%s",$ex->getMessage(),$xtra));
  358.         }
  359.         return false;
  360.     }
  361.     /**
  362.      * Cancel an open order on remote TaMi Server
  363.      * @param Order $order
  364.      * @return bool
  365.      */
  366.     public function cancelOrder(Order $order)
  367.     {
  368.         if ($this->additionalSysloggingSysLogRepository::logEntityOperation($this->db,self::LogRequest,"Order",$order->getId(),[],sprintf("TaMi:FahrauftragStorno"));
  369.         try
  370.         {
  371.             $resultXml $this->VermAuftrag(  $this->createStornoXml($order) );
  372.             $ok $this->processStornoConfirmation($resultXml,$order);
  373.             $this->em->flush($order);
  374.             return $ok;
  375.         }
  376.         catch (\Exception $ex)
  377.         {
  378.             $order->setRemoteStatus(Order::REMOTE_ERROR);
  379.             $xtra "";
  380.             if ($ex instanceof GuzzleHttp\Exception\RequestException)
  381.             {
  382.                 $r $ex->getResponse();
  383.                 if (is_object($r)) $xtra $r->getBody();
  384.             }
  385.             SysLogRepository::logEntityOperation($this->db,self::LogResponse,"Order",$order->getId(),[],
  386.                 sprintf("TaMi:EXCEPTION:%s:%s",$ex->getMessage(),$xtra));
  387.         }
  388.         return false;
  389.     }
  390.     /**
  391.      * React to a status callback coming from the remote TaMi Server
  392.      * @param Request $request
  393.      * @return Response
  394.      */
  395.     public function fahrAuftragStatusCallbackAction(Request $request)
  396.     {
  397.         if (!$this->tamiEnabled)
  398.         {
  399.             SysLogRepository::logEntityOperation($this->db,self::LogCallback,'',0,[],
  400.                 'Tami:fahrAuftragStatusCallback: Tami interface disabled.');
  401.             return new Response('Tami interface is disabled.',400);
  402.         }
  403.         // TODO: IP-Whitelisting to prevent malicious updates
  404.         try
  405.         {
  406.             $data $request->getContent();
  407.             SysLogRepository::logEntityOperation($this->db,self::LogCallback,'',0,[],
  408.                 sprintf("TaMi:fahrAuftragStatusCallback %s",$data));
  409.             $this->logData(1,$data);
  410.             $root simplexml_load_string$data );
  411.             $results = array();
  412.             foreach ($root->{"VermAuftrag"}->{"FahrAuftragStatus"} as $fas)
  413.             {
  414.                 $oid $this->aid($fas);
  415.                 $results [$oid] = $this->processStatusUpdateCallbackNode($fas);
  416.             }
  417.             $this->em->flush();
  418.             $responseText $this->createStatusUpdateCallbackReponseXml($results)->asXML();
  419.             $this->logData(0,$responseText);
  420.             return new Response($responseText200, ['Content-Type' => 'text/xml'] );
  421.         }
  422.         catch (\Exception $ex)
  423.         {
  424.             SysLogRepository::logEntityOperation($this->db,500,"",0,[],
  425.                 sprintf("TaMi:fahrAuftragStatusCallback:EXCEPTION:%s",$ex->getMessage()));
  426.             $r = new Response($ex->getMessage());
  427.             $r->setStatusCode(400,$ex->getMessage());
  428.             return $r;
  429.         }
  430.     }
  431.     protected function updateAvailabilityFromOrder(array $one,$knownOrder)
  432.     {
  433.         $rep $this->em->getRepository(Availability::class);
  434.         $mrep =  $this->em->getRepository(CoopMember::class);
  435.         $member $mrep->findOneBy(['number'=>$one['carId']]);
  436.         $av $rep->findOneBy(['createdFromRemoteOrderId'=>$one['orderId']]);
  437.         if ($av===null)
  438.         {
  439.             $av = new Availability();
  440.             $av->setAvailType(  $knownOrder Availability::KMG Availability::BASF );
  441.             $av->setCreatedFromRemoteOrderId($one['orderId']);
  442.         }
  443.         $av->setAvailFrom( new \DateTime($one['time']) );
  444.         $until = clone($av->getAvailFrom());
  445.         $until->add(new \DateInterval('PT1H'));
  446.         $av->setAvailUntil$until );
  447.         $av->setMember($member);
  448.         $statusText array_key_exists($one['tamiStatus'],self::$tamiStatusMap) ? self::$tamiStatusMap[$one['tamiStatus']] : $one['tamiStatus'];
  449.         $av->setExtraInfo(sprintf('#%s: %s',$one['orderId'],$statusText));
  450.         $rep->persistFlush($av);
  451.     }
  452.     public function updateCallbackAction(Request $request)
  453.     {
  454.         if (!$this->tamiEnabled)
  455.         {
  456.             SysLogRepository::logEntityOperation($this->db,self::LogCallback,'',0,[],
  457.                 'Tami:updateCallback: Tami interface is disabled');
  458.             return new JsonResponse(['success' =>false'message'=>'Tami interface is disabled']);
  459.         }
  460.         try
  461.         {
  462.             $xml $request->getContent();
  463.             $rep $this->em->getRepository(Order::class);
  464.             $this->logData(1,$xml);
  465.             $root simplexml_load_string$xml );
  466.             $data = [];
  467.             foreach ($root->{"JobList"}->{"Job"} as $job)
  468.             {
  469.                 $data []= [
  470.                     'orderId' => $this->aid($job),
  471.                     'carId' => (int)$job->{"FhzId"},
  472.                     'driverId' => (int)$job->{"FhrId"},
  473.                     'tamiStatus' => (int)$job->{"Status"},
  474.                     'time' => (string)$job->{"ZeitFahrt"}
  475.                 ]  ;
  476.             }
  477.             SysLogRepository::logEntityOperation($this->db,self::LogCallback,'',0,$data,
  478.                     sprintf("TaMi:Callback %s",$request->getMethod()));
  479.             foreach ($data as $one)
  480.             {
  481.                 /** @var Order $order */
  482.                 $order $rep->findOneBy(array("remoteOrderId"=>$one['orderId']));
  483.                 if ($order!==null)
  484.                 {
  485.                     $order->setOrderStatus($this->statusCache[$one['tamiStatus']]);
  486.                     $rep->flush($order);
  487.                     $this->updateAvailabilityFromOrder($one,true);
  488.                 }
  489.                 else
  490.                 {
  491.                     $this->updateAvailabilityFromOrder($one,false);
  492.                 }
  493.             }
  494.             return new JsonResponse(['success' =>true'data'=>$data]);
  495.         }
  496.         catch (\Exception $ex)
  497.         {
  498.             SysLogRepository::logEntityOperation($this->db,500,"",0,[],
  499.                 sprintf("TaMi:Callback:EXCEPTION:%s",$ex->getMessage()));
  500.             return new JsonResponse(['success' =>false'message'=>$ex->getMessage()]);
  501.         }
  502.     }
  503.     protected function createStornoXml(Order $order)
  504.     {
  505.         $now = new \DateTime();
  506.         $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><VermAuftrag/>',LIBXML_NOEMPTYTAG);
  507.         $xml->addAttribute("Sender",$this->clientID);
  508.         $fa $xml->addChild("FahrauftragStorno");
  509.         $fa->addAttribute("AuftragID",$order->getRemoteOrderId()); // created by remote server if empty, else handled as update
  510.         $fa->addAttribute("ZSt",$now->format($this::TimestampFormat));
  511.         return $xml;
  512.     }
  513.     protected function processStornoConfirmation($responseTextOrder $order)
  514.     {
  515.         $root simplexml_load_string($responseText);
  516.         /** @var SimpleXMLElement $fab */
  517.         $faba $root->{"FahrauftragStornoBestaetigen"}->attributes();
  518.         $resultCode $faba["Ergebniscode"];
  519.         $resultMsg $faba["Ergebnistext"];
  520.         $auftragId $this->aid($faba);
  521.         if ($resultCode==1)
  522.         {
  523.             // OrderStatus nicht mehr von Tami :: $order->setOrderStatus( $this->em->getReference("Diplix\\KMGBundle\\Entity\\OrderStatus",OrderStatus::STATUS_CANCELED) );
  524.             $order->setRemoteStatus(Order::REMOTE_SUCCESS);
  525.         }
  526.         else
  527.         {
  528.             $order->setRemoteStatus(Order::REMOTE_ERROR);
  529.         }
  530.         $order->setRemoteResult($resultCode);
  531.         $order->setRemoteResultText($resultMsg);
  532.         if ($this->additionalSysloggingSysLogRepository::logEntityOperation($this->db,self::LogResponse,"Order",$order->getId(),[],
  533.             sprintf("TaMi:FahrauftragStornoBestaetigen:%d:%s:%s",$resultCode,$resultMsg,$this->aid($faba,false)));
  534.         return ($order->getRemoteStatus()==Order::REMOTE_SUCCESS);
  535.     }
  536.     /**
  537.      * @param Order $order
  538.      * @return bool
  539.      */
  540.     public function getOrderStatus(Order $order)
  541.     {
  542.         if ($this->additionalSysloggingSysLogRepository::logEntityOperation($this->db,self::LogRequest,"Order",$order->getId(),[],sprintf("TaMi:FahrauftragStatus>"));
  543.         try
  544.         {
  545.             $resultXml $this->VermAuftrag(  $this->createStatusXml($order) );
  546.             $ok $this->processStatusResponse($resultXml,$order);
  547.             $this->em->flush($order);
  548.             return $ok;
  549.         }
  550.         catch (\Exception $ex)
  551.         {
  552.             $order->setRemoteStatus(Order::REMOTE_ERROR);
  553.             $xtra "";
  554.             if ($ex instanceof GuzzleHttp\Exception\RequestException)
  555.             {
  556.                 $r $ex->getResponse();
  557.                 if (is_object($r)) $xtra $r->getBody();
  558.             }
  559.             SysLogRepository::logEntityOperation($this->db,self::LogResponse,"Order",$order->getId(),[],
  560.                 sprintf("TaMi:EXCEPTION:%s:%s",$ex->getMessage(),$xtra));
  561.         }
  562.         return false;
  563.     }
  564.     protected function createStatusXml(Order $order)
  565.     {
  566.         $now = new \DateTime();
  567.         $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><VermAuftrag/>',LIBXML_NOEMPTYTAG);
  568.         $xml->addAttribute("Sender",$this->clientID);
  569.         $fa $xml->addChild("FahrauftragStatus");
  570.         $fa->addAttribute("AuftragID",$order->getRemoteOrderId()); // created by remote server if empty, else handled as update
  571.         $fa->addAttribute("ZSt",$now->format($this::TimestampFormat));
  572.         return $xml;
  573.     }
  574.      protected function processStatusResponse($responseTextOrder $order)
  575.     {
  576.         $root simplexml_load_string($responseText);
  577.         /** @var SimpleXMLElement $fab */
  578.         $faba $root->{"FahrauftragStatusBestaetigen"}->attributes();
  579.         $resultCode $faba["Ergebniscode"];
  580.         $resultMsg $faba["Ergebnistext"];
  581.         $auftragId $this->aid($faba);
  582.        if ($this->additionalSyslogging)  SysLogRepository::logEntityOperation($this->db,self::LogResponse,"Order",$order->getId(),[],
  583.             sprintf("TaMi:FahrauftragStatusBestaetigen:%d:%s:%s",$resultCode,$resultMsg,$this->aid($faba,false)));
  584.         if ($resultCode==1)
  585.         {
  586.             $status = (int)$root->{"FahrauftragStatusBestaetigen"}->{'AuftragStatus'};
  587.             if (array_key_exists($status,$this->statusCache))
  588.             {
  589.                 $order->setOrderStatus(  $this->statusCache[$status] );
  590.             }
  591.             else
  592.             {
  593.                 if ($this->additionalSysloggingSysLogRepository::logEntityOperation($this->db,self::LogResponse,"Order",$order->getId(),[],
  594.                     sprintf("TaMi:FahrauftragStatusBestaetigen:Unbekannter Status Code:%d",$status));
  595.                 return false;
  596.             }
  597.         }
  598.         else
  599.         {
  600.             // ignore on error
  601.         }
  602.         // being unable to update the status should not set the whole order to be in REMOTE_ERROR state
  603.         // nor change the result of the last active operation
  604.         // that's why we dont update the entities remote status fields
  605.         return ($resultCode == 1);
  606.     }
  607. }