Advertisement
Guest User

Untitled

a guest
Jan 29th, 2019
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.92 KB | None | 0 0
  1. <?php
  2.  
  3. namespace Reev\Rfc\Model;
  4.  
  5. class FelRfc
  6. {
  7. const XML_PATH_FEEL_RFC_ENABLE = 'fel_rfc/general/enable';
  8. const XML_PATH_FEEL_RFC_ENDPOINT_URI = 'fel_rfc/general/endpoint_uri';
  9. const XML_PATH_FEEL_RFC_ACCOUNT = 'fel_rfc/general/account';
  10. const XML_PATH_FEEL_RFC_PASSWORD = 'fel_rfc/general/password';
  11. const XML_PATH_FEEL_RFC_USER = 'fel_rfc/general/user';
  12. const XML_PATH_FEEL_RFC_TEST_MODE = 'fel_rfc/general/test_mode';
  13. const XML_PATH_FEEL_RFC_TEST_ENDPOINT_URI = 'fel_rfc/general/test_endpoint_uri';
  14. const XML_PATH_FEEL_RFC_TEST_ACCOUNT = 'fel_rfc/general/test_account';
  15. const XML_PATH_FEEL_RFC_TEST_PASSWORD = 'fel_rfc/general/test_password';
  16. const XML_PATH_FEEL_RFC_TEST_USER = 'fel_rfc/general/test_user';
  17. const XML_PATH_FEEL_RFC_EMISOR_NAME = 'fel_rfc/emisor/issuing_name';
  18. const XML_PATH_FEEL_RFC_EMISOR_TAX_REGIME = 'fel_rfc/emisor/tax_regime';
  19. const XML_PATH_FEEL_RFC_EMISOR_CFDI_KEY = 'fel_rfc/emisor/cfdi_key';
  20. const XML_PATH_FEEL_RFC_EMISOR_CP_EXPEDITION = 'fel_rfc/emisor/cp_expedition';
  21. const XML_PATH_FEEL_RFC_TEMPLATE_NAME = 'fel_rfc/emisor/tempĺate';
  22. const XML_PATH_FEEL_RFC_TITLE_EMAIL = 'fel_rfc/emisor/title_email';
  23. const XML_PATH_FEEL_RFC_MESSAGE_EMAIL = 'fel_rfc/emisor/message_email';
  24.  
  25. const STORE_SCOPE = \Magento\Store\Model\ScopeInterface::SCOPE_STORE;
  26.  
  27. protected $resultPageFactory;
  28. protected $scopeConfig;
  29. protected $cfdiFactory;
  30. protected $rfcFactory;
  31. protected $pricingHelper;
  32.  
  33. public function __construct(
  34. \Magento\Framework\View\Result\PageFactory $resultPageFactory,
  35. \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
  36. \Reev\Rfc\Model\RfcFactory $rfcFactory,
  37. \Reev\Rfc\Model\CfdiFactory $cfdiFactory,
  38. \Magento\Framework\Pricing\Helper\Data $pricingHelper)
  39. {
  40. $this->resultPageFactory = $resultPageFactory;
  41. $this->scopeConfig = $scopeConfig;
  42. $this->rfcFactory = $rfcFactory;
  43. $this->cfdiFactory = $cfdiFactory;
  44. $this->pricingHelper = $pricingHelper;
  45. }
  46.  
  47. public function createCfdi(\Magento\Sales\Model\Order $order)
  48. {
  49. if($this->isModuleEnable() && $order->getId()) {
  50. if($this->isTestMode())
  51. $endpointUri = $this->getTestEndpointUri();
  52. else
  53. $endpointUri = $this->getEndpointUri();
  54. $soap = new \SoapClient($endpointUri.'?WSDL');
  55.  
  56. $xml_request = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:tes="http://schemas.datacontract.org/2004/07/TES.V33.CFDI.Negocios">
  57. <soapenv:Header />
  58. <soapenv:Body>
  59. <tem:GenerarCFDI>
  60. <tem:credenciales>
  61. <tes:Cuenta>'.$this->getAccount().'</tes:Cuenta>
  62. <tes:Password>'.$this->getPassword().'</tes:Password>
  63. <tes:Usuario>'.$this->getUser().'</tes:Usuario>
  64. </tem:credenciales>
  65. <tem:cfdi>
  66. <tes:ClaveCFDI>'.$this->getEmisorCfdiKey().'</tes:ClaveCFDI>
  67. <tes:Conceptos>'.$this->getConcepts($order).'</tes:Conceptos>
  68. <tes:Emisor>
  69. <tes:Nombre>'.$this->getEmisorName().'</tes:Nombre>
  70. <tes:RegimenFiscal>'.$this->getEmisorTaxRegime().'</tes:RegimenFiscal>
  71. </tes:Emisor>
  72. <tes:LugarExpedicion>'.$this->getEmisorCpExpedition().'</tes:LugarExpedicion>
  73. <tes:Moneda>MXN</tes:Moneda>
  74. <tes:Receptor>'.$this->getReceptor($order).'</tes:Receptor>
  75. <tes:SubTotal>'.$this->pricingHelper->currency($order->getBaseSubtotalInclTax(),false,false).'</tes:SubTotal>
  76. <tes:Total>'.$this->pricingHelper->currency($order->getBaseSubtotalInclTax(),false,false).'</tes:Total>
  77. </tem:cfdi>
  78. </tem:GenerarCFDI>
  79. </soapenv:Body>
  80. </soapenv:Envelope>';
  81.  
  82. try {
  83. $soapXMLResult = $soap->__doRequest($xml_request,
  84. $endpointUri,
  85. 'http://tempuri.org/IConexionRemota/GenerarCFDI',
  86. '1.2');
  87.  
  88. $soapXMLResult = $this->deleteAllBetween('<a:CBB>','</a:CBB>',$soapXMLResult);
  89. $obj = new \SimpleXMLElement($soapXMLResult);
  90. $dataArr = $this->xmlNodeToArray($obj);
  91. $success = filter_var($dataArr['operacionexitosa'], FILTER_VALIDATE_BOOLEAN);
  92. $uuid = $this->saveInDb($xml_request, $dataArr, $order, $success);
  93. if($success && !empty($uuid)){
  94. $sendToMail = $this->sendCfdiToEmail($uuid, $order->getCustomerEmail());
  95. if($sendToMail['success'])
  96. $this->saveMailSentInDb($order);
  97. }
  98. return ['success'=>$success,'message'=>$dataArr['errorgeneral']];
  99.  
  100. }catch(Exception $e){
  101. return ['success'=>false,'message'=>$e->getMessage()];
  102. }
  103. }
  104. return ['success'=>false,'message'=>__('The module is not enabled, or there is not an order to create the cfdi')];
  105. }
  106.  
  107. public function sendCfdiToEmail($uuid, $email){
  108. if($this->isTestMode())
  109. $endpointUri = $this->getTestEndpointUri();
  110. else
  111. $endpointUri = $this->getEndpointUri();
  112. $soap = new \SoapClient($endpointUri.'?WSDL');
  113.  
  114. $xml_request = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:tes="http://schemas.datacontract.org/2004/07/TES.V33.CFDI.Negocios">
  115. <soapenv:Header />
  116. <soapenv:Body>
  117. <tem:EnviarCFDI>
  118. <tem:credenciales>
  119. <tes:Cuenta>'.$this->getAccount().'</tes:Cuenta>
  120. <tes:Password>'.$this->getPassword().'</tes:Password>
  121. <tes:Usuario>'.$this->getUser().'</tes:Usuario>
  122. </tem:credenciales>
  123. <tem:uuid>'.$uuid.'</tem:uuid>
  124. <tem:email>'.$email.'</tem:email>
  125. <tem:titulo>'.$this->getTitleEmailCfdi().'</tem:titulo>
  126. <tem:mensaje>'.$this->getMessageEmailCfdi().'</tem:mensaje>
  127. <tem:nombrePlantilla>'.$this->getTemplateName().'</tem:nombrePlantilla>
  128. </tem:EnviarCFDI>
  129. </soapenv:Body>
  130. </soapenv:Envelope>';
  131. try {
  132. $soapXMLResult = $soap->__doRequest($xml_request,
  133. $endpointUri,
  134. 'http://tempuri.org/IConexionRemota/EnviarCFDI',
  135. '1.2');
  136.  
  137. $soapXMLResult = $this->deleteAllBetween('<a:CBB>','</a:CBB>',$soapXMLResult);
  138. $obj = new \SimpleXMLElement($soapXMLResult);
  139. $dataArr = $this->xmlNodeToArray($obj);
  140. $success = filter_var($dataArr['operacionexitosa'], FILTER_VALIDATE_BOOLEAN);
  141. return ['success'=>$success,'message'=>$dataArr['errorgeneral']];
  142.  
  143. }catch(Exception $e){
  144. return ['success'=>false,'message'=>$e->getMessage()];
  145. }
  146.  
  147. }
  148.  
  149. public function getPdf($uuid){
  150. if($this->isModuleEnable()){
  151. if($this->isTestMode())
  152. $endpointUri = $this->getTestEndpointUri();
  153. else
  154. $endpointUri = $this->getEndpointUri();
  155. $soap = new \SoapClient($endpointUri.'?WSDL');
  156.  
  157. $xml_request = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:tes="http://schemas.datacontract.org/2004/07/TES.V33.CFDI.Negocios">
  158. <soapenv:Header/>
  159. <soapenv:Body>
  160. <tem:ObtenerPDF>
  161. <tem:credenciales>
  162. <tes:Cuenta>'.$this->getAccount().'</tes:Cuenta>
  163. <tes:Password>'.$this->getPassword().'</tes:Password>
  164. <tes:Usuario>'.$this->getUser().'</tes:Usuario>
  165. </tem:credenciales>
  166. <tem:uuid>'.$uuid.'</tem:uuid>
  167. <tem:nombrePlantilla>'.$this->getTemplateName().'</tem:nombrePlantilla>
  168. </tem:ObtenerPDF>
  169. </soapenv:Body>
  170. </soapenv:Envelope>';
  171.  
  172. try {
  173. $soapXMLResult = $soap->__doRequest($xml_request,
  174. $endpointUri,
  175. 'http://tempuri.org/IConexionRemota/ObtenerPDF',
  176. '1.2');
  177.  
  178. $obj = new \SimpleXMLElement($soapXMLResult);
  179.  
  180. $dataArr = $this->xmlNodeToArray($obj);
  181. $success = filter_var($dataArr['operacionexitosa'], FILTER_VALIDATE_BOOLEAN);
  182. return ['success'=>$success,'message'=>$dataArr['errorgeneral']];
  183.  
  184. }catch(Exception $e){
  185. return ['success'=>false,'message'=>$e->getMessage()];
  186. }
  187. }
  188. return ['success'=>false,'message'=>__('The module is not enabled, or there is not an order to create the cfdi')];
  189. }
  190.  
  191. public function getConcepts(\Magento\Sales\Model\Order $order){
  192. $str = '';
  193. foreach($order->getAllItems() as $item){
  194. $str .= '<tes:ConceptoR>
  195. <tes:Cantidad>'.$item->getQtyOrdered().'</tes:Cantidad>
  196. <tes:ClaveProdServ>'.$item->getProduct()->getSatrfcproducto().'</tes:ClaveProdServ>
  197. <tes:ClaveUnidad>H87</tes:ClaveUnidad>
  198. <tes:Descripcion>'.htmlspecialchars($item->getProduct()->getName()).'</tes:Descripcion>
  199. <tes:Importe>'.$this->pricingHelper->currency($item->getBaseRowTotalInclTax(),false,false).'</tes:Importe>
  200. <tes:NoIdentificacion>'.$item->getSku().'</tes:NoIdentificacion>
  201. <tes:ValorUnitario>'.$this->pricingHelper->currency($item->getBasePriceInclTax(),false,false).'</tes:ValorUnitario>
  202. <tes:Unidad>Pieza</tes:Unidad>
  203. </tes:ConceptoR>';
  204. }
  205. return $str;
  206. }
  207.  
  208. public function getReceptor(\Magento\Sales\Model\Order $order){
  209. $rfc = $this->rfcFactory->create()->load($order->getCustomerRfcId());
  210. $str = '';
  211. if($rfc->getId()) {
  212. $str = '<tes:Nombre>' . $rfc->getCompany() . '</tes:Nombre>
  213. <tes:Rfc>' . $rfc->getRfc() . '</tes:Rfc>
  214. <tes:UsoCFDI>' . $rfc->getCfdiCode() . '</tes:UsoCFDI>';
  215. }
  216. return $str;
  217. }
  218.  
  219. protected function xmlNodeToArray(\SimpleXMLElement $node)
  220. {
  221. $collectedKeys = [];
  222. $data = [];
  223. $namespaces = $node->getNamespaces(true);
  224.  
  225. foreach ($node->children($namespaces['s'])->children()->children()->children($namespaces['a']) as $label => $node) {
  226. $key = $this->mapKey($this->snakeToCamel($label));
  227. $childData = $this->extractNodeInformation($node);
  228.  
  229. if (isset($data[$key])) {
  230.  
  231. if (!isset($collectedKeys[$key])) {
  232. $collectedKeys[$key] = true;
  233. $data[$key] = [$data[$key]];
  234. }
  235.  
  236. $data[$key][] = $childData;
  237. } else {
  238. $data[$key] = $childData;
  239. }
  240. }
  241.  
  242. return $data;
  243. }
  244.  
  245. protected function mapKey(string $key)
  246. {
  247. $lcKey = str_replace('_', '', strtolower($key));
  248.  
  249. if (isset($this->keyMap[$lcKey])) {
  250. return $this->keyMap[$lcKey];
  251. }
  252.  
  253. return $key;
  254. }
  255.  
  256. protected function snakeToCamel($snakeString): string
  257. {
  258. // This line is why Elixir > PHP
  259. return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', strtolower($snakeString)))));
  260. }
  261.  
  262. protected function extractNodeInformation(\SimpleXMLElement $node)
  263. {
  264. $attributes = (array)$node->attributes();
  265. $nodeData = $this->getNodeValue($node);
  266.  
  267. if (count($attributes)) {
  268. $attributes = current($attributes);
  269. $data = ['attributes' => []];
  270.  
  271. foreach ($attributes as $attributeKey => $attributeValue) {
  272. $data['attributes'][$this->snakeToCamel($attributeKey)] = (string)$attributeValue;
  273. }
  274.  
  275. $data['value'] = $nodeData;
  276.  
  277. return $data;
  278. }
  279.  
  280. return $nodeData;
  281. }
  282.  
  283. protected function getNodeValue(\SimpleXMLElement $node)
  284. {
  285. if ($node->count()) {
  286. return $this->xmlNodeToArray($node);
  287. }
  288.  
  289. $stringValue = (string)$node;
  290.  
  291. return is_numeric($stringValue) ? (float)$stringValue : $stringValue;
  292. }
  293.  
  294. protected function deleteAllBetween($beginning, $end, $string) {
  295. $beginningPos = strpos($string, $beginning);
  296. $endPos = strpos($string, $end);
  297. if ($beginningPos === false || $endPos === false) {
  298. return $string;
  299. }
  300.  
  301. $textToDelete = substr($string, $beginningPos, ($endPos + strlen($end)) - $beginningPos);
  302.  
  303. return str_replace($textToDelete, '', $string); // recursion to ensure all occurrences are replaced
  304. }
  305.  
  306. public function isModuleEnable($storeScope = self::STORE_SCOPE){
  307. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_ENABLE, $storeScope);
  308. }
  309.  
  310. public function getEndpointUri($storeScope = self::STORE_SCOPE){
  311. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_ENDPOINT_URI, $storeScope);
  312. }
  313.  
  314. public function getAccount($storeScope = self::STORE_SCOPE){
  315. if($this->isTestMode())
  316. return $this->getTestAccount();
  317. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_ACCOUNT, $storeScope);
  318. }
  319.  
  320. public function getPassword($storeScope = self::STORE_SCOPE){
  321. if($this->isTestMode())
  322. return $this->getTestPassword();
  323. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_PASSWORD, $storeScope);
  324. }
  325.  
  326. public function getUser($storeScope = self::STORE_SCOPE){
  327. if($this->isTestMode())
  328. return $this->getTestUser();
  329. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_USER, $storeScope);
  330. }
  331.  
  332. public function isTestMode($storeScope = self::STORE_SCOPE){
  333. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_TEST_MODE, $storeScope);
  334. }
  335.  
  336. public function getTestEndpointUri($storeScope = self::STORE_SCOPE){
  337. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_TEST_ENDPOINT_URI, $storeScope);
  338. }
  339.  
  340. public function getTestAccount($storeScope = self::STORE_SCOPE){
  341. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_TEST_ACCOUNT, $storeScope);
  342. }
  343.  
  344. public function getTestPassword($storeScope = self::STORE_SCOPE){
  345. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_TEST_PASSWORD, $storeScope);
  346. }
  347.  
  348. public function getTestUser($storeScope = self::STORE_SCOPE){
  349. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_TEST_USER, $storeScope);
  350. }
  351.  
  352. public function getEmisorName($storeScope = self::STORE_SCOPE){
  353. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_EMISOR_NAME, $storeScope);
  354. }
  355.  
  356. public function getEmisorTaxRegime($storeScope = self::STORE_SCOPE){
  357. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_EMISOR_TAX_REGIME, $storeScope);
  358. }
  359.  
  360. public function getEmisorCfdiKey($storeScope = self::STORE_SCOPE){
  361. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_EMISOR_CFDI_KEY, $storeScope);
  362. }
  363.  
  364. public function getEmisorCpExpedition($storeScope = self::STORE_SCOPE){
  365. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_EMISOR_CP_EXPEDITION, $storeScope);
  366. }
  367.  
  368. public function getTemplateName($storeScope = self::STORE_SCOPE){
  369. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_TEMPLATE_NAME, $storeScope);
  370. }
  371.  
  372. public function getTitleEmailCfdi($storeScope = self::STORE_SCOPE){
  373. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_TITLE_EMAIL, $storeScope);
  374. }
  375.  
  376. public function getMessageEmailCfdi($storeScope = self::STORE_SCOPE){
  377. return $this->scopeConfig->getValue(self::XML_PATH_FEEL_RFC_MESSAGE_EMAIL, $storeScope);
  378. }
  379.  
  380. protected function saveInDb($request, $response, $order, $success){
  381. $cfdiRequest = $this->cfdiFactory->create();
  382. $uuid = null;
  383. if($success){
  384. $obj = new \SimpleXMLElement($response['xml']);
  385. $namespaces = $obj->getNamespaces(true);
  386. $child = $obj->children($namespaces['cfdi']);
  387. foreach($child as $key=>$node){
  388. if($key=='Complemento'){
  389. $uuid = $node->children($namespaces['tfd'])->attributes()['UUID'];
  390. }
  391. }
  392. $order->setCfdiGenerated($success)->save();
  393. }
  394. $cfdiRequest->setRequestXml($request)
  395. ->setResponse(json_encode($response))
  396. ->setSuccess($success)
  397. ->setOrderId($order->getId())
  398. ->setUuid($uuid)
  399. ->save();
  400.  
  401. return $uuid;
  402. }
  403.  
  404. protected function saveMailSentInDb($order){
  405. $order->setCfdiSentToMail(true)->save();
  406. }
  407.  
  408. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement