Shipping with MRW from Drupal Commerce: no more copy-pasting into the carrier portal

MRW and Drupal Commerce logos

Several of the e-commerce stores we build and run ship with MRW, one of the main carriers in Spain and Portugal. Until recently, shipping an order meant leaving the store: open MRW's customer portal, retype the customer's address, print the label, then copy the shipment number back into Drupal so the customer gets a tracking link. Multiply by every order, every day, and add returns, which meant doing the same dance with the addresses swapped.

We replaced that with a Drupal module. It now runs the daily expedition of the first of them, and we are releasing it to the community: Commerce MRW is available on drupal.org, with a 1.1.0 release.

What it does

Commerce MRW integrates Drupal Commerce with MRW through SAGEC, the carrier's SOAP webservice for creating and managing shipments (envíos). The whole expedition cycle happens on the shipment admin pages the team already uses:

  • Transmit shipments (TransmEnvio): one click creates the shipment on MRW's side and stores the returned shipment number as the Drupal shipment's tracking code, feeding the customer-facing tracking link.
  • Labels on demand (GetEtiquetaEnvio): the transport label PDF is streamed straight from SAGEC every time someone asks for it. Labels are never stored locally, so MRW stays the single source of truth and there is no stale-file problem.
  • Cancel (CancelarEnvio) transmitted shipments before the courier picks them up.
  • Return pickups: a request can carry a pickup address (DatosRecogida), so MRW collects the parcel at the customer's door and delivers it back to the store. Returns stop being a manual job in the carrier portal.
  • Tracking: a client for MRW's TrackingServices webservice queries the current status, or the full status history, of any shipment: by MRW number, by your own order reference, individually or in bulk.
  • "Transmit as": shipments whose shipping method is not MRW (say, a generic "Free shipping" flat rate) can still be shipped with MRW. The operator picks the executing method at transmit time and the choice is recorded on the shipment.

Service codes cover the SAGEC catalogue (Ecommerce, Urgente 19 Expedición, Urgente 13 and friends), and PRE (test) and PRO (production) environments are separate credential sets with a test-mode toggle, so you can validate the integration with your franchise before a single real parcel moves.

Small module, sharp edges

The SAGEC manual is short; reality is not. A few of the edges the module rounds off for you:

  • Postal codes are per-country folklore. Spain wants 5 digits with leading zeros, Portugal wants only the first 4 of its 7-digit codes, Andorra's letters become zeros, and Gibraltar is always 00010. The module normalizes all of it before SAGEC ever sees an address.
  • The tracking service hides behind a WCF quirk: it only accepts SOAP posts on its relative endpoint address, and answers 404 on the address the documentation leads you to. We found out so you do not have to.
  • No PHP SOAP extension required. Both clients build their envelopes by hand over Drupal's HTTP client, which also makes every request fully testable with mocked responses; the module ships with a kernel test suite that asserts the exact XML that goes over the wire.

Your store's rules stay yours

Carrier integrations die by hardcoding someone else's workflow, so Commerce MRW deliberately does not have one. Site-specific data travels through an event: subscribe to the TransmEnvio request event and fill whatever your store knows, the consignee's phone number, a NIF, delivery observations for the courier, or a full pickup address to turn a transmission into a return pickup. In one of our stores, three small subscribers do exactly that: one copies the customer's phone, one sends the backoffice's "carrier notes" field as delivery instructions, and one swaps the addresses when a shipment is flagged as a return.

Tracking follows the same philosophy. The module gives you the client and a documented integration recipe, but ships no polling and changes no shipment states: whether "delivered at destination" should transition your workflow, or just inform a human, is your call. That store runs an hourly cron that mirrors the last MRW status into the expedition dashboard, next to each tracking code; marking a shipment delivered stays a human decision, now an informed one.

Battle-tested, then released

Like our other contrib modules, this one shipped to drupal.org only after running a real store's daily expedition: real transmissions, real labels handed to the courier, and a tracking client validated against the production webservice before its release was tagged. The test suite (42 kernel tests at the time of writing) covers the SOAP envelopes, the postal code rules, the backoffice forms and the tracking parsing.

Get it

composer require drupal/commerce_mrw:^1.1

Requires Drupal 10.3+ or 11 and Commerce Shipping 3.x, plus SAGEC credentials from your MRW franchise (ask your franchise; ours enabled both the shipping webservice and the tracking service on request).

If you run a Drupal Commerce store shipping in Spain or Portugal, this is for you. The issue queue is open, and international shipments, ZPL labels and MRW delivery points are on the roadmap.