Skip to main content

Order Custom Field Not Showing in Drupal Commerce API

Problem/Motivation

When using the Commerce API module in Drupal, custom fields added to orders are not visible in the API response, despite being properly configured in the order entity. This documentation explains the issue and provides a solution for exposing custom order fields through the Commerce API.

Impact

  • Custom order fields are not accessible via the JSON:API endpoints
  • Unable to read custom field values through the API
  • Affects integration with external systems that need access to custom order data

Steps to Reproduce

  1. Add a custom field to the order entity (e.g., a text field named "Field note")
  2. Add an item to the cart
  3. Access the checkout endpoint via URL:
    /jsonapi/checkout/{checkout-uuid}
  4. Observe that the custom field is not present in the JSON response

Root Cause

The issue stems from the Commerce API module's FieldAccess service, which controls which fields are exposed through the API. By default, this service restricts access to custom fields for security reasons.

Solution

1. Create a Service Provider

Create a custom service provider to override the default FieldAccess service implementation.

File: modules/custom/my_module/src/MyModuleServiceProvider.php

<?php

namespace Drupal\my_module;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Drupal\Core\DependencyInjection\ServiceProviderInterface;

class MyModuleServiceProvider extends ServiceProviderBase implements ServiceProviderInterface {
public function alter(ContainerBuilder $container) {
$definition = $container->getDefinition('commerce_api.field_access');
$definition->setClass('Drupal\my_module\FieldAccess');
}
}

2. Extend the FieldAccess Class

Create a custom FieldAccess class that extends the original one and adds your custom fields to the allowed list.

File: modules/custom/my_module/src/FieldAccess.php

<?php

namespace Drupal\my_module;

use Drupal\commerce_api\FieldAccess as OriginalFieldAccess;

class FieldAccess extends OriginalFieldAccess {
/**
* {@inheritdoc}
*/
protected function getAllowedViewFieldNames(string $entity_type_id): array {
$field_names = parent::getAllowedViewFieldNames($entity_type_id);
if ($entity_type_id === 'commerce_order') {
$field_names = array_merge($field_names, [
'field_custom_field_1',
'field_custom_field_2',
'field_custom_field_3',
]);
}
return $field_names;
}
}

Implementation Notes

  1. Replace my_module with your actual custom module name
  2. Update the list of field names in getAllowedViewFieldNames() to match your custom field machine names
  3. Clear the Drupal cache after implementing these changes

Additional Information

  • This solution maintains the security of the Commerce API module while allowing specific custom fields to be exposed
  • Remember to only expose fields that are safe for API consumers to access