Title: Sahand &#8211; Unpaid Order SMS for WooCommerce
Author: sahandz
Published: <strong>November 11, 2026</strong>
Last modified: November 11, 2026

---

Search plugins

![](https://ps.w.org/sahand-unpaid-order-sms/assets/banner-772x250.png?rev=3796019)

![](https://ps.w.org/sahand-unpaid-order-sms/assets/icon-256x256.png?rev=3795934)

# Sahand – Unpaid Order SMS for WooCommerce

 By [sahandz](https://profiles.wordpress.org/sahandz/)

[Download](https://downloads.wordpress.org/plugin/sahand-unpaid-order-sms.1.2.0.zip)

 * [Details](https://wordpress.org/plugins/sahand-unpaid-order-sms/#description)
 * [Reviews](https://wordpress.org/plugins/sahand-unpaid-order-sms/#reviews)
 *  [Installation](https://wordpress.org/plugins/sahand-unpaid-order-sms/#installation)
 * [Development](https://wordpress.org/plugins/sahand-unpaid-order-sms/#developers)

 [Support](https://wordpress.org/support/plugin/sahand-unpaid-order-sms/)

## Description

Bring customers back to unpaid WooCommerce orders worldwide with SMS and email. 
Choose SMS, email, or both independently for customers and shop managers. Connect
Twilio, any HTTP SMS API, the WP SMS plugin, another plugin through a developer 
hook, or Kavenegar for Iran. Email uses WordPress wp_mail, so it works with your
SMTP or mail plugin.

**How it works**

 * X minutes or hours after an order is placed (you choose), if it is still unpaid,
   the customer gets the SMS and/or email you enabled. If the customer was active
   on the order in the last few minutes (for example just came back from the bank
   page to retry), the message waits a bit longer.
 * Optionally also when an order becomes _Failed_ or _Cancelled_ (after a short 
   wait you choose, so a customer who retries right away is not bothered).
 * Each message can contain a **personal one-time discount code** (percent or fixed
   amount, optional free shipping, valid for the hours you choose).
 * And a **one-click link back to checkout**: if the order can still be paid, the
   customer lands on its payment page with the discount applied; if it was cancelled,
   the cart is rebuilt with the same products and variations, the discount and the
   billing details already filled in.
 * Shop managers (one or more phone numbers and email addresses) can receive SMS
   and/or email to follow up.
 * Each order is processed at most once for its enabled channels, and not at all
   if the customer has paid another order in the meantime.
 * A log of every message, test buttons, and a tool to run it for a single order.

**SMS gateways and email**

 * Twilio: send from a phone number or Messaging Service SID.
 * Custom HTTP API: connect providers such as MeliPayamak, FarazSMS/IPPanel, SMS.
   ir, Vonage and Plivo using their API URL, GET/POST, form/JSON parameters, optional
   headers and success text.
 * WP SMS plugin: use its configured provider when wp_sms_send is available.
 * Another plugin (developer hook): delegate to sahand_uos_send_sms.
 * Email: HTML messages wrapped in WooCommerce styling, sent through wp_mail with
   a clickable checkout link.
 * Kavenegar: pattern (verify/lookup) messages, which Iranian operators require 
   for service SMS, and plain messages.
 * Test mode: SMS only goes to the log (including pattern previews). Enabled email
   channels still send real email.
 * Developers can add gateways with the `sahand_uos_sms_gateways` filter.

International phone numbers support + and 00 prefixes, Persian/Arabic digits, and
a configurable default country code (98). New SMS gateways use E.164; Kavenegar 
retains Iranian mobile formatting.

Translation ready, with Persian translation sources included in the project. Compatible
with WooCommerce High-Performance Order Storage (HPOS).

### External services

The optional “Keep messages on time on cached sites” feature is enabled by default.
Its browser tick only calls your own site’s WordPress AJAX endpoint and sends no
personal data; its request contains only the action name. It does not contact an
external service. It checks at most once every 5 minutes per browser, with a site-
wide 60-second lock and up to 5 due rescue checks per request.

This plugin connects to the Kavenegar SMS API (https://api.kavenegar.com), an Iranian
SMS gateway, to send the text messages. It is used only when you choose Kavenegar
as the gateway and enter your own Kavenegar API key; in Test mode no SMS is sent.

What is sent, and when:

 * When an unpaid order is due for a reminder (after the delay you set, or when 
   you press a test button or run the tool for one order): the recipient’s mobile
   number (the customer’s billing phone, or the shop manager numbers you entered),
   and the message content, which is either your template name plus its tokens (
   order number, discount code, the short code of the return link, the customer’s
   first name, the order total, etc.) or the plain message text with your sender
   line number, if you set one.
 * Your Kavenegar API key is part of the request URL, as required by the Kavenegar
   API.
 * The Kavenegar gateway sends no other data or requests to other services.

Service provider: Kavenegar (https://kavenegar.com). API documentation: https://
kavenegar.com/rest.html
 Terms of service: Kavenegar’s terms of use are shown and
accepted when you create your Kavenegar account: https://panel.kavenegar.com/Client/
Membership/Register Privacy policy: Kavenegar does not publish a separate privacy
policy page; their terms and contact page are at https://kavenegar.com/support/about

**Twilio**

When Twilio is selected and configured, the plugin sends the recipient phone number
and message text to https://api.twilio.com when an unpaid order is due, or when 
an administrator sends a test or runs an order manually. Requests include your Account
SID, Auth Token and From number or Messaging Service SID. Message text includes 
only the placeholders you choose.
 Terms: https://www.twilio.com/en-us/legal/tos
Privacy: https://www.twilio.com/en-us/legal/privacy

**Custom HTTP API**

Requests are sent only to the public HTTP/HTTPS URL the administrator enters, when
that gateway is selected and a reminder, test or manual send runs. Requests contain
the configured parameters (including phone number and message text where placeholders
are used) and headers, which may include API credentials. Redirects are not followed.
Review your chosen provider’s terms and privacy policy before configuring it. Requests
occur only for enabled SMS deliveries.

**WP SMS, developer hooks and email**

WP SMS and the developer hook pass the phone number and message text to the installed
plugin you select or implement. The hook also receives the order ID and recipient
role. That integration controls its external service usage. Email passes the recipient
address, subject and message body to wp_mail, using your site’s mail transport or
configured SMTP/mail plugin. No external email API is built into this plugin.

### Hooks

 * `sahand_uos_should_rescue` (bool, WC_Order, reason): return false to skip an 
   order.
 * `sahand_uos_message_vars` (array, WC_Order, coupon): add or change placeholders.
 * `sahand_uos_rescued` action (WC_Order, vars, reason): after messages were sent.
 * `sahand_uos_send_sms` (null, to, text, context): handle SMS through another plugin;
   return true or an array with ok for success.
 * `sahand_uos_sms_gateways` (array id => class): register gateways extending Sahand_UOS_Gateway.

## Screenshots

[⌊When to send (with the page-cache option) and the channels: choose an SMS gateway(
Twilio, any HTTP API, WP SMS, Kavenegar or a developer hook) and turn SMS and email
on per recipient.⌉⌊When to send (with the page-cache option) and the channels: choose
an SMS gateway (Twilio, any HTTP API, WP SMS, Kavenegar or a developer hook) and
turn SMS and email on per recipient.⌉[

When to send (with the page-cache option) and the channels: choose an SMS gateway(
Twilio, any HTTP API, WP SMS, Kavenegar or a developer hook) and turn SMS and email
on per recipient.

[⌊The customer and shop manager messages: SMS text (or an SMS pattern), email subject
and body, and a test button.⌉⌊The customer and shop manager messages: SMS text (
or an SMS pattern), email subject and body, and a test button.⌉[

The customer and shop manager messages: SMS text (or an SMS pattern), email subject
and body, and a test button.

[⌊The log of sent messages.⌉⌊The log of sent messages.⌉[

The log of sent messages.

## Installation

 1. Upload the plugin and activate it (WooCommerce must be active).
 2. Go to WooCommerce > Unpaid Order SMS.
 3. Choose your SMS gateway and enter its credentials, or enable email. Set the default
    country code and each recipient’s channels. Existing SMS switches are preserved
    on upgrade; email starts disabled.
 4. Customize customer and manager messages using the same placeholders for SMS, email
    subjects and email bodies. Kavenegar users can also set approved patterns and tokens.
 5. Enter a test phone/email and use the test button for the recipient. Review the 
    log, then tick “Enable”.

**Example Kavenegar template for the customer** (tokens: token = {order_id}, token2
= {coupon}, token3 = {link_code}, token10 = {first_name}):

    ```
    %token10 عزیز، سفارش %token شما پرداخت نشد. کد تخفیف شما: %token2
    تکمیل خرید: example.com/?suos=%token3
    ```

## FAQ

### How do I connect any HTTP SMS provider?

Choose “Custom HTTP API (any provider)” and copy the endpoint and authentication
details from your provider’s API documentation. Enter one key=value parameter per
line, for example:

    ```
    apikey=YOUR_KEY
    to={to}
    text={message}
    ```

{to} is E.164 (for example +989120000000); {to_local} is the national form with 
a leading 0, based on your default country code. Parameters are substituted after
parsing, then URL-encoded for GET/form or JSON-encoded without URL encoding for 
JSON. Optional headers use one Name: value per line. HTTP 2xx counts as success;
set “Success text” if your provider also requires a specific response marker. The
form supports flat key/value APIs; use the developer hook for APIs requiring nested
payloads, signatures or another protocol.

### How do I connect another SMS plugin with a hook?

Select “Another plugin (developer hook)”. Add the following five-line example to
your integration plugin, replacing my_sms_plugin_send with its actual send function
and adapting its success result:

    ```
    add_filter( 'sahand_uos_send_sms', function ( $result, $to, $text, $context ) {
        if ( ! function_exists( 'my_sms_plugin_send' ) ) { return $result; }
        $sent = my_sms_plugin_send( $to, $text );
        return true === $sent;
    }, 10, 4 );
    ```

The context contains order_id and recipient (customer/admin; test-customer/test-
admin with order_id 0 for tests). Return true or an array with a truthy ok key for
success. A null result means no plugin handled the filter. Only Kavenegar sends 
pre-approved patterns; the test gateway can preview them without sending.

### Can I send only email?

Yes. Disable SMS and enable email independently for each recipient. Customer email
uses the order’s billing email and is skipped when invalid. Manager addresses are
entered separately. Email uses the WooCommerce wrapper and wp_mail, so your SMTP/
mail plugin handles delivery. A successful log means the transport accepted the 
message; it does not guarantee inbox delivery.

### My site uses page cache

Leave “Keep messages on time on cached sites” enabled in WooCommerce > Unpaid Order
SMS, then clear your page cache so cached pages include the small browser tick. 
It runs due rescue checks during visits even when a full-page cache serves the page.
Visitors must allow JavaScript and local storage; no visits means no browser ticks.
For reliable timing even without visitors, configure a real server cron to call 
wp-cron.php every 5 minutes, then add `define('DISABLE_WP_CRON', true);` to wp-config.
php. The plugin shows a notice with your site’s cron example if a check runs more
than 15 minutes late.

### Why are spaces in some tokens replaced with “_”?

Kavenegar accepts only one word in token, token2 and token3 (no spaces or half-spaces;
it answers error 431). Put names and amounts in token10 or token20, which may contain
spaces.

### What if my delay is longer than WooCommerce’s “Hold stock” time?

The order is cancelled first; the message is still sent, and the link rebuilds the
cart.

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“Sahand – Unpaid Order SMS for WooCommerce” is open source software. The following
people have contributed to this plugin.

Contributors

 *   [ sahandz ](https://profiles.wordpress.org/sahandz/)

[Translate “Sahand – Unpaid Order SMS for WooCommerce” into your language.](https://translate.wordpress.org/projects/wp-plugins/sahand-unpaid-order-sms)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/sahand-unpaid-order-sms/),
check out the [SVN repository](https://plugins.svn.wordpress.org/sahand-unpaid-order-sms/),
or subscribe to the [development log](https://plugins.trac.wordpress.org/log/sahand-unpaid-order-sms/)
by [RSS](https://plugins.trac.wordpress.org/log/sahand-unpaid-order-sms/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.2.0

 * Add independent customer and manager SMS/email channels with backward-compatible
   SMS setting migration.
 * Add Twilio, configurable HTTP APIs, WP SMS and a developer send hook; retain 
   Kavenegar and log-only testing.
 * Add international phone normalization and a default country code, plus national-
   number placeholders for HTTP APIs.
 * Add WooCommerce-wrapped HTML email through wp_mail, email templates and multi-
   channel tests and logs.
 * Simplify settings with gateway-specific fields and update Persian translations
   and service disclosures.

#### 1.1.0

 * Add the default-on “Keep messages on time on cached sites” setting and a lightweight
   browser tick that runs already-due rescue checks on cached sites.
 * Track late rescue checks without changing scheduled action arguments, and show
   shop managers a per-user dismissible notice with server cron guidance.
 * Document page-cache setup and the tick’s local-only, no-personal-data request.

#### 1.0.0

 * First release.

## Meta

 *  Version **1.2.0**
 *  Last updated **4 days ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.2 or higher **
 *  Tested up to **7.1.4**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [abandoned cart](https://wordpress.org/plugins/tags/abandoned-cart/)[email](https://wordpress.org/plugins/tags/email/)
   [sms](https://wordpress.org/plugins/tags/sms/)[unpaid orders](https://wordpress.org/plugins/tags/unpaid-orders/)
   [woocommerce](https://wordpress.org/plugins/tags/woocommerce/)
 *  [Advanced View](https://wordpress.org/plugins/sahand-unpaid-order-sms/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/sahand-unpaid-order-sms/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/sahand-unpaid-order-sms/reviews/)

## Contributors

 *   [ sahandz ](https://profiles.wordpress.org/sahandz/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/sahand-unpaid-order-sms/)