Menggunakan kaedah penghantaran tersuai secara pemrograman semasa membuat pesanan - Magento 2.4.3-p1
P粉300541798
P粉300541798 2024-03-26 13:45:22
0
1
400

Saya cuba menggunakan kaedah penghantaran tersuai apabila mengimport pesanan menggunakan arahan konsol. Semuanya berfungsi dengan baik kecuali bahagian belakang tidak menunjukkan kaedah penghantaran dan apabila saya menyemak pesanan selepas itu: Tangkapan skrin

Struktur asas modul dan kaedah penghantaran dijana menggunakan mage2gen.com dan boleh dijalankan pada bahagian hadapan dan belakang jika saya membuat pesanan secara manual.

Menariknya, jika saya menggunakan $shippingAddress->setShippingMethod('flatrate_flatrate'); selepas mengumpul penghantaran, kaedah penghantaran telah ditetapkan dengan betul, tetapi saya tidak boleh membuatnya berfungsi dengan mana-mana kaedah penghantaran lain atau kaedah penghantaran tersuai saya.

Bantuan akan sangat dihargai! Sila beritahu saya jika saya perlu menambah lebih banyak kod.

Terima kasih! (Agak baru untuk 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>

Model pembawa:

<?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')];
    }
}

Arahan konsol pesanan import:

<?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.');
        }
    }
}

P粉300541798
P粉300541798

membalas semua(1)
P粉032977207

Masalahnya ialah pemalam penghantaran yang bercanggah dan ditulis dengan buruk. Jadi tidak mengapa, terima kasih kepada semua yang meluangkan masa untuk membaca kod saya.

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan