cXML: the <Shipping> and <Tax> header blocks are configurable through field trees, each with its own tab in the administration — see cXML – Shipping & Tax.
New data fields shippingCostsNetPrice, shippingCostsTaxAmount, shippingMethodTranslatedName and cartTaxAmount. The shipping data fields are now available for cXML as well — see All Data Fields.
New field filter "System price digits", which formats a value with the decimals configured on the system (cXML only) — see cXML – Configure Fields.
Product custom field "UNSPSC number" (agiqon_connector_unspsc) for the UNSPSC commodity code, created on installation and update, available as the data field productUnspsc — see Product Extensions.
The default cXML systems fill <Classification domain="UNSPSC"> and <UnitOfMeasure>, so the generated ItemDetail is valid against the cXML 1.2 DTD.
OCI: the control parameters ~target, ~OkCode and ~caller are returned to the procurement system unchanged — see OCI – Login.
OCI: saving a system warns when another active system uses the same variable names for user name, password and hook URL.
Breaking: the shipping method extension is no longer named after OCI: agiqon_oci_shipping_method becomes agiqon_connector_shipping_method, ociShippingMethod becomes connectorShippingMethod — see Shipping Methods.
The option "guest session" is now called "separate cart session" — wording only, the behaviour is unchanged.
cXML: <Shipping><Description> uses the translated shipping method name, or the name from the shipping method extension when one is maintained, and carries the xml:lang attribute required by the cXML 1.2 DTD — as does the Tax block.
cXML: the shared secret is read from the first Sender credential regardless of its domain. The secret itself is still verified — see cXML – Authentication.
cXML: the field configuration dialog follows the layout of the OCI field configuration.
OCI: an empty login parameter counts as not supplied, so a blank TOKEN no longer breaks the username/password login.
shippingNumber and shippingInternArticleNumber always returned an empty value, for cXML and OCI; shippingInternArticleNumber returned the shipping number instead of the internal article number.
shippingName was escaped twice in cXML.
cXML: the field filters substring, number format and divide-by are applied again.
currencyIsoCode returns the active context currency instead of the sales channel's default currency.
Duplicating a cXML system no longer loses the data field assignments of its fields.
Saving or closing the cXML field configuration no longer leaves the administration unusable.
OCI login: only active systems are considered and the customer assignment decides which of them a request belongs to — see OCI – Customers & Units.
OCI: the token custom field can be saved in the administration again.
OCI: a deactivated customer account can no longer log in via token.
The punchout return form posts into the window requested via ~target, falling back to _top.
Administration: the German labels of the "additional field" and "payload field" data field types are translated again.
Breaking change: the shipping method entity extension was renamed. Integrations using addAssociation('ociShippingMethod'), extensions.ociShippingMethod or the table agiqon_oci_shipping_method have to switch to connectorShippingMethod / agiqon_connector_shipping_method. A migration renames the table, the maintained values are preserved.
Shipping and tax are rendered from field trees now. The migration creates them for every existing cXML system, so the output stays the same; adjust them under Shipping / Tax.
Field filters take effect again. Substring, number format and divide-by filters configured for cXML fields were silently ignored until now and will change the generated XML. Review the field configuration of your cXML systems before updating productive integrations.
<Shipping><Description> can change if a translation or a shipping method extension name is maintained. <Shipping><Money> still returns the gross amount — switch the field to shippingCostsNetPrice if a net value is required.
In multi-currency shops currencyIsoCode now follows the active currency.
OCI logins now require the customer to be assigned to one of the systems addressed by the request. If a customer is assigned to a system whose variable names the procurement system does not send, that login is rejected from this version on. The log entry names the candidate systems and the customer's system — check the customer assignment under Customers before updating productive integrations.
A deactivated customer account can no longer log in via token. Accounts deactivated in Shopware that still punched out via token lose access.
The token custom field has to be entered once per OCI system that uses the token login — the value could not be saved before.
~target, ~OkCode and ~caller are returned automatically now. If one of them was mapped by hand via transmissionAdditionalDataField, it is sent twice from this version on — remove that field from the field configuration.
The cXML punchout level 2 form on the product detail page posts into the top window now; it carried no target before.
New option Close button behavior: on closing the session the buyer can be redirected to the procurement system's hook URL, configurable per system. See OCI – Login and cXML – Create system.
The filter fix applies to new installations only. If the default OCI system is already installed, re-save the fields vendormat, matgroup and quantity once in the administration — see Updating the plugin.
CxmlSystemApiService::duplicate() no longer fails with a "This value should not be blank" DAL validation error when a cXML field has an empty/blank name (e.g. from legacy data); a stable fallback name is now assigned automatically and a warning is logged so the affected field can be renamed in the admin UI.
New migration automatically renames legacy field references (productUnitOciExtension, productCxmlUnitExtension) to the new productSystemUnit data field on OCI and cXML fields, so field mappings created before the new unit data field was introduced keep working.
transmissionAdditionalDataField data field for field mappings, resolving values from a transmission's additional-fields payload via a configurable extra key.
lineItemPayloadField data field for field mappings, resolving values from a cart line item's payload via a configurable extra key.
Dedicated rotating log files per connector area under log/AgiqonConnector/:
api_<env>.log — License API HTTP calls
oci_<env>.log — OCI login and function controllers
cxml_<env>.log — cXML login controller
connector_<env>.log — general connector events
Each file rotates with up to 14 files at DEBUG level.
Typed exception classes for license API errors:
LicenseValidationException — thrown on 4xx responses (carries HTTP status code)
LicenseApiUnavailableException — thrown on network/connection failures
OciAuthenticationException — for failed OCI authentication flows
License check result caching to reduce live HTTP calls on every login:
Results cached for 10 minutes via Symfony cache.object
24-hour stale fallback: logins continue to work during temporary license API outages
Cache is invalidated on 401/403 responses so invalid licenses are never served from cache
Structured server-side logging to OCI login controller: every failure branch (wrong credentials, inactive system, missing fields, invalid URL, invalid license) is logged as WARNING; successful logins are logged as INFO; function dispatch errors as ERROR.
Structured server-side logging to cXML login controller: equivalent coverage for all failure and success paths.
Structured logging to OciDownloadJsonController: unhandled errors in the download JSON flow are now logged as ERROR.
errorType and hint fields in the test-connection API response to help administrators diagnose configuration issues:
missing_config — Client ID or Client Secret not set
network_error — license API unreachable
auth_error — credentials rejected by the license API
Structured server-side logging to CxmlAuthController: all failure paths (invalid/expired auth key, customer not found, system not found, malformed stored XML) are logged as WARNING; successful auth flows as INFO.
OciUndefinedFunctionController now logs unsupported OCI function names as WARNING.
All Symfony DI service configuration files migrated from XML to YAML (.xml → .yaml). Plugin developers extending the service container should use the .yaml format going forward.
Transmission detail page redesigned: improved layout and visual structure across all tabs.
Transferred transmissions now allow adding, editing and removing cart items as long as no order has been created yet.
Removed dead HTTP request method validation blocks in OciLoginController and CxmlLoginController that referenced an undefined class (HTTPRequestMethod) and lacked a return statement, causing a potential fatal PHP error at runtime. The OciLoginController now correctly validates the configured HTTP method of the customer's OCI system after authentication.
Replaced deprecated utf8_encode() with mb_convert_encoding() in CxmlDuplicateController (deprecated since PHP 8.2, removed in PHP 9).
CxmlLoginController and CxmlInspectController now catch SimpleXMLElement parse exceptions and return a proper error response instead of an unhandled 500.
CxmlInspectController Twig template path corrected from @Storefront/... to @AgiqonConnector/... (template was never found at runtime).
CxmlDuplicateController now correctly extends AbstractController instead of StorefrontController; storefront-scoped base class was incompatible with the API route scope.
OciProductService::addProductToCart() now returns the recalculated cart from CartService::add() instead of the original cart object, ensuring prices are always up to date after adding a line item.
OciCustomerService::deleteOldTempCustomers() no longer filters by languageId; temporary customers created in any language context are now cleaned up correctly.
CxmlLoginController URL decoding unified to html_entity_decode() to handle all HTML entities, not just &.
ConnectorTransmissionController::updateCart() and CxmlDuplicateController::duplicateSystem() now validate the incoming ID as a valid UUID before executing any DAL queries, preventing invalid input from reaching the database layer.
OciCustomerService and OciProductService single-result queries now set Criteria::setLimit(1) to avoid fetching unnecessary rows when only the first match is needed.
ConnectorResponseGenerator promoted to abstract class; shared resolveDataFieldValue() and getConfigKey() methods extracted from OciConnectorResponseGenerator and CxmlConnectorResponseGenerator to eliminate duplication.
OCI login controller credential-presence check extracted into an explicit $credentialsPresent variable for improved readability.
Complete architectural rewrite of the plugin (version 3.x series).
OCI and cXML protocol logic moved from storefront/checkout classes into a dedicated Connector domain layer.
Each OCI function (DETAIL, VALIDATE, SOURCING, BACKGROUND_SEARCH, DOWNLOADJSON, QUANTITYCHECK) now has its own dedicated controller.
Each cXML transfer type (Inspect, TransferCart, TransferDirect) now has its own dedicated controller.
Shipping method extension to mark shipping methods as OCI/cXML-compatible directly in the Shopware shipping method administration.
Unified administration module: OCI and cXML systems are now managed in a single consolidated plugin module with improved navigation and ACL support.
Role-based access control (ACL) for all connector administration views.
New DataField system: a typed, registry-based mapping layer for product, order, line item, shipping, context and system fields. Custom fields can be registered via the Symfony service container without manual configuration.
New transmission management in the administration: a list view and a detail view for all connector transmissions, including status tracking (open, order created, transferred, closed, cancelled).
Transmissions now have a dedicated number range for unique transmission numbers.
Transmission customers are recorded per transmission to track which customer was logged in.
Dashboard in the administration showing transmission statistics and key metrics.
Transmission mode can be configured per system: "manual" (transfer triggered by the user) or "auto" (transfer happens automatically on logout).
Cart payload and active rule IDs are saved on the transmission for reproducibility.
Payment method and shipping method can now be configured per OCI and cXML system. If no method is configured, the customer's last used methods are applied automatically.
New order settings card added to the cXML system detail view.