我在使用控制台命令导入订单时尝试使用自定义送货方式。 一切正常,除了后端没有显示运输方式,当我事后检查订单时: 截图
模块基本结构和运输方法是使用 mage2gen.com 生成的,如果我手动创建订单,则可以在前端和后端运行。
有趣的是,如果我在收集运费后使用 $shippingAddress->setShippingMethod('flatrate_flatrate'); ,运输方式设置正确,但我无法让它与任何其他运输方式或我的自定义运输方式一起使用。
帮助将不胜感激!请告诉我是否应该添加更多代码。
谢谢! (对 Mage2 来说相当陌生)
系统.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>
运营商型号:
<?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')];
}
}
导入订单控制台命令:
<?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.');
}
}
} Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
问题在于一个冲突的、写得不好的运输插件。所以没关系,感谢所有花时间阅读我的代码的人。