├── registration.php ├── .travis.yml ├── etc ├── catalog_attributes.xml ├── module.xml ├── di.xml ├── config.xml └── adminhtml │ └── system.xml ├── Model ├── ResourceModel │ ├── ShippingInformation │ │ └── Collection.php │ └── ShippingInformation.php ├── Order │ └── Shipment │ │ └── Track.php ├── System │ └── Config │ │ └── Source │ │ ├── Environment.php │ │ ├── Method.php │ │ └── AgencyJadlog.php ├── ShippingInformation.php ├── Adminhtml │ └── Attribute │ │ └── Validation │ │ └── Mapping.php └── Carrier │ └── MelhorEnvios.php ├── composer.json ├── i18n └── pt_BR.csv ├── .gitignore ├── phpunit.xml.dist ├── .circleci └── config.yml ├── Plugin └── PrintShippingLabelPlugin.php ├── Service └── v2 │ ├── MelhorEnviosService.php │ └── Environment │ └── Connector.php ├── Setup ├── UpgradeData.php └── UpgradeSchema.php ├── README.md ├── Block └── Adminhtml │ └── System │ └── Config │ └── Fieldset │ └── Mapping.php └── view └── adminhtml └── templates └── array_dropdown.phtml /registration.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Model/ResourceModel/ShippingInformation/Collection.php: -------------------------------------------------------------------------------- 1 | _init('Lb\MelhorEnvios\Model\ShippingInformation', 'Lb\MelhorEnvios\Model\ResourceModel\ShippingInformation'); 11 | $this->_setIdFieldName($this->getResource()->getIdFieldName()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lcsbaroni/melhorenvio-magento2", 3 | "description": "Modulo melhor envios magento 2", 4 | "type": "magento2-module", 5 | "version": "0.4.3", 6 | "require": { 7 | "php": ">=7.0" 8 | }, 9 | "autoload": { 10 | "files": [ 11 | "registration.php" 12 | ], 13 | "psr-4": { 14 | "Lb\\MelhorEnvios\\": "" 15 | } 16 | }, 17 | "minimum-stability": "dev", 18 | "require-dev": { 19 | "phpunit/phpunit": "^7.5", 20 | "friendsofphp/php-cs-fixer": "^2.14" 21 | }, 22 | "scripts": { 23 | "tests": "phpunit", 24 | "cs": "php-cs-fixer fix -v --dry-run" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Model/Order/Shipment/Track.php: -------------------------------------------------------------------------------- 1 | create(\Lb\MelhorEnvios\Model\ShippingInformation::class) 15 | ->getCollection() 16 | ->addFieldToFilter('tracking_number', $this->getTrackNumber()) 17 | ->fetchItem(); 18 | 19 | if ($package) { 20 | $package->delete(); 21 | } 22 | 23 | return parent::delete(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /i18n/pt_BR.csv: -------------------------------------------------------------------------------- 1 | "Product Attribute Unit", "Unidade do atributo" 2 | "Insurance value", "Valor declarado" 3 | "Receipt", "Aviso de recebimento" 4 | "Own hand", "Mão Propria" 5 | "State register", "Inscrição Estadual" 6 | "Product attributes mapping", "Mapa de atributos do produto" 7 | "Available shipping methods", "Metódos de entrega disponíveis" 8 | "Adding days to delivery time", "Dias de acréscimo para entrega" 9 | "Text delivery time", "Texto tempo de entrega" 10 | "Free Shipping Eligible", "Elegível a frete grátis" 11 | "Free Method fallback", "Fallback do metodo de entrega gratuita" 12 | "Text free shipping", "Texto para frete grátis" 13 | "Adding days to delivery when free shiping is enable", "Dias de acréscimo para entrega quando frete grátis" 14 | "Additional days", "Dias adicionais (tempo de CD)" 15 | -------------------------------------------------------------------------------- /Model/ResourceModel/ShippingInformation.php: -------------------------------------------------------------------------------- 1 | _init('melhor_envios_shipping_information', 'entity_id'); 17 | } 18 | 19 | /** 20 | * Load an object by id 21 | * 22 | * @return $this 23 | */ 24 | public function loadById(\Lb\MelhorEnvios\Model\ShippingInformation $model, $id) 25 | { 26 | if ($id) { 27 | $this->load($model, $id); 28 | } 29 | 30 | return $this; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Model/System/Config/Source/Environment.php: -------------------------------------------------------------------------------- 1 | __('Production'), 26 | 'value' => self::PRODUCTION 27 | ], 28 | [ 29 | 'label' => __('Sandbox'), 30 | 'value' => self::SANDBOX 31 | ] 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #--------------------------# 2 | # Magento Default Files # 3 | #--------------------------# 4 | 5 | /app/etc/local.xml 6 | 7 | /media/* 8 | !/media/.htaccess 9 | 10 | !/media/customer 11 | /media/customer/* 12 | !/media/customer/.htaccess 13 | 14 | !/media/dhl 15 | /media/dhl/* 16 | !/media/dhl/logo.jpg 17 | 18 | !/media/downloadable 19 | /media/downloadable/* 20 | !/media/downloadable/.htaccess 21 | 22 | !/media/xmlconnect 23 | /media/xmlconnect/* 24 | 25 | !/media/xmlconnect/custom 26 | /media/xmlconnect/custom/* 27 | !/media/xmlconnect/custom/ok.gif 28 | 29 | !/media/xmlconnect/original 30 | /media/xmlconnect/original/* 31 | !/media/xmlconnect/original/ok.gif 32 | 33 | !/media/xmlconnect/system 34 | /media/xmlconnect/system/* 35 | !/media/xmlconnect/system/ok.gif 36 | 37 | /var/* 38 | !/var/.htaccess 39 | 40 | !/var/package 41 | /var/package/* 42 | !/var/package/*.xml 43 | 44 | /vendor/ 45 | composer.lock 46 | -------------------------------------------------------------------------------- /Model/ShippingInformation.php: -------------------------------------------------------------------------------- 1 | _init('Lb\MelhorEnvios\Model\ResourceModel\ShippingInformation'); 29 | $this->setIdFieldName('entity_id'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | tests/unit/ 25 | 26 | 27 | 28 | 29 | 30 | etc/ 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # PHP CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-php/ for more details 4 | # 5 | version: 2 6 | jobs: 7 | build: 8 | docker: 9 | # specify the version you desire here 10 | # - image: circleci/php:7.1-browsers 11 | - image: lcsbaroni/php:7.1 12 | 13 | # Specify service dependencies here if necessary 14 | # CircleCI maintains a library of pre-built images 15 | # documented at https://circleci.com/docs/2.0/circleci-images/ 16 | # - image: circleci/mysql:9.4 17 | 18 | working_directory: /www 19 | 20 | steps: 21 | - checkout 22 | 23 | # Download and cache dependencies 24 | - restore_cache: 25 | keys: 26 | - v1-dependencies-{{ checksum "composer.json" }} 27 | # fallback to using the latest cache if no exact match is found 28 | - v1-dependencies- 29 | 30 | - run: composer install -n --prefer-dist 31 | 32 | - save_cache: 33 | paths: 34 | - ./vendor 35 | key: v1-dependencies-{{ checksum "composer.json" }} 36 | 37 | # run tests! 38 | # - run: composer tests 39 | -------------------------------------------------------------------------------- /etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 1 7 | 0 8 | your_token 9 | sandbox 10 | Lb\MelhorEnvios\Model\Carrier\MelhorEnvios 11 | Melhor Envios 12 | Melhor Envios 13 | 0 14 | I 15 | - Average %d work days 16 | This shipping method is not available. To use this shipping method, please contact us. 17 | 0 18 | 0 19 | 0 20 | 0 21 | 0 22 | 300 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Plugin/PrintShippingLabelPlugin.php: -------------------------------------------------------------------------------- 1 | getShipment()->getOrder()->getShippingMethod(); 10 | 11 | if (strstr($shippinhMethod, \Lb\MelhorEnvios\Model\Carrier\MelhorEnvios::CODE)) { 12 | $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); 13 | $package = $objectManager->create(\Lb\MelhorEnvios\Model\ShippingInformation::class) 14 | ->getCollection() 15 | ->addFieldToFilter('increment_id', $subject->getShipment()->getIncrementId()) 16 | ->addFieldToFilter('shipping_id', $subject->getShipment()->getId()) 17 | ->fetchItem(); 18 | 19 | $url = 'https://melhorenvio.com.br'; 20 | if ($package) { 21 | $url = $package->getLabelUrl(); 22 | } 23 | 24 | return $subject->getLayout()->createBlock( 25 | 'Magento\Backend\Block\Widget\Button' 26 | )->setData( 27 | ['label' => __('Print Shipping Label'), 'onclick' => 'window.open(\'' . $url . '\')'] 28 | )->toHtml(); 29 | } 30 | 31 | return $subject; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Model/System/Config/Source/Method.php: -------------------------------------------------------------------------------- 1 | 1, 'label' => 'Correios - PAC'], 23 | ['value' => 2, 'label' => 'Correios - Sedex'], 24 | ['value' => 3, 'label' => 'Jadlog - Normal'], 25 | ['value' => 4, 'label' => 'Jadlog - Expresso'], 26 | ['value' => 5, 'label' => 'Shippify - Expresso'], 27 | ['value' => 7, 'label' => 'Jamef - Rodoviário'], 28 | ]; 29 | 30 | /** 31 | * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig 32 | */ 33 | public function __construct( 34 | \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig 35 | ) 36 | { 37 | $this->scopeConfig = $scopeConfig; 38 | } 39 | 40 | /** 41 | * Return key sorted shop item categories 42 | * @return array 43 | */ 44 | public function toOptionArray() 45 | { 46 | if (isset($this->_methodsOptions)) { 47 | return $this->_methodsOptions; 48 | } 49 | return []; 50 | } 51 | 52 | /** 53 | * @return array 54 | */ 55 | public function getAvailableCodes() { 56 | $methods = $this->toOptionArray(); 57 | $codes = []; 58 | foreach ($methods as $method) { 59 | $codes[] = $method['value']; 60 | } 61 | return $codes; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Service/v2/MelhorEnviosService.php: -------------------------------------------------------------------------------- 1 | token = $token; 45 | $this->environment = $environment; 46 | $this->logger = $logger; 47 | 48 | $prefix = ""; 49 | if ($this->environment == \Lb\MelhorEnvios\Model\System\Config\Source\Environment::SANDBOX) { 50 | $prefix = "sandbox."; 51 | } 52 | 53 | $this->host = 'https://'. $prefix .'melhorenvio.com.br'; 54 | } 55 | 56 | /** 57 | * @return Connector 58 | */ 59 | public function getConnector() : Connector 60 | { 61 | if (!$this->connector instanceof Connector) { 62 | $this->connector = new Connector($this->token, $this->logger); 63 | } 64 | 65 | return $this->connector; 66 | } 67 | 68 | /** 69 | * @param $function 70 | * @param $parameters 71 | * @return mixed 72 | */ 73 | public function doRequest($function, $parameters) 74 | { 75 | $parameters['host'] = $this->host; 76 | return $this->getConnector()->doRequest($function, $parameters); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Setup/UpgradeData.php: -------------------------------------------------------------------------------- 1 | eavSetupFactory = $eavSetupFactory; 25 | } 26 | 27 | /** 28 | * @param ModuleDataSetupInterface $setup 29 | * @param ModuleContextInterface $context 30 | */ 31 | public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context) 32 | { 33 | if (version_compare($context->getVersion(), '0.0.4') < 0) 34 | { 35 | $eavSetup = $this->eavSetupFactory->create(['setup' => $setup]); 36 | 37 | $eavSetup->addAttribute( 38 | \Magento\Catalog\Model\Product::ENTITY, 39 | 'additional_days_for_delivery', 40 | [ 41 | 'type' => 'decimal', 42 | 'label' => 'Additional days for delivery', 43 | 'input' => 'text', 44 | 'global' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::SCOPE_GLOBAL, 45 | 'visible' => true, 46 | 'required' => false, 47 | 'user_defined' => false, 48 | 'searchable' => false, 49 | 'filterable' => false, 50 | 'comparable' => false, 51 | 'visible_on_front' => false, 52 | 'used_in_product_listing' => false, 53 | 'unique' => false, 54 | 'group' => 'Product Details', 55 | 'note' => "Tempo de CD" 56 | ] 57 | ); 58 | 59 | $setup->endSetup(); 60 | 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Melhor Envio - Magento 2 2 | [![Build Status](https://img.shields.io/travis/lcsbaroni/melhorenvio-magento2/master.svg?style=flat-square)](https://travis-ci.org/lcsbaroni/melhorenvio-magento2) 3 | [![CircleCI](https://circleci.com/gh/lcsbaroni/melhorenvio-magento2.svg?style=svg)](https://circleci.com/gh/lcsbaroni/melhorenvio-magento2) 4 | [![Latest Stable Version](https://img.shields.io/packagist/v/lcsbaroni/melhorenvio-magento2.svg?style=flat-square)](https://packagist.org/packages/lcsbaroni/melhorenvio-magento2) 5 | [![Total Downloads](https://img.shields.io/packagist/dt/lcsbaroni/melhorenvio-magento2.svg?style=flat-square)](https://packagist.org/packages/lcsbaroni/melhorenvio-magento2) 6 | 7 | Modulo do melhor envio para magento 2 8 | 9 | --- 10 | Descrição 11 | --------- 12 | --- 13 | Com o módulo instalado e configurado, você pode oferecer como forma de envio todas as transportadoras integradas com o melhor envio. As funcionalidades do modulo são: 14 | 15 | - Cotação de frete (página do produto e carrinho) - OK 16 | - Finalizar pedido com frete do melhor envio - OK 17 | - Possibilidade de dar frete grátis com base nas regras de carrinho - OK 18 | - Fallback de transportadora - Caso a transportadora escolhida para frete grátis esteja desabilitada, pode se escolher outra como fallback - OK 19 | - Rastrear pedido - Exibe o código de rastreio e link para rastreio no admin e no pedido do cliente - OK 20 | - Comprar frete escolhido pelo cliente - OK 21 | - Escolher agência para despachar pacote (jadlog por exemplo) - OK 22 | - Imprimir etiqueta de envio - OK 23 | - Carta de agradecimento de pedido - É gerado uma carta de agradecimento com os dados do pedido para ser enviada dentro da caixa. 24 | 25 | Veja nossa [wiki](https://github.com/lcsbaroni/melhorenvio-magento2/wiki) para mais detalhes 26 | ------------- 27 | 28 | Contribuições 29 | ------------- 30 | --- 31 | Achou e corrigiu um bug ou tem alguma feature em mente e deseja contribuir? 32 | 33 | * Faça um fork. 34 | * Adicione sua feature ou correção de bug. 35 | * Envie um pull request no [GitHub]. 36 | * Obs.: O Pull Request não deve ser enviado para o branch master e sim para o branch correspondente a versão ou para a branch de desenvolvimento. 37 | 38 | [Melhor Envio]: https://www.melhorenvio.com.br/ 39 | [API Melhor Envio]: https://docs.melhorenvio.com.br/ 40 | [Magento]: https://www.magentocommerce.com/ 41 | [PHP]: http://www.php.net/ 42 | [GitHub]: https://github.com/lcsbaroni/melhorenvio-magento2 43 | -------------------------------------------------------------------------------- /Model/Adminhtml/Attribute/Validation/Mapping.php: -------------------------------------------------------------------------------- 1 | _scopeCode = $switcher->getWebsiteId(); 40 | } 41 | 42 | /** 43 | * Validates attribute mapping entries 44 | * @return $this 45 | * @throws \Exception 46 | */ 47 | public function save() 48 | { 49 | $mappingValues = (array)$this->getValue(); //get the value from our config 50 | $attributeCodes = []; 51 | if ($this->_config->getValue('carriers/melhorenvios/active',\Magento\Store\Model\ScopeInterface::SCOPE_WEBSITE, $this->_scopeCode)) { 52 | foreach ($mappingValues as $value) { 53 | if (in_array($value['attribute_code'], $attributeCodes)) { 54 | throw new \Exception(__('Cannot repeat Magento Product size attributes')); 55 | } 56 | 57 | $attributeCodes[] = $value['attribute_code']; 58 | } 59 | } 60 | 61 | return parent::save(); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Block/Adminhtml/System/Config/Fieldset/Mapping.php: -------------------------------------------------------------------------------- 1 | addColumn('melhorenvios', array( 32 | 'label' => __('MelhorEnvíos'), 33 | 'style' => 'width:120px', 34 | )); 35 | $this->addColumn('magentoproduct', array( 36 | 'label' => __('Product Attribute'), 37 | 'style' => 'width:120px', 38 | )); 39 | 40 | $this->addColumn('unit', array( 41 | 'label' => __('Attribute Unit'), 42 | 'style' => 'width:120px', 43 | )); 44 | 45 | $this->setTemplate('array_dropdown.phtml'); 46 | $this->attributeCollection = $attributeCollection; 47 | 48 | parent::__construct($context); 49 | } 50 | 51 | /** 52 | * @return $this 53 | */ 54 | public function _getAttributes() 55 | { 56 | $attributes = $this->attributeCollection 57 | ->addFieldToFilter('is_visible', 1) 58 | ->addFieldToFilter('frontend_input', ['nin' => ['boolean', 'date', 'datetime', 'gallery', 'image', 'media_image', 'select', 'multiselect', 'textarea']]) 59 | ->load(); 60 | 61 | 62 | return $attributes; 63 | } 64 | 65 | /** 66 | * @return array 67 | */ 68 | public function _getStoredMappingValues() 69 | { 70 | $prevValues = []; 71 | foreach ($this->getArrayRows() as $key => $_row) { 72 | $prevValues[$key] = ['attribute_code' => $_row->getData('attribute_code'), 'unit' => $_row->getData('unit')]; 73 | } 74 | 75 | return $prevValues; 76 | } 77 | 78 | /** 79 | * @return array 80 | */ 81 | public function _getMeLabel() 82 | { 83 | return [__('Length'), __('Width'), __('Height'), __('Weight'), __('Additional days')]; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Model/System/Config/Source/AgencyJadlog.php: -------------------------------------------------------------------------------- 1 | scopeConfig = $scopeConfig; 40 | $this->logger = $logger; 41 | } 42 | 43 | /** 44 | * @return array 45 | */ 46 | public function toOptionArray() { 47 | $function = '/api/v2/me/shipment/agencies?company='. self::JADLOG_COMPANY_ID . '&country=BR'; 48 | $parameters = [ 49 | 'method' => \Zend\Http\Request::METHOD_GET, 50 | 'data' => [] 51 | ]; 52 | 53 | $response = $this->getService()->doRequest($function, $parameters); 54 | $response = json_decode($response); 55 | 56 | if (empty($response)) { 57 | return []; 58 | } 59 | 60 | $result = []; 61 | foreach ($response as $item) { 62 | if ($item->status != 'available') { 63 | continue; 64 | } 65 | 66 | $result[$item->id] = $item->name . ' - ' . $item->address->address; 67 | } 68 | 69 | asort($result); 70 | 71 | return $result; 72 | } 73 | 74 | /** 75 | * @return MelhorEnviosService 76 | */ 77 | public function getService() : MelhorEnviosService 78 | { 79 | if (!$this->service instanceof MelhorEnviosService) { 80 | $this->service = new MelhorEnviosService( 81 | $this->getConfigData('token'), 82 | $this->getConfigData('environment'), 83 | $this->logger 84 | ); 85 | } 86 | 87 | return $this->service; 88 | } 89 | 90 | /** 91 | * @param string $field 92 | * @return mixed 93 | */ 94 | private function getConfigData(string $field) 95 | { 96 | $path = 'carriers/melhorenvios/' . $field; 97 | 98 | return $this->scopeConfig->getValue( 99 | $path, 100 | \Magento\Store\Model\ScopeInterface::SCOPE_STORE 101 | ); 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /Setup/UpgradeSchema.php: -------------------------------------------------------------------------------- 1 | getVersion(), '0.4.0', '<')) { 21 | $this->createShippingTable($setup); 22 | } 23 | } 24 | 25 | /** 26 | * @param SchemaSetupInterface $setup 27 | * @return $this 28 | */ 29 | protected function createShippingTable(SchemaSetupInterface $setup) 30 | { 31 | $installer = $setup; 32 | 33 | $installer->startSetup(); 34 | 35 | /** 36 | * Create table 'melhor_envios_shipping_information' 37 | */ 38 | $table = $installer->getConnection()->newTable( 39 | $installer->getTable('melhor_envios_shipping_information') 40 | )->addColumn( 41 | 'entity_id', 42 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 43 | null, 44 | ['identity' => true, 'nullable' => false, 'primary' => true], 45 | 'shipping ID' 46 | )->addColumn( 47 | 'shipping_id', 48 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 49 | null, 50 | ['nullable' => false], 51 | 'Shiping Id' 52 | )->addColumn( 53 | 'increment_id', 54 | \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 55 | 32, 56 | ['nullable' => false], 57 | 'Order Id' 58 | )->addColumn( 59 | 'package_id', 60 | \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT, 61 | null, 62 | ['nullable' => false], 63 | 'Package Id' 64 | )->addColumn( 65 | 'tracking_number', 66 | \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 67 | 50, 68 | ['nullable' => false], 69 | 'Tracking number' 70 | )->addColumn( 71 | 'label_url', 72 | \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 73 | 255, 74 | ['nullable' => false], 75 | 'label url' 76 | )->addColumn( 77 | 'creation_time', 78 | \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, 79 | null, 80 | ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT], 81 | 'Creation Time' 82 | )->addColumn( 83 | 'update_time', 84 | \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, 85 | null, 86 | ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE], 87 | 'Modification Time' 88 | ); 89 | 90 | $installer->getConnection()->createTable($table); 91 | 92 | $installer->endSetup(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /view/adminhtml/templates/array_dropdown.phtml: -------------------------------------------------------------------------------- 1 | getHtmlId() ? $this->getHtmlId() : '_' . uniqid(); 6 | $productCode = $block->_getAttributes(); 7 | $units = [ 8 | 'size' => ['cm', 'mt'], 9 | 'weight' => ['kg', 'gr'], 10 | 'additional_days' => ['days'], 11 | ]; 12 | $meCode = ['length','width','height', 'weight', 'additional_days']; 13 | $meLabel = $block->_getMeLabel(); 14 | $prevValues = []; 15 | 16 | $prevValues = $block->_getStoredMappingValues(); 17 | 18 | ?> 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | $meOption):?> 28 | 29 | 32 | 42 | 48 | 58 | 59 | 60 |
30 | 31 | 33 | 41 | 49 | 57 |
61 |
62 | -------------------------------------------------------------------------------- /Service/v2/Environment/Connector.php: -------------------------------------------------------------------------------- 1 | token = $token; 21 | $this->logger = $logger; 22 | } 23 | 24 | /** 25 | * @return \Zend\Http\Client 26 | */ 27 | public function getClient() 28 | { 29 | if (!$this->client instanceof \Zend\Http\Client) { 30 | $this->client = new \Zend\Http\Client(); 31 | $options = [ 32 | 'maxredirects' => 0, 33 | 'timeout' => 30 34 | ]; 35 | $this->client->setOptions($options); 36 | $this->client->setHeaders([ 37 | 'Authorization' => 'Bearer ' . $this->token, 38 | 'Content-Type' => 'application/json', 39 | 'Accept' => 'application/json', 40 | ]); 41 | } 42 | 43 | return $this->client; 44 | } 45 | 46 | /** 47 | * @param \Zend\Http\Client $client 48 | * @return \Zend\Http\Client 49 | */ 50 | public function setClient(\Zend\Http\Client $client) 51 | { 52 | return $this->client = $client; 53 | } 54 | 55 | /** 56 | * @param $function 57 | * @param $parameters 58 | * @return mixed 59 | */ 60 | public function doRequest($function, $parameters) 61 | { 62 | try { 63 | $method = isset($parameters['method']) ? $parameters['method'] : \Zend\Http\Request::METHOD_POST; 64 | 65 | $data = json_encode($parameters['data']); 66 | $this->getClient()->setMethod($method); 67 | $this->getClient()->setRawBody($data); 68 | $this->getClient()->setUri($parameters['host'] . $function); 69 | 70 | $this->logger->notice($data); 71 | 72 | $response = $this->getClient()->send(); 73 | 74 | } catch( \Zend\Http\Client\Adapter\Exception\TimeoutException $e) { 75 | $this->logger->error($e); 76 | throw new \Exception($e->getMessage()); 77 | } 78 | 79 | $this->logger->notice(json_encode($response->getBody())); 80 | if ($response->getStatusCode() < 200 || $response->getStatusCode() > 299) { 81 | $responseErrorMessage = json_decode($response->getBody()); 82 | 83 | if (empty($responseErrorMessage) || !property_exists($responseErrorMessage, 'message')) { 84 | $responseErrorMessage = new \stdClass(); 85 | $responseErrorMessage->message = "Melhor envios - Transaction Failed!"; 86 | } 87 | 88 | $errorsMessages = ""; 89 | if (property_exists($responseErrorMessage, 'errors')) { 90 | foreach ($responseErrorMessage->errors as $error) 91 | $errorsMessages .= implode("\n", $error); 92 | } 93 | 94 | throw new \Exception($responseErrorMessage->message . $errorsMessages . sprintf(' (statusCode: %s)', (int) $response->getStatusCode())); 95 | } 96 | 97 | return $response->getBody(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /etc/adminhtml/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | Magento\Config\Model\Config\Source\Yesno 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Lb\MelhorEnvios\Model\System\Config\Source\Environment 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Lb\MelhorEnvios\Block\Adminhtml\System\Config\Fieldset\Mapping 30 | Lb\MelhorEnvios\Model\Adminhtml\Attribute\Validation\Mapping 31 | 32 | 33 | 34 | Lb\MelhorEnvios\Model\System\Config\Source\Method 35 | 36 | 37 | 38 | integer validate-zero-or-greater 39 | 40 | 1 41 | 42 | 43 | 44 | 45 | 46 | 1 47 | 48 | 49 | 50 | 51 | 52 | 1 53 | 54 | 55 | 56 | 57 | Magento\Config\Model\Config\Source\Yesno 58 | 59 | 1 60 | 61 | 62 | 63 | 64 | 65 | 1 66 | 1 67 | 68 | 69 | 70 | 71 | integer validate-zero-or-greater 72 | 73 | 1 74 | 1 75 | 76 | 77 | 78 | 79 | Lb\MelhorEnvios\Model\System\Config\Source\Method 80 | This service must be enabled 81 | 82 | 1 83 | 1 84 | 85 | 86 | 87 | 88 | Lb\MelhorEnvios\Model\System\Config\Source\Method 89 | Used if the main carrier / method is not available for this location 90 | 91 | 1 92 | 1 93 | 94 | 95 | 96 | 97 | Magento\Config\Model\Config\Source\Yesno 98 | 99 | 1 100 | 101 | 102 | 103 | 104 | Magento\Config\Model\Config\Source\Yesno 105 | 106 | 1 107 | 108 | 109 | 110 | 111 | Magento\Config\Model\Config\Source\Yesno 112 | 113 | 1 114 | 115 | 116 | 117 | 118 | Lb\MelhorEnvios\Model\System\Config\Source\AgencyJadlog 119 | 120 | 121 |
122 |
123 |
124 | -------------------------------------------------------------------------------- /Model/Carrier/MelhorEnvios.php: -------------------------------------------------------------------------------- 1 | _rateResultFactory = $rateResultFactory; 99 | $this->shippingInformation = $ShippingInformation; 100 | 101 | parent::__construct( 102 | $scopeConfig, 103 | $rateErrorFactory, 104 | $logger, 105 | $xmlSecurity, 106 | $xmlElFactory, 107 | $rateFactory, 108 | $rateMethodFactory, 109 | $trackFactory, 110 | $trackErrorFactory, 111 | $trackStatusFactory, 112 | $regionFactory, 113 | $countryFactory, 114 | $currencyFactory, 115 | $directoryData, 116 | $stockRegistry, 117 | $data 118 | ); 119 | } 120 | 121 | /** 122 | * @return array 123 | */ 124 | public function getAllowedMethods() 125 | { 126 | return [ 127 | 'Correios_1' => 'Correios - PAC', 128 | 'Correios_2' => 'Correios - SEDEX', 129 | 'Jadlog_3' => 'Jadlog - Normal', 130 | 'Jadlog_4' => 'Jadlog - Expresso', 131 | 'Shippify_5' => 'Shippify - Expresso', 132 | 'Jamef_7' => 'Jamef - Rodoviário', 133 | ]; 134 | } 135 | 136 | /** 137 | * @param RateRequest $request 138 | * @return bool|Result 139 | */ 140 | public function collectRates(RateRequest $request) 141 | { 142 | if (!$this->getConfigFlag('active')) { 143 | return false; 144 | } 145 | 146 | $function = '/api/v2/me/shipment/calculate'; 147 | $parameters = [ 148 | 'method' => \Zend\Http\Request::METHOD_GET, 149 | 'data' => [ 150 | "from" => [ 151 | "postal_code" => $request->getPostcode(), 152 | "address" => $request->getCity(), 153 | "number" => $request->getRegion() 154 | ], 155 | "to" => [ 156 | "postal_code" => $request->getDestPostcode(), 157 | "address" => $request->getDestRegionCode(), 158 | "number" => $request->getDestRegionId() 159 | ], 160 | "package" => $this->_createDimensions($request), 161 | "options" => [ 162 | "insurance_value" => (bool) $this->getConfigData('insurance_value') ? $request->getPackageValue() : self::INSURANCE_VALUE, // valor declarado/segurado 163 | "receipt" => (bool) $this->getConfigData('receipt'), // aviso de recebimento 164 | "own_hand" => (bool) $this->getConfigData('own_hand'), // mão pŕopria 165 | "collect" => false 166 | ], 167 | "services" => $this->getConfigData('availablemethods') 168 | ] 169 | ]; 170 | 171 | $response = $this->getService()->doRequest($function, $parameters); 172 | $response = json_decode($response); 173 | 174 | if (empty($response)) { 175 | return false; 176 | } 177 | 178 | /** @var \Magento\Shipping\Model\Rate\Result $result */ 179 | $result = $this->_rateResultFactory->create(); 180 | 181 | $this->freeShippingCarrierId = $this->getConfigData('free_shipping_service'); 182 | 183 | foreach ($response as $carrier) { 184 | if (isset($carrier->error)) { 185 | $this->getFreeShippingFallback($carrier); 186 | 187 | continue; 188 | } 189 | /** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */ 190 | $method = $this->_rateMethodFactory->create(); 191 | 192 | $method->setCarrier($this->_code); 193 | 194 | $method->setCarrierTitle($this->getConfigData('name')); 195 | 196 | $method->setMethod($carrier->company->name . "_" . $carrier->id); 197 | $delivery_time = 0; 198 | $description = $carrier->company->name . " " .$carrier->name; 199 | if (property_exists($carrier, 'delivery_time')) { 200 | $delivery_time = ($this->additionalDaysForDelivery > $this->getConfigData('add_days') ? $this->additionalDaysForDelivery : $this->getConfigData('add_days')); 201 | $delivery_time += $carrier->delivery_time; 202 | 203 | $description = $carrier->company->name . " " .$carrier->name 204 | . sprintf($this->getConfigData('text_days'), $delivery_time); 205 | } 206 | $method->setMethodTitle($description); 207 | 208 | if ($this->getConfigData('free_shipping_enabled') && 209 | $carrier->id == $this->freeShippingCarrierId 210 | && $request->getFreeShipping() 211 | ) { 212 | $carrier->price = 0; 213 | $carrier->discount = 0; 214 | 215 | $delivery_time += $this->getConfigData('add_days_free_shipping'); 216 | $method->setMethodTitle($this->getConfigData('free_shipping_text') . sprintf($this->getConfigData('text_days'), $delivery_time)); 217 | } 218 | 219 | $amount = $carrier->price; 220 | $method->setPrice($amount); 221 | $method->setCost($amount - $carrier->discount); 222 | 223 | $result->append($method); 224 | } 225 | 226 | return $result; 227 | } 228 | 229 | private function getFreeShippingFallback($carrier) 230 | { 231 | if ($carrier->id == $this->freeShippingCarrierId) { 232 | $this->freeShippingCarrierId = $this->getConfigData('free_shipping_service_fallback'); 233 | } 234 | 235 | } 236 | 237 | /** 238 | * @param RateRequest $request 239 | * @return array 240 | */ 241 | protected function _createDimensions(RateRequest $request) 242 | { 243 | $volume = 0; 244 | $items = $this->getItems($request->getAllItems()); 245 | foreach($items as $item) { 246 | 247 | $qty = $item->getQty() ?: 1; 248 | $item = $item->getProduct(); 249 | 250 | $this->additionalDaysForDelivery = ( 251 | $this->additionalDaysForDelivery >= $this->_getShippingDimension($item, 'additional_days') ? 252 | $this->additionalDaysForDelivery : $this->_getShippingDimension($item, 'additional_days') 253 | ); 254 | $volume += ( 255 | $this->_getShippingDimension($item, 'height') * 256 | $this->_getShippingDimension($item, 'width') * 257 | $this->_getShippingDimension($item, 'length') 258 | ) * $qty; 259 | 260 | } 261 | 262 | $root_cubic = round(pow($volume, (1/3))); 263 | 264 | $width = ($root_cubic < self::MIN_WIDTH) ? self::MIN_WIDTH : $root_cubic; 265 | $height = ($root_cubic < self::MIN_HEIGHT) ? self::MIN_HEIGHT : $root_cubic; 266 | $length = ($root_cubic < self::MIN_LENGTH) ? self::MIN_LENGTH : $root_cubic; 267 | 268 | return [ 269 | "weight" => $request->getPackageWeight(), 270 | "width" => $width, 271 | "height" => $height, 272 | "length" => $length 273 | ]; 274 | } 275 | 276 | /** 277 | * Return items for further shipment rate evaluation. We need to pass children of a bundle instead passing the 278 | * bundle itself, otherwise we may not get a rate at all (e.g. when total weight of a bundle exceeds max weight 279 | * despite each item by itself is not) 280 | * 281 | * @return array 282 | */ 283 | private function getItems($allItems) 284 | { 285 | $items = []; 286 | foreach ($allItems as $item) { 287 | /* @var $item Mage_Sales_Model_Quote_Item */ 288 | if ($item->getProduct()->isVirtual() || $item->getParentItem()) { 289 | // Don't process children here - we will process (or already have processed) them below 290 | continue; 291 | } 292 | 293 | if ($item->getHasChildren() && $item->isShipSeparately()) { 294 | foreach ($item->getChildren() as $child) { 295 | if (!$child->getFreeShipping() && !$child->getProduct()->isVirtual()) { 296 | $items[] = $child; 297 | } 298 | } 299 | } else { 300 | // Ship together - count compound item as one solid 301 | $items[] = $item; 302 | } 303 | } 304 | 305 | return $items; 306 | } 307 | 308 | /** 309 | * @param $item 310 | * @param $type 311 | * @return int 312 | */ 313 | public function _getShippingDimension($item, $type) 314 | { 315 | $attributeMapped = $this->getConfigData('attributesmapping'); 316 | $attributeMapped = json_decode($attributeMapped, true) ?: unserialize($attributeMapped); 317 | $dimension = 0; 318 | $value = $item->getData($attributeMapped[$type]['attribute_code']); 319 | if ($value) { 320 | $dimension = $value; 321 | } 322 | 323 | return $dimension; 324 | } 325 | 326 | /** 327 | * @return MelhorEnviosService 328 | */ 329 | public function getService() : MelhorEnviosService 330 | { 331 | if (!$this->service instanceof MelhorEnviosService) { 332 | $this->service = new MelhorEnviosService( 333 | $this->getConfigData('token'), 334 | $this->getConfigData('environment'), 335 | $this->_logger 336 | ); 337 | } 338 | 339 | return $this->service; 340 | } 341 | 342 | /** 343 | * @return bool 344 | */ 345 | public function isTrackingAvailable(){ 346 | return true; 347 | } 348 | 349 | /** 350 | * @param string $number 351 | * @return \Magento\Shipping\Model\Tracking\Result\Status 352 | */ 353 | public function getTrackingInfo($number) 354 | { 355 | $tracking = $this->_trackStatusFactory->create(); 356 | $tracking->setCarrier($this->_code); 357 | $tracking->setCarrierTitle($this->getConfigData('name')); 358 | $tracking->setTracking($number); 359 | $tracking->setUrl(self::TRACKING_URL . $number); 360 | 361 | return $tracking; 362 | } 363 | 364 | /** 365 | * @param $taxVat 366 | * @return string 367 | */ 368 | private function getCustomerTaxVat($taxVat) 369 | { 370 | //if customer doesn't have document, use a fake. Required for Jadlog 371 | if (!$taxVat) { 372 | $taxVat = '85117687183'; //fake document 373 | } 374 | 375 | return $taxVat; 376 | } 377 | 378 | /** 379 | * @param array $street 380 | * @return array 381 | */ 382 | private function buildAddress(array $street) : array 383 | { 384 | $keys = [ 385 | 'street', 386 | 'number', 387 | 'complement', 388 | 'neighborhood' 389 | ]; 390 | 391 | if (sizeof($keys) == sizeof($street)) { 392 | $result = array_combine($keys, $street); 393 | } else { 394 | $result = [ 395 | 'street' => $street[0], 396 | 'number' => $street[1], 397 | 'complement' => '', 398 | 'neighborhood' => $street[2] 399 | ]; 400 | } 401 | 402 | return $result; 403 | } 404 | 405 | /** 406 | * @param array $items 407 | * @return float 408 | */ 409 | private function getInsuranceValue(array $items) : float 410 | { 411 | $value = self::INSURANCE_VALUE; 412 | if ($this->getConfigData('insurance_value')) { 413 | $value = 0.00; 414 | foreach ($items as $item) { 415 | $value += $item['price']; 416 | } 417 | } 418 | 419 | return $value; 420 | } 421 | 422 | /** 423 | * @param \Magento\Framework\DataObject $request 424 | * @return \Magento\Framework\DataObject 425 | */ 426 | protected function _doShipmentRequest(\Magento\Framework\DataObject $request) 427 | { 428 | $data = [ 429 | 'increment_id' => $request->getOrderShipment()->getIncrementId(), 430 | 'shipping_id' => $request->getOrderShipment()->getId(), 431 | 'package_id' => $request->getData('package_id'), 432 | 'tracking_number' => '', 433 | 'label_url' => '' 434 | ]; 435 | 436 | $result = new \Magento\Framework\DataObject(); 437 | 438 | $customerTaxVat = $this->getCustomerTaxVat($request->getOrderShipment()->getOrder()->getCustomerTaxVat()); 439 | $shippingAddress = $request->getOrderShipment()->getOrder()->getShippingAddress(); 440 | $shippingAddressParsed = $this->buildAddress($shippingAddress->getStreet()); 441 | 442 | $addressFrom = explode(',', $request->getShipperAddressStreet1()); 443 | $addressFrom[] = $request->getShipperAddressStreet2(); 444 | $addressFrom = $this->buildAddress($addressFrom); 445 | 446 | $function = '/api/v2/me/cart'; 447 | $parameters = [ 448 | 'method' => \Zend\Http\Request::METHOD_POST, 449 | 'data' => [ 450 | "service" => explode('_', $request->getShippingMethod())[1], 451 | "agency" => $this->getConfigData('jadlog_agency'), // id da agência de postagem (obrigatório se for JadLog) 452 | "from" => [ 453 | "name" => $request->getShipperContactCompanyName(), 454 | "phone" => $request->getShipperContactPhoneNumber(), 455 | "document" => strlen($this->getConfigData('taxvat')) > 11 ? '' : $this->getConfigData('taxvat'), 456 | "company_document" => strlen($this->getConfigData('taxvat')) < 11 ? '' : $this->getConfigData('taxvat'), // cnpj (obrigatório se não for Correios) 457 | "state_register" => $this->getConfigData('state_register'), // inscrição estadual (obrigatório se não for Correios) pode ser informado "isento" 458 | "postal_code" => $request->getShipperAddressPostalCode(), 459 | "address" => $addressFrom['street'], 460 | "complement" => $addressFrom['complement'], 461 | "number" => $addressFrom['number'], 462 | "district" => $addressFrom['neighborhood'], 463 | "city" => $request->getShipperAddressCity(), 464 | "state_abbr" => $request->getShipperAddressStateOrProvinceCode(), 465 | "country_id" => $request->getShipperAddressCountryCode(), 466 | ], 467 | "to" => [ 468 | "name" => $request->getRecipientContactPersonName(), 469 | "phone" => $request->getRecipientContactPhoneNumber(), // telefone com ddd (obrigatório se não for Correios) 470 | "email" => $request->getData('recipient_email'), 471 | "document" => $customerTaxVat, // obrigatório se for transportadora e não for logística reversa 472 | "company_document" => "", // (opcional) (a menos que seja transportadora e logística reversa) 473 | "state_register" => "", // (opcional) (a menos que seja transportadora e logística reversa) 474 | "address" => $shippingAddressParsed['street'], 475 | "complement" => $shippingAddressParsed['complement'], 476 | "number" => $shippingAddressParsed['number'], 477 | "district" => $shippingAddressParsed['neighborhood'], 478 | "city" => $request->getRecipientAddressCity(), 479 | "state_abbr" => $request->getRecipientAddressStateOrProvinceCode(), 480 | "country_id" => $request->getRecipientAddressCountryCode(), 481 | "postal_code" => $request->getRecipientAddressPostalCode(), 482 | ], 483 | "products" => $this->getListProducts($request->getData('package_items')), 484 | "package" => $this->getShippingPackages($request->getData('package_params')), 485 | "options" => [ // opções 486 | "insurance_value" => $this->getInsuranceValue($request->getPackageItems()), // valor declarado/segurado 487 | "receipt" => (bool) $this->getConfigData('receipt'), // aviso de recebimento 488 | "own_hand" => (bool) $this->getConfigData('own_hand'), // mão pŕopria 489 | "collect" => false, // coleta 490 | "reverse" => false, // logística reversa (se for reversa = true, ainda sim from será o remetente e to o destinatário) 491 | "non_commercial" => true, // envio de objeto não comercializável (flexibiliza a necessidade de pessoas júridicas para envios com transportadoras como Latam Cargo, porém se for um envio comercializável a mercadoria pode ser confisca pelo fisco) 492 | ] 493 | ] 494 | ]; 495 | 496 | $this->_prepareShipmentRequest($request); 497 | 498 | try { 499 | $response = $this->getService()->doRequest($function, $parameters); 500 | $response = json_decode($response); 501 | } catch (\Exception $e) { 502 | return $result->setErrors("Não foi possível adicionar a etiqueta ao carrinho - " . $e->getMessage()); 503 | } 504 | 505 | $shippingOrderID = $response->id; 506 | 507 | $function = "/api/v2/me/shipment/checkout"; 508 | $parameters = [ 509 | 'method' => \Zend\Http\Request::METHOD_POST, 510 | 'data' => [ 511 | "orders" => [ // lista de etiquetas (opcional) 512 | $shippingOrderID 513 | ], 514 | "wallet" => $response->price 515 | ] 516 | ]; 517 | 518 | try { 519 | $response = $this->getService()->doRequest($function, $parameters); 520 | $response = json_decode($response); 521 | } catch (\Exception $e) { 522 | return $result->setErrors("Não foi possível comprar a etiqueta - " . $e->getMessage()); 523 | } 524 | 525 | $function = "/api/v2/me/shipment/generate"; 526 | $parameters = [ 527 | 'method' => \Zend\Http\Request::METHOD_POST, 528 | 'data' => [ 529 | "orders" => [ 530 | $shippingOrderID 531 | ] 532 | ] 533 | ]; 534 | 535 | try { 536 | $response = $this->getService()->doRequest($function, $parameters); 537 | $response = json_decode($response); 538 | } catch (\Exception $e) { 539 | return $result->setErrors("Não foi possível gerar a etiqueta - " . $e->getMessage()); 540 | } 541 | 542 | $function = "/api/v2/me/shipment/print"; 543 | $parameters = [ 544 | 'method' => \Zend\Http\Request::METHOD_POST, 545 | 'data' => [ 546 | "mode" => "public", 547 | "orders" => [ 548 | $shippingOrderID 549 | ] 550 | ] 551 | ]; 552 | 553 | try { 554 | $response = $this->getService()->doRequest($function, $parameters); 555 | $response = json_decode($response); 556 | } catch (\Exception $e) { 557 | return $result->setErrors("Não foi possível imprimir a etiqueta - " . $e->getMessage()); 558 | } 559 | 560 | $labelUrl = $response->url; 561 | 562 | $function = "/api/v2/me/shipment/tracking"; 563 | $parameters = [ 564 | 'method' => \Zend\Http\Request::METHOD_POST, 565 | 'data' => [ 566 | "orders" => [ 567 | $shippingOrderID 568 | ] 569 | ] 570 | ]; 571 | 572 | try { 573 | $response = $this->getService()->doRequest($function, $parameters); 574 | $response = json_decode($response); 575 | } catch (\Exception $e) { 576 | return $result->setErrors("Não foi possível encontrar o tracking - " . $e->getMessage()); 577 | } 578 | 579 | $result->setShippingLabelContent($labelUrl); 580 | $result->setTrackingNumber($response->$shippingOrderID->tracking); 581 | $data['tracking_number'] = $response->$shippingOrderID->tracking; 582 | $data['label_url'] = $labelUrl; 583 | 584 | $this->shippingInformation->setData($data)->save(); 585 | 586 | return $result; 587 | } 588 | 589 | /** 590 | * @param array $packageItems 591 | * @return array 592 | */ 593 | private function getListProducts(array $packageItems) : array 594 | { 595 | $products = []; 596 | 597 | // lista de produtos para preenchimento da declaração de conteúdo 598 | foreach ($packageItems as $item) { 599 | $products[] = [ 600 | "name" => $item['name'], // nome do produto (max 255 caracteres) 601 | "quantity" => $item['qty'], // quantidade de items desse produto 602 | "unitary_value" => $item['price'], // R$ 4,50 valor do produto 603 | "weight" => $item['weight'], // peso 1kg, opcional 604 | ]; 605 | } 606 | 607 | return $products; 608 | } 609 | 610 | /** 611 | * @param $packageParams 612 | * @return array 613 | */ 614 | private function getShippingPackages($packageParams) : array 615 | { 616 | $package = []; 617 | 618 | foreach ($packageParams as $package) { 619 | $package = [ 620 | "weight" => $package['weight'], 621 | "width" => $package['width'], 622 | "height" => $package['height'], 623 | "length" => $package['length'] 624 | ]; 625 | } 626 | 627 | return $package; 628 | } 629 | } 630 | --------------------------------------------------------------------------------