=== BluPay for WooCommerce ===
Tags: woocommerce, cryptocurrency, payments, bitcoin, usdt
Requires at least: 6.2
Tested up to: 7.1.3
Requires PHP: 7.4
WC requires at least: 7.0
WC tested up to: 11.2.1
Stable tag: 0.4.1
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Accept cryptocurrency payments in your WooCommerce store via BluPay — a custodial crypto payment gateway.

== Description ==

BluPay for WooCommerce lets you accept cryptocurrency payments at checkout with no on-chain expertise required. Funds are credited to your BluPay merchant balance after blockchain confirmation, with shop-level conversion and fee settings handled by BluPay.

Features:

* Crypto payments at WooCommerce checkout (BTC, ETH, USDT, USDC, and more)
* Persian and English settings, following the WordPress user language
* Responsive admin settings with connection testing and notification URL copying
* Exact Toman/Rial denomination mapping, including thousand-unit aliases
* Central live crypto quotes for fiat invoice currencies enabled by BluPay
* Read-only currency support checks and indicative crypto previews with rate sources, timestamps, and fee breakdowns
* Sandbox and Production environments
* Webhook-driven order status updates
* HPOS (High-Performance Order Storage) compatible
* Logs all gateway events to WooCommerce → Status → Logs

This release implements end-to-end checkout: invoice creation against the BluPay API, HMAC-verified webhook handling, automatic WooCommerce order status mapping, and support for both classic and block checkout.

== Installation ==

1. Upload the `blupay` folder to `/wp-content/plugins/`, or install via wp-admin → Plugins → Add New → Upload Plugin.
2. Activate the plugin through the "Plugins" menu in WordPress.
3. Make sure WooCommerce is installed and active.
4. Go to WooCommerce → Settings → Payments → BluPay (Crypto) and configure your API key, webhook signing secret, and environment. Shop ID is optional.
5. Copy the Webhook URL shown on the settings screen and paste it into your BluPay merchant dashboard.

== Frequently Asked Questions ==

= Which cryptocurrencies are supported? =

BluPay supports the major cryptocurrencies (Bitcoin, Ethereum, USDT, USDC, and others). The exact list is determined by your merchant account configuration in the BluPay dashboard.

= Where do I get an API key? =

Sign up for a merchant account at https://blupay.me/ and generate an API key from the BluPay merchant dashboard.

= Is BluPay custodial or non-custodial? =

BluPay is a custodial gateway. Customer funds are received by BluPay, optionally converted, and settled to your merchant balance.

= Is HPOS supported? =

Yes — this plugin declares compatibility with WooCommerce custom order tables (HPOS).

= Does the plugin support Cart and Checkout blocks? =

Yes. BluPay registers a payment method for WooCommerce Cart and Checkout blocks and also supports the classic checkout.

= How do Toman, Rial and other fiat currencies work? =

WooCommerce keeps the original order amount and currency. The plugin normalizes IRT/TMN/TOMAN to Toman and IRR/RLS/RIAL to Rial. Thousand Toman (IRHT) and thousand Rial (IRHR) amounts are multiplied by exactly 1,000 before invoice creation. BluPay calculates the crypto equivalent centrally from an available live rate. This requires a compatible BluPay API and enabled invoice currencies. Fiat price units do not provide bank settlement.

= What does the Rates and currency conversion section do? =

Save your BluPay connection settings, then select Check rates. The section shows the WooCommerce currency, normalized invoice currency and denomination multiplier, whether conversion is currently available, and the crypto/network methods enabled for your BluPay shop. Available rates show their providers, observation time, and expiry time. Editing an unsaved API connection disables these checks until you save it.

Enter a sample amount in the original store currency and choose an available crypto/network method to preview conversion. The result separates the crypto equivalent before fees, gateway fee, network fee, and indicative amount payable, with the customer or merchant fee payer shown for each fee. The authenticated API determines live/sandbox mode and live/mock rate labels. A live shop cannot receive a numerical mock preview.

These checks create no invoice, payment, wallet reservation, or ledger entry and do not change WooCommerce amounts or payment settings. The section provides no manual exchange-rate override. Checkout calculates the actual payment amount again when the customer selects a payment method; an admin preview does not lock a payment rate. Unsupported currencies, unavailable or expired rates, and invalid responses produce no numerical preview.

Rate checks require a BluPay API that implements authenticated GET /v1/quotes/context and POST /v1/quotes/preview with the currencies:read API-key permission. Installing this plugin does not activate those endpoints, live rate providers, or fiat currencies in production. They must be deployed, enabled, and verified by the BluPay operator before the new conversion features are advertised as available.

= How do I change the admin language? =

Choose Persian or English under WordPress Users → Profile → Language. English is the default source language, and the plugin includes a complete Persian translation with right-to-left layout. Customer-facing title and description remain editable store settings.

== External services ==

This plugin connects to the BluPay API at https://blupay.me/api/v1 to create payment invoices, test the merchant's API connection, and check rates or preview conversion. Requests occur when an authorized store administrator chooses one of these actions or a customer chooses BluPay at checkout. A saved custom API URL may be used for a self-hosted deployment; HTTP rate-preview requests are limited to explicit local-development endpoints.

When an invoice is created, the plugin sends the order amount, currency, WooCommerce order ID, store name, customer billing email (when available), return URL, and webhook URL to BluPay. The API key is sent in the X-API-Key request header. BluPay sends signed payment status webhooks back to the store so the WooCommerce order can be updated.

Rate checks use the saved API URL and key. They send the normalized store currency; a sample preview also sends the normalized sample amount and selected currency/network identifier. They do not send customer billing data, an order ID, or the webhook signing secret. BluPay may update the API key's last-used timestamp and refresh its rate cache, but these read-only actions create no financial records.

BluPay terms of service: https://blupay.me/terms
BluPay privacy policy: https://blupay.me/privacy

== Changelog ==

= 0.4.1 =
* Reject signed webhook order references that do not match the stored invoice/order identity before receipt recovery, order/stock effects or cancellation.
* Add native WordPress update notices and one-click installation for future releases.
* Verify Ed25519-signed publisher metadata and the exact ZIP SHA-256/size before installation; reject insecure URLs, redirects, tampered packages and downgrades.
* Show Persian/English release notes before updates and the installed release notes in gateway settings.
* Existing installations without this updater need one initial manual upgrade. Completely inactive plugins cannot run this update provider.
* No gateway credentials or customer data are sent in update checks. Updates require PHP Sodium and normal WordPress update/filesystem permissions.


= 0.4.0 =
* Redesign the gateway settings for clear setup, checkout preferences, and diagnostics on desktop and mobile.
* Bundle Persian translations and a local, licensed Vazirmatn font; support WordPress user language and RTL layout.
* Test entered connection values without saving, copy the webhook URL, and show or hide credentials.
* Normalize Toman/Rial aliases with exact decimal arithmetic without changing WooCommerce accounting.
* Add bilingual read-only rate checks and indicative conversion previews using the saved API connection and shop-enabled payment methods.
* Show rate providers, observation/expiry times, the crypto equivalent before fees, indicative amount payable, and fee-payer breakdowns; expire previews without a stale fallback.
* Require authenticated, compatible quote endpoints; reject unsupported inputs, unavailable rates, and numerical mock quotes for live shops without creating financial records.
* Harden API requests with explicit TLS verification, no redirects, bounded responses and private, localized failure messages. Remote API connections require HTTPS; HTTP is limited to explicit local/development endpoints.
* Reject invalid amounts before creating a remote invoice and safely release only the local pre-request claim.
* Verified with WordPress 7.1.3, WooCommerce 11.2.1, and PHP 8.3.


= 0.3.9 =
* Recover an exact cancelled webhook after a lost response with a signed receipt GET, without replaying a paid callback.
* Add a short-lived, site-bound operator capability for the optional atomic paid and cancellation paths; both remain off by default.

= 0.3.8 =
* Persist a receipt tied to the signed webhook event ID and exact request body before acknowledging a completed callback. Repeated delivery of the same event can recover its acknowledgement without repeating WooCommerce effects.
* Add an authenticated receipt proof endpoint so BluPay can verify a committed callback after an uncertain delivery. Pending or conflicting receipts cannot produce a completion proof.

= 0.3.7 =
* Serialize checkout, admin order saves and refunds with signed BluPay callbacks on the same durable order claim.
* Reject stale order edits before status and stock side effects, while preserving a legitimate refund after the claim clears.

= 0.3.6 =
* Ignore stale, signed invoice-status callbacks after a newer revision and keep confirmed payments from regressing.
* Require reconciliation for unversioned non-paid callbacks after an order has entered the versioned status stream.

= 0.3.5 =
* Allow 60 minutes for new checkout invoices so Bitcoin payments have a usable broadcast window.

= 0.3.4 =
* Verify checkout pending status in the authoritative WooCommerce order table before requesting a BluPay invoice. Fail safely when status persistence fails.

= 0.3.3 =
* Verify that non-paid webhook status changes persist before acknowledging the event, so a failed WooCommerce order save remains retryable and quarantined for review.

= 0.3.2 =
* Serialize signed webhook callbacks across PHP workers so delayed or duplicate events cannot race WooCommerce order updates.
* Return a retryable response when the database processing lock is busy or unavailable.

= 0.3.1 =
* Preserve confirmed WooCommerce orders when older invoice webhooks arrive.
* Prevent a second checkout invoice on a paid order and flag unresolved payment completion for review.

= 0.3.0 =
* Added and declared compatibility with WooCommerce Cart and Checkout blocks.
* Fixed block checkout availability when the optional Shop ID setting is blank.
* Declared WooCommerce as a plugin dependency.
* Tested with WordPress 7.0, WooCommerce 11.0, and PHP 8.3.
* Updated WordPress.org metadata and documented the external BluPay API service.

= 0.2.0 =
* Initial working payment flow + webhook receiver.
* Implemented `BluPay_API::create_invoice` against `POST /v1/invoices/` with idempotency key support.
* Implemented `BluPay_Gateway::process_payment` — creates an invoice, persists `_blupay_invoice_link`, redirects buyers to BluPay.
* Implemented `BluPay_Webhook::handle` — verifies HMAC-SHA256 signature, enforces 5-minute clock-skew window, idempotency by event id, ring-buffered to last 1000 events.
* Mapped BluPay invoice statuses to WC order statuses (spec §16.4). Admin choice between `processing` and `completed` on Paid.
* Added `Webhook Secret` and `Order status on Paid` gateway settings.
* Added WC Cart/Checkout Blocks support (minimal label + edit + canMakePayment shim).
* Surfaced last received webhook + timestamp on the settings screen.

= 0.1.0 =
* Initial skeleton release: admin settings page, gateway registration, webhook route stub, HPOS compatibility declaration.

== Screenshots ==

1. Settings page in WooCommerce → Settings → Payments → BluPay (Crypto).
2. Test Connection button on the settings screen.
3. Customer-facing payment option at checkout.
4. Rates and currency conversion with current support, rate provenance, and an indicative fee breakdown.

== Upgrade Notice ==

= 0.4.0 =
Adds bilingual admin settings, fiat denomination normalization, and read-only conversion previews. Rate previews require the compatible BluPay quote endpoints and currencies:read permission. Production fiat support requires separately deployed and verified API providers, flags, and catalog activation; installing the plugin alone does not enable it. Existing orders and saved settings are retained.


= 0.3.8 =
Install to make completed webhook acknowledgements durable and enable authenticated receipt verification for uncertain deliveries.

= 0.3.7 =
Install to prevent a simultaneous checkout or admin edit from overwriting a confirmed BluPay callback. Existing order metadata is retained.

= 0.3.6 =
Install before enabling BluPay's versioned invoice-status webhook stream; existing checkout and legacy paid callbacks remain supported.

= 0.3.5 =
New checkout invoices use a 60-minute payment window. Existing invoices keep their original deadline.

= 0.3.4 =
Prevents creating a BluPay invoice when checkout pending status was not persisted. Existing orders and webhook behavior are retained.

= 0.3.3 =
Prevents a failed WooCommerce status save from being acknowledged as a successful BluPay webhook. Existing checkout and paid-order behavior is preserved.

= 0.3.2 =
Prevents concurrent signed callbacks from racing payment completion and order status changes. Requires a shared MySQL or MariaDB writer for the WordPress site.

= 0.3.1 =
Protects paid order status and inventory from delayed invoice callbacks. Review any unresolved payment-completion notice before retrying.

= 0.3.0 =
Adds current WooCommerce compatibility metadata and fixes availability in block checkout when Shop ID is left blank.

= 0.2.0 =
First functional release — checkout + webhook receiver. Paste your shop's webhook secret in BluPay settings before going live.

= 0.1.0 =
Initial release.
