Title: Donation Router for GiveWP &amp; PayPal – Route Donations by Donor Country
Author: Al Amin Ahamed
Published: <strong>19.05.2026</strong>
Last modified: 17.08.2026

---

Поиск плагинов

![](https://ps.w.org/alamin-donation-router/assets/banner-772x250.png?rev=3650376)

![](https://ps.w.org/alamin-donation-router/assets/icon.svg?rev=3650376)

# Donation Router for GiveWP & PayPal – Route Donations by Donor Country

 Автор: [Al Amin Ahamed](https://profiles.wordpress.org/mralaminahamed/)

[Скачать](https://downloads.wordpress.org/plugin/alamin-donation-router.1.2.0.zip)

 * [Детали](https://ru.wordpress.org/plugins/alamin-donation-router/#description)
 * [Отзывы](https://ru.wordpress.org/plugins/alamin-donation-router/#reviews)
 *  [Установка](https://ru.wordpress.org/plugins/alamin-donation-router/#installation)
 * [Разработка](https://ru.wordpress.org/plugins/alamin-donation-router/#developers)

 [Поддержка](https://wordpress.org/support/plugin/alamin-donation-router/)

## Описание

Donation Router for GiveWP & PayPal extends the GiveWP PayPal Donations gateway 
so that a single WordPress installation can accept donations through several PayPal
Business accounts, automatically routing each transaction to the correct account
based on the donor’s declared country.

This plugin is an independent, third-party extension. It is not affiliated with,
endorsed by, or sponsored by GiveWP (StellarWP) or PayPal. The names «GiveWP» and«
PayPal» appear here solely to describe compatibility with those products.

**You need at least two PayPal Business accounts and one GiveWP donation form per
country for this plugin to do anything.** With a single PayPal account there is 
nothing to route, and GiveWP’s own PayPal Donations setup already covers you.

This plugin is designed for organisations that operate two or more legally distinct
charity entities — for example a US 501(c)(3) and a Canadian CRA-registered charity—
that share a single donation website but must process payments through separate 
PayPal accounts and issue separate tax receipts.

**Key features:**

 * **Multi-account admin panel** — Add and manage any number of PayPal Business 
   accounts under Donation Forms  PayPal Accounts. Each account stores legal entity
   details (name, tax ID, address, country) alongside AES-256-GCM encrypted API 
   credentials.
 * **Country routing rules** — Define which PayPal account and GiveWP form handles
   donations from each country. One active rule per country, fully configurable 
   from the admin.
 * **Country selector popup** — A donor-facing modal popup (shortcode `[ador_country_selector]`)
   asks donors to identify their country before proceeding to checkout. Selection
   is stored in sessionStorage to avoid repeated prompts.
 * **Runtime credential routing** — The plugin intercepts GiveWP’s IoC container
   at payment time, substituting the correct PayPal credentials transparently. No
   GiveWP core files are modified.
 * **Per-account webhook handling** — Each PayPal account receives its own webhook
   endpoint (`/wp-json/ador/v1/webhook/{account_id}`) with independent HMAC signature
   verification.
 * **Per-entity email tags** — Seven GiveWP email template tags populate receipt
   emails with the correct legal entity name, address, tax ID, tax-deductibility
   statement, and a unique per-entity receipt number.
 * **PDF receipts** — Optional on-demand PDF receipt download on the GiveWP success
   page, generated by dompdf.
 * **Connect with PayPal** — Onboard any number of PayPal Business accounts through
   GiveWP’s own approved-partner flow. No separate PayPal app to configure, and 
   no pasting client secrets by hand.
 * **Import GiveWP’s existing account** — One click adopts the PayPal account GiveWP
   is already connected to, reusing its stored credentials, so it becomes routable
   and receipt-customisable without a second OAuth.
 * **Live and sandbox side by side** — Every account carries an environment. Routing
   only applies an account whose environment matches GiveWP’s current mode, so a
   sandbox account can never take a live donation.
 * **Setup readiness panel** — The Accounts screen reports whether donations are
   actually routing: missing rules, accounts in the wrong environment, rules pointing
   at deactivated accounts or unpublished forms, missing webhooks, and donations
   that bypassed routing. It collapses to a single line once nothing needs attention.
 * **Per-account webhook registration** — Register each account’s webhook and its
   event subscriptions at PayPal from the admin, using that account’s own credentials.
 * **Security-first design** — AES-256-GCM credential storage, nonce protection,
   capability checks, webhook signature verification, and `$wpdb->prepare()` throughout.

#### How it works

 1. A donor lands on your donation page and the country selector asks which country
    they are giving from. Their answer is remembered for the rest of the visit.
 2. The plugin looks up the routing rule for that country to find the donation form
    and the PayPal Business account that should receive the gift.
 3. When the donor pays, the correct account’s credentials are substituted into GiveWP’s
    PayPal gateway for that request only. PayPal charges the right legal entity — nothing
    is transferred between accounts afterwards.
 4. The donation records which account processed it and which country the donor selected.
 5. PayPal notifies the site on that account’s own webhook endpoint, and the capture,
    denial or refund is recorded against the donation.
 6. The receipt email renders that entity’s registered name, address, tax ID, tax-deductibility
    statement and its own receipt number.

If a country has no routing rule, nothing breaks: the donation proceeds through 
GiveWP’s default PayPal account, and the readiness panel reports that it happened.

#### More from us

Other free plugins by the same author, all on WordPress.org.

**For any site**

 * [Swift Menu Duplicator](https://wordpress.org/plugins/swift-menu-duplicator/)—
   Duplicate menus in one click, snapshot revisions, export and import, WP-CLI and
   REST.
 * [Author Profile Blocks](https://wordpress.org/plugins/author-profile-blocks/)—
   Author and team profiles as Gutenberg blocks — grid, carousel, list and single.

**For the WordPress AI Client**

 * [AI Provider for OpenCode Zen](https://wordpress.org/plugins/alamin-ai-provider-for-opencode-zen/)—
   One API key, 57 models including GPT-5, Claude and Gemini 3, for the WordPress
   AI Client.
 * [AI Provider for MiniMax](https://wordpress.org/plugins/alamin-ai-provider-for-minimax/)—
   MiniMax M2 and M3 models for text generation, for the WordPress AI Client.

### External services

This plugin sends data to PayPal’s REST API to authenticate with PayPal Business
accounts and to verify the HMAC-SHA256 signatures of inbound webhook events.

**PayPal REST API** (`https://api-m.paypal.com`, `https://api-m.sandbox.paypal.com`,`
https://api.paypal.com`, `https://api.sandbox.paypal.com`)

 * **What is sent:** PayPal Client ID and Client Secret (decrypted in memory at 
   request time, never stored in plaintext) are exchanged for OAuth 2.0 bearer tokens
   during donation checkout. Webhook event payloads are forwarded to PayPal’s `/
   v1/notifications/verify-webhook-signature` endpoint for signature verification.
 * **When it is sent:** Only when a donation is being processed through a PayPal
   Business account configured in this plugin, or when PayPal sends a webhook event
   to this site.
 * **Service terms:** [PayPal User Agreement](https://www.paypal.com/us/legalhub/useragreement-full)
   | [PayPal Privacy Statement](https://www.paypal.com/us/legalhub/privacy-full)

## Скриншоты

[⌊PayPal accounts — every configured PayPal Business account with its legal entity,
mode, and Active/Inactive status, plus per-row Edit, Deactivate and Delete actions.⌉⌊
PayPal accounts — every configured PayPal Business account with its legal entity,
mode, and Active/Inactive status, plus per-row Edit, Deactivate and Delete actions
.⌉[

PayPal accounts — every configured PayPal Business account with its legal entity,
mode, and Active/Inactive status, plus per-row Edit, Deactivate and Delete actions.

[⌊Connect an account — the Connect with PayPal onboarding flow, which saves each
connected Business account as its own managed account rather than overwriting a 
single global one.⌉⌊Connect an account — the Connect with PayPal onboarding flow,
which saves each connected Business account as its own managed account rather than
overwriting a single global one.⌉[

Connect an account — the Connect with PayPal onboarding flow, which saves each connected
Business account as its own managed account rather than overwriting a single global
one.

[⌊Country routing — the rules mapping each donor country to the donation form and
PayPal account that should receive it. One active rule per country.⌉⌊Country routing—
the rules mapping each donor country to the donation form and PayPal account that
should receive it. One active rule per country.⌉[

Country routing — the rules mapping each donor country to the donation form and 
PayPal account that should receive it. One active rule per country.

[⌊Webhook setup — the unique per-account webhook URL to register in PayPal, with
one-click copy and the list of event types to subscribe to.⌉⌊Webhook setup — the
unique per-account webhook URL to register in PayPal, with one-click copy and the
list of event types to subscribe to.⌉[

Webhook setup — the unique per-account webhook URL to register in PayPal, with one-
click copy and the list of event types to subscribe to.

[⌊Choose your country — the donor-facing modal (shortcode [ador_country_selector]),
naming the legal entity that will receive the gift and its tax treatment.⌉⌊Choose
your country — the donor-facing modal (shortcode [ador_country_selector]), naming
the legal entity that will receive the gift and its tax treatment.⌉[

Choose your country — the donor-facing modal (shortcode `[ador_country_selector]`),
naming the legal entity that will receive the gift and its tax treatment.

[⌊Plugin settings — the country selector popup, geolocation provider, PDF receipts,
and the legal-review acknowledgement.⌉⌊Plugin settings — the country selector popup,
geolocation provider, PDF receipts, and the legal-review acknowledgement.⌉[

Plugin settings — the country selector popup, geolocation provider, PDF receipts,
and the legal-review acknowledgement.

[⌊Receipts and legal details — per-account legal entity details and the tax-deductibility
statement editor, with the email tags that resolve to this account's name, tax ID,
address and receipt number.⌉⌊Receipts and legal details — per-account legal entity
details and the tax-deductibility statement editor, with the email tags that resolve
to this account's name, tax ID, address and receipt number.⌉[

Receipts and legal details — per-account legal entity details and the tax-deductibility
statement editor, with the email tags that resolve to this account’s name, tax ID,
address and receipt number.

## Установка

#### Before you start

This plugin extends GiveWP and does nothing on its own. You will need:

 * **GiveWP**, installed and active, with its **PayPal Donations** gateway enabled
   under GiveWP  Settings  Payment Gateways. Without that gateway there is no PayPal
   checkout to route.
 * **Two or more PayPal Business accounts.** With a single account there is nothing
   to route — GiveWP’s own PayPal Donations setup is all you need.
 * **A GiveWP donation form for each country you want to route.** A routing rule
   points at a specific form, so the forms have to exist before you can create the
   rules.
 * `AUTH_KEY` and `SECURE_AUTH_SALT` set to strong, unique values in `wp-config.
   php`. Credentials are encrypted with a key derived from them; a standard WordPress
   install already has these.

#### Installing

From **Plugins  Add New**, search for «Donation Router for GiveWP», then install
and activate. Everything the plugin needs is bundled — there is no Composer or build
step.

To install from source instead, clone the repository into `wp-content/plugins/`,
then run `composer install --no-dev --optimize-autoloader` and `yarn install --immutable&&
yarn build`. Only the source checkout needs this; the released package does not.

#### Setting it up

 1. Go to **Donation Forms  PayPal Accounts**. The readiness panel at the top of this
    screen tracks everything below and tells you what is still outstanding.
 2. Add your first PayPal Business account — **Connect with PayPal** (recommended: 
    uses GiveWP’s approved partner, so there is no PayPal app to create and no client
    secret to paste), **Import from GiveWP** if GiveWP is already connected to one,
    or by entering a Client ID and Secret from your own PayPal Developer app.
 3. Fill in that account’s legal entity details — registered name, tax ID, and address.
    These are what appear on its receipts, and they are the reason to run more than
    one account.
 4. Repeat for each entity. Each account carries an environment (live or sandbox); 
    routing only uses an account whose environment matches GiveWP’s current mode.
 5. Under the **Country Routing** tab, add a rule per country: the donor’s country,
    the GiveWP form they should see, and the account that should receive the money.
    One active rule per country.
 6. Copy the `[ador_country_selector]` shortcode — shown on the Country Routing tab
    with a copy button — onto your donation landing page. This is what asks donors 
    which country they are giving from.
 7. Register each account’s webhook, either with the **Register webhook** action on
    the Accounts list or by pasting the URL from **Webhook Setup** into your PayPal
    Developer app. Without it, captures and refunds are never recorded against the 
    donation.
 8. Under the **Settings** tab, review the tax-deductibility statement for each account
    and tick the legal-review acknowledgement once a qualified adviser has approved
    them.

When the readiness panel collapses to a single «Ready» line, the setup is complete.
Make one small live donation and confirm it appears under the account you expected.

For detailed configuration instructions, see [operations.md](https://github.com/mralaminahamed/donation-router-for-givewp-paypal-donations/blob/trunk/resources/docs/operations/operations.md)
in the GitHub repository.

## Часто задаваемые вопросы

### Do I need a PayPal Developer app for every account?

No. **Connect with PayPal** on the Add Account screen onboards a PayPal Business
account through GiveWP’s own approved partner, so no separate PayPal app or client
secret is needed. If GiveWP is already connected to a PayPal account, **Import from
GiveWP** adopts it without a second authorisation. Manual entry of a Client ID and
Secret remains available.

### Does this work with recurring donations?

Not yet — and this matters if you sell them. GiveWP’s PayPal Commerce gateway supports
subscriptions via the paid Recurring Donations add-on, which creates a PayPal billing
plan through its own code path. This plugin routes credentials on the one-time donation
path only, so with that add-on active a recurring donation’s plan is created under
GiveWP’s default PayPal account rather than the account for the donor’s country.
Renewals then bill at PayPal against that plan, so nothing later can redirect them.
One-time donations route correctly. If you need per-country routing for recurring
gifts, treat it as unsupported for now.

### All my donations are going to the wrong PayPal account. Why?

Almost always an environment mismatch. Every account here is either **live** or **
sandbox**, and routing only applies an account whose environment matches GiveWP’s
current mode. If GiveWP is in test mode and your accounts are live — or the reverse—
every account is skipped and the donation falls through to GiveWP’s own default 
PayPal account. The account still shows as **Active**, because it is; it is just
unusable in that mode.

The readiness panel on the Accounts screen reports this directly. The other causes
it detects are a country with no active routing rule, a rule pointing at an account
that was deactivated afterwards, and a rule whose donation form was deleted or unpublished.
All four produce the same symptom: the money quietly reaches the default account.

### My country has no tax-deductibility statement. What do I do?

Write your own. The plugin ships default statement text for the **United States**(
501(c)(3)) and **Canada** (CRA) only; every other country starts blank, because 
the correct wording is jurisdiction-specific and getting it wrong is a compliance
problem rather than a formatting one.

Edit an account and fill in its **Tax-Deductibility Statement**, using the email
tags listed beneath the field to pull in that entity’s name, tax ID and receipt 
number. Have a qualified tax or legal adviser approve the wording for each entity
before you take live donations, then tick the legal-review acknowledgement under**
Settings**. That acknowledgement is a reminder for your own records — the plugin
does not block donations while it is unticked.

### Can one PayPal account receive donations from several countries?

Yes. The constraint is one active rule per _country_, not per account — the `country_code`
column carries a unique key. Point as many countries as you like at the same account.
A single European entity serving a dozen countries is a normal setup.

### What happens if I change AUTH_KEY or SECURE_AUTH_SALT?

Every stored PayPal credential becomes permanently unreadable. The encryption key
is derived from those two constants, so rotating either one means the ciphertext
can no longer be decrypted — there is no recovery path, and you must re-enter or
re-connect each account.

The Accounts screen detects this and tells you what happened rather than failing
obscurely. If you plan to rotate salts, have your credentials to hand first, or 
re-run **Connect with PayPal** for each account afterwards.

### How do refunds work?

Refund a donation the normal GiveWP way and the plugin routes the refund back through
the account that originally took the payment, using the account recorded on that
donation rather than whichever account is currently default.

Two situations stop a refund with an explanatory message instead of failing at PayPal:
the original account has since been deactivated (reactivate it first), or that account’s
environment no longer matches GiveWP’s current mode (switch GiveWP to that mode 
first). Both are deliberate — the alternative is an opaque authentication error 
from PayPal.

### What happens if I deactivate or delete an account that still has routing rules?

Deactivating an account leaves the rules pointing at it untouched, and donations
for those countries fall through to GiveWP’s default PayPal account. The readiness
panel flags this specific situation, since nothing else about the admin would show
it. Repoint or deactivate the affected rules as well.

Deleting an account asks for confirmation and deregisters its webhook at PayPal 
first. Donations already processed keep their record of which account handled them,
so past receipts remain correct.

### Is geolocation required? What does it actually do?

No, it is optional and off unless you enable it. When on, it pre-selects a country
in the selector modal as a _hint_ — the donor’s own choice always wins, and no country
is ever chosen on their behalf. If no hint is available the modal simply opens with
nothing pre-selected.

Three providers are supported: Cloudflare’s `CF-IPCountry` header, the MaxMind GeoIP
Detect plugin, and any plugin implementing WordPress’s `geoip_country_code` filter.
Hints are cached for an hour per visitor.

### How are receipt numbers generated? Can there be gaps?

Each account gets its own sequence, restarting annually, formatted as country-year-
sequence — for example `US-2026-00001` and `CA-2026-00001` run independently.

Gaps are possible and are not a fault. Numbers are allocated atomically at the moment
a donation record is created, so an allocated number is never reused even under 
simultaneous donations; but if a donation is later deleted, its number is not recycled.
If your jurisdiction requires strictly gapless receipt numbering, verify that this
satisfies your auditor before relying on it.

### What does the plugin store on each donation?

Three pieces of metadata: which account processed it (`_ador_processing_account_id`),
the country the donor selected (`_ador_donor_country`), and the receipt number allocated
for it (`_ador_receipt_number`). No other donor data is stored by this plugin — 
everything else about a donation lives in GiveWP as usual.

The account that processed a donation is recorded at payment time and is not editable
afterwards, because it reflects which legal entity actually received the money.

### What happens when I uninstall?

Deleting the plugin through the Plugins screen removes its two database tables, 
its options, its per-account receipt templates and sequences, and its transients.
Deactivating alone changes nothing, so you can deactivate safely while troubleshooting.

Donation records, receipt numbers already written to donation metadata, and GiveWP’s
own data are untouched — but once the accounts table is gone, receipt email tags
for past donations resolve to empty strings. Export anything you need first.

### Which payment gateways does this plugin support?

This plugin supports the GiveWP PayPal Donations gateway (also known as PayPal Commerce/
PPCP) only. It does not affect or support other GiveWP gateways such as Stripe, 
Authorize.net, or PayPal Standard.

### How many PayPal accounts can I add?

There is no hard limit. Each account needs its own credentials and its own webhook,
but you no longer have to create a PayPal Developer app per account: **Connect with
PayPal** onboards each one through GiveWP’s approved partner and stores the resulting
credentials for you, and the webhook can be registered from the Accounts list. Entering
a Client ID and Secret from your own Developer app is still supported if you prefer
it.

### How are PayPal credentials stored? Is it safe?

Yes. PayPal Client IDs and Client Secrets are never stored in plaintext. They are
encrypted with AES-256-GCM using a key derived via HKDF-SHA256 (RFC 5869) from your
WordPress `AUTH_KEY` and `SECURE_AUTH_SALT` constants (32-byte key). The random 
nonce and GCM authentication tag are stored alongside the ciphertext as a base64
blob. Credentials are never written to any log. If `AUTH_KEY` or `SECURE_AUTH_SALT`
are changed, stored credentials become unreadable and must be re-entered.

### Can I test with PayPal sandbox accounts before going live?

Yes, and it is worth doing. Add sandbox accounts exactly the way you add live ones—**
Connect with PayPal** works against the sandbox too, and manual Client ID and Secret
entry still works if you prefer. Each account records the environment it belongs
to, so live and sandbox accounts for the same merchant can sit side by side without
interfering.

Switch GiveWP into test mode while you do this: routing only uses accounts whose
environment matches GiveWP’s current mode, so sandbox accounts are inert in live
mode and vice versa. Sandbox webhooks need a publicly reachable HTTPS URL, so use
a tunnelling tool such as ngrok for local development. See [operations.md](https://github.com/mralaminahamed/donation-router-for-givewp-paypal-donations/blob/trunk/resources/docs/operations/operations.md)
for a full sandbox testing procedure.

### What happens if a routing rule is missing for a donor’s country?

If no active routing rule exists for the selected country, the credential router
falls back to GiveWP’s primary PayPal account. The donation is not blocked — it 
proceeds normally using the default account. An error entry is written to the PHP
error log with prefix `[ADOR]` for the operator’s attention.

### Does this plugin modify GiveWP core files?

No. The plugin hooks into GiveWP exclusively through WordPress filters, actions,
and GiveWP’s public IoC container (`give()`). No GiveWP core files are modified.

### Can I use this plugin with GiveWP’s built-in email receipts?

Yes. The plugin registers additional GiveWP email template tags that you can insert
into your existing GiveWP email templates (GiveWP  Settings  Emails). Tags include`{
paypal_account_entity_name}`, `{paypal_account_entity_tax_id}`, `{paypal_account_receipt_number}`,
and four others. Tags return an empty string for donations not routed through this
plugin, so existing templates work without changes.

### The PDF receipt is not generating. What should I check?

First check that **PDF Receipts** is enabled under the plugin’s **Settings** tab—
it is off by default. dompdf ships inside the released package, so there is nothing
to install; if you are running from a source checkout instead, run `composer install`
to fetch it. Then look in the PHP error log for a line beginning `[ADOR] PDF receipts
disabled:`, which names the underlying cause.

If the button appears but downloading returns «You do not have permission», update
to the latest version — releases before this one refused the download to everyone
except administrators.

## Отзывы

Нет отзывов об этом плагине.

## Участники и разработчики

«Donation Router for GiveWP & PayPal – Route Donations by Donor Country» — проект
с открытым исходным кодом. В развитие плагина внесли свой вклад следующие участники:

Участники

 *   [ Al Amin Ahamed ](https://profiles.wordpress.org/mralaminahamed/)

[Перевести «Donation Router for GiveWP & PayPal – Route Donations by Donor Country» на ваш язык.](https://translate.wordpress.org/projects/wp-plugins/alamin-donation-router)

### Заинтересованы в разработке?

[Посмотрите код](https://plugins.trac.wordpress.org/browser/alamin-donation-router/),
проверьте [SVN репозиторий](https://plugins.svn.wordpress.org/alamin-donation-router/),
или подпишитесь на [журнал разработки](https://plugins.trac.wordpress.org/log/alamin-donation-router/)
по [RSS](https://plugins.trac.wordpress.org/log/alamin-donation-router/?limit=100&mode=stop_on_copy&format=rss).

## Журнал изменений

#### 1.2.0 — 2026-08-17

**Added**

 * Setup readiness panel on the PayPal Accounts screen — ten checks computed from
   the site’s real state, reporting whether donations are actually being routed 
   and linking to the screen that fixes each problem. It collapses to a single line
   once nothing is failing.
 * Detection for three failures the admin could not previously show: an account 
   whose environment does not match GiveWP’s test-mode setting (skipped by routing,
   yet still badged Active), a routing rule pointing at an account that was deactivated
   afterwards, and a rule whose donation form was deleted or unpublished. In each
   case donations silently reach GiveWP’s default PayPal account.
 * A record of donations that bypassed routing, shown in the panel with the form,
   the reason and when it last happened. Previously this appeared only in the PHP
   error log.
 * Contextual Help tabs on the plugin screen covering setup order, country routing,
   and the receipt email tags.
 * The donor selector shortcode is now shown on the Country Routing tab with a copy
   button — it previously appeared nowhere in the admin.

**Changed**

 * The legal-review acknowledgement no longer states that donations are blocked 
   until it is ticked. Nothing in the payment or receipt path enforced it, so the
   notice now describes what the plugin actually does.
 * New plugin icon, banners and social card, rebuilt on the WordPress admin colour
   palette so the listing matches the plugin’s own interface.
 * Listing screenshots now show the plugin’s real interface in a branded frame.
 * The donor country selector’s CSS classes are renamed from `givewp-country-selector-*`
   to `ador-country-selector-*`. If your theme or custom CSS targets the old names,
   update them.

**Fixed**

 * PDF receipt downloads only worked for administrators. The permission check read
   a GiveWP meta key that GiveWP 4.x no longer writes, so every donor was refused,
   and the download link was missing the email argument the check authorises a guest
   donor against.
 * The Accounts screen no longer fails with a fatal error when stored credentials
   cannot be decrypted — for example after `AUTH_KEY` or `SECURE_AUTH_SALT` is changed.
   It now explains what happened and what to do.
 * The bypassed-routing notice names the form that failed most recently rather than
   the first one recorded.
 * A healthy readiness panel no longer turns red when expanded.
 * PayPal environment names are now translatable.

#### 1.1.0 — 2026-07-06

**Added**

 * Per-account live/sandbox environment — manage the same PayPal merchant independently
   in live and sandbox; routing only applies an account whose mode matches the site’s
   current GiveWP mode.
 * Import GiveWP’s already-connected PayPal account in one click (reuses stored 
   credentials, no second OAuth).
 * Re-sync an imported account’s credentials from GiveWP (same-merchant, same-mode
   guarded).
 * Re-activate a deactivated account directly from the Accounts list.
 * Delete a PayPal account from the Accounts list (confirmation required; deregisters
   the account’s PayPal webhook first).
 * GiveWP version compatibility guard — refuses below GiveWP 3.0 and warns on untested
   GiveWP majors (`ador_block_on_untested_givewp` filter to fail closed).

**Changed**

 * Accounts list gains a Mode column (live/sandbox badge).
 * The Import button is always shown on the Accounts list for discoverability — 
   disabled with an inline reason when there is nothing to import (GiveWP not connected,
   or the account is already imported).
 * Flat, minimal admin restyle built on the WordPress core colour palette — status/
   mode badges, buttons, modals, notices, and the receipt templates. Primary calls
   to action now use WordPress’s native primary-button style.
 * Schema 1.1.0: adds the `mode` column and a composite `UNIQUE(merchant_id, mode)`
   constraint.
 * Schema now migrates on plugin update, not only on activation.

**Fixed**

 * List-table bulk actions now reach their handlers. The bulk **Apply** collided
   with `WP_List_Table`‘s own action field and dispatched to no handler, dying with
   an empty error page; the routing field is now printed after the table so it wins.
 * Refunds to routed accounts no longer fail silently — the PayPal access token 
   is re-minted at refund time instead of reusing the stale connect-time token, 
   and a refund whose account mode does not match the site mode is blocked with 
   an actionable admin error.
 * Inbound webhooks for a genuinely unknown account return 404, while a real processing
   error now logs and returns 500 instead of being masked as not-found.
 * Cached PayPal access tokens are encrypted at rest and re-minted on decrypt failure.
 * Credential routing no longer fatals against GiveWP’s PayPal Commerce contract(
   overrider parameter-type compatibility).
 * Per-account credentials no longer leak to `wp_options` when GiveWP refreshes 
   an access token.
 * Inbound PayPal webhooks read the WP-canonicalised transmission headers, fixing
   signature verification and dropped events.

**Removed**

 * The unused `ador_paypal_mode` option.

#### 1.0.0 — 2026-05-07

**Added**

 * Multi-account admin panel (Donation Forms  PayPal Accounts) with Accounts, Country
   Routing, and Settings tabs.
 * Account add/edit form with AES-256-GCM encrypted credential storage.
 * Country routing rules with add/edit/bulk-deactivate actions.
 * Custom database tables `{prefix}ador_accounts` and `{prefix}ador_country_routing`
   with schema versioning.
 * `PayPal_Credential_Router` intercepting GiveWP’s IoC container before every PayPal
   AJAX payment request to substitute per-account credentials.
 * IoC container rebinding for both `MerchantDetail::class` and `MerchantDetails::
   class` covering all GiveWP PayPal credential resolution paths.
 * Refund routing with inactive-account guard.
 * Per-account REST webhook endpoint `POST /wp-json/ador/v1/webhook/{account_id}`
   with HMAC-SHA256 signature verification and idempotency checking.
 * Country selector popup shortcode `[ador_country_selector]` with sessionStorage
   persistence.
 * Geolocation hint (non-binding IP-based country pre-selection).
 * Seven GiveWP email template tags for per-entity receipt details.
 * Per-entity sequential receipt numbers allocated atomically via `FOR UPDATE` lock.
 * Default tax-deductibility statement templates for US and Canada.
 * PDF receipt generation via dompdf behind `ador_pdf_receipts_enabled` option flag.
 * Action hooks `ador_credentials_routed` and `ador_webhook_processed`.
 * PHPStan level 8, WPCS 3.x, PHPUnit 9.6 with Brain\Monkey test suite.

**Security**

 * AES-256-GCM encryption for all stored PayPal credentials with HKDF-SHA256 key
   derivation.
 * PayPal HMAC-SHA256 webhook signature verification on all inbound webhook events.
 * WordPress nonce protection on all admin form submissions and AJAX endpoints.
 * `current_user_can( 'manage_give_settings' )` capability checks on all admin-only
   actions.
 * `$wpdb->prepare()` for all parameterised database queries.

## Мета

 *  Версия **1.2.0**
 *  Обновление: **2 месяца назад**
 *  Активных установок: **Менее 10**
 *  Версия WordPress ** 6.4 или выше **
 *  Совместим вплоть до: **7.0.6**
 *  Версия PHP ** 8.1 или выше **
 *  Язык
 * [English (US)](https://wordpress.org/plugins/alamin-donation-router/)
 * Метки:
 * [charity](https://ru.wordpress.org/plugins/tags/charity/)[donations](https://ru.wordpress.org/plugins/tags/donations/)
   [givewp](https://ru.wordpress.org/plugins/tags/givewp/)[paypal](https://ru.wordpress.org/plugins/tags/paypal/)
 *  [Дополнительно](https://ru.wordpress.org/plugins/alamin-donation-router/advanced/)

## Оценки

Пока что нет ни одного отзыва.

[Ваш отзыв](https://wordpress.org/support/plugin/alamin-donation-router/reviews/#new-post)

[Посмотреть всеотзывы](https://wordpress.org/support/plugin/alamin-donation-router/reviews/)

## Участники

 *   [ Al Amin Ahamed ](https://profiles.wordpress.org/mralaminahamed/)

## Поддержка

Есть что сказать? Нужна помощь?

 [Перейти в форум поддержки](https://wordpress.org/support/plugin/alamin-donation-router/)

## Пожертвование

Хотите поддержать улучшение этого плагина?

 [ Пожертвовать на развитие плагина ](https://alaminahamed.com/donate)