Sendit.ma for WooCommerce

Description

This plugin connects your WooCommerce store to your Sendit.ma account, a delivery service operating in Morocco. It removes double data entry: orders are sent to Sendit in one click (or automatically), shipping is priced from the customer’s city, and delivery statuses flow back into WooCommerce.

The plugin interface is in French, the working language of the merchants it serves.

Main features

  • Parcel creation — send an order to Sendit from the order screen, as a bulk action, or automatically (in the background) when an order reaches a status you choose. The parcel goes to the order’s delivery address.
  • No duplicate parcels — simultaneous sends of the same order are blocked, and a send that got no answer from Sendit is checked at Sendit before anything is created again.
  • Dynamic shipping rates — the rate comes from the Sendit district the customer selects at checkout. Enable it globally or product by product. Free shipping, store pickup and an optional “free above X MAD” threshold on the Sendit rate are supported.
  • City / district selector — replaces the “City” field with a searchable list of Sendit districts, for Moroccan addresses only. Works with both the classic checkout and the block checkout (WooCommerce 8.9+).
  • PDF labels — download the label for one order, or generate a combined PDF for a selection of orders.
  • Automatic status tracking — the Sendit webhook adds a timestamped note at each step and moves the order to “Completed”, “Cancelled”, “Failed” or “On hold” depending on the delivery outcome.
  • Parcel options — “allow try on” and “allow opening” can be set globally, per order, or in bulk, and are synced to Sendit.
  • Cities and rates kept current — the list is fetched when you save your API keys and refreshed weekly, so Sendit rate changes reach your store without anyone remembering to press a button.
  • HPOS compatible — works with WooCommerce High-Performance Order Storage.

External service required

This plugin is a connector: it only works with a Sendit.ma account. Sendit.ma is a Moroccan delivery service operated by Sendit (ICE 002745443000051, 120 Bd de la Grande Ceinture, Casablanca, Morocco). The plugin performs no delivery function of its own — it sends your orders to the Sendit API and displays what comes back.

What is sent, when, and where

  • https://app.sendit.ma/api/v1/login — when you save the settings and when you test the connection: your API keys, in exchange for a session token.
  • https://app.sendit.ma/api/v1/districts — when you save API keys, once a week, and whenever you force a sync: no customer data, only a request for the list of cities and rates.
  • https://app.sendit.ma/api/v1/deliveries — when a parcel is created, triggered by you or by the order status you configured: the recipient’s name, phone number and delivery address, the order reference, the items and quantities, the amount to collect, and the parcel options. If a creation gets no answer, the next attempt first searches this endpoint by the recipient’s phone number to find a parcel that may already exist.
  • https://app.sendit.ma/api/v1/deliveries/{code} — when you change the parcel options of a sent order, or attach an existing parcel to an order by its code: the parcel code and the options.
  • https://app.sendit.ma/api/v1/deliveries/getlabels — when you download a label: the code of the parcel concerned.

Nothing is transmitted until you enter your API keys. The plugin sends data to no other recipient, loads no external resources, and collects no usage statistics.

In the other direction: Sendit calls your store’s webhook URL to report delivery progress. That URL carries a token, and requests without a valid token are rejected.

By using this plugin you accept the terms of the Sendit service:

  • Terms of use: https://plugins.sendit.ma/terms
  • Privacy policy: https://plugins.sendit.ma/privacy

The plugin is free and no feature is restricted. Physical deliveries carried out by Sendit.ma are billed separately, at Sendit.ma’s published rates.

Screenshots

Installation

  1. In the WordPress admin, go to Plugins Add New Upload Plugin and upload the ZIP file.
  2. Activate the plugin. WooCommerce must be installed and active.
  3. Go to WooCommerce Sendit.ma.
  4. Enter your Public Key and Secret Key (available in your Sendit.ma account).
  5. Save. The city list is fetched automatically as soon as valid keys are stored, and refreshed once a week from then on.
  6. Choose your pickup city and the activation mode that suits you, then save again.
  7. Copy the Webhook URL shown on the page and paste it into the Webhook section of your Sendit.ma account, so delivery statuses are reported automatically.

FAQ

The Sendit shipping method does not appear at checkout

Check three things: the city list has been synced, the activation mode in the Sendit settings matches what you need (“Per Product” requires ticking the box on each product), and a WooCommerce shipping zone covering Morocco contains the “Sendit.ma Shipping” method.

The list of cities is empty

Save the settings page with valid API keys: the list is fetched automatically. If it fails, the notice at the top of the page states the reason (invalid keys, network blocking, and so on). Force a city sync in WooCommerce Sendit.ma retries immediately.

Do I have to sync the cities by hand?

No. The list is fetched automatically when you save valid API keys, and refreshed once a week so rate changes made at Sendit reach your store on their own. The button is only there to force an immediate refresh.

Delivery statuses are not updating

The webhook URL must be saved in your Sendit.ma account exactly as shown, including its token (the token= parameter at the end). Without that token, requests are rejected for security reasons.

Can I change the delivery district after the order is placed?

Yes, from the Sendit.ma Delivery Options panel on the order screen, as long as the parcel has not been created yet.

Can I offer free delivery?

Yes, two ways. Add WooCommerce’s “Free shipping” method to your Morocco shipping zone (with a minimum amount or a coupon): when it is available it replaces the paid Sendit rate, and the order is still sent to Sendit. Or set “Free delivery from (MAD)” in the settings of the Sendit.ma Shipping method itself. Store pickup is always offered alongside Sendit, and WooCommerce Sendit.ma Other shipping methods lets you show your other carriers too.

A send got no answer from Sendit. Can I send it again?

Yes. The plugin remembers the unanswered attempt, and the next send first looks for the parcel at Sendit: if it exists, it is attached to the order, otherwise a new one is created. If the parcel was created from your Sendit account, enter its code under “Attach an existing parcel” in the order’s Sendit panel.

How much does Sendit collect on delivery?

The order total minus refunds, or nothing for an order already paid online (bank transfer received, card). When in doubt the plugin collects. You can type a different amount in the order’s Sendit panel before sending it, for a deposit for example. Orders in a currency other than MAD need that amount, since Sendit collects in dirhams.

Can I keep my API keys out of the database?

Yes. Define SENDIT_MA_PUBLIC_KEY and SENDIT_MA_SECRET_KEY in wp-config.php; they take precedence over the settings page. The secret key you save in the settings is never displayed again: leave the field empty to keep it.

What happens to my checkout if I turn Sendit off?

Choosing “Disable Sendit” in the settings, or deactivating the plugin, gives you back WooCommerce’s own checkout fields. Customer addresses keep their city name.

Is the plugin free?

Yes. The plugin is free and no feature is gated. You need an active Sendit.ma account, and Sendit bills the physical deliveries separately at its published rates.

Reviews

There are no reviews for this plugin.

Contributors & Developers

“Sendit.ma for WooCommerce” is open source software. The following people have contributed to this plugin.

Contributors

Changelog

2.2.8

  • Arabic checkout. On a store whose language is Arabic (ar, ary), the city / district field, its search and the checkout messages are shown in Arabic, and districts are listed with the Arabic name provided by Sendit followed by the Latin one, so customers can search in either script. The value saved on the order and sent to Sendit is unchanged. Arabic names are fetched at the next city sync, which runs on its own after the update. The field is laid out right to left on right-to-left stores.
  • The city / district field keeps the look of the page. It no longer turns dark when the visitor’s device is in dark mode while the store’s theme stays light.

2.2.7

  • Order screen shows the parcel options that are really sent. In the order’s Sendit panel, “Default (…)” next to “Allow try on” could read “Yes” while “No” was sent to Sendit, as long as the plugin settings had never been saved. The label now uses the same default as the parcel itself (try on: No, opening: Yes, unless changed in the settings).

2.2.6

Delivery address, duplicate parcels, free shipping and checkout fixes, from issues reported by a merchant and reproduced on a test store.

  • Parcels now go to the delivery address. When an order had a separate shipping address, the parcel was created with the billing name, phone, address and city. The plugin now uses the shipping address (falling back to the billing phone only when no delivery phone was given), on both checkouts. The classic checkout also gets a district selector for the shipping address.
  • No more duplicate parcels. Each order is locked while it is being sent, so a double click, a bulk send and an automatic send can no longer each create a parcel. The “Send to Sendit.ma” order action no longer creates a second parcel for an order that already has one.
  • A send without an answer is no longer repeated blindly. After a timeout or a Sendit server error, the order remembers the attempt; the next send searches Sendit for the parcel and attaches it instead of creating a second one. A parcel can also be attached by hand from the order screen, after checking it belongs to the order.
  • Correct amount to collect. Refunds are subtracted, and orders already paid online are sent with nothing to collect (the plugin errs on the side of collecting when the payment method is unclear). The amount can be set per order. Orders in a currency other than MAD are refused until an amount in MAD is given.
  • Free shipping works again. WooCommerce free shipping and store pickup are no longer hidden when Sendit applies; free shipping replaces the paid Sendit rate, and those orders are still sent to Sendit. New “Free delivery from (MAD)” option on the Sendit method, and a setting to show other carriers next to Sendit. Customers outside Morocco are offered your other methods instead of none.
  • Checkout restored when Sendit does not apply. With “Disable Sendit”, a cart without Sendit products, or an address outside Morocco, the checkout keeps WooCommerce’s own fields. Company, address line 2, state and postcode are no longer removed; state and postcode are only hidden for Moroccan addresses. The city is saved as a name rather than a district number, and numbers saved by earlier versions in customer accounts are converted.
  • Checkout validation. A Moroccan phone number and an unambiguous district are checked when the order is placed, instead of failing at sending time.
  • Ambiguous cities are no longer guessed. A typed city matching several districts (Azrou, Bouskoura) used to be sent to the first one; the merchant now picks the district on the order.
  • Automatic sends run in the background through WooCommerce’s Action Scheduler, so customers never wait for Sendit at checkout; rate-limited or unanswered sends are retried. Pickup orders, virtual orders, orders abroad and orders shipped by another carrier are no longer sent automatically. Large bulk sends finish in the background instead of timing out.
  • Webhook: TOPICKUP and RETURNED statuses are recognised, a late status can no longer move a delivered order back, an order put on hold by a delivery incident returns to its previous status when the parcel moves again (without re-sending the “processing” email), repeated events are ignored, the body size is limited, and the secret can be rotated from the settings with a 15-minute grace period.
  • Account changes: the cached Sendit token is tied to the API keys, so a new account is used immediately; parcels created with a previous account are flagged instead of failing obscurely.
  • API keys can be defined in wp-config.php. The saved secret key is no longer printed in the settings page.
  • Error messages keep Sendit’s validation details but no longer include raw error pages. Parcel product lists use the purchased item names, subtract refunded quantities and skip virtual items. Label links are only shown for Sendit URLs. Bulk option changes only update the order once Sendit confirms.

2.2.5

  • WooCommerce is now declared as a required plugin. The plugin header carries Requires Plugins: woocommerce, so WordPress 6.5 and later will not let the plugin be activated before WooCommerce is installed and active, and offers to install it from the activation screen. Previously the activation succeeded and the store owner only discovered the dependency from an admin notice afterwards. Older WordPress versions ignore the header and keep the existing notice, so nothing changes for them.

2.2.4

  • Settings sanitisation hardened against non-scalar input. Every register_setting() callback now rejects arrays and objects before passing anything to a string function. This matters on WordPress 5.8 and 5.9, which the plugin supports: sanitize_key() only gained its own is_scalar() guard in WordPress 6.0, so on those versions a crafted nested array in the auto-send status field reached strtolower() and caused a fatal error when saving the settings. The pickup-district option no longer uses intval() directly, which silently turned an array into district 1.

2.2.3

Addresses the points raised in the WordPress.org plugin review.

  • Select2 updated from 4.0.13 (2020) to 4.1.0. The bundled copy was five years old. The library version is now a constant used for cache-busting, so an upgraded store actually receives the new file instead of serving the old one from browser cache. Verified on the block checkout: the city list, its search, selection and the resulting rate all behave as before.
  • Permission check added to bulk label printing. WordPress validates the bulk-action nonce, but not authorisation. The other two bulk actions already checked edit_shop_orders; printing labels did not, so a user without rights over orders could have triggered label generation and obtained the parcel PDF address.
  • The city-sync notice is now confined to the Sendit settings page. It could previously appear on any admin screen.

2.2.2

  • Plugin URI and Author URI now point to different pages, as the directory requires: the plugin page at plugins.sendit.ma/woocommerce, and the company site at www.sendit.ma.

2.2.1

Release preparation for the WordPress.org directory, plus automatic city syncing.

  • Cities now sync on their own. Saving valid API keys fetches the city and rate list immediately — the separate “sync” step is no longer something to remember. A sync only re-runs when the keys change or the list is empty, so saving the page repeatedly costs nothing. If it fails, the page says why, and the next save retries.
  • Weekly refresh now reaches existing stores. The weekly city refresh was only scheduled when the plugin was activated, so stores that updated in place never got it and could keep charging outdated rates. It is now scheduled on load as well.
  • The manual button remains as “Force a city sync”, for an immediate refresh.
  • Plugin renamed to “Sendit.ma for WooCommerce” to follow the WooCommerce trademark naming rules.
  • Readme rewritten in English, as the directory requires, and the external service Sendit.ma now fully documented.
  • API keys and the shipping strategy option now go through explicit sanitisation callbacks.
  • Label download now verifies that the PDF address returned by the API belongs to Sendit before redirecting to it.
  • Translation identifier aligned with the plugin folder (sendit-ma-integration), which WordPress.org requires before it will distribute translations.
  • Added the translation template languages/sendit-ma-integration.pot (146 strings), previously missing: no translation could have been produced without it.

2.2.0

Version validated on a real store (WordPress 7.1, WooCommerce 11.1), on both the classic and block checkouts, with and without High-Performance Order Storage.

Important fixes:

  • City search restored on the block checkout. The field listed 500+ cities as a raw list with no search: the library it needs was being removed from the page by WooCommerce right after it loaded. It is now bundled with the plugin. The field also keeps working after each address recalculation, which was not the case before.
  • Phone number now required at checkout. Sendit rejects any parcel without a phone number (HTTP 422). The block checkout left the field optional, so an order could be saved without a number and then fail to send indefinitely. This can be turned off.
  • No more accidental free shipping. A district missing from the rate list (removed at Sendit, stale customer address, unsynced list) offered “Shipping: 0 MAD”. No rate is offered in that case now.
  • Consistent default parcel options. The settings showed “try on: No” while “Yes” was being sent to Sendit on a fresh install.
  • Native city, postcode and state fields hidden on the block checkout. The state field stayed visible next to the Sendit field, inviting customers to fill in the wrong one.
  • No resources loaded from an external CDN: the search library ships with the plugin.

Performance:

  • The city and rate lists (~22 KB) are no longer loaded on every page view of the site, only where they are used.
  • Checkout styles and scripts are now real files, cached by the browser, instead of being re-injected into the HTML on every load (~320 lines).

Other:

  • Automatic weekly refresh of cities and rates.
  • Deactivating the plugin no longer deletes the city list; deleting the plugin does erase all data, API keys included.
  • The API test endpoint now checks user capabilities.
  • Fixed an untranslatable label and translations inserted into JavaScript (a single apostrophe was enough to break the checkout script).
  • Compatibility headers updated (WordPress 7.1, WooCommerce 11.1).

2.1.1

  • HPOS and block checkout compatibility declarations: WooCommerce no longer shows the plugin as incompatible.
  • Fixed: the confirmation message for a manual send was displayed in red, like an error.
  • Fixed: bulk label printing returned no message when none of the selected orders had a Sendit code.
  • Fixed: possible PHP notice when saving an order whose city field was absent from the checkout.
  • Added the required version headers (WordPress, PHP, WooCommerce) and the plugin documentation.

2.1

  • Compatibility with the WooCommerce block checkout (8.9+), with a searchable district selector.
  • Automatic sending to Sendit when the order status changes.
  • “Send to Sendit” bulk action and a direct send button on the order screen.
  • Parcel options (try on / opening) configurable by default, per order, and in bulk.
  • Webhook secured by token, with timestamped order notes at each delivery step.
  • Product and variant details forwarded to Sendit.