Appearance
WooCommerce Integration
The official Wasal Delivery WordPress plugin connects your WooCommerce store to Wasal. When a WooCommerce order reaches a configured status, the plugin automatically creates a Wasal delivery order — no manual re-entry. It also injects governorate/neighborhood selectors at checkout, shows live delivery fees, and keeps the WooCommerce order status in sync with the delivery status.
Status: Available now. Server endpoints are under the
/woocommerce/prefix.
How it works
- At checkout, the customer picks a governorate and neighborhood from cascading dropdowns (populated from Wasal).
- The shipping method shows a live delivery fee for the selected area.
- When the WooCommerce order hits the configured trigger status (e.g.
processing), the plugin pushes it to Wasal as a delivery order. - As the Wasal order progresses, Wasal sends a signed webhook back to WordPress, which updates the WooCommerce order status.
Authentication
The plugin authenticates server-to-server with a static API key — no session required.
- Wasal generates a WooCommerce API key for the merchant.
- The generated key is prefixed
wc_. - The merchant enters it in the plugin's settings page as API Key.
- Every plugin request sends
Authorization: Bearer <key>.
The WooCommerce key (
wc_) is separate from the generic Merchant Integration API keys (pk_live_/pk_test_). The plugin uses thewc_key against the/woocommerce/endpoints described below.
API endpoints
Public (no auth)
| Method | Path | Purpose |
|---|---|---|
GET | /woocommerce/governorate-area/tree | Populates the governorate → neighborhood cascading dropdowns at checkout. Cached in a WP transient for 1 hour. |
Authenticated (Bearer wc_ key)
| Method | Path | Purpose |
|---|---|---|
GET | /woocommerce/customer/find?phone= | Look up whether a billing phone is already a Wasal customer for this merchant. Called before order creation. |
POST | /woocommerce/customer | Create a new Wasal customer (only if the phone lookup returns nothing). |
GET | /woocommerce/order/delivery-fee-preview | Live delivery fee for the selected area; used by the Wasal shipping method. Falls back to a flat rate if unreachable. |
POST | /woocommerce/order | Create a Wasal order from the WC order. |
PUT | /woocommerce/order/:orderId/cancel | Cancel the Wasal order when the WC order is cancelled. |
PUT | /woocommerce/order/:orderId/activate | Activate a Wasal draft order (created outside the order window). |
GET | /woocommerce/order/:orderId/history | Fetch the order statusHistory[], rendered as a timeline in the WC order sidebar. |
Test file: download wasal-woocommerce.http to run the full integration flow step-by-step in VS Code REST Client or JetBrains HTTP Client.
Field mapping (WooCommerce → Wasal)
| WooCommerce field | Wasal field | Notes |
|---|---|---|
get_billing_phone() | Customer identity | Used to find or create the customer. |
get_billing_first/last_name() | customer.name | Combined on create. |
get_billing_email() | customer.email | Optional. |
_wasal_governorate_id (order meta) | address.governorateId | Set at checkout. |
_wasal_neighborhood_id (order meta) | address.neighborhoodId | Set at checkout. |
get_items() | items[] | { name, sku, qty, price, subtotal, total, currency }. |
get_subtotal() | pricing.subtotal | |
get_shipping_total() | pricing.deliveryFee | |
get_total() | pricing.total | |
get_woocommerce_currency() | pricing.currency | |
payment_method === 'cod' | paymentMethod: 'cod' | Otherwise prepaid. |
get_total() (COD) | amountToCollect | 0 for prepaid. |
get_customer_note() | merchantNotes | |
| WC order ID | orderMerchantReferenceNumber | Used to match back on webhooks. |
settings['branch_id'] | branchId | From plugin settings. |
settings['special_handling_tags'] | specialHandlingTags | Comma-separated; defaults to none. |
Outbound webhooks (Wasal → WooCommerce)
When a Wasal order status changes, the server pushes a signed webhook to URLs the merchant registers in the Wasal merchant dashboard.
Server side
- Events:
order.created,order.status_changed,order.delivered,order.cancelled - Signature header:
X-Wasal-Signature: sha256=HMAC(secret, rawBody) - Managed via the Webhooks section of the merchant dashboard
Plugin side (inbound receiver)
- WordPress REST endpoint:
POST /wp-json/wasal/v1/order-update - Validates
X-Wasal-Signatureagainst the configured Webhook Secret - Maps Wasal status → WooCommerce status:
| Wasal status | WooCommerce status |
|---|---|
delivered | completed |
cancelled | cancelled |
failed | failed |
WooCommerce order meta keys
| Meta key | Set by | Purpose |
|---|---|---|
_wasal_governorate_id | Checkout | Passed to Wasal on order/customer create. |
_wasal_neighborhood_id | Checkout | Same. |
_wasal_order_id | Order push | Wasal order identifier — used for cancel/activate/history. |
_wasal_order_number | Order push | Human-readable number — used in the tracking link. |
_wasal_status | Order push + webhook | Last known Wasal status — shown in the orders list. |
Setup
- Install and activate the Wasal Delivery plugin in WordPress.
- Ask the Wasal team to generate a WooCommerce API key for your merchant.
- In WordPress, go to Wasal Delivery → Settings:
- API Base URL — e.g.
https://www.wasal.org/api/v1 - API Key — paste the generated
wc_key - Branch ID — the branch that will handle WooCommerce orders
- Auto-push — enable and set the trigger WC status (e.g.
processing) - Default Special Handling Tags — e.g.
none(comma-separated)
- API Base URL — e.g.
- In the Wasal merchant dashboard → Webhooks, add a webhook pointing to
https://your-wp-site.com/wp-json/wasal/v1/order-updateand copy the generated secret. - Back in WordPress, paste it as Webhook Secret.
- Add the
[wasal_track]shortcode to a page for customer-facing order tracking.
Security notes
- The WooCommerce API key authorizes full order creation for the merchant — keep it secret and rotate it if exposed.
- All webhook payloads are HMAC-signed; the receiver rejects any request with a missing or invalid
X-Wasal-Signature. - Always run WordPress over HTTPS so the key and webhook payloads are encrypted in transit.
- Regenerating the API key invalidates the old one — update the plugin settings immediately after regeneration.
