# WooCommerce phone lookup for Amazon Connect

A small WordPress plugin that lets an Amazon Connect flow find WooCommerce orders from the caller ID, whatever format the shopper typed the phone in.

**The problem it fixes.** WooCommerce's REST `search` parameter matches the stored text. A caller ID arrives in E.164 (`+15555550042`); a shopper types `(555) 555-0042`. On October 28, 2026, against WooCommerce 11.2.1, the E.164 search returned nothing on both legacy storage and HPOS (see [`../benchmark/`](../benchmark/README.md)).

**What it does.**

1. On every order save (checkout, admin, REST), it stores the last 10 digits of the billing phone in order meta `_fm_phone_digits`. Phones with fewer than 7 digits are not stored.
2. It adds a read-only endpoint, `GET /wp-json/wc-fm-connect/v1/orders-by-phone?phone=<any format>&per_page=10`, which normalises the input the same way and returns matching orders, newest first, in the same field names as `/wc/v3/orders` (trimmed to id, status, total, currency, date, customer, billing email and phone, line-item quantities).
3. It lets WooCommerce's REST key authentication cover that namespace, so the same read-only consumer key and secret work. Without a key the endpoint returns 401.
4. A WP-CLI command backfills existing orders: `wp fm-connect backfill-phones [--batch=200]`. It writes meta only, so order modified dates do not change.

It reads and writes through the WooCommerce CRUD API, so it works with both legacy post storage and HPOS.

## Install

1. Copy `fm-connect-phone-lookup.php` to `wp-content/plugins/fm-connect-phone-lookup/` and activate it, or drop it into `wp-content/mu-plugins/`.
2. Run `wp fm-connect backfill-phones` once.
3. In the Lambda, set `WC_PHONE_ENDPOINT=true`. The adapter (`../bigcommerce-woocommerce/woocommerce.mjs`) then sends phone lookups to this endpoint. Email and order-ID lookups still use `/wc/v3/orders`. It still confirms every hit client-side and returns `ambiguous` when two buyers share the number.

## Tested

On October 28, 2026, in Docker: WordPress `php8.3-apache`, WooCommerce 11.2.1, MySQL 8.4, 202 seeded orders.

| Check | Legacy storage | HPOS |
| --- | --- | --- |
| `+15555550042`, `(555) 555-0042`, `+1 555.555.0042` find the order stored as `(555) 555-0042` | yes | yes |
| Shared number returns `ambiguous` | yes | yes |
| Unknown number returns `not_found` | yes | yes |
| New order gets `_fm_phone_digits` on save | yes | yes (`+44 20 7946 0958` → `2079460958`) |
| Backfill restores digits on 202 orders after the meta was deleted | yes | not run |
| No key → 401; under 7 digits → 400 | yes | not run |
| 200 lookups with E.164 caller IDs via the adapter | p50 31 ms, p95 37 ms, all found or ambiguous | p50 28 ms, p95 31 ms, all found or ambiguous |

A bug the live test caught: the first version filtered with `meta_query`. On legacy storage, `wc_get_orders()` ignored it and returned the newest orders unfiltered. The adapter's client-side check rejected those, so callers got `not_found` instead of a wrong order, but the lookup did not work. The plugin now uses `meta_key` and `meta_value`, which both storage modes honour.

## Limits

- **Last 10 digits** is right for North American numbers. Set `FM_CONNECT_PHONE_DIGITS` for your market. Two different countries' numbers can share the last 10 digits, and the `ambiguous` check is what protects you then.
- **Not indexed.** The meta lookup is a plain meta query. On a large store, measure it, and consider an index on the meta table or a dedicated lookup table.
- **Order-level only.** It matches the billing phone on orders, not customer accounts or shipping phones.
- **No identity check.** A phone match is context for the agent, not proof of who is calling.
- Reference code. Review it, and test it on staging, before production use. MIT licence.
