=== PD.Cash Payment Gateway ===
Contributors: pdcash
Tags: payments, payment gateway, woocommerce, pd.cash
Requires at least: 5.8
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 1.3.9
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Accept PD.Cash payments: securely link your account, watch your live balance, take payments at WooCommerce checkout.

== Description ==

PD.Cash Payment Gateway connects your WordPress site to your PD.Cash account.

* **Secure account linking** — sign in at PD.Cash, review the requested permissions and approve your WordPress site. Your PD.Cash password is never shared with WordPress.
* **Manual connection available** — API key and secret fields remain available as a fallback, including free sandbox keys for testing.
* **Live balance in your dashboard** — a WordPress dashboard widget and the PD.Cash admin page show your current balance against your API key, with one-click refresh.
* **Package and gateway visibility** — see your current package, available payment gateways and each gateway's supported amounts when the PD.Cash account-capabilities API is available.
* **Free Plan upgrade guidance** — when PD.Cash provides an eligible paid-package offer, Free Plan accounts can see its currently active public payment methods and supported amounts before upgrading.
* **Cached help articles** — the administrator dashboard retrieves presentation-only PD.Cash knowledge-base links, caches them for six hours, and keeps saved or bundled help available during an outage.
* **WooCommerce checkout** — customers are redirected to a secure PD.Cash hosted payment page. Orders complete automatically via webhooks with an API-side verification step, plus a 5-minute polling fallback for sites webhooks can't reach.
* **Sandbox mode** — use pk_sandbox_ keys to test the full flow without real money; sandbox and live data never mix.
* **Everything else on PD.Cash** — payouts, transaction history, disputes, branding and the rest of the toolkit live in your PD.Cash dashboard; the plugin links you straight there.

== Installation ==

1. Upload the plugin to `/wp-content/plugins/` and activate it.
2. Open **PD.Cash** in the WordPress admin menu.
3. Click **Connect PD.Cash**, sign in on pd.cash and approve the connection. Secure account linking requires an HTTPS WordPress site with a working REST API.
4. If account linking is unavailable, use the manual API key and secret fields. Sandbox keys remain supported.
5. With WooCommerce active, enable **PD.Cash** under WooCommerce → Settings → Payments.

== External services ==

This plugin connects to PD.Cash (`https://pd.cash`) to link the merchant account, retrieve account balance and payment capabilities, create hosted payment invoices, verify invoice and transaction status, and retrieve a public list of knowledge-base articles.

When a customer checks out with PD.Cash, the plugin sends the payment amount, an opaque WooCommerce order reference, customer name and email address, site URL, webhook URL, and plugin version to PD.Cash. OAuth account linking sends the WordPress site URL, callback URL, installation identifier, and a short-lived ownership proof. PD.Cash returns account, invoice, and transaction information required to display the dashboard and complete the order.

The public knowledge-base request sends no credentials, customer, order, merchant, or site data. It sends only a generic plugin user agent and accepts a small presentation-only JSON document containing article titles, summaries, PD.Cash help URLs, contexts, and timestamps. The normalized response is cached for six hours, with a saved copy retained for up to seven days.

PD.Cash Privacy Policy: https://pd.cash/privacy
PD.Cash Terms of Service: https://pd.cash/terms

== Frequently Asked Questions ==

= Do I need WooCommerce? =
The live balance widget works with plain WordPress. Checkout payments require WooCommerce.

= Which currencies are supported? =
USD only. The current minimum, maximum and supported gateway amounts come from the authenticated PD.Cash API response and are shown on the plugin dashboard.

= Can my prices end in cents? =
Yes, whenever at least one payment method available to your PD.Cash account can settle the exact total. Exact support always wins, so a $24.70 order stays $24.70 when an available method accepts it. Otherwise the plugin keeps PD.Cash visible when the nearest supported amount (for example $24.99) is within the safety tolerance, adding only the difference as a visible fee line. You can turn this fallback off in the PD.Cash gateway settings.

= How are payments confirmed? =
PD.Cash sends a webhook to your site when a payment completes. The plugin never trusts the webhook alone: it re-verifies every payment against the PD.Cash API with your credentials before marking the order paid. A cron poller also checks pending orders every 5 minutes as a fallback.

= Why can't an old order create a new payment link? =
One WooCommerce order is permanently bound to at most one PD.Cash invoice. This prevents two payable links for the same order after a timeout, account change, order edit or expired provider retry window. Cancel the old order and place a new one when a fresh link is required.

= Is there a test mode? =
Yes. Generate free sandbox keys (pk_sandbox_/sk_sandbox_) on the PD.Cash API Access page and paste them into the plugin. Sandbox payments never touch real money.

= Is connecting through PD.Cash secure? =
The plugin uses OAuth 2.0 Authorization Code with PKCE S256, a single-use state value and explicit consent on pd.cash. Access and rotating refresh tokens are encrypted before WordPress stores them. Disconnecting asks PD.Cash to revoke the grant before the local token copy is removed. The plugin never receives your PD.Cash password or an OAuth client secret.

== Changelog ==

= 1.3.9 =
* Fixed: automatic updates work again. Version 1.3.7 introduced a check that re-read the downloaded update file at install time, but WordPress removes that file moments earlier, so every update from 1.3.7 was refused with "The PD.Cash update package is not part of the verified release manifest." Sites already on 1.3.7 or 1.3.8 need one manual update to this version; after that automatic updates resume.
* The update package is still verified in full against the signed release manifest before anything is installed, and an update with no verified download, or whose file is altered while it is still on disk, is still refused.

= 1.3.8 =
* Exact-capable methods stay available at the unchanged order total while other merchant-available methods can also remain available at the smallest supported higher total inside the safety tolerance (for example $24.70 and $24.99 options at the same checkout).
* Choosing the higher-total option adds only the difference as a clearly named fee line, keeps the cart, order and invoice totals aligned, and removes the line as soon as another payment method is selected.
* Block and classic checkout both refresh their totals when the payment method changes, so the round-up line always matches the selected method.
* Checkout availability now follows the amounts the connected account can actually take instead of a fixed whole-dollar rule, with authenticated background refresh and a bounded last-known fallback that never adds a checkout-time network request.
* Integration problems are now reported instead of failing quietly, so a store owner learns about a rejected or mis-stated payment amount rather than discovering a missing payment option.
* Fixed: WooCommerce log retention no longer stops working while this plugin is active. Previously the scheduled log cleanup silently deleted nothing, and stored logs from every plugin on the store were kept past the configured retention period.
* Fixed: choosing the exact order total at classic checkout can no longer be replaced by the higher total if the available payment amounts change between opening the page and placing the order.
* Fixed: the order-received page and its payment status check no longer fail if the order changes while the page is still checking, which previously could show an error page to a customer who had just paid.
* Fixed: orders confirmed by the background status check now record the PD.Cash fee, so reported net earnings are correct however the payment was confirmed.
* Fixed: the five-minute account refresh now reschedules correctly on stores that customise WordPress cron intervals. It could previously be pushed forward on every page load and never run at all.
* Fixed: the payment status schedule now repairs a wrong or duplicated entry instead of only a missing one.
* Fixed: diagnostic reporting no longer stops permanently once its queue fills, and an affected store repairs itself without any action.
* Fixed: block checkout no longer causes WooCommerce to record a deprecation notice for every order placed through it.
* Security: permission to redirect to pd.cash is now granted only while connecting an account, instead of for every request, and requests refused for insufficient permissions answer HTTP 403 rather than 200.
* Accessibility: screen readers now announce status changes that previously went unannounced, including a payment check that gives up, a failed balance or report refresh, and a copy-to-clipboard that did not succeed.
* Accessibility: report range buttons and card links on the PD.Cash screens now meet the 44px minimum touch target on phones and tablets.
* Fixed: removed a small horizontal scroll on the PD.Cash admin screens.
* Fixed: the "Check payment status now" button on the order screen now works. It previously submitted to the wrong place and never ran the check, because its form was nested inside the WooCommerce order form and discarded by the browser.
* Fixed: an order settled before fees were recorded now says so on the order screen instead of leaving the fee and net lines blank with no explanation.
* Fixed: diagnostic reporting is no longer discarded while an account connection is being changed. The reports explaining a connection problem were the ones being thrown away.
* Fixed: the scheduled payment check is now fully removed when the plugin is deactivated or uninstalled, including older entries that could previously be left behind on the site forever.
* Fixed: a PD.Cash order action for an unknown order now answers HTTP 404 instead of 200.

= 1.3.7 =
* Consolidated the admin dashboard design system: unified color, radius, shadow, and type tokens, fixed a doubled mobile page inset, and gave every dashboard card a proper heading structure.
* Improved dashboard interactions: balance refresh keeps filter text, open amount lists, and focus, shows a spinner, and no longer force-reloads the page; a persistent Sandbox mode indicator appears in the page header; clipboard and report-range actions announce results to screen readers.
* Removed the technical cache-source badge from the Help & diagnostics card.
* Persisted the exact invoice-creation intent before contacting PD.Cash, bound it to the active account connection, and guaranteed that one WooCommerce order can never create a second provider invoice.
* Reused the same stored idempotency key after an ambiguous network response; once its safe retry window ends, the order must be cancelled and replaced instead of rotating to another payment link.
* Bound every displayed or settled invoice to its exact provider order reference, amount, environment and connection generation, with final WooCommerce hook fences against last-moment order changes.
* Made manual/OAuth credential changes transactional, strengthened signed-update rollback and archive checks, and kept benign settings saves from invalidating active payment links.
* Bounded unsigned unknown-invoice webhook lookups and administrator order scans, and automatically repairs a missing payment-status poller schedule.
* Added defense-in-depth validation for remote account data, customer-safe API errors, webhook requests, administrator chart rendering, and secret redaction.
* Added a cached, read-only knowledge-base feed with strict public JSON validation, ETag revalidation, stale and bundled fallbacks, and no changes to payment API payloads.
* Kept PD.Cash available in WooCommerce Blocks while account capabilities are still loading, while continuing to enforce verified method-specific amount rules once known.
* Hardened malformed administrator inputs against non-scalar values and added a legacy-browser visual fallback for the customer payment box.

= 1.3.6 =
* Checkout now shows the specific reason when PD.Cash cannot create a payment (for example an amount below the accepted minimum) instead of a generic failure, and records the reason on the order.
* Updated the default checkout title to "Pay With" and simplified the payment-page redirect message while preserving merchant-customized copy.

= 1.3.5 =
* Reordered payment methods everywhere to the merchant-preferred order: Cash App, Crypto, Apple Pay, Google Pay, PayPal, Chime.

= 1.3.4 =
* Refreshed the Chime and Crypto brand marks (Chime "C" badge, Bitcoin mark) across the dashboard and checkout pills.
* Summarized supported amounts as "low – high · count" with scannable per-amount chips.
* Localized "Last updated" timestamps to the site's date, time and timezone settings.
* Fixed a checkout error when a payment was retried after an order edit, and made retried payments reuse the correct invoice everywhere.
* Explained the USD whole-dollar requirement in the gateway settings and warned when the store currency is not USD.
* Kept unsigned per-payment notifications working when a webhook secret is configured; signatures are still verified whenever present.
* Loaded bundled translations, cleaned up uninstall data, and improved accessibility of the reporting range filter and external links.
* Replaced checkout image marks with compact branded payment pills using locally hosted, namespaced Font Awesome glyphs and visible method names.
* Redesigned the administrator payment-method list as responsive branded cards with bundled SVG marks, compact amount disclosures and identical initial-load and refresh rendering.
* Replaced the browser disconnect dialog with an accessible confirmation shown directly inside the PD.Cash settings page.
* Made Today the default Payments overview range while keeping every longer reporting range available.
* Reduced cached account and analytics data to a strict public contract, re-sanitized older caches, and removed private method and routing metadata before WordPress storage or display.
* Made webhook responses, connection errors, retry logs and cache cleanup fail closed without exposing upstream response details.
* Added a provider-neutral Card presentation for account-enabled card payments.

= 1.3.3 =
* Completed the dashboard analytics range controls, trend chart and withdrawal, pending and failed-payment summaries.
* Restored WordPress's standard administrator-controlled auto-update toggle instead of forcing automatic updates.
* Repaired signed-update key continuity so existing installations can authenticate this release and future key rotation remains explicit.
* Avoided loading plugin translations before WordPress initialization when the polling schedule is inspected early.
* Redacted PD.Cash credentials and tokens from all WooCommerce log handlers and bounded API retries below common PHP execution limits.

= 1.3.2 =
* Added optional brand-coloured Font Awesome payment-method icons through the pdcash_use_fontawesome_icons filter; bundled local marks remain the dependency-free default.
* Added native signed update metadata and the standard WordPress plugin auto-update controls.
* Published the authenticated update manifest and immutable package verification pipeline.

= 1.3.1 =
* Only pending or on-hold orders with an exact current whole-dollar USD total can settle automatically; changed, cancelled, failed, or mismatched payments require merchant reconciliation.
* Validated returned invoice amounts and opaque order references before storing a payment link, and rotate expired retry links while keeping historic invoices reconcilable.
* Made unsigned webhook verification reservations atomic, aligned pending-connection protection with the reconciliation window, and fail closed if disconnect credential removal cannot be saved.
* Added immutable signed-update fixtures and a reproducible production-package build check.

= 1.3.0 =
* Hardened credential storage, hosted payment URL validation, webhook handling, and signed update verification.
* Replaced externally shared WooCommerce order keys with opaque payment references.
* Reused pending payment links and retained invoice history so existing payments remain reconcilable.
* PD.Cash now accepts only exact whole-dollar USD order totals; fractional totals are not converted into a higher charge.

= 1.2.7 =
* Display withdrawal totals as positive outflow amounts in the WordPress dashboard while retaining the signed API value for accounting.

= 1.2.6 =
* Made the current package's available payment methods and API-supported amounts explicit for paid accounts.
* Improved Google Pay and Chime mark sizing across the dashboard and both WooCommerce checkout types.
* Updated the Crypto mark to a neutral network symbol that does not imply a specific digital asset.

= 1.2.5 =
* Free Plan accounts can now see an API-driven upgrade view of payment methods currently active for the recommended paid package, including their supported amounts.
* Upgrade availability is fail-closed and keeps provider, routing and other internal payment metadata out of WordPress.

= 1.2.4 =
* Updated the Crypto artwork and versioned payment-method image URLs so refreshed assets appear immediately after an update.

= 1.2.3 =
* Refined the PD.Cash admin screen with payment-method filtering, collapsible long amount lists and clearer mobile labels.
* Improved filter accessibility with a live no-results announcement.

= 1.2.2 =
* New "Payment pipeline" health card on the settings page: last webhook received, poller schedule (with a warning when WP-Cron is disabled), and how many orders are awaiting payment.
* Payment events (invoice created, webhook results, confirmations, failures) are now logged under WooCommerce > Status > Logs, source "pdcash".

= 1.2.1 =
* Order-received page now watches for payment confirmation live and updates automatically once PD.Cash confirms — no manual reload.
* Failed or cancelled PD.Cash orders now explain what happened and offer a one-click payment retry.
* The pending-payment box shows the exact amount due and invoice ID, and inherits the theme's colors instead of hardcoded greys.

= 1.2.0 =
* New PD.Cash panel on the order edit screen (classic and HPOS): invoice ID, environment, exact charge, PD.Cash fee and net once paid, payment page link, and a "Check payment status now" button for on-demand confirmation.
* Webhook verification now records the PD.Cash fee on the order.

= 1.1.9 =
* Improved whole-dollar checkout validation across classic and block checkout.

= 1.1.8 =
* Refund guidance: attempting an API refund now explains the manual PD.Cash dashboard flow instead of failing silently, and a new "PD.Cash: mark as manually refunded" order action records dashboard refunds in WooCommerce.

= 1.1.7 =
* Connection failure notices now quote the exact PD.Cash error message, so rejected or unreachable credentials are diagnosable at a glance.

= 1.1.6 =
* Settings now show the site's webhook endpoint URL with a copy button, next to the webhook secret it pairs with.

= 1.1.5 =
* Block checkout: "Proceed to PD.Cash" place-order button, live availability that reacts to cart total and currency, merchant description markup rendered faithfully, supported-methods strip and a secure-redirect note in the payment panel, and translation support for checkout strings.

= 1.1.4 =
* New customer email: the PD.Cash payment link is sent as soon as an order is placed, so shoppers can finish paying from their inbox. Manage it under WooCommerce > Settings > Emails.
* New order action to re-send the payment link for unpaid PD.Cash orders.

= 1.1.3 =
* Show which PD.Cash account is connected (email address) on the settings page, account summary and dashboard widget.

= 1.1.2 =
* Replace gateway availability dots with accessible text status pills.
* Remove the redundant live-mode badge and post-connection success banner.
* Keep operational notices in the correct dashboard location and improve their dismiss controls.

= 1.1.1 =
* Fix dashboard widget package row overlapping the upgrade and manage actions in narrow columns.
* Match the dashboard widget primary button to the PD.Cash brand colour used on the settings page.

= 1.1.0 =
* Add secure PD.Cash account linking with OAuth 2.0 Authorization Code, PKCE S256, explicit consent, encrypted token storage, refresh-token rotation and revocation.
* Keep manual API key credentials as a fallback and automatically use OAuth bearer authentication for linked accounts.
* Show the current account package and available gateways with their supported amount ranges in the PD.Cash settings page and WordPress dashboard widget.
* Display only explicitly available, API-named gateways and remove internal gateway metadata before caching or rendering.
* Improve the account dashboard layout, responsive gateway table and refresh feedback.
* Use pd.cash exclusively for production API and account links.
* Refresh balance and account capabilities independently, preserving the latest verified account data when one service is temporarily unavailable.
* Harden hosted checkout validation, webhook verification, polling fairness, API error handling and connection-state recovery.
* Isolate parallel OAuth connection attempts and re-register older cached clients during the secure server transition.
* Encrypt manual API and webhook secrets at rest, including automatic migration from earlier plaintext settings.
* Bound dashboard API latency and rate-limit unsigned webhook verification attempts without weakening payment checks.
* Add privacy-policy guidance, external-service disclosure and translation support.
* Keep API and webhook secrets out of rendered settings HTML.

= 1.0.0 =
* Initial release: account connect, live balance dashboard widget, WooCommerce gateway (classic + block checkout), webhook confirmation with API verification, polling fallback, sandbox support.
