=== Inboxy for WooCommerce ===
Contributors: codelinkegy
Tags: whatsapp, woocommerce, otp login, abandoned cart, order confirmation
Requires at least: 6.5
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 2.0.12
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

WhatsApp for your WooCommerce store: order confirmation, status updates, abandoned carts, phone login and a live chat widget.

== Description ==

Inboxy for WooCommerce connects your store to [Inboxy](https://inboxy.chat), a customer
communication platform, so you can reach customers on WhatsApp about the orders they place with
you — and so they can reach you.

Cash on delivery is the reason most merchants install this. An unconfirmed address is the largest
single cause of a failed delivery, and a WhatsApp message a customer actually reads turns a guess
into a confirmation before the parcel leaves.

= What you get =

* **Order confirmation on WhatsApp.** When an order is placed, the customer receives a message
  with the order details and Confirm and Postpone buttons. Their answer comes back to your store
  as an order note and a tag.
* **Order status updates.** Tell the customer the moment their order is paid, shipped, cancelled
  or refunded, without anyone on your team typing it.
* **Abandoned cart recovery.** Carts left at checkout are tracked — with the shopper's explicit
  consent, never without — and a recovery message goes out after a delay you choose.
* **Review requests after delivery.** Ask how the order went once it has arrived.
* **WhatsApp phone login.** Customers sign in with a phone number and a one-time code on
  WhatsApp, instead of a password. You choose when they are asked: when they add to cart, at
  checkout, as a welcome popup, or only when they press a button. And whether they can skip it.
* **A chat widget on your storefront.** Conversations land in your Inboxy inbox, your AI agent can
  answer them, and a signed-in customer arrives with their name attached instead of as "Visitor
  4821".
* **Store sync.** Orders, products and customers stay in sync with Inboxy over WooCommerce
  webhooks, so your team answers messages with the order in front of them.

Every part is a switch. A store that only wants phone login turns the rest off.

= Setup =

1. Install and activate.
2. Go to WooCommerce → Inboxy.
3. Press **Connect with Inboxy**, sign in, and approve your store. You come straight back.

That is it — no token to copy. The plugin creates the WooCommerce REST API key and the webhooks
it needs, and removes both when you disconnect. If you would rather paste an API token by hand,
that option is still on the same screen.

= What you need =

An Inboxy account with a WhatsApp Business number connected. WhatsApp requires a business to use
a template Meta has approved before it can message a customer first; Inboxy creates and submits
that template for you, but Meta's review is not instant. The plugin tells you exactly which of
those steps is still outstanding rather than failing silently.

== External services ==

This plugin sends data to Inboxy, a third-party service operated by Code Link, and it will not
function without it. **Nothing is sent until you connect the plugin.**

**Service:** Inboxy — https://inboxy.chat
**Endpoint:** https://api.inboxy.chat
**Terms of service:** https://inboxy.chat/terms-of-service
**Privacy policy:** https://inboxy.chat/privacy-policy

What is sent, and when:

* **When you connect:** your store URL, store name and currency, and a WooCommerce REST API key
  that this plugin creates so Inboxy can read your orders, products and customers. If you connect
  with the one-click button, your site URL and site name are also sent to
  `https://app.inboxy.chat` so the approval screen can show you which store you are approving.
* **When an order is placed, changed or deleted:** the order, including the customer's name,
  phone number, email address and shipping address. This is what a WhatsApp confirmation is built
  from, and it cannot be sent without them.
* **When a product or customer is created or changed:** that product or customer record.
* **When a shopper abandons a checkout:** their cart contents, and their name, email address and
  phone number **only if they ticked the consent box at checkout**. Their IP address is stored
  locally as proof of that consent. No consent means no data leaves your site and no recovery
  message is sent.
* **When a customer signs in by phone:** their phone number, so the one-time code can be
  delivered over WhatsApp.
* **After you connect, after each plugin update, and once a day:** the plugin version, the
  WordPress version, the WooCommerce version and your site URL, so Inboxy support can tell which
  version your store runs. Nothing about shoppers or orders is in it.
* **When the chat widget is enabled and a visitor opens it:** the widget establishes its own
  visitor session with Inboxy. For a signed-in WooCommerce customer, and only when you leave
  "tell Inboxy who a signed-in customer is" switched on, their name, email address and phone
  number are sent so your agent knows who they are talking to. Nothing is sent for guests.

**Update check (only in the copy you download from inboxy.chat, not in the WordPress.org
copy):** twice a day WordPress asks `https://app.inboxy.chat/plugins/wordpress/inboxy-for-woocommerce.json`
whether a newer version exists. It is a plain request for a public file: no site URL, no token,
no cookies. An update is installed only when its SHA-256 matches the one published in that file.
Add `define( 'INBOXY_DISABLE_UPDATES', true );` to wp-config.php to switch it off. The
WordPress.org copy is updated by WordPress.org and contains no update code.

Data sent to Inboxy is held under Inboxy's privacy policy. Deleting this plugin removes the API
key, the webhooks, the stored credentials and the local abandoned-cart table from your site.

== Frequently Asked Questions ==

= Do I need an Inboxy account? =

Yes. Create one at app.inboxy.chat, connect a WhatsApp Business number, then press Connect with
Inboxy from the plugin.

= Do I have to copy an API token? =

No. Press Connect with Inboxy, approve the store, and you come back connected. Pasting a token is
still available on the same screen if you prefer it, or if you are connecting a site that cannot
reach app.inboxy.chat from a browser.

= Do I need a WhatsApp Business account? =

Yes. WhatsApp is connected inside Inboxy, not inside WordPress. Messages a business sends first
must use a template Meta has approved in advance, on your own WhatsApp Business account. Inboxy
creates and submits that template for you, but Meta's review is not instant — usually minutes,
sometimes a day. The Order confirmation tab shows you the template's real status.

= Why did my test order not send a WhatsApp message? =

Open WooCommerce → Inboxy → Order confirmation. It reports the three things that have to be true
separately: the store is connected, the WhatsApp channel is connected, and the template is
approved. "Send a test to my phone" on the same tab reports WhatsApp's own answer, which is the
fastest way to find out which one is missing.

= Is my API token secure? =

It is encrypted before it is stored, using your site's own WordPress salts. On a site with no
salts configured, a random key is generated for that install alone. It is never stored in plain
text, and it is never written to a log.

= When are customers asked to log in with WhatsApp? =

Whenever you choose: when they add to cart, at checkout, as a welcome popup after a delay, or only
when they press a button. You can also let them skip it, which is on by default — a shopper who
cannot get past a popup leaves, and you would see the lost order without ever seeing the cause.

= Can I put a "Login with WhatsApp" button somewhere specific? =

Yes. Use the shortcode `[inboxy_otp_login]` anywhere on your site, or `[inboxy_otp_login
text="Sign in"]` to change the label. A button is also added to the WooCommerce My Account sign-in
form automatically.

= Does WhatsApp login work with the new block checkout? =

Yes. Both the block checkout and the older shortcode checkout are supported.

= Does the chat widget slow my site down? =

It is one asynchronous script in the footer with no stylesheet of its own, and nothing loads until
that script runs. It is never in the way of your page rendering. It is hidden on the checkout page
by default, because a chat bubble over a payment field costs orders.

= Is abandoned-cart recovery GDPR-safe? =

The plugin only tracks a cart when the shopper ticks a consent box at checkout, and it stores when
and where that consent was given. Without consent, nothing leaves your site and no recovery
message is sent. Recovery data older than 90 days is deleted automatically.

= What happens when I disconnect? =

The WooCommerce API key this plugin created is deleted, all eight webhooks are removed, and the
local configuration is cleared. Data already in Inboxy stays in your Inboxy account.

= What happens when I delete the plugin? =

Everything above, plus the encrypted token, the encryption key, and the local abandoned-cart
table, which holds shopper personal data. Define `INBOXY_KEEP_CART_DATA_ON_UNINSTALL` in
wp-config.php if you are deliberately reinstalling and want to keep the cart table.

= I used to have the separate Inboxy OTP Login plugin. =

This plugin replaces it, and the connector plugin, with one install. Activating this one
deactivates both of them for you, and your connection and settings carry over.

**Leave them deactivated. Do not delete Inboxy WooCommerce Connector.** Deleting it runs its own
uninstall routine, which removes the WooCommerce REST API key and the eight webhooks it created —
and those are the ones this plugin is now using. Your storefront would keep working and your
orders would quietly stop reaching Inboxy, which is the worst combination to debug. An inactive
plugin costs you nothing.

If it has already happened, press Connect with Inboxy on the Connection tab: this plugin keeps
its own credentials under its own names, so it still knows who you are and rebuilds the key and
the webhooks without you finding a token again.

Deleting Inboxy OTP Login is harmless — it has no uninstall routine.

= WhatsApp login says Meta did not allow the code template. What now? =

Meta decides whether a WhatsApp Business account may create templates. When it refuses, the
plugin shows what Meta said and what to do: reconnect WhatsApp in Inboxy, then check the account's
status in Meta Business Suite under WhatsApp Manager. WhatsApp login stays off until the template
is accepted, and your shoppers keep signing in the normal way. If Meta is still reviewing the
template (usually minutes, sometimes a day) the plugin says so instead of calling login active.

= Which plugin version is my store running, and how do I update? =

The version is shown at the top of WooCommerce → Inboxy and on the Plugins screen. Updates arrive
on the Plugins screen like any other plugin's. Inboxy support sees the same number, because the
plugin reports it (see External services).

= Does the plugin work with the block-based Checkout? =

Orders, order confirmation and WhatsApp login work with both checkouts. Abandoned-cart tracking and
the consent checkbox hook the classic shortcode checkout, so a store on the block Checkout captures
no abandoned carts yet.

= Is it compatible with High Performance Order Storage? =

Yes, and it declares so. It never reads orders from post meta.

== Screenshots ==

1. Connect your store to Inboxy in one step. Press Connect with Inboxy and approve the store; there is no token to copy.
2. Order confirmation: three separate answers (store connected, WhatsApp connected, template approved) show which prerequisite is still missing.
3. WhatsApp messages: where your abandoned-cart reminders and order updates stand in Inboxy, with a link to set each one up.
4. WhatsApp login: choose when shoppers are asked to sign in, and whether they can skip it.
5. A WhatsApp order confirmation as the customer receives it, with Confirm and Postpone buttons.

== Changelog ==

= 2.0.12 =
* The plugin version is shown at the top of WooCommerce → Inboxy, and the plugin reports it to Inboxy after you connect, after each update and once a day, so support can see which version your store runs. Only version numbers and your site URL are sent.
* WhatsApp login: when Meta refuses to create the code template (error 2388185, "does not have permission to create message template", and the other refusals Meta gives), the plugin now says what it means and what to do, in English and Arabic. A template that is still in review is reported as in review, and a rejected one no longer shows as "active".
* WhatsApp login: a shopper who asks for a code while login is misconfigured (plan, switched off, template not approved) sees one calm sentence instead of the merchant's error text.
* Updates for the copy downloaded from inboxy.chat: WordPress now shows "Update available" for new releases and installs them only when the download matches its published SHA-256. The WordPress.org copy has no update code.
* Privacy: added the suggested text to Settings → Privacy, and listed the version report and update check under External services.
* Tested: a mocked WhatsApp AUTHENTICATION template flow end to end (setup, code sent through the template, wrong code, correct code, one-time use, login), the template refusals, the update channel (including a download with a wrong checksum), and activation, nonce and capability checks on every admin action.

= 2.0.11 =
* Tested on WordPress 7.1.3 and WooCommerce 11.2.1 (PHP 8.3), with High-Performance Order Storage both on and off: install, connect, orders, abandoned carts, WhatsApp login, disconnect, reconnect, deactivate, reactivate, delete and reinstall.
* Fix: Disconnect now also stops the abandoned-cart check that ran every five minutes.
* Fix: deleting the plugin now also removes your Data Sharing choices, the WhatsApp login rate-limit records and the "phone verified by WhatsApp" mark on customer accounts. The customer accounts themselves are kept.
* Fix: abandoned-cart times stay in your site's time zone. Sending a cart to Inboxy no longer moves its "last activity" time to the database server's clock.

= 2.0.10 =
* The chat widget follows your store's language: on an Arabic site it now shows in Arabic, right to left (it was always English).
* WhatsApp login, "At checkout": the description now says what the mode does. It is a check in the shopper's browser, not an order block, and the popup may not appear on the block-based Checkout. Do not rely on it as fraud protection for cash-on-delivery orders.
* Documentation and Support links open inboxy.chat/help.

= 2.0.9 =
* Fix: "Turn off WhatsApp login" (formerly Disconnect on the WhatsApp login tab) turns off only WhatsApp login. It used to also run the store Disconnect and delete the API token the store connection uses.
* Fix: deactivating and reactivating the plugin keeps a connected store connected and turns its webhooks back on (they stayed paused and the store showed Not Connected).
* Fix: Data Sharing changes now reach Inboxy. Every save used to stop on this site, so Inboxy kept syncing customer records after you switched them off.

= 2.0.8 =
* WhatsApp messages: an older automation that is still the only sender for this store (the message is not set up in Inboxy yet) says so, instead of warning about a duplicate.

= 2.0.7 =
* The Automations tab is now "WhatsApp messages". Abandoned-cart reminders (up to three, with delays and discount codes) and order updates with review requests (one approved template per status) are set up on their own pages in Inboxy, the same way for every store. The tab shows where yours stand and opens the page for this store; it no longer installs automations, which could message a customer twice.
* An older automation from this tab that still sends one of those messages is listed with a Pause button.

= 2.0.6 =
* Fix: Disconnect now tells Inboxy the store is disconnected (it stayed listed as connected there).
* Automations: choose each automation's WhatsApp template on this tab. "Order status updates" now sends the new status in the message ({{3}}), so one template reads right for every change.
* Order confirmation tab: shows whether THIS store's answers are written back to WooCommerce, and where to switch it on, instead of a company-wide store count.

= 2.0.5 =
* Fix: errors from Inboxy showed as "[object Object]" — when activating WhatsApp login, and in the phone-login popup your shoppers see. They now show the actual reason (for example WhatsApp's own refusal).

= 2.0.4 =
* Fix: after connecting with one click, the WhatsApp login tab still asked for an API token. It now goes straight to choosing the message language.

= 2.0.3 =
* Fix: abandoned carts reached Inboxy marked hours in the future on stores outside UTC (cart times were sent in the site's local time without a zone). They are sent in UTC now.

= 2.0.2 =
* Fix: saving on the Order confirmation, Automations and Website chat tabs failed with "Could not reach Inboxy" (their security tokens were never sent to the page).

= 2.0.1 =
* Fix: WooCommerce → Inboxy settings page was missing on real sites (the admin screen was built after WordPress had already collected the admin menu). Activation and the Settings link now open it.

= 2.0.0 =
* Inboxy WooCommerce Connector and Inboxy OTP Login are now one plugin. One install, one API
  token, one settings location. The old plugins asked for the same token twice.
* **Upgrading from the two old plugins is now safe.** This plugin declares the same class names
  they do, because it is the two of them merged — so activating it while either was still on
  took the whole site down, front end included, with no warning. Activating now deactivates
  them for you, and if one is ever switched back on this plugin stands down with a notice
  naming it instead of crashing. Your settings and your connection carry across either way.
* **Deleting the old connector no longer takes your connection with it.** This plugin used to
  store its credentials under the names the old connector's uninstall routine deletes, so tidying
  up after the upgrade silently destroyed them. It keeps them under its own names now, and
  carries the old values across once on upgrade. Deleting the old connector still removes the
  WooCommerce REST key and webhooks it created — nothing in a plugin can prevent that — but this
  plugin still holds your token, so one press of Connect with Inboxy rebuilds both.
* **Connect with Inboxy** — connect in one step instead of copying an API token between two
  sites. Pasting a token is still there as the advanced path.
* **Order confirmation tab** — see whether it is on, whether your WhatsApp channel is connected
  and whether Meta has approved your template, as three separate answers. All three failures used
  to look identical from a storefront: no message arrived.
* **Automations tab** — switch on order status updates, abandoned cart recovery and post-delivery
  review requests, each installed paused until you turn it on.
* **WhatsApp login, on your terms** — four modes (add to cart, checkout, site open, on request), a
  skip option that is on by default, a `[inboxy_otp_login]` shortcode, a button on the My Account
  form, and support for the block checkout. Previously it intercepted add-to-cart with no way to
  change it and no way to skip.
* **Chat widget on the storefront** — one asynchronous script in the footer, hidden on checkout by
  default, with signed-in customers identified to your agent. Previously this meant pasting a
  snippet into a theme file, where the next theme update silently removed it.
* Full Arabic translation, and the settings pages read correctly right-to-left.
* Declares WooCommerce High Performance Order Storage compatibility. The code was already
  compatible; without the declaration WooCommerce warned merchants that it might not be.
* Fixed: the plugin's activation routine never ran, because its hook was registered later in the
  request than the only moment it could fire.
* Fixed: the settings page loaded with no styles and no scripts, because its asset gate named a
  different page than the menu registered.
* Fixed: on a store with a shipping plugin, orders never reached "shipped" or "delivered" inside
  Inboxy, so review-request automations could not fire.
* Fixed: the abandoned-cart cutoff was shifted twice by the site's timezone offset, so on any site
  not on UTC the wrong carts were considered abandoned.
* Deleting the plugin now also removes the OTP module's stored token and encryption key, and the
  plugin's cached state.
* Deactivating no longer deletes the OTP credentials. Deactivation is temporary — every plugin
  update runs through it — and destroying a token on a temporary state change is not recoverable.
  Permanent removal belongs to uninstall.
* The plugin no longer writes to your PHP error log unless WP_DEBUG is on.
* Minimum WordPress is now 6.5, which is the version that honours the Requires Plugins header.
  Below it the WooCommerce dependency is not enforced at all.

= 1.4.0 and earlier =

This plugin's history is the combined history of the two plugins it replaces: Inboxy WooCommerce
Connector up to 1.4.0 and Inboxy OTP Login up to 1.1.0. The notable entries:

* Abandoned-cart consent is stored and transmitted, and Inboxy refuses recovery outreach when
  consent cannot be established.
* The stored proof-of-consent IP address can no longer be forged through a spoofed header.
* The documented 90-day abandoned-cart retention actually runs.
* Deactivation pauses the WooCommerce webhooks instead of leaving a "deactivated" store
  delivering every order indefinitely.
* Encryption never falls back to a hard-coded key.
* The abandoned-cart query whitelists its ORDER BY column, closing a SQL injection vector.
* OTP registration requires a short-lived, one-time server proof, so a replayed request cannot
  create an account without passing WhatsApp verification.

== Upgrade Notice ==

= 2.0.12 =
Shows the plugin version, explains Meta's WhatsApp template refusals, and (for the copy from inboxy.chat) adds update notices on the Plugins screen.

= 2.0.0 =
Replaces both Inboxy plugins with one. Deactivate Inboxy WooCommerce Connector and Inboxy OTP
Login after installing. Your settings carry over.
