0

I am attempting to write a custom shipping method module for our site since we use an internal service to determine shipping. I created a custom module that seems to be working with Commerce Shipping to pull back the correct rates when you click the Recalculate shipping button after entering your address.

In my module I have the getRates() function that is called after the address validates.

public function getRates(){
    $rates =[];
    $shipping_methods = $this->shipping_service->get_suborder_shipping_methods();

    foreach ($shipping_methods as $shipping_object) {
      $price = new Price((string)  floatval(str_replace(['$','USD',' '],'',$shipping_object->{'<TotalCharge>k__BackingField'})),'USD');
      $service_name = $shipping_object->{'<Name>k__BackingField'};
      $rates[] = new ShippingRate([
        'shipping_method_id' => $shipping_object->{"<Id>k__BackingField"},
        'service' => new ShippingService($shipping_object->{"<Id>k__BackingField"}, $service_name),
        'amount' => $price,
      ]);
    }
    return $rates;
  }

Two problems occur after you select a rate and click the Review order and pay:

1.) The shipping total is not updated in the Commerce cart details (and I am not sure how to capture the selected options and update it...event or hook) 2.) I get an Error: Call to a member function getPlugin() on null in Drupal\commerce_shipping\ShipmentManager->applyRate().

I was using the UPS Shipping Method Module as a cheat sheet but I believe I am missing somethings.

How do I capture the selected options when the Review Orders and Pay button are clicked and any ideas why I am getting the getPlugin error?

Thank you for any and all help / hints!

Update:

<?php

namespace Drupal\srs\Plugin\Commerce\ShippingMethod;

use Drupal\commerce_price\Price;
use Drupal\commerce_shipping\Entity\ShipmentInterface;
use Drupal\commerce_shipping\PackageTypeManagerInterface;
use Drupal\commerce_shipping\Plugin\Commerce\ShippingMethod\ShippingMethodBase;
use Drupal\commerce_shipping\ShippingRate;
use Drupal\commerce_shipping\ShippingService;
use Drupal\Core\Form\FormStateInterface;
use Drupal\srs\Company\SRS\SRSServiceRepository;
use Drupal\state_machine\WorkflowManagerInterface;

/**
 * Provides the UPS shipping method.
 *
 * @CommerceShippingMethod(
 *  id = "srs_shipping_service",
 *  label = @Translation("SRS Shipping Service"),
 * )
 */

class SRSShipping extends ShippingMethodBase
{

  /**
   * Constructs a new SRS Service.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\commerce_shipping\PackageTypeManagerInterface $package_type_manager
   *   The package type manager.
   * @param \Drupal\state_machine\WorkflowManagerInterface $workflow_manager
   *   The workflow manager.
   */

  public function __construct(array $configuration, $plugin_id, $plugin_definition, PackageTypeManagerInterface $package_type_manager, WorkflowManagerInterface $workflow_manager)
  {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $package_type_manager, $workflow_manager);
    $this->shipping_service = new SRSServiceRepository();

  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration()
  {
    return parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state)
  {
    return parent::buildConfigurationForm($form, $form_state);
  }
  /**
   * {@inheritdoc}
   */
  public function calculateRates(ShipmentInterface $shipment)
  {
    $rates = [];
    if ($shipment->getShippingProfile()->get('address')->isEmpty()) {
      return $rates;
    }

    if($this->validateAddress($shipment->getShippingProfile()->get('address')->first(), $shipment->getShippingProfile()->get('field_phone_number')->first() )){
      $rates =[];
      $shipping_methods = $this->shipping_service->get_suborder_shipping_methods();

      foreach ($shipping_methods as $shipping_object) {
        $price = new Price((string)  floatval(str_replace(['$','USD',' '],'',$shipping_object->{'<TotalCharge>k__BackingField'})),'USD');
        $service_name = $shipping_object->{'<Name>k__BackingField'};
        $rates[] = new ShippingRate([
          'shipping_method_id' => $shipping_object->{"<Id>k__BackingField"},
          'service' => new ShippingService($shipping_object->{"<Id>k__BackingField"}, $service_name),
          'amount' => $price,
        ]);
      }
    }


    return $rates;
  }

  public function validateAddress($addressItems, $phone_number){
    $address = [
      'address' => $addressItems->getAddressLine1(),
      'address2' => $addressItems->getAddressLine2(),
      'city' => $addressItems->getLocality(),
      'state' => $addressItems->getAdministrativeArea(),
      'country' => $addressItems->getCountryCode(),
      'zip_code' => $addressItems->getPostalCode(),
      'last_name' => $addressItems->getFamilyName(),
      'first_name' => $addressItems->getGivenName(),
      'phone_number' => $phone_number->get('value')->getValue(),
    ];
    return $this->shipping_service->validate_address('shipping',$address);
  }

}
6
  • 1
    I show how to create a custom shipping method over here Allow shipping that is calculated using a base rate plus a rate per item? – No Sssweat Dec 22 '20 at 7:04
  • Thanks Sssweat, I looked at your sample and I don't see much difference between what I created. I did move the getRates up to the condition in calculateRates. Since I don't have any manual configuration, I just added the default and returned the parent:: calls – Wally Kolcz Dec 22 '20 at 13:30
  • I can tell you a difference. I created programmatically a Shipping Method plugin while it seems that you did not? Did you create the Shipping Method via the UI and currently trying to override the amount of the rate? – No Sssweat Dec 22 '20 at 14:40
  • I created this custom shipping method module programmatically at \Drupal\srs\Plugin\Commerce\ShippingMethod and added it as a shipping method through the UI when it showed as an option. – Wally Kolcz Dec 22 '20 at 16:50
  • can you post your plugin code? – No Sssweat Dec 22 '20 at 17:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.