=== BrickellPay Gateway for WooCommerce ===
Contributors: asanchez97
Tags: woocommerce, payment gateway, payments, credit card, checkout
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.13
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Accept credit and debit card payments in your WooCommerce store via BrickellPay's secure payment platform.

== Description ==

BrickellPay Gateway for WooCommerce lets your store accept credit and debit card payments through BrickellPay, a payment platform with smart routing and automatic processor failover. The plugin integrates with WooCommerce checkout, supports both one-time and subscription payments, and uses tokenized card data so your server never sees raw card numbers (PCI scope reduction).

= Key features =

* **Hosted-field tokenization** — card data is tokenized in the customer's browser via the BrickellPay-provided iframe SDK, so your WordPress site never receives or stores raw PANs.
* **Smart processor routing** — when the primary processor declines, the gateway automatically retries the transaction on a configured fallback processor without re-prompting the customer. Routing rules are configured in your BrickellPay merchant account.
* **Real-time payment status** — uses SignalR to deliver KYC and payment notifications without polling.
* **WooCommerce Subscriptions support** — saved-card renewals work out of the box.
* **HPOS-compatible** — declares support for WooCommerce High-Performance Order Storage.
* **Refund + void from the WooCommerce admin** — managed directly on the order screen.

= Requirements =

* WordPress 6.2 or later
* PHP 7.4 or later
* WooCommerce 8.0 or later
* An active BrickellPay merchant account with API credentials (sign up at https://brickellpay.com)
* HTTPS on the storefront (required for any production card-acceptance flow)

= External services =

This plugin requires external services to function. Some are operated by BrickellPay; one is operated by a separate third-party company (IoniaPay). Both are documented below. The exact hostnames may vary between sandbox and production environments.

**Services operated by BrickellPay:**

1. **BrickellPay API host** — `https://api.brickellpay.com/` (sandbox: `https://sandbox.api.brickellpay.com/`). REST API for server-side transaction operations.
2. **BrickellPay Tokenization Facade host** — `https://payments.brickellpay.com/` (sandbox: `https://sandbox.payments.brickellpay.com/`). Serves the tokenization facade JavaScript and the underlying tokenization/verify SDK modules. Also exposes a CORS-open proxy at `/api/v2/consumer/*` that the SDK calls from the customer's browser to authenticate cards and verify transactions.
3. **BrickellPay SignalR notification hub** — host provided per-merchant by the API's `/merchant-config` endpoint. Separate WebSocket endpoint for real-time payment + KYC notifications.

**Service operated by a third party (IoniaPay):**

4. **IoniaPay** — operated by IoniaPay, LLC, a separate company from BrickellPay. IoniaPay is the card-tokenization and consumer-verification (KYC) provider used when your BrickellPay merchant account is configured to route through the Ionia processor. It is reached at two hosts:
   * `https://code.ionia.app/` — loaded **in the customer's browser**. Serves the Ionia card-tokenization SDK (`/lib`) that renders the card form, and the Terms & Conditions documents (`/docs/toc_new.html`, `/docs/toc_existing.html`) shown to the customer inside the verification modal.
   * `https://sandbox.ioniapay.ionia.app/` — called **from your server only** (never from the browser). Used as a fallback for saved-card lookups when the BrickellPay API cannot resolve a stored card. Only reached in sandbox/test mode.

   **What is sent to IoniaPay, and when:**
   * When a customer reaches checkout on an Ionia-routed merchant, their browser loads the Ionia SDK and (for the verification step) the Terms & Conditions document. This discloses the customer's IP address and user agent to IoniaPay, as with any browser request.
   * When a customer submits card details, the card number, expiry, and CVV go from the SDK's iframes directly to IoniaPay for tokenization. This data does not pass through your WordPress server.
   * For consumer verification / KYC, the customer's email address, phone number, name, and billing address are sent so IoniaPay can create or match a consumer record and deliver an SMS verification code.
   * For saved-card lookups (sandbox/test mode only), your server sends the stored card identifier and a session token.

   IoniaPay terms of service: https://ioniapay.com/terms-of-service
   IoniaPay privacy policy: https://ioniapay.com/privacy-policy

   If your merchant account is not configured to route through Ionia, none of these Ionia hosts are contacted.

The plugin uses these hosts for the following operations:

* **Tokenization facade** — the plugin loads `https://payments.brickellpay.com/js/embed/brickellpay-tokenization-facade-v1.js` as a single script tag, and exposes a stable `window.BrickellPay` API to this plugin. The facade then lazy-loads the underlying tokenization and verify modules (`tokenization-X.Y.Z.min.js`, `verify-X.Y.Z.min.js`) from the **Ionia CDN** at `https://code.ionia.app/lib` — see the IoniaPay entry above; this is a third-party host, not a BrickellPay one. Both the facade URL and the SDK origin are overridable by environment variable or filter for self-hosted setups.
* **Card tokenization (browser → facade)** — when a customer enters card details at checkout, the form is rendered by the facade using VGS Collect iframes. Card data goes directly from the iframe to BrickellPay's tokenization endpoint, then a token is returned. The PAN never reaches your WordPress server.
* **Browser authentication and 3DS (browser → facade host)** — the SDK posts to `https://payments.brickellpay.com/api/v2/consumer/authenticate-browser` and `/verify-transaction/{id}/update` from the customer's origin. These are CORS-open endpoints owned by BrickellPay.
* **Charge / authorization / capture / refund / void (server → API host)** — the plugin sends transaction requests (amount, currency, billing address, customer email/phone) from your server to the BrickellPay API host.
* **Real-time notifications (SignalR)** — the customer's browser opens a WebSocket to the BrickellPay SignalR hub to receive KYC + payment status updates. The Microsoft SignalR client library that initiates the WebSocket is bundled locally (Apache 2.0); the hub itself is a separate BrickellPay-controlled host.

The data sent includes: customer email, phone number, billing/shipping address, order amount, order line items, the WooCommerce order ID, and a tokenized payment method reference. Raw card data (PAN, CVV, expiry) is sent only from the browser iframe to BrickellPay, never from your WordPress server.

BrickellPay terms of service: https://brickellpay.com/terms
BrickellPay privacy policy: https://brickellpay.com/privacy

= Required Content-Security-Policy =

If your site enforces a Content-Security-Policy, it must permit the following directives so the BrickellPay tokenization facade, the Ionia card-tokenization SDK, the Terms & Conditions frame, and the VGS Collect iframes can load:

`script-src  'self' https://payments.brickellpay.com https://code.ionia.app https://js.verygoodvault.com;`
`frame-src   'self' https://code.ionia.app https://*.verygoodvault.com;`
`connect-src 'self' https://payments.brickellpay.com <your-merchant-API-URL>;`
`img-src     'self' data: https://payments.brickellpay.com;`

For sandbox installations, also allow `https://sandbox.payments.brickellpay.com` in `script-src` and `connect-src`.

= Bundled third-party libraries =

* **Microsoft SignalR JavaScript Client** v6.0.1 — Apache License 2.0. Source: https://github.com/dotnet/aspnetcore. Bundled at `assets/js/vendor/signalr.min.js`; license notice at `assets/js/vendor/signalr-NOTICE.txt`. Used for real-time payment-status notifications.
* **intl-tel-input** v29.2.2 — MIT License. Source: https://github.com/jackocnr/intl-tel-input. Bundled at `assets/js/vendor/intl-tel-input/dist/`; license at `assets/js/vendor/intl-tel-input/LICENSE`. Used for the country selector and E.164 phone formatting/validation on the checkout verification step. The "WithUtils" build is bundled so no library file is fetched at runtime.

The BrickellPay tokenization SDK and verify SDK are normally **not** bundled — they are loaded at runtime from the BrickellPay tokenization facade (declared above under "External services"). One exception: a point-in-time copy of the facade script is included at `assets/js/vendor/brickellpay-tokenization-facade-v2.0.0-local.js` and is used **only when the gateway is in test/sandbox mode**, so that development environments do not depend on a deployment being live. Production installations always load the facade from the BrickellPay host.

== Installation ==

= From your WordPress dashboard =

1. Go to **Plugins → Add New** and search for "BrickellPay Gateway for WooCommerce".
2. Click **Install Now**, then **Activate**.
3. Go to **WooCommerce → Settings → Payments**, enable **BrickellPay**, and click **Manage**.
4. Enter your **API Key** and **API Secret** (from your BrickellPay merchant dashboard).
5. Choose **Sandbox** or **Live** mode and save changes.

= Manual install =

1. Upload the unzipped `brickellpay-woocommerce/` folder to `/wp-content/plugins/`.
2. Activate the plugin through the **Plugins** menu in WordPress.
3. Configure as described above.

== Frequently Asked Questions ==

= Do I need a BrickellPay account? =

Yes. You must sign up at https://brickellpay.com and obtain API credentials before you can accept payments through this plugin.

= Does this plugin work with WooCommerce Subscriptions? =

Yes. Saved-card renewals are supported. The plugin stores the BrickellPay payment token on the parent order and uses it to charge renewals automatically.

= Does the plugin store credit card numbers on my WordPress site? =

No. Card data is tokenized in the customer's browser and only the token is sent to your server. This significantly reduces your PCI DSS scope.

= What happens when a payment is declined? =

If your BrickellPay merchant configuration includes a fallback processor, the gateway automatically retries the transaction on the fallback processor before declining the customer.

= Can I issue refunds from WooCommerce? =

Yes. Refunds and voids initiated from the WooCommerce order screen are routed to the same processor that handled the original charge.

= How do I report a bug or request support? =

Visit https://brickellpay.com/contact or open a thread in the plugin's support forum on WordPress.org.

= My site has a Content-Security-Policy — do I need to allow anything? =

Yes. The card-tokenization script is loaded from `code.ionia.app`. If your site (or a security plugin) sets a `script-src` Content-Security-Policy directive, add `https://code.ionia.app` to it, or the card form will fail to load.

== Screenshots ==

1. BrickellPay settings screen in WooCommerce.
2. Customer-facing checkout with the BrickellPay payment option.
3. Card details modal with tokenized inputs.
4. Real-time payment status notification on the thank-you page.
5. Refund flow from the WooCommerce order admin.

== Changelog ==

= 1.0.13 =
* Fixed: terms and conditions consent is now recorded before the first card is added, so the acceptance is captured for every checkout rather than only for those that reach the card step.
* Fixed: consent is also captured on the inline cardless route, which previously completed without recording it.
* Fixed: a new user is no longer asked to accept the terms twice during a single checkout.

= 1.0.12 =
* Fixed: release 1.0.11 was built from a branch that predated the 1.0.10 review fixes, so several of them were absent from the submitted package even though they had already been made. This release carries them forward. Specifically restored: the bundled intl-tel-input library at v29.2.2 (1.0.11 shipped v18.2.1 again), the `== External services ==` disclosure covering IoniaPay, the correct `Contributors` username, the removal of the `Plugin URI` header, and the per-field schema sanitization of the test-mode `create-user` request body.
* Removed: the empty `assets/js/vendor/intl-tel-input/build/` directory left behind when the library moved to `dist/`.
* Fixed: the distribution package no longer contains `.htaccess`. WordPress.org does not permit hidden files in an uploaded plugin, and the file guards nothing in that package — everything it denies access to (`.env` and dev files) is already excluded from it. It remains in the repository for manually deployed installs, where it does protect those files.
* Changed: `Tested up to` raised to 7.1.

= 1.0.11 =
* Added: `Requires Plugins: woocommerce` header, so WordPress verifies the WooCommerce dependency before activation.
* Fixed: the sandbox API endpoint shipped with a local development default. Distributed builds now point at the public sandbox host.
* Fixed: in API tokenization mode the card fields rendered without labels or placeholders and in the wrong order. They now match the surrounding billing fields, with cardholder and card number full width and expiry and CVC side by side.
* Fixed: the expiry field now inserts the `/` separator as the customer types. Entering the digits without it was rejected during tokenization and surfaced as a generic card error.
* Fixed: a returning customer with no saved card reached a dead end after identity verification. The card form is now shown instead.
* Fixed: a saved card that cannot be selected no longer blocks adding the same card again.
* Fixed: checkout could stop listening for the verification result if the payment session identifier had not yet arrived, leaving the customer on the verification screen with no error.
* Changed: when the tokenization mode is not the hosted iframe, the checkout now records it to the store log instead of proceeding silently.
* Security: certificate verification enforced on all outbound requests; environment files blocked from HTTP access; test-mode-only flags are no longer honored outside test mode.

= 1.0.10 =
* Added: full disclosure of IoniaPay (IoniaPay, LLC) as a third-party external service in the readme, covering both the browser-loaded `code.ionia.app` SDK/Terms host and the server-side `ioniapay.ionia.app` saved-card fallback, what data is sent to each and when, and links to IoniaPay's terms of service and privacy policy.
* Fixed: the readme incorrectly stated that the tokenization/verify SDK modules are fetched from the BrickellPay facade host. They are loaded from the Ionia CDN; corrected and cross-referenced.
* Changed: updated the bundled intl-tel-input library from v18.2.1 to v29.2.2. This is an API migration, not a version bump — v25 removed `isPossibleNumber()` and swapped the meaning of the remaining validators, so the checkout phone gate now reads strict validation from `isValidNumberPrecise()` and keeps `isValidNumber()` for the sandbox-only relaxation. Reading the new API as if it were the old one would have silently downgraded live phone validation to a length-only check. Also migrated `preferredCountries` to `countryOrder` and dropped the separate `utilsScript` fetch in favour of the bundled "WithUtils" build.
* Changed: declared intl-tel-input in the readme's bundled-libraries list, and documented the test-mode-only local copy of the tokenization facade.
* Fixed: the thank-you page shipping-address correction no longer prints an inline `<script>` block; it is registered through `wp_enqueue_script` with its data passed via `wp_localize_script`.
* Security: the `brickellpay_create_user` AJAX body (test mode only) is now rebuilt field by field against its expected schema instead of being forwarded as a decoded blob. Unknown keys are dropped, text fields are sanitized, numeric fields are reduced to digits, and required fields are enforced before any upstream call.
* Fixed: the `Plugin URI` header pointed at a page that returned 404. There is no plugin-specific landing page to point it at, and WordPress.org rejects a `Plugin URI` that duplicates `Author URI`, so the header has been removed — `Author URI` alone now carries the link. The support link in the FAQ was likewise a 404 and now points at an existing page.
* Fixed: `Contributors` now lists the plugin owner's actual WordPress.org username.

= 1.0.9 =
* Fixed: the card form failed to load with a 404 on `tokenization-1.0.4.min.js`. The self-hosted SDK directory that URL pointed at has been retired — no version resolves there any more — so the plugin now requests SDK 1.0.5 and pins the SDK origin to Ionia's CDN instead of inheriting whichever default the tokenization facade happens to ship with. Both values remain overridable by env var or filter.

= 1.0.8 =
* Changed: migrated the Ionia card-tokenization facade to v2 (Ionia SDK 1.0.5). The card-form mount now requires and passes a JWT, matching the facade's new contract; behavior is unchanged for shoppers.

= 1.0.7 =
* Fixed: a KYC 10099 notification that carries a failure flag is no longer swallowed by the generic transaction-failure handler before its recovery can run. Specific KYC status codes are now dispatched ahead of the generic catch-all, so recovery (user-verify retry) fires as intended. Retains the 1.0.6 diagnostics.

= 1.0.6 =
* Fixed: the checkout error-message lookup (admin-ajax brickellpay_get_error_message) is now registered early, so it no longer returns an unregistered-action "0"/400 on requests that don't instantiate the gateway.
* Diagnostic: added non-invasive breadcrumb logging across the SignalR-notification and 10099-recovery path (window.brickellpayDumpDiag()), to pinpoint where the 10099 recovery bails in real (SignalR-connected) environments. No behavior change to the payment flow.

= 1.0.5 =
* Fixed: Resend Code (AZ #2339) fired a request that Ionia rejected with HTTP 400, with no resend ever reaching Ionia's logs. The button's own click handlers were resolving a stale payment token as the auth bearer instead of the session token when the auth session had expired, bypassing an earlier fix made deeper in the same code path.

= 1.0.4 =
* Fixed: a real KYC 10099 notification arriving while a speculative card-fetch was already in flight got silently dropped, leaving checkout stuck with no retry and no charge attempt (AB#1/AB#2). The coalesced notification is now queued and replayed once the in-flight attempt resolves.

= 1.0.3 =
* Fixed: removed all remaining error_log() calls (Plugin Check flags the call itself regardless of any surrounding debug-only guard) — the plugin already treats logging as disabled-for-security elsewhere, so these were inconsistent with that policy anyway.
* Fixed: a phpcs:ignore comment used a non-standard dash character and was silently not suppressing its target warning; corrected to the standard delimiter with a clearer rationale.

= 1.0.2 =
* Fixed: text domain now matches the assigned plugin slug (brickellpay-gateway-for-woocommerce) so translations load correctly.
* Fixed: removed a discouraged, unnecessary translation-loading call (WordPress.org loads plugin translations automatically).
* Housekeeping: debug logging now only fires when WP_DEBUG is enabled; added missing translator comments; minor input-sanitization hardening.

= 1.0.1 =
* Fixed: KYC 10099 recovery could abort with "incomplete data" and never retry, when an earlier card-less status push had already consumed the one-time retry.
* Fixed: existing-user SMS verification now sends at Validate instead of only at Place Order.
* Fixed: terms & conditions "read more" link now opens in a new tab instead of being inert.
* Fixed: new-user checkout now defaults the billing country to United States.
* Fixed: billing phone field label no longer shows a lingering "(optional)" suffix.
* Fixed: the "Processing your payment..." loader no longer gets stuck on screen when a checkout error is shown.
* Fixed: the "X is a required field" notice now clears once the field is filled in.
* Fixed: the Resend Code button no longer risks sending the wrong token type on retry.

= 1.0.0 =
* Initial public release.
* WooCommerce HPOS support.
* Card tokenization, sale/auth/capture, refund, void.
* Smart routing with automatic processor failover.
* Real-time SignalR notifications.
* WooCommerce Subscriptions integration.

== Upgrade Notice ==

= 1.0.0 =
Initial public release of BrickellPay Gateway for WooCommerce.
