Migrate to WhatArmy/FedexRest

Created on 30 January 2024, 10 months ago
Updated 18 March 2024, 8 months ago

Problem/Motivation

I https://www.drupal.org/project/commerce_fedex/issues/3200092#comment-152... ✨ Migrate to PHP FedEx API Wrapper Needs work

Proposed resolution

Migrate to WhatArmy/FedexRest

Remaining tasks

Test in live mode different cases and improve/fix code if it's needed.
Add caching of the access token?

User interface changes

There were some changes on settings form. So review and resave the settings before testing the changes.

API changes

Data model changes

πŸ“Œ Task
Status

Fixed

Version

2.0

Component

Code

Created by

πŸ‡ΊπŸ‡¦Ukraine khiminrm

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @khiminrm
  • πŸ‡ΊπŸ‡¦Ukraine khiminrm

    I've already changed base code of the module to use WhatArmy/FedexRest. Pushed current fixes to the issue fork. Have not fixed tests yet and have not tested all possible cases. What is hard to do on FedEx sandbox environment as structure of the requests and responses are predefined https://developer.fedex.com/api/en-ca/guides/sandboxvirtualization.html. So it would be great if more people will try to test these changes, especially by using live mode.
    The WhatArmy/FedexRest is pretty new and does not contain all possible properties and methods, so I had to add some fixes and use custom fork on local environment to develop and test. My PR: https://github.com/WhatArmy/FedexRest/pull/19. I hope it will be reviewed and merged soon.

  • πŸ‡ΊπŸ‡¦Ukraine khiminrm

    I've fixed compatibility with D10, fixed code standards errors.
    Also I've removed 'meter_number', because haven't found how it can be used with FedEx REST API.
    Still waiting for feedback for https://github.com/WhatArmy/FedexRest/pull/19

  • πŸ‡ΊπŸ‡¦Ukraine khiminrm

    I've fixed getting access token for live mode.
    Debugging errors received during testing in live mode:

    'code' => 'INVALID.INPUT.EXCEPTION',
                'message' => 'Invalid field value in the input',
  • πŸ‡ΊπŸ‡¦Ukraine khiminrm

    I've fixed values for the rateRequestType. this caused error from the previous comment.

    Investigating calculation of the dimensions. I have doubts that it works correct. For now it gets values from the custom_box package type from commerce_shipping.commerce_package_types.yml and as result of the conversions we have 0.01 cm for all dimensions and this is wrong even by the type of the value - it should be integer and maybe we have to use dimensions from the product variations.

  • πŸ‡ΊπŸ‡¦Ukraine khiminrm

    Attaching missed patch file for the #10

  • πŸ‡ΊπŸ‡¦Ukraine khiminrm

    have added fixes for the dimensions. Not sure if it's the best and correct solution.

  • πŸ‡ΊπŸ‡¦Ukraine khiminrm

    fixed the declaredValue amount

  • πŸ‡ΊπŸ‡¦Ukraine khiminrm

    I've improved logic for the settings. Allowed only 'Each item in its own box' for the Packaging strategy if there is no other package types then default custom_box, because the calculations use dimensions from the selected default package type and in custom_box (default type from the commerce_shipping) are too small and will be 0 after converting to CM. If there any other ideas, please, feel free to share them.

  • πŸ‡ΊπŸ‡¦Ukraine khiminrm

    Have fixed code in sub-modules and made minor changes on settings form.

  • Status changed to Needs review 10 months ago
  • Open in Jenkins β†’ Open on Drupal.org β†’
    Core: 9.5.x + Environment: PHP 7.4 & MySQL 5.7
    last update 10 months ago
    Composer require-dev failure
  • Seeing this after applying the patch when creating or editing a shipping method:

    Error: Class "FedexRest\Services\Ship\Type\PickupType" not found in Drupal\commerce_fedex\Plugin\Commerce\ShippingMethod\FedEx->defaultConfiguration() (line 223 of modules/contrib/commerce_fedex/src/Plugin/Commerce/ShippingMethod/FedEx.php).
    Drupal\commerce_shipping\Plugin\Commerce\ShippingMethod\ShippingMethodBase->setConfiguration(Array) (Line: 74)
    Drupal\commerce_shipping\Plugin\Commerce\ShippingMethod\ShippingMethodBase->__construct(Array, 'fedex', Array, Object, Object) (Line: 174)
    Drupal\commerce_fedex\Plugin\Commerce\ShippingMethod\FedEx->__construct(Array, 'fedex', Array, Object, Object, Object, Object, Object, Object, Object, Object) (Line: 193)
    Drupal\commerce_fedex\Plugin\Commerce\ShippingMethod\FedEx::create(Object, Array, 'fedex', Array) (Line: 21)
    Drupal\Core\Plugin\Factory\ContainerFactory->createInstance('fedex', Array) (Line: 83)
    Drupal\Component\Plugin\PluginManagerBase->createInstance('fedex', Array) (Line: 103)
    Drupal\commerce\Plugin\Commerce\InlineForm\PluginConfiguration->buildInlineForm(Array, Object) (Line: 143)
    Drupal\commerce\Plugin\Field\FieldWidget\PluginSelectWidget->formElement(Object, 0, Array, Array, Object) (Line: 26)
    Drupal\commerce\Plugin\Field\FieldWidget\PluginRadiosWidget->formElement(Object, 0, Array, Array, Object) (Line: 448)
    Drupal\Core\Field\WidgetBase->formSingleElement(Object, 0, Array, Array, Object) (Line: 216)
    Drupal\Core\Field\WidgetBase->formMultipleElements(Object, Array, Object) (Line: 117)
    Drupal\Core\Field\WidgetBase->form(Object, Array, Object) (Line: 186)
    Drupal\Core\Entity\Entity\EntityFormDisplay->buildForm(Object, Array, Object) (Line: 121)
    Drupal\Core\Entity\ContentEntityForm->form(Array, Object) (Line: 107)
    Drupal\Core\Entity\EntityForm->buildForm(Array, Object) (Line: 25)
    Drupal\commerce_shipping\Form\ShippingMethodForm->buildForm(Array, Object)
    call_user_func_array(Array, Array) (Line: 536)
    Drupal\Core\Form\FormBuilder->retrieveForm('commerce_shipping_method_edit_form', Object) (Line: 283)
    Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
    Drupal\Core\Controller\FormController->getContentResult(Object, Object) (Line: 39)
    Drupal\layout_builder\Controller\LayoutBuilderHtmlEntityFormController->getContentResult(Object, Object)
    call_user_func_array(Array, Array) (Line: 123)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 627)
    Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 121)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
    Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 181)
    Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 76)
    Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
    Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 28)
    Drupal\Core\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 32)
    Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 106)
    Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
    Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 50)
    Drupal\ban\BanMiddleware->handle(Object, 1, 1) (Line: 48)
    Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 36)
    Drupal\Core\StackMiddleware\AjaxPageState->handle(Object, 1, 1) (Line: 51)
    Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 704)
    Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
  • Ah, have to add the package manually.

    For any trying to test this, you need to run:
    composer require whatarmy/fedex-rest

    For the patch to work.

  • Why is Meter Number removed?

    I cannot get rates with the patch.

    My credentials are current, but all I get is:
    Authorization token is missing. Make sure it is included

    #0 /var/www/html/vendor/whatarmy/fedex-rest/src/FedexRest/Services/Rates/CreateRatesRequest.php(353): FedexRest\Services\AbstractRequest->request()
    #1 /var/www/html/web/modules/contrib/commerce_fedex/src/Plugin/Commerce/ShippingMethod/FedEx.php(479): FedexRest\Services\Rates\CreateRatesRequest->request()
    #2 /var/www/html/web/modules/contrib/commerce_shipping/src/ShipmentManager.php(89): Drupal\commerce_fedex\Plugin\Commerce\ShippingMethod\FedEx->calculateRates(Object(Drupal\commerce_shipping\Entity\Shipment))
    #3 /var/www/html/web/modules/contrib/commerce_shipping/src/Plugin/Field/FieldWidget/ShippingRateWidget.php(151): Drupal\commerce_shipping\ShipmentManager->calculateRates(Object(Drupal\commerce_shipping\Entity\Shipment))
    #4 /var/www/html/web/core/lib/Drupal/Core/Field/WidgetBase.php(459): Drupal\commerce_shipping\Plugin\Field\FieldWidget\ShippingRateWidget->formElement(Object(Drupal\Core\Field\EntityReferenceFieldItemList), 0, Array, Array, Object(Drupal\Core\Form\FormState))
    #5 /var/www/html/web/core/lib/Drupal/Core/Field/WidgetBase.php(219): Drupal\Core\Field\WidgetBase->formSingleElement(Object(Drupal\Core\Field\EntityReferenceFieldItemList), 0, Array, Array, Object(Drupal\Core\Form\FormState))
    #6 /var/www/html/web/core/lib/Drupal/Core/Field/WidgetBase.php(120): Drupal\Core\Field\WidgetBase->formMultipleElements(Object(Drupal\Core\Field\EntityReferenceFieldItemList), Array, Object(Drupal\Core\Form\FormState))
    #7 /var/www/html/web/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php(186): Drupal\Core\Field\WidgetBase->form(Object(Drupal\Core\Field\EntityReferenceFieldItemList), Array, Object(Drupal\Core\Form\FormState))
    #8 /var/www/html/web/modules/contrib/commerce_shipping/src/Plugin/Commerce/CheckoutPane/ShippingInformation.php(335): Drupal\Core\Entity\Entity\EntityFormDisplay->buildForm(Object(Drupal\commerce_shipping\Entity\Shipment), Array, Object(Drupal\Core\Form\FormState))
    #9 /var/www/html/web/modules/contrib/commerce/modules/checkout/src/Plugin/Commerce/CheckoutFlow/CheckoutFlowWithPanesBase.php(546): Drupal\commerce_shipping\Plugin\Commerce\CheckoutPane\ShippingInformation->buildPaneForm(Array, Object(Drupal\Core\Form\FormState), Array)
    #10 [internal function]: Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowWithPanesBase->buildForm(Array, Object(Drupal\Core\Form\FormState), 'order_informati...')
    #11 /var/www/html/web/core/lib/Drupal/Core/Form/FormBuilder.php(536): call_user_func_array(Array, Array)
    #12 /var/www/html/web/core/lib/Drupal/Core/Form/FormBuilder.php(283): Drupal\Core\Form\FormBuilder->retrieveForm('commerce_checko...', Object(Drupal\Core\Form\FormState))
    #13 /var/www/html/web/core/lib/Drupal/Core/Form/FormBuilder.php(224): Drupal\Core\Form\FormBuilder->buildForm(Object(Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\MultistepDefault), Object(Drupal\Core\Form\FormState))
    #14 /var/www/html/web/modules/contrib/commerce/modules/checkout/src/Controller/CheckoutController.php(143): Drupal\Core\Form\FormBuilder->getForm(Object(Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\MultistepDefault), 'order_informati...')
    #15 [internal function]: Drupal\commerce_checkout\Controller\CheckoutController->formPage(Object(Drupal\Core\Routing\RouteMatch))
    #16 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)
    #17 /var/www/html/web/core/lib/Drupal/Core/Render/Renderer.php(627): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
    #18 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(121): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
    #19 /var/www/html/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
    #20 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(181): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
    #21 /var/www/html/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
    #22 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #23 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #24 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/ContentLength.php(28): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #25 /var/www/html/web/core/modules/big_pipe/src/StackMiddleware/ContentLength.php(32): Drupal\Core\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #26 /var/www/html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #27 /var/www/html/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #28 /var/www/html/web/core/modules/ban/src/BanMiddleware.php(50): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #29 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\ban\BanMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #30 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #31 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/AjaxPageState.php(36): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #32 /var/www/html/web/core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\AjaxPageState->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #33 /var/www/html/web/core/lib/Drupal/Core/DrupalKernel.php(704): Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    #34 /var/www/html/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
    #35 {main}

    The first section of the request is missing access_token

    	Sending FedEx request.
    \FedexRest\Services\Rates\CreateRatesRequest::__set_state(array(
       'api_endpoint' => '/rate/v1/rates/quotes',
       'access_token' => '',
       'production_mode' => false,
       'production_url' => 'https://apis.fedex.com',
       'testing_url' => 'https://apis-sandbox.fedex.com',
       'raw' => false,
       'shipper' => 

    LMK Thanks

  • Status changed to Needs work 9 months ago
  • πŸ‡ΊπŸ‡ΈUnited States TomTech

    Hi @tonytheferg!

    Appreciate the feedback!

    Working on re-rolling the MR given D10 compatibility (and other changes related to the test suite) have been merged in.

    Also adding in more validation and messaging.

    Expect to tag this as a new version release, given that SOAP -> REST is not a straight swap out.

    Things to note:

    1. Your SOAP credentials will NOT work with REST. You'll need to go to developer.fedex.com, and create a REST API project, to get new credentials.
    2. IRT meter, this property is not used in the REST API, hence the removal.
  • Assigned to TomTech
  • πŸ‡ΊπŸ‡ΈUnited States TomTech
  • There are 13 api's to choose from when creating a project. Do we know which ones we will need for Drupal?

  • Ok, so I enabled them all, and created new api keys.
    Sandbox/test credentials were not working:
    This was the response for test credentials:

    FedEx response received.
    (object) array(
       'transactionId' => 'APIF_SV_RATC_TxID607eddad-0918-4e6c-93c0-eef236e4568b',
       'errors' => 
      array (
        0 => 
        (object) array(
           'code' => 'REQUEST.MISMATCH',
           'message' => 'The response is unavailable for the request payload sent to this virtualized sandbox instance. Please use the exact request payload from API JSON Collection available for download through FedEx Developer Portal and try again.',
        ),
      ),
    )

    And this is the message I get with live/production credentials:

    	FedEx response received.
    (object) array(
       'transactionId' => 'a8593635-4162-40fd-a731-7aa28bbcb542',
       'errors' => 
      array (
        0 => 
        (object) array(
           'code' => 'REQUESTEDSHIPMENT.RATEREQUESTTYPE.REQUIRED',
           'message' => 'Rate request type is required. Please update and try again.',
        ),
      ),
    )
  • Ok, production error it seems was from not having pricing options set under FedEx Options.

    Maybe those checkboxes should be required.

  • Another note, with the shipping method plugin:
    https://git.drupalcode.org/project/commerce_fedex/-/blob/8.x-1.x/src/Plu...

    We can use the config value as the #default_value on password form elements so that every time you edit the method you don't have to re-paste the password.
    '#default_value' => $this->configuration['api_information']['api_password'],

  • πŸ‡ΊπŸ‡ΈUnited States TomTech

    Hi @tonytheferg !

    The primary API needed is the "Rates and Transit Times API".

    I'm still working on the re-roll, which addresses additional issues and edge cases, including having a fallback for the rate request type.

    IRT the password issue, please see: πŸ› When updating the configuration form your password gets wiped. Closed: duplicate .

  • Cool. Thanks @TomTech!

    I see you are grinding it out on FedEx. :) That's great!

    I noticed the slow response times issue as well,
    I agree that is needed as the requests are rather slow.

  • πŸ‡ΊπŸ‡ΈUnited States TomTech

    Changing the target version to 2.0.x for REST implementation.

    • khiminrm β†’ authored 6c4155e2 on 3417970-migrate-to-whatarmyfedexrest-2
      Issue #3417970 by khiminrm, tonytheferg, TomTech: Migrate to WhatArmy/...
    • khiminrm β†’ authored 6c4155e2 on 2.0.x
      Issue #3417970 by khiminrm, tonytheferg, TomTech: Migrate to WhatArmy/...
  • Status changed to Fixed 9 months ago
  • πŸ‡ΊπŸ‡ΈUnited States TomTech

    A new 2.0.x branch has been created and an alpha release has been tagged for REST.

    Closing out this ticket, as the initial development is in place. Expect to see a few items come up as further testing is done. (But, would be happy if there aren't any!) Unit tests would be a good addition, as this module is pretty light in that regard.

  • πŸŽ‰
    Is there a reason we can't opt into security coverage?

  • πŸ‡ΊπŸ‡ΈUnited States mikelutz Michigan, USA

    Lol. We could, except this project has never had a stable release, so there's never been anything to cover. We went from 7.x-dev to 8.x-1-rc2, and we are back at alpha now. πŸ˜‚πŸ˜‚ I never got the 1.x branch to a point I was comfortable to call stable. Hopefully soon, with all the recent activity.

  • Hey @TomTech, there is this, that could use fixed as well:
    https://www.drupal.org/project/commerce_fedex/issues/3264329 β†’

    It's simple. I have an even subscriber in place just to clean up after it.

    Commerce Shipping titles the Shipment #1, etc

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024