I'm not sure what can cause this but I'm going to give you the steps to debug the problem.
The error
The error you're getting:
Invalid carrier specified.
Comes from the following file: app/code/core/Mage/Sales/Model/Order/Shipment/Api.php
in the addTrack()
method:
public function addTrack($shipmentIncrementId, $carrier, $title, $trackNumber)
{
$shipment = Mage::getModel('sales/order_shipment')->loadByIncrementId($shipmentIncrementId);
/* @var $shipment Mage_Sales_Model_Order_Shipment */
if (!$shipment->getId()) {
$this->_fault('not_exists');
}
$carriers = $this->_getCarriers($shipment);
if (!isset($carriers[$carrier])) {
$this->_fault('data_invalid', Mage::helper('sales')->__('Invalid carrier specified.'));
}
$track = Mage::getModel('sales/order_shipment_track')
->setNumber($trackNumber)
->setCarrierCode($carrier)
->setTitle($title);
$shipment->addTrack($track);
try {
$shipment->save();
$track->save();
} catch (Mage_Core_Exception $e) {
$this->_fault('data_invalid', $e->getMessage());
}
return $track->getId();
}
As you can see this method does the following:
- load the shipment
- get the carriers for the shipment
- check if the carrier provided is allowed
- create the tracking
- add the tracking to the shipment
- save both tracking and shipment
Investigating
As you can see, the list of allowed carriers is retrieved via a protected method in that same class _getCarriers
:
protected function _getCarriers($object)
{
$carriers = array();
$carrierInstances = Mage::getSingleton('shipping/config')->getAllCarriers(
$object->getStoreId()
);
$carriers['custom'] = Mage::helper('sales')->__('Custom Value');
foreach ($carrierInstances as $code => $carrier) {
if ($carrier->isTrackingAvailable()) {
$carriers[$code] = $carrier->getConfigData('title');
}
}
return $carriers;
}
Here how I would start the debugging process.
Add the following line at the beggining of the addTrack()
method:
Mage::log("---".$carrier."---");
Then add the following line before return $carriers;
in the _getCarriers()
method:
Mage::log($carriers);
Call your sales_order_shipment.addTrack
and check your var/log/system.log
for the result
Case 1: your carrier code is not a key of the carriers array
Two possibilities here:
Your carrier is not enabled / allowed for the specified store. Indeed the following code retrieves the list of all carriers but it filters them by store id. Double check the carrier configuration using the scope dropdown:
$carrierInstances = Mage::getSingleton('shipping/config')->getAllCarriers(
$object->getStoreId()
);
Your carrier does not have tracking available. I guess you already did check that but open the model that corresponds to the carrier and check what the isTrackingAvailable()
method returns. If such method is not declared in the carrier model, that means it returns false and thus tracking is not available for this carrier.
Case 2: your carrier code is a key of the carrier array
First, ensure that there's no whitespaces around your carrier code. That's the reason why I added the ---
before and after the carrier code in the debugging code.
You can further investigate the differences by replacing:
if (!isset($carriers[$carrier])) {
$this->_fault('data_invalid', Mage::helper('sales')->__('Invalid carrier specified.'));
}
By:
foreach ($carriers as $key => $value) {
Mage::log("checking key: ".$key."---");
Mage::log("provided key: ".$carrier."---");
}
if (!isset($carriers[$carrier])) {
$this->_fault('data_invalid', Mage::helper('sales')->__('Invalid carrier specified.'));
}
If you're in this case, it's pretty much a typo IMO.
AFAIK the track object is the same in M2.
However, the rest of the code has changed.
$data = array(
'carrier_code' => 'ups',
'title' => 'United Parcel Service',
'number' => 'TORD23254WERZXd3', // Replace with your tracking number
);
$track = $this->trackFactory->create()->addData($data);
$shipment->addTrack($track)->save();
Where $this->trackFactory
an instance of Magento\Sales\Model\Order\Shipment\TrackFactory
and $shipment
is your shipment object.
Best Answer
You can find the Magento 2 generation logic here, especialy for repositories :
If the class is missing, Magento will try to generate it
For your case here : {magento-root-dir}/var/generation/Magento/Sales/Api/Data/ShipmentTrack.php
vendor/magento/magento2-base/app/etc/di.xml
vendor/magento/framework/ObjectManager/Code/Generator/Repository.php