Ich versuche, beim Importieren einer Bestellung über einen Konsolenbefehl eine benutzerdefinierte Versandmethode zu verwenden. Alles funktioniert einwandfrei, außer dass das Backend die Versandart nicht anzeigt und wenn ich anschließend die Bestellung überprüfe: Screenshot
Die Grundstruktur und Versandart des Moduls werden mit mage2gen.com generiert und können sowohl im Frontend als auch im Backend ausgeführt werden, wenn ich die Bestellung manuell erstelle.
Interessanterweise ist die Versandart korrekt eingerichtet, wenn ich $shippingAddress->setShippingMethod('flatrate_flatrate');
nach dem Abholen des Versands verwende, aber ich kann sie mit keiner anderen Versandart oder meiner benutzerdefinierten Versandart zum Laufen bringen.
Hilfe wäre sehr dankbar! Bitte sagen Sie mir, ob ich mehr Code hinzufügen soll.
Danke! (Ganz neu bei Mage2)
System.xml:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> <system> <section id="carriers" sortOrder="1000" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <group id="hellocash" sortOrder="10" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>HelloCash</label> <field id="active" type="select" sortOrder="10" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Enabled</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> <field id="name" type="text" sortOrder="20" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Method Name</label> </field> <field id="price" type="text" sortOrder="30" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Price</label> <validate>validate-number validate-zero-or-greater</validate> </field> <field id="sort_order" type="text" sortOrder="40" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Sort Order</label> </field> <field id="title" type="text" sortOrder="50" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Title</label> </field> <field id="sallowspecific" type="select" sortOrder="60" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Ship to Applicable Countries</label> <frontend_class>shipping-applicable-country</frontend_class> <source_model>Magento\Shipping\Model\Config\Source\Allspecificcountries</source_model> </field> <field id="specificcountry" type="multiselect" sortOrder="70" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Ship to Specific Countries</label> <can_be_empty>1</can_be_empty> <source_model>Magento\Directory\Model\Config\Source\Country</source_model> </field> <field id="specificerrmsg" type="textarea" sortOrder="80" showInWebsite="1" showInStore="1" showInDefault="1" translate="label"> <label>Displayed Error Message</label> </field> </group> </section> </system> </config>
Trägermodell:
<?php /** * Copyright © Dan All rights reserved. * See COPYING.txt for license details. */ declare(strict_types=1); namespace Dan\HelloCash\Model\Carrier; use Magento\Quote\Model\Quote\Address\RateRequest; use Magento\Shipping\Model\Rate\Result; class HelloCash extends \Magento\Shipping\Model\Carrier\AbstractCarrier implements \Magento\Shipping\Model\Carrier\CarrierInterface { protected $_code = 'hellocash'; protected $_isFixed = true; protected $_rateResultFactory; protected $_rateMethodFactory; /** * Constructor * * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig * @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory * @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory * @param array $data */ public function __construct( \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory, \Psr\Log\LoggerInterface $logger, \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory, \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory, array $data = [] ) { $this->_rateResultFactory = $rateResultFactory; $this->_rateMethodFactory = $rateMethodFactory; parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data); } /** * {@inheritdoc} */ public function collectRates(RateRequest $request) { if (!$this->getConfigFlag('active')) { return false; } $shippingPrice = $this->getConfigData('price'); $result = $this->_rateResultFactory->create(); if ($shippingPrice !== false) { $method = $this->_rateMethodFactory->create(); $method->setCarrier($this->_code); $method->setCarrierTitle($this->getConfigData('title')); $method->setMethod($this->_code); $method->setMethodTitle($this->getConfigData('name')); if ($request->getFreeShipping() === true) { $shippingPrice = '0.00'; } $method->setPrice($shippingPrice); $method->setCost($shippingPrice); $result->append($method); } return $result; } /** * getAllowedMethods * * @return array */ public function getAllowedMethods() { return [$this->_code => $this->getConfigData('name')]; } }
Bestellkonsolenbefehl importieren:
<?php /** * Copyright © DAN All rights reserved. * See COPYING.txt for license details. */ declare(strict_types=1); namespace Dan\HelloCash\Console\Command; use Dan\HelloCash\Api\Data\SyncLogInterfaceFactory; use Dan\HelloCash\Api\HelloCash as HelloCashApi; use Dan\HelloCash\Enum\SyncLogType; use Dan\HelloCash\Exception\SyncException; use Dan\HelloCash\Exception\SyncOrderException; use Dan\HelloCash\Model\SyncLogRepository; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\ProductFactory; use Magento\Config\Model\Config; use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Framework\App\State; use Magento\Framework\DB\Transaction; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\View\Result\PageFactory; use Magento\Quote\Model\Quote\Address\Rate as ShippingRate; use Magento\Quote\Model\QuoteManagement; use Magento\Sales\Api\OrderRepositoryInterface; use Magento\Sales\Model\Order\Email\Sender\OrderSender; use Magento\Store\Api\Data\StoreInterface; use Magento\Customer\Model\Customer\Interceptor as CustomerInterceptor; use Magento\Customer\Model\CustomerFactory; use Magento\Framework\App\Area; use Magento\Framework\Encryption\Encryptor; use Magento\Quote\Model\QuoteFactory; use Magento\Store\Model\StoreManagerInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Magento\Sales\Model\Service\InvoiceService; use Magento\Sales\Model\Order\Email\Sender\InvoiceSender; class SyncOrders extends SyncCommand { const NAME_ARGUMENT = 'name'; const NAME_OPTION = 'option'; protected CustomerFactory $customerFactory; protected CustomerInterceptor $customer; protected OutputInterface $output; protected StoreInterface $store; protected StoreManagerInterface $storeManager; protected QuoteFactory $quoteFactory; /** * @var PageFactory */ protected PageFactory $resultPageFactory; /** * @var OrderRepositoryInterface */ protected OrderRepositoryInterface $orderRepository; /** * @var ProductRepositoryInterface */ protected ProductRepositoryInterface $productRepository; /** * @var ProductRepositoryInterface */ protected $customerRepository; /** * @var QuoteFactory */ protected QuoteFactory $quote; /** * @var QuoteManagement */ protected QuoteManagement $quoteManagement; /** * @var OrderSender */ protected OrderSender $orderSender; protected ProductFactory $productFactory; protected ObjectManagerInterface $objectManager; protected ShippingRate $shippingRate; protected InvoiceService $invoiceService; protected Transaction $transaction; protected InvoiceSender $invoiceSender; private string $customerEmail; private string $customerPassword; private string $customerPhone; protected function __construct( HelloCashApi $api, Config $config, Encryptor $encryptor, SyncLogRepository $syncLogRepository, SyncLogInterfaceFactory $syncLogFactory, CustomerFactory $customerFactory, StoreManagerInterface $storeManager, CustomerRepositoryInterface $customerRepository, QuoteFactory $quote, ProductFactory $productFactory, ObjectManagerInterface $objectManager, ShippingRate $shippingRate, State $state, Transaction $transaction ) { $this->customerFactory = $customerFactory; $this->storeManager = $storeManager; $this->customerRepository = $customerRepository; $this->quote = $quote; $this->productFactory = $productFactory; $this->state = $state; $this->objectManager = $objectManager; $this->shippingRate = $shippingRate; $this->transaction = $transaction; parent::__construct($api, $config, $encryptor, $syncLogRepository, $syncLogFactory); $this->customerEmail = (string)$this->config->getConfigDataValue('hello_cash_general/sync_order/customer_email'); $this->customerPassword = $this->encryptor->decrypt($this->config->getConfigDataValue('hello_cash_general/sync_order/customer_password')); $this->customerPhone = (string)$this->config->getConfigDataValue('hello_cash_general/sync_order/customer_phone'); } /** * {@inheritdoc} */ protected function configure() { $this->setName('dan_hellocash:sync-orders'); $this->setDescription('Imports the HelloCash orders into your Magento shop.'); $this->setDefinition([ new InputArgument(self::NAME_ARGUMENT, InputArgument::OPTIONAL, 'Name'), new InputOption(self::NAME_OPTION, '-a', InputOption::VALUE_NONE, 'Option functionality') ]); parent::configure(); } /** * {@inheritdoc} */ protected function execute( InputInterface $input, OutputInterface $output ) { try { $this->output = $output; $this->state->setAreaCode(Area::AREA_FRONTEND); $this->store = $this->storeManager->getStore(); $this->websiteId = $this->storeManager->getWebsite()->getId(); $this->createSyncLog(SyncLogType::ORDERS); $ordersHellocash = $this->getOrders(); $this->syncLog->setTotal((int)$ordersHellocash->count); $this->syncLogRepository->save($this->syncLog); foreach ($ordersHellocash->invoices as $orderHellocash) { try { if ('1' === $orderHellocash->invoice_cancellation) { continue; } $orderHellocash = $this->getOrder((int)$orderHellocash->invoice_id); $this->createOrder($orderHellocash); } catch (SyncOrderException $exception) { $this->handleOrderError($orderHellocash, $exception); } finally { $this->syncLog->setProcessed($this->syncLog->getProcessed() + 1); $this->syncLogRepository->save($this->syncLog); } } $this->handleSuccess(); } catch (SyncException $exception) { $this->handleFatalError('A problem occurred calling the HelloCash API. (status: ' . $exception->getStatusCode() . ', message: "' . $exception->getMessage() . '")'); } finally { $this->finishSync(); } } protected function createOrder(\stdClass $orderHelloCash) { $this->createCustomer($orderHelloCash); $quote = $this->quote->create(); $quote->setStore($this->store); $quote->setCurrency(); /** * Registered Customer */ $customer = $this->customerRepository->getById($this->customer->getId()); $quote->assignCustomer($customer); foreach ($orderHelloCash->items as $item) { $product = $this->productFactory ->create() ->loadByAttribute('hellocash_article_id', (int)$item->item_article_id); if (!$product) { throw new SyncOrderException('Product not found. (HelloCash ID: ' . $item->item_article_id . ', name: "' . $item->item_name . '")'); } $product->setPrice((float)$item->item_price); $quote->addProduct( $product, (float)$item->item_quantity ); } $addressData = $this->createAddressData($orderHelloCash->company); $quote->getBillingAddress()->addData($addressData); $quote->getShippingAddress()->addData($addressData); $this->shippingRate ->setCode('hellocash_hellocash') ->getPrice(); $shippingAddress = $quote ->getShippingAddress() ->addShippingRate($this->shippingRate); $shippingAddress->setCollectShippingRates(true); $shippingAddress->collectShippingRates(); $shippingAddress->setShippingMethod('hellocash_hellocash'); $quote->setPaymentMethod('hellocash'); $quote->setInventoryProcessed(true); $quote->save(); $quote->getPayment()->importData(['method' => 'hellocash']); $quote->collectTotals()->save(); $quoteManagement = $this->objectManager->create(QuoteManagement::class); $order = $quoteManagement->submit($quote); $order ->setHellocashInvoiceId((int)$orderHelloCash->invoice_id) ->setEmailSent(1) ->setStatus('pending') ->save(); if (!$order->getEntityId()) { throw new SyncOrderException('Failed to get the order ID after saving.'); } $this->createInvoice($order); $order ->setStatus('complete') ->save(); return $order; } protected function createCustomer(\stdClass $invoiceHellocash): CustomerInterceptor { if (isset($this->customer)) { return $this->customer; } $this->verifyCustomerCredentials(); $this->customer = $this->customerFactory ->create() ->setWebsiteId($this->websiteId) ->setStore($this->store); if (!$this->customer->loadByEmail($this->customerEmail)->getId()) { $this->customer ->setFirstname('Cashier') ->setLastname('HelloCash') ->setEmail($this->customerEmail) ->setPassword($this->customerPassword); $this->customer->save(); /** * @TODO: Ask Daniel why this is not working. */ // $this->customerRepository->save($this->customer); } return $this->customer; } protected function createAddressData(\stdClass $companyHellocash): array { $address = [ 'firstname' => $companyHellocash->name, 'lastname' => 'HelloCash', 'country_id' => 'AT', 'city' => $companyHellocash->city, 'street' => $companyHellocash->street, //'region' => $companyHellocash->city, 'postcode' => $companyHellocash->postalCode, 'telephone' => $this->customerPhone, // 'fax' => $companyHellocash->postalCode, 'save_in_address_book' => 1 ]; return $address; } public function createInvoice($order) { $this->invoiceService = $this->objectManager->create(InvoiceService::class); $invoice = $this->invoiceService ->prepareInvoice($order) ->register() ->save(); $this->transaction ->addObject($invoice) ->addObject($invoice->getOrder()) ->save(); $this->invoiceSender = $this->objectManager->create(InvoiceSender::class); $this->invoiceSender->send($invoice); $order ->addCommentToStatusHistory(__('Notified customer about invoice creation #%1.', $invoice->getId())) ->setIsCustomerNotified(true) ->save(); return $invoice; } protected function verifyCustomerCredentials() { if (empty($this->customerEmail)) { throw new SyncException('The customer email is not set in the module\'s admin configuration! Please set it.'); } if (empty($this->customerPassword)) { throw new SyncException('The customer password is not set in the module\'s admin configuration! Please set it.'); } if (empty($this->customerPhone)) { throw new SyncException('The customer phone number is not set in the module\'s admin configuration! Please set it.'); } } }
问题在于一个冲突的、写得不好的运输插件。所以没关系,感谢所有花时间阅读我的代码的人。