One SMS/OTP integration, implemented idiomatically for four platforms: WooCommerce, OpenCart 3.x, PrestaShop 1.7/8, and Magento 2. Every plugin talks to the same Hellio Messaging REST API and exposes the same four features and the same settings, so a merchant who uses two carts sees one product.
Product name: Hellio Messaging. Vendor: Hellio Solutions. Homepage: https://helliomessaging.com. Support: support@helliomessaging.com. Version 1.0.0.
- Base URL: setting
api_base_url, defaulthttps://api.helliomessaging.com. - Auth:
Authorization: Bearer {api_token}(a Sanctum personal access token the merchant generates in their Hellio dashboard). - Every request also sends
Accept: application/json. POSTs sendContent-Type: application/jsonand a freshIdempotency-Key: {uuid}header (safe to retry without double-charging). - Timeout 15s. Never let an API failure break checkout or order processing: wrap every call in try/catch, log the error, and continue.
Request body:
{ "recipients": ["233241111111", "..."], "sender": "MyStore", "message": "..." }recipients: array of phone strings, each max 20 chars, 1..10000 items.sender: Sender ID, max 11 chars, must be approved on the Hellio account.message: max 1600 chars. Success202:
{ "data": { "reference": "uuid", "campaign_id": 123, "status": "queued",
"accepted_recipients": 1, "invalid_recipients": 0, "segments": 1,
"estimated_cost": "0.0350", "currency": "GHS" } }Errors carry { "message": "...", "error": "sender_not_approved" } with status
422 (sender_not_approved, no_valid_recipients, traffic_not_routable),
402 (insufficient_balance), 403 (spend_limit_exceeded).
{ "mobile_number": "233241111111", "sender": "MyStore",
"length": 6, "expiry": 5, "purpose": "checkout" }mobile_numberrequired, max 20.senderrequired, max 11.lengthoptional 4..10 (digits).expiryoptional 1..1440 (minutes).purposeoptional, max 32. Success201:{ "data": { "reference": "uuid", "mobile_number": "...", "expires_in_minutes": 5, "status": "queued" } }. Same error envelope as above, plus429(throttled, honourRetry-After).
{ "mobile_number": "233241111111", "code": "123456" }200 { "data": { "verified": true, "status": "verified" } }, or 422
{ "data": { "verified": false, "status": "invalid" } }.
Used by the "Test connection" button. 200 returns the wallet balance JSON.
Exchanges account credentials for an API token, so the merchant connects the plugin once with their Hellio login instead of pasting a token.
{ "email": "me@store.com", "password": "...", "device_name": "WooCommerce",
"two_factor_code": "123456" }email,passwordrequired.device_nameoptional (labels the token).two_factor_codeonly needed if the account has 2FA enabled. Success201:{ "data": { "token": "1|xxxxx", "abilities": ["sms:send", ...], "user": { "name": "...", "email": "..." } } }. Storedata.tokenas theapi_tokensetting. Errors:401(invalid_credentials),403(email_unverified,account_locked),422(two_factor_required),429(throttled). The endpoint is rate-limited per email+IP; ontwo_factor_requiredreveal a 2FA-code field and let the merchant retry.
- Connect with your Hellio login (primary): email + password fields and a
"Connect" button that POSTs to /v1/auth/token and stores the returned token,
so the merchant authenticates once and never handles a raw token. If the
response is
two_factor_required, reveal a 2FA-code field and retry. Show the connected account's email once connected, with a "Disconnect" action. Pasting a token by hand stays available as an alternative. - Send SMS panel (doubles as the test-send and a quick send-to-list): a recipients box that accepts one number or many pasted numbers (comma, space or newline separated), a Sender ID field (defaults to the saved Sender ID but editable), and a message box that accepts the template placeholders. A "Send" button renders the placeholders against a sample order (or blank if none), splits the pasted numbers, and sends them via /v1/sms/send in one call (chunk at 500 if a very long list is pasted), then shows the API result (accepted count, reference/status, or the error). This lets a merchant confirm sending, preview a personalised message, and fire off an ad-hoc blast without opening the full Bulk page. The Bulk page still exists for audience-based sends (all customers / by order status).
enabledmaster toggle.api_base_url(default above),api_token(stored encrypted/masked).sender_iddefault Sender ID (max 11).default_dial_codee.g.233. Applied to local numbers: strip a leading0and prepend this when the number has no+and no country code.- Test connection button, calls GET /v1/balance, shows balance or the error.
- Customer order-status SMS: a per-status enable toggle + editable template.
- Admin new-order alert: enable + admin recipient number(s), comma separated + template.
- Checkout OTP: enable + code length + expiry minutes.
- Bulk SMS: an admin page (compose + choose audience + send).
- Customer order-status SMS. On an order changing to a status the merchant enabled, render that status's template and SMS the order's billing phone.
- Admin new-order alert. On a new order, SMS each configured admin number with the alert template.
- Checkout OTP. Before an order is placed, the customer verifies their phone: a "Send code" action (server-side endpoint, token never reaches the browser) calls otp/send; a code field + verify calls otp/verify; the order is blocked server-side until verified. Skip gracefully if OTP disabled.
- Bulk / marketing SMS. Admin page: compose a message, pick an audience (all customers, or customers filtered by order status, or a pasted list), send via /v1/sms/send in chunks of 500, report sent/failed counts.
{order_id} {order_number} {order_status} {order_total} {currency}
{customer_name} {customer_first_name} {store_name} {shop_url}
{tracking_url} {date}. Unknown placeholders render empty.
- Server-side sends only; the API token never reaches the browser.
- Defensive: an API/network failure logs and returns, never throwing into checkout or order save.
- Escape/sanitise all admin I/O; use the platform's CSRF/nonce mechanism.
- No em-dash character anywhere in code or copy. Use a period, comma, colon, parentheses, or a plain hyphen.
- Ship a README per plugin (install, configure, placeholder list, changelog)
and the manifest/metadata the platform requires. Run
php -lon every PHP file; all must be syntax-clean.