381 lines
14 KiB
PHP
381 lines
14 KiB
PHP
<?php
|
|
|
|
namespace KupShop\CeskaPostaBundle;
|
|
|
|
use Psr\Log\LoggerInterface;
|
|
|
|
class CeskaPosta
|
|
{
|
|
protected $idContract;
|
|
protected $customerID;
|
|
protected $postCode;
|
|
protected $locationNumber;
|
|
protected $idExtTransaction;
|
|
|
|
public $ns = 'https://b2b.postaonline.cz/schema/B2BCommon-v1';
|
|
public $ns2 = 'https://b2b.postaonline.cz/schema/POLServices-v1';
|
|
|
|
public $request_url;
|
|
public $request;
|
|
public $response;
|
|
public $error;
|
|
protected $logger;
|
|
|
|
public function __construct(LoggerInterface $logger)
|
|
{
|
|
$this->logger = $logger;
|
|
$this->idContract = findModule(\Modules::CESKA_POSTA, 'idContract');
|
|
$this->customerID = findModule(\Modules::CESKA_POSTA, 'customerID');
|
|
$this->postCode = findModule(\Modules::CESKA_POSTA, 'postCode');
|
|
$this->locationNumber = findModule(\Modules::CESKA_POSTA, 'locationNumber');
|
|
}
|
|
|
|
public function configure($idContract, $customerID, $postCode, $locationNumber)
|
|
{
|
|
$this->idContract = $idContract;
|
|
$this->customerID = $customerID;
|
|
$this->postCode = $postCode;
|
|
$this->locationNumber = $locationNumber;
|
|
}
|
|
|
|
public function getHeader($type = '')
|
|
{
|
|
$this->idExtTransaction++;
|
|
$header = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<b2bRequest xmlns="'.$this->ns.'" xmlns:ns2="'.$this->ns2.'">
|
|
<header>
|
|
<idExtTransaction>'.$this->idExtTransaction.'</idExtTransaction>
|
|
<timeStamp>'.date('Y-m-d\TH:i:s.vP').'</timeStamp>
|
|
<idContract>'.$this->idContract.'</idContract>
|
|
</header>
|
|
';
|
|
if ($type == 'getParcelsPrinting') {
|
|
$header .= '<serviceData>
|
|
<ns2:getParcelsPrinting>
|
|
<ns2:doPrintingHeader>
|
|
<ns2:customerID>'.$this->customerID.'</ns2:customerID>
|
|
<ns2:contractNumber>'.$this->idContract.'</ns2:contractNumber>
|
|
<ns2:shiftHorizontal>0</ns2:shiftHorizontal>
|
|
<ns2:shiftVertical>0</ns2:shiftVertical>
|
|
</ns2:doPrintingHeader>
|
|
<ns2:doPrintingData></ns2:doPrintingData>
|
|
</ns2:getParcelsPrinting>
|
|
</serviceData>
|
|
';
|
|
}
|
|
if ($type == 'sendParcels') {
|
|
$header .= '<serviceData>
|
|
<ns2:sendParcels>
|
|
<ns2:doParcelHeader>
|
|
<ns2:transmissionDate>'.date('d.m.Y').'</ns2:transmissionDate>
|
|
<ns2:customerID>'.$this->customerID.'</ns2:customerID>
|
|
<ns2:postCode>'.$this->postCode.'</ns2:postCode>
|
|
<ns2:locationNumber>'.$this->locationNumber.'</ns2:locationNumber>
|
|
</ns2:doParcelHeader>
|
|
<ns2:doParcelData>
|
|
<ns2:doParcelParams></ns2:doParcelParams>
|
|
<ns2:doParcelAddress></ns2:doParcelAddress>
|
|
</ns2:doParcelData>
|
|
</ns2:sendParcels>
|
|
</serviceData>
|
|
';
|
|
}
|
|
|
|
$header .= '</b2bRequest>';
|
|
$simple_xml = simplexml_load_string($header);
|
|
|
|
return $simple_xml;
|
|
}
|
|
|
|
public function get_b2bRequest($order, $type = 'sendParcels')
|
|
{
|
|
$b2bRequest = $this->getHeader($type);
|
|
$serviceData = $b2bRequest->serviceData;
|
|
|
|
$doParcelParams = $serviceData->children('ns2', true)->sendParcels->doParcelData->doParcelParams;
|
|
$doParcelParams->addChild('ns2:recordID', $order->id, $this->ns2);
|
|
$doParcelParams->addChild('ns2:currency', $order->currency, $this->ns2);
|
|
|
|
$delivery_address = !empty($order->delivery_street); // true - use delivery address, false - use invoice address
|
|
|
|
// surname = name surname firm
|
|
// surname - string50
|
|
$surname = ($delivery_address ? $order->delivery_name : $order->invoice_name).' ';
|
|
$surname .= $delivery_address ? $order->delivery_surname.(!empty($order->delivery_firm) ? ' '.$order->delivery_firm : '') : $order->invoice_surname;
|
|
|
|
// street - string40
|
|
$street = $delivery_address ? $order->delivery_street : $order->invoice_street;
|
|
|
|
// firstName = custom_address (Address line 2 / Upřesnění adresy), if exists
|
|
// firstName - string50
|
|
$custom_address = ($delivery_address && !empty($order->delivery_custom_address)) ? ', '.$order->delivery_custom_address : (!$delivery_address && !empty($order->invoice_custom_address) ? ', '.$order->invoice_custom_address : '');
|
|
|
|
// city = city, state
|
|
// city - string40
|
|
$city = $delivery_address ? $order->delivery_city : $order->invoice_city;
|
|
$city .= ($delivery_address && !empty($order->delivery_state)) ? ', '.$order->delivery_state : (!$delivery_address && !empty($order->invoice_state) ? ', '.$order->invoice_state : '');
|
|
|
|
// zipCode - string25
|
|
$zip = $delivery_address ? $order->delivery_zip : $order->invoice_zip;
|
|
|
|
$country = $delivery_address ? $order->delivery_country : $order->invoice_country;
|
|
|
|
if ($transliterator = \Transliterator::create('Russian-Latin/BGN')) {
|
|
$surname = $transliterator->transliterate($surname);
|
|
$street = $transliterator->transliterate($street);
|
|
$custom_address = $transliterator->transliterate($custom_address);
|
|
$city = $transliterator->transliterate($city);
|
|
}
|
|
|
|
if (mb_strlen($surname) > 50) {
|
|
$surname = mb_substr($surname, 0, 50);
|
|
}
|
|
if (mb_strlen($city) > 40) {
|
|
$city = mb_substr($city, 0, 40);
|
|
}
|
|
|
|
$doParcelAddress = $serviceData->children('ns2', true)->sendParcels->doParcelData->doParcelAddress;
|
|
$doParcelAddress->addChild('ns2:surname', '', $this->ns2)[0] = trim($surname);
|
|
if (!empty($custom_address)) {
|
|
$doParcelAddress->addChild('ns2:firstName', '', $this->ns2)[0] = trim($custom_address);
|
|
}
|
|
$doParcelAddress->addChild('ns2:subject', 'F', $this->ns2);
|
|
$doParcelAddress->addChild('ns2:street', '', $this->ns2)[0] = trim($street);
|
|
$doParcelAddress->addChild('ns2:city', '', $this->ns2)[0] = trim($city);
|
|
$doParcelAddress->addChild('ns2:zipCode', '', $this->ns2)[0] = trim($zip);
|
|
$doParcelAddress->addChild('ns2:isoCountry', trim($country), $this->ns2);
|
|
if (in_array($country, ['US', 'MX', 'AU', 'BR', 'CA', 'ES'])) {
|
|
$state = ($delivery_address && !empty($order->delivery_state)) ? $order->delivery_state : $order->invoice_state;
|
|
$doParcelAddress->addChild('ns2:subIsoCountry', trim($state), $this->ns2);
|
|
}
|
|
$doParcelAddress->addChild('ns2:emailAddress', $order->invoice_email, $this->ns2);
|
|
$phone = trim($order->invoice_phone);
|
|
if (mb_strlen($phone) > 13) {
|
|
$phone = mb_substr($phone, mb_strlen($phone) - 13);
|
|
}
|
|
$doParcelAddress->addChild('ns2:mobileNumber', '', $this->ns2)[0] = trim($phone);
|
|
|
|
return $b2bRequest;
|
|
}
|
|
|
|
public function sendParcels($b2bRequest)
|
|
{
|
|
$this->request_url = 'https://b2b.postaonline.cz/services/POLService/v1/sendParcels';
|
|
|
|
$this->request = $b2bRequest->asXML();
|
|
|
|
if (!$this->sendToCeskaPosta($this->request, $this->request_url)) {
|
|
return false;
|
|
}
|
|
$parser = xml_parser_create();
|
|
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
|
|
if (!xml_parse_into_struct($parser, $this->response, $values, $index)) {
|
|
$this->error = 'xml_parse error: '.xml_error_string(xml_get_error_code($parser)).' at line '.xml_get_current_line_number($parser);
|
|
xml_parser_free($parser);
|
|
|
|
return false;
|
|
}
|
|
xml_parser_free($parser);
|
|
if (array_key_exists('v1:B2BFaultMessage', $index)) {
|
|
$i = $index['v1:errorDetail'][0];
|
|
$v = $values[$i]['value'];
|
|
$this->error = 'Error! B2BFaultMessage: '.$v;
|
|
|
|
return false;
|
|
}
|
|
if (!array_key_exists('v1:b2bASyncResponse', $index)) {
|
|
$this->error = 'Error! No b2bASyncResponse!';
|
|
|
|
return false;
|
|
}
|
|
if (!array_key_exists('v1:idTransaction', $index)) {
|
|
$this->error = 'Error! No idTransaction!';
|
|
|
|
return false;
|
|
}
|
|
$i = $index['v1:idTransaction'][0];
|
|
$idTransaction = $values[$i]['value'];
|
|
|
|
return $idTransaction;
|
|
}
|
|
|
|
public function getResultParcels($idTransaction)
|
|
{
|
|
$this->request_url = 'https://b2b.postaonline.cz/services/POLService/v1/getResultParcels';
|
|
|
|
$b2bRequest = $this->getHeader('getResultParcels');
|
|
$b2bRequest->addChild('idTransaction', $idTransaction);
|
|
$this->request = $b2bRequest->asXML();
|
|
|
|
if (!$this->sendToCeskaPosta($this->request, $this->request_url)) {
|
|
return false;
|
|
}
|
|
$parser = xml_parser_create();
|
|
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
|
|
if (!xml_parse_into_struct($parser, $this->response, $values, $index)) {
|
|
$this->error = 'xml_parse error: '.xml_error_string(xml_get_error_code($parser)).' at line '.xml_get_current_line_number($parser);
|
|
xml_parser_free($parser);
|
|
|
|
return false;
|
|
}
|
|
xml_parser_free($parser);
|
|
if (array_key_exists('v1:B2BFaultMessage', $index)) {
|
|
$i = $index['v1:errorDetail'][0];
|
|
$v = $values[$i]['value'];
|
|
$this->error = 'Error! B2BFaultMessage: '.$v;
|
|
$i = $index['v1:errorCode'][0];
|
|
$errorCode = $values[$i]['value'];
|
|
if ($errorCode == 10) {
|
|
// 10 = UNFINISHED_PROCESS = Zpracování není ještě ukončeno
|
|
sleep(1);
|
|
|
|
return $this->getResultParcels($idTransaction);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
if (!array_key_exists('v1_1:responseCode', $index)) {
|
|
$this->error = 'Error! No responseCode!';
|
|
|
|
return false;
|
|
}
|
|
$i = $index['v1_1:responseCode'][0];
|
|
$responseCode = $values[$i]['value'];
|
|
if ($responseCode != '1') {
|
|
$this->error = 'Error! ';
|
|
foreach ($index['v1_1:responseCode'] as $key => $i) {
|
|
$responseCode = $values[$i]['value'];
|
|
$i = $index['v1_1:responseText'][$key];
|
|
$v = $values[$i]['value'];
|
|
$this->error .= $responseCode.': '.$v.'; ';
|
|
}
|
|
|
|
// ignore error
|
|
// 09.03.2018:
|
|
// getResultParcels vrati Error! 19: BATCH_INVALID, i kdyz je vsechno OK,
|
|
// a vrati take parcelCode
|
|
return false;
|
|
}
|
|
if (!array_key_exists('v1_1:parcelCode', $index)) {
|
|
$this->error .= 'Error! No parcelCode!';
|
|
|
|
return false;
|
|
}
|
|
$parcelCode = [];
|
|
foreach ($index['v1_1:parcelCode'] as $i) {
|
|
$parcelCode[] = $values[$i]['value'];
|
|
}
|
|
|
|
return array_unique($parcelCode);
|
|
}
|
|
|
|
public function getParcelsPrinting($parcelCode, $idForm, $print_position = null)
|
|
{
|
|
$this->request_url = 'https://b2b.postaonline.cz/services/POLService/v1/getParcelsPrinting';
|
|
|
|
$b2bRequest = $this->getHeader('getParcelsPrinting');
|
|
$serviceData = $b2bRequest->serviceData;
|
|
$doPrintingHeader = $serviceData->children('ns2', true)->getParcelsPrinting->doPrintingHeader;
|
|
$doPrintingHeader->addChild('ns2:idForm', $idForm, $this->ns2);
|
|
if ($print_position) {
|
|
$doPrintingHeader->addChild('ns2:position', $print_position, $this->ns2);
|
|
}
|
|
$doPrintingData = $serviceData->children('ns2', true)->getParcelsPrinting->doPrintingData;
|
|
foreach ($parcelCode as $code) {
|
|
$doPrintingData->addChild('ns2:parcelCode', $code, $this->ns2);
|
|
}
|
|
|
|
$this->request = $b2bRequest->asXML();
|
|
|
|
if (!$this->sendToCeskaPosta($this->request, $this->request_url)) {
|
|
return false;
|
|
}
|
|
$parser = xml_parser_create();
|
|
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
|
|
if (!xml_parse_into_struct($parser, $this->response, $values, $index)) {
|
|
$this->error = 'xml_parse error: '.xml_error_string(xml_get_error_code($parser)).' at line '.xml_get_current_line_number($parser);
|
|
xml_parser_free($parser);
|
|
|
|
return false;
|
|
}
|
|
xml_parser_free($parser);
|
|
if (array_key_exists('v1:B2BFaultMessage', $index)) {
|
|
$i = $index['v1:errorDetail'][0];
|
|
$v = $values[$i]['value'];
|
|
$this->error = 'Error! B2BFaultMessage: '.$v;
|
|
|
|
return false;
|
|
}
|
|
if (!array_key_exists('v1_1:responseCode', $index)) {
|
|
$this->error = 'Error! No responseCode!';
|
|
|
|
return false;
|
|
}
|
|
$i = $index['v1_1:responseCode'][0];
|
|
$responseCode = $values[$i]['value'];
|
|
if ($responseCode != '1') {
|
|
$i = $index['v1_1:responseText'][0];
|
|
$v = $values[$i]['value'];
|
|
$this->error = 'Error! '.$responseCode.': '.$v;
|
|
|
|
return false;
|
|
}
|
|
if (!array_key_exists('v1_1:file', $index)) {
|
|
$this->error = 'Error! No file!';
|
|
|
|
return false;
|
|
}
|
|
$i = $index['v1_1:file'][0];
|
|
$f = $values[$i]['value'];
|
|
|
|
$pdf = base64_decode($f);
|
|
|
|
return $pdf;
|
|
}
|
|
|
|
public function sendToCeskaPosta($request = '', $url = null)
|
|
{
|
|
$this->logger->notice('Ceska Posta Podani Online', ['request_url' => $url, 'request' => $request]);
|
|
$curl = $this->createCurl($request, $url);
|
|
$this->response = curl_exec($curl);
|
|
if ($this->response === false) {
|
|
$this->error = 'curl_error: '.curl_error($curl);
|
|
$this->logger->notice('Ceska Posta Podani Online', ['error' => $this->error]);
|
|
|
|
return false;
|
|
} else {
|
|
$this->error = '';
|
|
$this->logger->notice('Ceska Posta Podani Online', ['response' => $this->response]);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public function createCurl($encodedBody, $url = null)
|
|
{
|
|
if (empty($url)) {
|
|
$url = $this->request_url;
|
|
}
|
|
|
|
$curl = curl_init();
|
|
curl_setopt($curl, CURLOPT_URL, $url);
|
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
|
// curl_setopt($curl, CURLOPT_VERBOSE, true);
|
|
// curl_setopt($curl, CURLOPT_CERTINFO, true);
|
|
|
|
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
|
|
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
|
|
curl_setopt($curl, CURLOPT_CAINFO, __DIR__.DIRECTORY_SEPARATOR.'Resources/Certificates/postsignum_vca4.pem');
|
|
|
|
curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'P12');
|
|
curl_setopt($curl, CURLOPT_SSLCERT, __DIR__.DIRECTORY_SEPARATOR.'Resources/Certificates/post_2024.p12');
|
|
curl_setopt($curl, CURLOPT_SSLCERTPASSWD, 'wpj');
|
|
|
|
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
|
|
curl_setopt($curl, CURLOPT_POSTFIELDS, $encodedBody);
|
|
|
|
return $curl;
|
|
}
|
|
}
|