=== LayerHop — Crypto payments, any token ===
Contributors: layerhop
Tags: crypto, woocommerce, payment gateway, usdc, stablecoin
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.1.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Accept crypto in WooCommerce: customers pay with any token on any chain, you receive USDC or USDT in your own wallet.

== Description ==

LayerHop lets your customers pay with **any token on any chain** they hold (ETH, SOL, USDC on another chain, memecoins…) while you are always paid in the stablecoin you choose: **USDC** on Ethereum, Arbitrum, Base, Optimism, BNB Chain, Polygon or Solana, or **USDT** on Ethereum, Arbitrum, BNB Chain or Solana.

LayerHop is non-custodial. The payer's wallet sends the funds and the route delivers them straight to your payout address. An order is only marked paid after LayerHop has verified the delivery on chain and the plugin has double-checked the session with the LayerHop API.

**WooCommerce gateway**

* "Crypto (any token) — LayerHop" payment method for the classic checkout and the Cart & Checkout blocks.
* Redirect to the hosted LayerHop payment page, or open it as a popup on your site.
* Orders stay *Pending payment* until the signed `checkout.session.completed` webhook arrives, then move to *Processing* (or *Completed* for virtual downloads) with an order note: payer, the token and chain they paid with, and the transaction hashes.
* Failed attempts are noted (the customer can retry with the same link); expired sessions cancel the order.
* Exact amounts: the order total is converted to the token's base units with string math, never floating point.
* Test mode with an `lh_test_` API key: payments are simulated, nothing moves on chain.
* Refunds: send them from your own wallet in the LayerHop dashboard. When a refund completes, the plugin adds an order note; a full refund moves the order to *Refunded*.
* A **LayerHop payment** box on each order: session status (fetched live from LayerHop), what the customer paid with, transaction hashes, a **Check payment status now** button and a link to refund in the dashboard.
* Settings page with a **setup checklist** (API key, payout address, webhook secret, last webhook received, last rejected webhook, store currency) and a **Test connection** button.
* Translation ready (`layerhop` text domain, POT file included).
* Compatible with High-Performance Order Storage (HPOS).

**Payment button (no WooCommerce needed)**

Create a product (a fixed price) in the LayerHop dashboard, then add the shortcode anywhere:

`[layerhop_button product="prod_…" label="Pay with crypto" reference="order-42"]`

or use the **LayerHop payment button** block.

== Installation ==

1. Install and activate the plugin (Plugins → Add New → Upload, or copy the `layerhop` folder to `wp-content/plugins/`).
2. Create an account and an API key at [dashboard.layerhop.com](https://dashboard.layerhop.com). Use an `lh_test_` key first to try everything without real funds.
3. In WooCommerce → Settings → Payments → **Crypto (any token) — LayerHop**: enable it, paste the API key, choose what you receive (for example USDC on Base) and enter your payout address.
4. Click **Test connection** in the setup checklist at the top of the settings page. It should say *Connected — Test mode*.
5. In the LayerHop dashboard open **Webhooks** (with **Test mode** on for a test key), add the webhook URL shown on the settings page (`https://your-site/wp-json/layerhop/v1/webhook`), select the `checkout.session.*` events, and paste the signing secret into the plugin settings.
6. Place a test order. The checklist then shows *Last webhook received*.

Full guide: [docs.layerhop.com/guides/wordpress](https://docs.layerhop.com/guides/wordpress).

Your store currency must be USD (or a custom USDC/USDT currency): LayerHop settles 1 unit of store currency as 1 USDC/USDT. With another currency the method is hidden at checkout and an admin notice explains why.

== Frequently Asked Questions ==

= Does LayerHop hold my money? =

No. Payments are delivered straight to your payout address on the chain you chose.

= When is an order marked paid? =

When LayerHop sends the signed `checkout.session.completed` webhook. The plugin verifies the signature (HMAC-SHA256, 5-minute tolerance, secret rotation supported), then fetches the session from the LayerHop API with your key and checks status, amount, recipient and token before calling `payment_complete()`. Replayed or duplicate events are ignored.

= My site is not reachable from the internet (local development). =

Webhooks cannot reach `localhost`. Use the LayerHop CLI to forward test events: `LAYERHOP_API_KEY=lh_test_… LAYERHOP_WEBHOOK_SECRET=<your secret> npx @layerhop/cli listen --forward-to http://localhost:8080/wp-json/layerhop/v1/webhook`. The thank-you page also asks LayerHop for the session status while the customer waits, so orders are confirmed even if a webhook is delayed.

= How do I refund a customer? =

Open the order, click **Refund in LayerHop dashboard** in the LayerHop payment box and sign the refund from your payout wallet. LayerHop is non-custodial, so the plugin cannot send money itself (the WooCommerce *Refund via gateway* button is therefore not available). When the refund completes LayerHop sends `checkout.session.refunded`: the plugin adds an order note with the amount and transaction, and a full refund moves the order to *Refunded* (recorded as a WooCommerce refund, without restocking).

= An order stays "Pending payment" although the customer paid. =

Click **Check payment status now** in the LayerHop payment box on the order. It asks LayerHop for the session and, if it is verifiably paid, completes the order. Then check the setup checklist: if *Last rejected webhook* is shown, the webhook secret in the plugin does not match the endpoint in the dashboard (test and live endpoints have different secrets).

= Which currencies are supported? =

USD, plus the custom codes USDC and USDT. Developers can extend the list with the `layerhop_supported_currencies` filter if their store currency is pegged 1:1 to the US dollar.

= Can customers pay from any wallet? =

Any EVM wallet (MetaMask, Rabby, Coinbase Wallet, WalletConnect…) or Solana wallet (Phantom, Solflare, Backpack…).

= Where are the logs? =

Enable "Debug log" in the settings and open WooCommerce → Status → Logs (source `layerhop`). Errors are always logged. API keys and secrets are never logged.

== External services ==

This plugin connects to LayerHop, a crypto payment routing service, to take payments.

* **api.layerhop.com** — when a customer places an order with this payment method, the plugin sends the order amount, your settlement token and payout address, your store name, the order number, the order id and key (as metadata) and the return URLs to create a checkout session. It reads sessions back from the same API to confirm payments and refunds, to show the LayerHop payment box on orders, and when you click **Test connection** (which lists your most recent checkout session). Every request carries your API key. No customer personal data (name, email, address) is sent.
* **dashboard.layerhop.com** and **docs.layerhop.com** — only linked from the admin screens (API keys, webhooks, refunds, setup guide); nothing is loaded from them automatically.
* **layerhop.com** — customers pay on the hosted page `https://layerhop.com/pay/…`. In popup mode and for the payment button the plugin loads `https://layerhop.com/checkout.js` on the order-pay page and on pages with the button.

LayerHop [terms of service](https://layerhop.com/terms) and [privacy policy](https://layerhop.com/privacy).

== Screenshots ==

1. Settings with the setup checklist and Test connection.
2. The LayerHop payment method at checkout.
3. The hosted LayerHop payment page (pay with any token on any chain).
4. A paid order with the LayerHop payment box (status, paid with, transactions, Check payment status now, Refund in dashboard).

== Changelog ==

= 1.1.0 =
* New: LayerHop payment box on orders — live session status, hosted payment link, what the customer paid with, payer, source and delivery transactions (explorer links in live mode), refunded amount.
* New: "Check payment status now" button on orders (runs the same verified reconciliation as the thank-you page status check).
* New: refunds — `checkout.session.refunded` adds an order note; a full refund sets the order to Refunded and records a WooCommerce refund. "Refund in LayerHop dashboard" link on paid orders.
* New: setup checklist on the settings page (API key, payout address, webhook secret, last webhook received, last rejected webhook, store currency) and a "Test connection" button.
* New: copy button for the webhook URL; clearer setting descriptions.
* New: translation template `languages/layerhop.pot`; block editor strings are translatable.
* `invoice.*` webhook events are acknowledged and ignored.
* Uninstall also removes the stored webhook status.

= 1.0.0 =
* First release: WooCommerce gateway (classic and block checkout, redirect and popup modes, signed webhooks, HPOS), `[layerhop_button]` shortcode and block.

== Upgrade Notice ==

= 1.1.0 =
Order payment box with a "Check payment status now" button, automatic Refunded status after a full refund from the LayerHop dashboard, and a setup checklist with "Test connection". No settings change needed.

= 1.0.0 =
First release.
