├── 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 | [](https://travis-ci.org/lcsbaroni/melhorenvio-magento2)
3 | [](https://circleci.com/gh/lcsbaroni/melhorenvio-magento2)
4 | [](https://packagist.org/packages/lcsbaroni/melhorenvio-magento2)
5 | [](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 | |
30 |
31 | |
32 |
33 |
41 | |
42 |
48 |
49 |
57 | |
58 |
59 |
60 |
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 |
--------------------------------------------------------------------------------