EffortLess Easy Online Payment

Description

EffortLess Easy Online Payment lets you sell physical goods, digital goods, or services directly from WordPress, without WooCommerce. Add a product, place its shortcode on any page or post, and it renders a self contained checkout form.

Checkout supports four gateways: PayPal, Stripe, LINE Pay and ECPay. A site can enable more than one at once, and the customer picks which one to pay with. See the Frequently Asked Questions section below for full setup details on every gateway and setting.

For physical products, an allowlist of delivery countries, each with its own fee, determines shipping cost and can collect a delivery address at checkout.

ELEOP is Multisite aware: products, orders and settings stay isolated per site, and a Super Admin can optionally share payment gateway credentials from Network Admin.

External services

This plugin connects to the following third-party services to process payments. No card details ever pass through your WordPress server — they are entered directly into the payment provider’s own hosted fields.

PayPal (used when PayPal is enabled)
What it is: PayPal’s Checkout Orders API and JavaScript SDK, used to create and capture payments.
What is sent, and when: product name/SKU, price, quantity, currency, and — for physical products with shipping enabled — the delivery address entered at checkout. Sent on every checkout attempt while PayPal is enabled, to api-m.paypal.com (Live) or api-m.sandbox.paypal.com (Sandbox); the checkout button/fields are loaded from www.paypal.com/sdk/js.
PayPal’s Terms of Service: https://www.paypal.com/webapps/mpp/ua/useragreement-full
PayPal’s Privacy Policy: https://www.paypal.com/webapps/mpp/ua/privacy-full

Stripe (used when Stripe is enabled)
What it is: Stripe’s Payment Intents API and Stripe.js, used to process embedded card payments and, when wallet buttons are enabled, Apple Pay/Google Pay via Stripe’s Express Checkout Element. If a webhook signing secret is configured, Stripe also calls this site’s own server (inbound, not outbound) to confirm a payment’s final status.
What is sent, and when: the order total and currency, plus the product ID and SKU as reference metadata. Sent on every checkout attempt while Stripe is enabled, to api.stripe.com; the card entry fields are loaded from js.stripe.com. If the optional webhook is configured, Stripe separately sends this site the PaymentIntent id, status, amount and currency whenever a payment succeeds or fails.
Stripe’s Terms of Service: https://stripe.com/legal/ssa
Stripe’s Privacy Policy: https://stripe.com/privacy

Apple Pay via PayPal (used when wallet buttons are enabled and PayPal is enabled)
What it is: Apple’s Apple Pay JS SDK, used to render the Apple Pay button and payment sheet.
What is sent, and when: loaded from applepay.cdn-apple.com whenever wallet buttons are enabled and eligible; payment authorization is handled by Apple and PayPal, not by this plugin directly.
Apple’s Privacy Policy: https://www.apple.com/legal/privacy/

LINE Pay (used when LINE Pay is enabled)
What it is: LINE Pay’s Online API v4, a redirect based checkout — the customer’s browser is sent to LINE Pay’s own site to authorize payment, then returned to yours.
What is sent, and when: the order total, currency, product name, quantity and unit price. Sent on every checkout attempt while LINE Pay is enabled, to api-pay.line.me (Live) or sandbox-api-pay.line.me (Sandbox).
LINE Pay’s Merchant Terms of Use: https://terms2.line.me/paymerchant_TOS_TH?lang=en
LINE’s Privacy Policy: https://line.me/en/terms/policy/

ECPay (used when ECPay is enabled)
What it is: ECPay’s AllInOne Checkout — the customer’s browser submits a signed form directly to ECPay’s own site to authorize payment; ECPay then confirms the result to your site server-to-server.
What is sent, and when: the order total (TWD), product name, and quantity, signed with your ECPay Hash Key/IV. Sent on every checkout attempt while ECPay is enabled, to payment.ecpay.com.tw (Live) or payment-stage.ecpay.com.tw (Sandbox).
ECPay’s Terms of Service: https://support.ecpay.com.tw/10075/
ECPay’s Privacy Policy: https://support.ecpay.com.tw/terms-privacy/

Installation

  1. Upload the plugin ZIP in WordPress: Plugins > Add New > Upload Plugin.
  2. Activate it normally, or Network Activate it from Network Admin.
  3. On a normal site, open EffortLess Easy Online Payment > Settings.
  4. For a shared multisite merchant, a Super Admin can first open Network Admin > Settings > EffortLess Easy Online Payment.
  5. Under Enabled Gateways, check one or more of PayPal, Stripe, LINE Pay and ECPay — the customer will see a button for each one you enable and configure. Active Gateway is now only used as the default when Enabled Gateways is saved empty, and to drive the Sandbox/Live mode notice on this screen.
  6. Keep each enabled gateway’s Mode set to Sandbox / Test while testing.
  7. For PayPal: enter the Sandbox Client ID and Sandbox Secret under PayPal API. For Stripe: enter the Test Publishable Key and Test Secret Key under Stripe API. For LINE Pay: enter the Channel ID and Channel Secret under LINE Pay API. For ECPay: enter the Merchant ID, Hash Key and Hash IV under ECPay API (ECPay issues separate test credentials for its Stage sandbox). Only enter credentials for the gateways you enabled.
  8. Open EffortLess Easy Online Payment > Products > Add Product.
  9. Set title, type, currency, price and maximum quantity. For a physical product, delivery countries and fees are configured once for the whole site under Settings > Shipping, not per product.
  10. Publish.
  11. Copy the shortcode shown in the Products list, for example:
    [eleop_checkout id=”123″]
  12. Paste it into a page.

FAQ

How does Multisite work?

ELEOP can be activated on an individual site or Network Activated.

Each site always keeps its own: Products, Orders, Shop / brand name, Notification email, Success message, and optional local PayPal credentials.

A Super Admin can optionally configure shared payment defaults at Network Admin > Settings > EffortLess Easy Online Payment. The Network Admin can set: Sandbox / Live mode, Sandbox Client ID and Secret, Live Client ID and Secret, Apple Pay enabled/disabled, and Apple domain-association content.

Each subsite can then choose “Inherit PayPal / Apple Pay settings from Network Admin”. When inheritance is enabled, only the payment-provider configuration is inherited. Products and orders never become network-global.

For subdomain multisite installations, each exact storefront domain/subdomain still needs to be registered with PayPal for Apple Pay eligibility. ELEOP serves the effective association content from each site’s own /.well-known/apple-developer-merchantid-domain-association.

What does each setting do? (Settings > Multisite, Enabled Gateways, Active Gateway, Checkout, Product editor, Apple Pay, Shipping, Network Admin)

Multisite (shown only when the site is part of a Multisite network)
* Inherit PayPal / Apple Pay settings from Network Admin — when checked and a Super Admin has enabled shared network defaults, this site’s PayPal Mode, Client ID/Secret, Apple Pay toggle and domain-association content are taken from Network Admin instead of the fields below. Products, orders, brand name, notification email and checkout text always stay local to this site regardless of this setting.

Enabled Gateways
* Enabled Gateways — checkboxes for PayPal, Stripe, LINE Pay and ECPay. Checkout shows a button for every enabled gateway that also has its credentials configured and supports the product’s currency (LINE Pay: USD, TWD or THB only; ECPay: TWD only; PayPal and Stripe: any supported currency). Buttons are shown in a fixed order: PayPal, Stripe, LINE Pay, ECPay.

Active Gateway
* Payment Gateway — PayPal, Stripe, LINE Pay or ECPay. No longer the only gateway offered at checkout, and no longer what decides checkout’s fallback gateway or which gateway shows the wallet-buttons option — those now follow a fixed priority order. Active Gateway still has two narrower roles: it is the default Enabled Gateways is set to if that field is ever saved empty, and it drives the Sandbox/Live mode notice shown at the top of this settings screen.

Checkout
* Brand / shop name — shown in the PayPal checkout flow and in Apple Pay’s payment sheet.
* Wallet buttons — enables Apple Pay through PayPal when the merchant account, browser, device and verified domain are eligible; Apple Pay and Google Pay through Stripe (via the Express Checkout Element) when this site’s domain has been registered in the Stripe Dashboard’s Payment method domains page; or Apple Pay through ECPay (no separate domain registration needed). PayPal, Stripe and ECPay can each show a wallet button; LINE Pay has no wallet integration. When more than one wallet-capable gateway is enabled and eligible for the product’s currency, only one gateway’s wallet button is shown at checkout, chosen by a fixed priority order: PayPal, then Stripe, then ECPay.
* New order email — where the “payment received” notification is sent.
* Success message — shown to the customer after a completed payment.

Product editor
* SKU / Reference — an optional product code or reference identifier; defaults to “ELEOP-{product-id}”. Text field, no length limit.
* Product type — Physical goods, Digital goods, or Service; defaults to Physical goods. Determines whether shipping validation and fees apply at checkout.
* Currency — TWD, USD, EUR, GBP, JPY, AUD, CAD, HKD, or SGD; defaults to USD. Only one currency per page is supported.
* Unit price — the customer facing price per unit, required; decimal format (e.g., 39.00).
* Maximum quantity — how many units the customer may order in a single checkout, constrained 1 to 100; defaults to 10.
* Checkout heading — the label shown above the quantity selector on the checkout form; defaults to “Buy now”. Text field.

Apple Pay domain verification
* Association file — paste the exact contents of the domain-association file from the PayPal Developer Dashboard. ELEOP serves it automatically at /.well-known/apple-developer-merchantid-domain-association, resolved relative to your site’s home address; on a subdirectory install, the file is available under that subdirectory path.

Shipping
* Shipping — enables shipping and delivery-country validation for physical products. Off = physical products behave like digital/service products (no shipping fields, no fee).
* Delivery address — collects a full name/phone/postcode/city/district/address at checkout. Off = only the delivery country is collected (no address fields).
* Delivery countries and fees — one country per line: CODE:FEE (e.g. TW:60.00), using ISO 3166-1 two-letter country codes. Add :0 to a line to keep a country listed but temporarily disabled (e.g. FR:15.00:0). Defaults to TW:60.00 only.

Network Admin (Super Admin only, Multisite): Network Admin > Settings > EffortLess Easy Online Payment
* Allow subsites to inherit these network settings — master toggle; if off, the “Inherit” checkbox on subsites has no effect even when checked.
* Mode, Sandbox/Live Client ID and Secret — the shared PayPal credentials subsites can inherit.
* Apple Pay, Apple domain-association content — the shared Apple Pay configuration subsites can inherit.

How do I configure each gateway’s API credentials?

PayPal API
* Mode — Sandbox / Test or Live. Sandbox simulates payments; Live charges real money.
* Sandbox Client ID / Sandbox Secret — from the PayPal Developer Dashboard, Sandbox app.
* Live Client ID / Live Secret — from the PayPal Developer Dashboard, Live app. Only required if PayPal is enabled and Mode is Live.

Stripe API
* Mode — Test or Live.
* Test Publishable Key / Test Secret Key — from the Stripe Dashboard, Test mode.
* Live Publishable Key / Live Secret Key — from the Stripe Dashboard, Live mode. Only required if Stripe is enabled and Mode is Live.
* Test Webhook Signing Secret / Live Webhook Signing Secret — optional, one per Mode. Each comes from its own webhook endpoint you create in the Stripe Dashboard (Test mode and Live mode each have a separate endpoint and secret) pointed at the URL shown on this settings screen, listening for payment_intent.succeeded and payment_intent.payment_failed. Closes the gap where a payment succeeds but the buyer’s browser never returns to confirm it. Only the field matching the currently selected Mode is used — Stripe requires the live endpoint to use HTTPS.

LINE Pay API
* Mode — Sandbox / Test or Live.
* Channel ID / Channel Secret — from the LINE Pay Merchant Center, matching the selected Mode. Only required if LINE Pay is enabled.
* LINE Pay only supports checkout in USD, TWD or THB. A checkout attempt in any other product currency is rejected before contacting LINE Pay.

ECPay API
* Mode — Sandbox / Test or Live.
* Merchant ID, Hash Key, Hash IV — from the ECPay Merchant Backend, matching the selected Mode. Only required if ECPay is enabled.
* ECPay only supports checkout in TWD, as whole number amounts. A checkout attempt in any other product currency, or with a fractional total, is rejected before contacting ECPay.

How do I test Apple Pay in the PayPal sandbox?

PayPal requires Apple Pay to be enabled for the sandbox app and requires each checkout domain to be registered.

  1. In PayPal Developer Dashboard, use Sandbox mode.
  2. Enable Apple Pay for the app/account.
  3. Download PayPal’s sandbox Apple domain-association file.
  4. Paste that file into the ELEOP site settings, or into Network Settings if sites inherit it.
  5. Verify that https://YOUR-DOMAIN/.well-known/apple-developer-merchantid-domain-association returns the file.
  6. Register the exact domain/subdomain in PayPal.
  7. Use an Apple sandbox tester and test card on an Apple Pay capable device/browser.

Sandbox transactions are simulated and do not touch live PayPal accounts.

What should I check before switching to Live mode?

Do not switch ELEOP to Live until you have: created Live PayPal API credentials, completed any PayPal onboarding required for Apple Pay, verified every production storefront domain that will offer Apple Pay through PayPal, registered every production storefront domain in the Stripe Dashboard if wallet buttons are enabled and Stripe is enabled, and performed your own end to end checks.

What security measures does this plugin implement?

  • PayPal Client Secret stays on the server and is never sent to the browser.
  • In Multisite, shared secrets are stored with update_site_option() and are not rendered in subsite settings screens.
  • Product price, currency, shipping, and quantity limits are read from WordPress on the server.
  • The browser sends only product identity and requested quantity.
  • Captured amount/currency are checked against the locally stored expected amount.
  • Checkout endpoints are rate limited per IP.
  • Product requests use a server generated HMAC token.
  • Products and orders use WordPress per-site tables, so they remain isolated naturally in Multisite.

What are the known limitations?

  • More than one gateway can be enabled at once — PayPal, Stripe, LINE Pay and ECPay can all be offered together on the same checkout, and the customer picks which one to pay with. A gateway only shows a button when it is enabled, has its credentials configured, and supports the product’s currency (for example, ECPay only ever shows for TWD products, and LINE Pay only for USD, TWD or THB products).
  • When wallet buttons are enabled and more than one wallet-capable gateway (PayPal, Stripe, ECPay) is enabled and eligible, only one gateway’s wallet button is shown, in priority order PayPal, then Stripe, then ECPay. LINE Pay never shows a wallet button.
  • Stripe, LINE Pay and ECPay checkout’s charged total includes the shipping fee for physical products, but none of these gateways yet collects or receives a delivery address (that address is still validated and stored locally by ELEOP) — a future update will add this. PayPal checkout does pass the validated address through to PayPal.
  • A LINE Pay order only completes when the customer’s browser returns to your site after authorizing on LINE Pay. If the customer closes the tab before returning, the order stays pending indefinitely on your site (LINE Pay itself eventually expires the unfinished authorization) — there is currently no automatic reconciliation for this case.
  • ECPay’s payment confirmation reaches your site via its own server-to-server notification (which ECPay itself retries for about a day if your site is unreachable), not via the customer’s browser returning — so a completed ECPay payment is always recorded even if the customer closes the tab immediately after paying. The page the customer’s browser lands on after paying only ever displays the order’s status at that moment; if it still shows “processing”, refreshing the page later will show the final result once ECPay’s notification has arrived.
  • ECPay checkout currently offers credit/debit card and, when wallet buttons are enabled and the browser is eligible, Apple Pay (ATM, convenience-store and barcode payment are not offered).
  • Shipping defaults to Taiwan only (TW:60.00) until an administrator edits the delivery countries and fees list in Settings > Shipping.
  • Multisite network-level inheritance covers only PayPal credentials, and Apple Pay/wallet-button settings when PayPal is the site’s active gateway — Stripe credentials, wallet-button settings on any non-PayPal site, and shipping rules are always configured per site, never inherited from Network Admin. The Stripe webhook (when configured) is also per-site: each site with Stripe enabled needs its own webhook endpoint registered in the Stripe Dashboard.
  • The Stripe webhook is optional — Stripe checkout works through its existing client-side confirmation flow without it. Configuring it adds a second, server-to-server confirmation path that only matters for the case where a payment succeeds but the buyer’s browser never returns to confirm it.
  • The Test and Live Webhook Signing Secret fields are independent and must each be filled in from that mode’s own Stripe Dashboard endpoint. Only the secret matching the currently selected Mode is used.
  • Digital and service products never show shipping fields or a shipping fee, regardless of the Shipping settings.
  • A page should not contain ELEOP checkouts using different currencies at the same time, because the PayPal JavaScript SDK is initialized for a currency at page load. Use one currency per checkout page.
  • Apple Pay and Google Pay through Stripe require registering this site’s domain in the Stripe Dashboard’s Payment method domains page (Test mode and Live mode are registered separately) before the wallet buttons will appear. Until the domain is registered, Stripe checkout continues to work normally via the card fields.
  • Apple Pay through ECPay needs no separate domain registration — ECPay’s checkout is entirely hosted on ECPay’s own domain. The Apple Pay button through ECPay only appears in Safari on an Apple Pay capable device. Apple Pay may need to be separately enabled on your ECPay merchant account before it will work.

I configured a gateway but checkout doesn’t work

Check the following, in order:

  1. The gateway you’re testing is checked under Settings > Enabled Gateways, has its Mode set correctly, and has the matching credentials filled in.
  2. The gateway supports the product’s currency — LINE Pay only shows for USD, TWD or THB products, and ECPay only for TWD products.
  3. The product is Published, not a draft.
  4. For a physical product: Settings > Shipping has Shipping enabled, and the destination country being tested has an enabled rule in the Delivery countries and fees list (the default only allows TW).
  5. Only one currency per page: a page must not mix ELEOP checkouts for different currencies, since the checkout script is initialized once per page.

I set up the Stripe webhook but orders still aren’t completing

Check the following:

  1. The webhook secret field matching the currently selected Mode is filled in.
  2. The endpoint URL shown on the Settings screen is publicly reachable from the internet.
  3. For a Live-mode endpoint, the URL must use HTTPS.
  4. Only payment_intent.succeeded and payment_intent.payment_failed events are acted on, and only for an order whose gateway is Stripe.
  5. With WP_DEBUG enabled, a failed or ignored webhook call writes a diagnostic line to the PHP error log naming the reason.

Reviews

There are no reviews for this plugin.

Contributors & Developers

“EffortLess Easy Online Payment” is open source software. The following people have contributed to this plugin.

Contributors

Changelog

1.1.7

  • Fixed three dead third-party links in the External services section, found by the WordPress.org review team: ECPay’s Terms of Service and Privacy Policy URLs (both 404) now point at ECPay’s current support-site pages, and LINE Pay’s Terms of Use URL (400 error) now points at LINE Pay’s current Merchant Terms of Use. Every External services URL was re-checked with a live HTTP request before release.

1.1.6

  • Restructured this readme so the plugin’s real documentation (previously under custom headings like Features, Multisite, Settings, Apple Pay sandbox, Going live, Security notes and Notes and limitations) now lives under Installation and Frequently Asked Questions, the only two headings besides Description that WordPress.org’s readme parser keeps separate. Every custom heading’s content is merged by that parser into the Description section before its length is checked, which is why a persistent “Description section too long” scan warning survived several rounds of shortening the literal Description paragraph — the paragraph itself was never the source of the excess length. No documentation content was removed, only relocated; External services keeps its own required heading, so its content still contributes to that combined length, but is small enough on its own to stay within limit.

1.1.5

  • Shortened the Description section further and removed apostrophes, em dashes and an arrow character from it. Superseded by the 1.1.6 restructuring above, which addresses the actual cause.

1.1.4

  • Fixed two spots in this readme where a section-heading-style double-equals reference appeared inside a sentence rather than as an actual heading — a readme parser that isn’t strictly line-anchored can mistake that for a section boundary and mis-scan surrounding content. Reworded both to plain text references instead.

1.1.3

  • Fixed the order lookup used by every capture path (checkout capture, LINE Pay return, ECPay notify, Stripe webhook) to no longer bypass other plugins’ post-query filters (e.g. a translation plugin’s language scoping) — it previously set suppress_filters to true.
  • Shortened the Description section in this readme; no functional change (the removed detail is fully covered under the Settings section below).

1.1.2

  • Updated “Tested up to” to WordPress 7.1.

1.1.1

  • Fixed a backward-compatibility bug: a site that had a single payment gateway configured before this release (e.g. Stripe only, no PayPal) lost checkout entirely after upgrading, because the new Enabled Gateways setting defaulted to PayPal instead of the site’s actual configured gateway. Enabled Gateways now correctly falls back to the site’s Active Gateway whenever no Enabled Gateways value has been saved.
  • On a checkout page offering more than one gateway, a Stripe SDK load failure no longer shows a shared red error message across the whole checkout form — the other gateways’ buttons keep working, and the failure is only logged to the browser console. A checkout misconfigured with no gateways at all now shows a clear “temporarily unavailable” message instead of rendering blank.
  • The Stripe card fields container no longer renders visibly before Stripe actually loads, avoiding an orphaned “or pay with card” divider on checkouts where Stripe isn’t an eligible gateway.
  • Removed an unused data attribute on the checkout markup left over from an earlier Apple Pay implementation.
  • Hardened the checkout order REST endpoint against a malformed array-valued gateway parameter.

1.1.0

  • Added multi-gateway checkout choice: a site can now enable more than one payment gateway at once (new “Enabled Gateways” checkboxes in Settings, alongside the existing Active Gateway select). Checkout shows a button for every enabled gateway that is configured and supports the product’s currency, in a fixed order (PayPal, Stripe, LINE Pay, ECPay), and the customer chooses which one to pay with. A gateway that doesn’t support the product’s currency never shows a button even when enabled (LINE Pay: USD, TWD or THB only; ECPay: TWD only).
  • The Active Gateway setting’s role is now narrower: it is the default Enabled Gateways falls back to when saved empty, and it drives the settings screen’s Sandbox/Live mode notice — checkout’s own fallback gateway and its wallet-button gateway are now decided by a fixed priority order instead, and Active Gateway is no longer the only gateway offered at checkout.
  • When wallet buttons (Apple Pay) are enabled and more than one wallet-capable gateway (PayPal, Stripe, ECPay) is enabled and eligible, only one gateway’s wallet button is shown, chosen by a fixed priority order: PayPal, then Stripe, then ECPay — never more than one wallet button at once. LINE Pay has no wallet integration.

1.0.0

  • First stable release. Verified a complete live PayPal Sandbox transaction end to end using this exact release build: order creation against PayPal’s real Orders v2 API, buyer approval through PayPal’s own sandbox checkout page, and capture against PayPal’s real Capture API, independently cross-checked directly against PayPal afterward. No code changes; this release marks the plugin’s first version confirmed to complete an actual gateway transaction rather than being verified by code review and automated tests alone.

0.2.25

  • Full code and security review of the whole plugin. Documented a gap in the uninstall instructions: on a Multisite network, the shared Network Admin payment settings (including PayPal live/sandbox credentials a Super Admin may have configured) weren’t mentioned in the manual-removal steps, so they could be left behind indefinitely after uninstalling. No code behavior changed; the dedicated security review found no exploitable issue.

0.2.24

  • Restricted the Products and Orders admin screens to administrators only: both custom post types previously used plain WordPress post capabilities, which meant an Editor-role user could view every order (customer name, email, phone, delivery address, gateway IDs) and delete payment records, and an Author-role user could create or edit products with an arbitrary price. Both now require the manage_options capability, matching every other admin action this plugin already gates the same way.
  • Fixed the Apple Pay domain-verification file handler to compare against the same site-URL-derived path the settings page tells you to check, instead of a hardcoded domain-root path — on a WordPress install in a subdirectory, the handler previously never matched the URL the plugin itself advertised.
  • Fixed a gap where a Super Admin’s blank Network Admin domain-verification field could silently clear a subsite’s own value on save; it’s now only inherited when the network field actually has content, matching how the existing Apple Pay toggle inheritance already works.
  • Added a distinct admin email when a captured payment’s amount doesn’t match the expected order total, so this integrity check is no longer silent — previously the order was flagged internally but nobody was notified.
  • Fixed a race window where a concurrent or retried capture request on an order already flagged for a mismatched amount could receive a false “payment succeeded” response instead of the correct error; the order’s own status was never affected, only what a second, near-simultaneous request was told.
  • Added a lightweight lock around payment capture to reduce the chance of a duplicate admin notification when two capture attempts for the same order land at nearly the same moment (e.g. the buyer’s browser and a gateway webhook arriving together).
  • Fixed several smaller inconsistencies found reviewing the whole plugin together: a stale settings description that said “both gateways” when there are four; a missing context field in the gateway interface’s own documentation; a duplicated order-lookup method between two files, now shared; an unused capture-time field written by only one of the four gateways, now removed since nothing displayed it; and a checkout return URL now validated against the site’s own domain before being handed to a payment gateway as a redirect target.
  • Translated the remaining hardcoded English text in the admin settings, network settings, and order/product detail screens so the plugin’s declared text domain actually covers the full admin interface.
  • readme.txt: documented every Product editor field (previously only partially covered), added ECPay to a shipping-address limitation note that only mentioned two of the three affected gateways, and noted that the Apple Pay domain-verification URL resolves under a subdirectory install’s own path.

0.2.23

  • Fixed a stale Settings description that still listed only PayPal, Stripe and LINE Pay as Active Gateway options; it now also mentions ECPay.

0.2.22

  • Added a PHPUnit test suite for development use. This is dev-only tooling: it is not shipped in the release package and has no effect on the plugin’s behavior when installed on a site. It covers the ECPay CheckMacValue signature algorithm, Stripe webhook signature verification, capture idempotency (a completed order’s capture_order() is never invoked twice), capture amount- and currency-mismatch handling, the reserved order-meta keys that a capture result cannot overwrite, and a regression test for the multisite Apple Pay settings-inheritance behavior fixed in an earlier release. No plugin logic was changed for this work — the only edits outside tests/ are the version bump itself.

0.2.21

  • Code-standards cleanup: the three original REST routes (order creation, capture, and the LINE Pay return handler) now use named, individually-justified permission callbacks instead of the bare PHP function __return_true, matching the pattern already used by the ECPay and Stripe routes. No behavior change — these routes were already, and remain, intentionally public.
  • Fixed the two remaining PHPCS findings: a read-only admin-notice flag that didn’t need nonce verification, and two custom-table-free order lookups by gateway ID that have no faster built-in WordPress alternative. Both are now individually documented rather than left as open warnings.
  • Verified this release end-to-end against a real WordPress 7.0 core install (not just the working tree): installed from a built zip, activated with no errors, and rendered every admin screen plus a live checkout page with no PHP warnings, notices, or fatal errors.

0.2.20

  • The wallet-buttons (“Apple Pay”) setting is now enforced server-side for ECPay checkout too, not just hidden client-side — a request that asks for Apple Pay falls back to the standard credit/debit card flow when the setting is disabled, matching how the other gateways already handle this. No change when the setting is enabled.
  • Reworded a stale readme.txt sentence that described ECPay checkout as credit/debit-card-only; it now also mentions the Apple Pay option added in 0.2.19.
  • readme.txt: noted that Apple Pay through ECPay may need to be separately enabled on the merchant’s ECPay account, and broadened the multisite note about per-site wallet-button settings to cover ECPay as well as Stripe.

0.2.19

  • Added Apple Pay as a second ECPay payment option, alongside the existing credit/debit card checkout — same AllInOne Checkout form-POST flow and capture logic, just a different ChoosePayment value, since Apple Pay’s payment confirmation behaves identically to card’s (unlike ATM/CVS/barcode, which remain out of scope). Reuses the existing wallet-buttons setting, now covering all three gateways that offer one (PayPal, Stripe, ECPay). No separate domain registration is needed for ECPay’s Apple Pay, unlike PayPal or Stripe. The wallet-buttons setting defaults to enabled, so existing ECPay sites will start showing the Apple Pay button to eligible Safari visitors automatically; the setting is also now enforced server-side, so a checkout still falls back to the standard credit/debit card flow when the setting is disabled, even if the request asks for Apple Pay.

0.2.18

  • Fixed the Express Checkout Element’s wallet container staying permanently hidden after a shipping-country or amount change re-evaluated available payment methods; the “available” branch now also clears the inline display: none set by the earlier “unavailable” branch, not just visibility.

0.2.17

  • Fixed Stripe wallet buttons being mounted into a hidden-attribute container, which deviated from Stripe’s documented pattern and risked the Express Checkout Element failing to size itself; buttons are now shown/hidden with style.visibility, matching Stripe’s own example.
  • Fixed the Express Checkout Element’s confirm handler not signaling failures back to the wallet’s payment sheet, which could leave it stuck open after a declined or errored payment.
  • Fixed a multisite issue where the Network Admin’s PayPal-only Apple Pay override could silently control the wallet-buttons setting on a subsite whose active gateway is Stripe; the override now only applies when the subsite’s active gateway is PayPal.

0.2.16

  • Added Apple Pay and Google Pay to Stripe checkout, via Stripe’s Express Checkout Element sharing the same Elements instance as the existing card fields. Reuses the existing wallet-buttons setting (previously labeled “Apple Pay”, now gateway-agnostic) rather than adding a separate processor selector, since only one gateway is active per site at a time. Requires registering this site’s domain in the Stripe Dashboard before the wallet buttons appear; card checkout is unaffected either way.
  • This setting defaults to enabled, so existing Stripe sites will start showing wallet buttons automatically (once, and only once, their domain is registered in the Stripe Dashboard) — no other action is needed.

0.2.15

  • Split the Stripe webhook signing secret into separate Test and Live fields, matching every other Stripe credential’s per-Mode pattern — a single shared secret previously kept working with a stale value after switching Mode, silently failing signature verification.
  • Added WP_DEBUG-guarded diagnostic logging to the Stripe webhook’s order-not-found and wrong-gateway branches, so a failed or ignored webhook call can be diagnosed from the PHP error log.
  • Added a Frequently Asked Questions entry covering the Stripe webhook’s real preconditions.

0.2.14

  • Added an optional Stripe webhook endpoint (payment_intent.succeeded / payment_intent.payment_failed) so a payment is captured even if the buyer’s browser never completes the client-side confirmation round trip. Verifies Stripe’s own HMAC-SHA256 request signature before trusting anything in the payload, and reuses the exact same amount-verification and idempotency logic the client-driven capture path already uses.

0.2.13

  • Fixed ECPay’s notify endpoint being unreachable on any subdirectory WordPress install: the inbound request path is now compared against the same home_url()-derived path used to build ECPay’s ReturnURL, instead of a bare constant that never matched once a site had a subdirectory in its address.
  • Fixed the ECPay notify handler being able to finalize an order that belongs to a different, unrelated gateway (which has no CheckMacValue-style signature check of its own) — it now requires the resolved gateway to actually be ECPay before processing.
  • Fixed ECPay’s notify handler sanitizing POSTed values before verifying ECPay’s CheckMacValue signature, which could reject a genuine notification whose fields happened to contain characters sanitize_text_field() strips or alters.
  • ECPay notify failures caused by an invalid signature or a not-yet-configured gateway now withhold the “1|OK” acknowledgement so ECPay’s own retry mechanism can recover once the issue is fixed; every other outcome (order not found, unrelated gateway, amount mismatch, already-completed, success) still acks normally.
  • Added WP_DEBUG-guarded error logging to every ECPay notify failure path, matching the existing PayPal/Stripe/LINE Pay logging pattern.
  • Fixed the checkout page’s “processing” status for ECPay never re-checking the order’s current status on a later page load — it previously stayed on “processing” forever even after the order had since completed or failed.
  • ECPay checkout is now restricted to credit/debit card (ChoosePayment=Credit); ECPay’s ATM, convenience-store and barcode payment methods are not yet supported and are documented as out of scope.

0.2.12

  • Added ECPay as a fourth payment gateway option (ECPay’s AllInOne Checkout — a signed form-POST checkout: the customer’s browser submits a signed form directly to ECPay, authorizes there, and ECPay confirms the result to your site server-to-server). TWD only, whole-number amounts; a checkout attempt in any other currency or with a fractional total is rejected before contacting ECPay.
  • ECPay’s payment confirmation uses its own server-to-server notification (which ECPay itself retries for about a day if unreachable) as the sole authoritative capture path, reusing the same capture/amount-verification logic PayPal, Stripe and LINE Pay already share. The page the customer’s browser returns to after paying is a separate, not-guaranteed-to-fire mechanism that only ever displays the order’s already-current status — it never changes order state itself.

0.2.11

  • Fixed the LINE Pay captured-amount check: it previously echoed back the same order total it sent to LINE Pay’s Confirm API, so the amount-mismatch check compared a value against itself and could never fail. It now sums LINE Pay’s own Confirm response (the per-payment-method amounts LINE Pay reports it captured) for a genuinely independent check, matching how PayPal and Stripe already report a captured amount sourced from their own API response. LINE Pay’s Confirm response has no currency field, so the currency side remains a comparison against the expected value; this is documented as a limitation of LINE Pay’s API.
  • Fixed the “Payment cancelled.” notice on the checkout page, which could never appear because the cancel redirect carries no order identifier.
  • The “payment successful” notice on the checkout page now also requires the order to be a genuine order post with a stored Completed status, not just a guessable order ID for the right product.
  • Added rate limiting to the LINE Pay return endpoint, consistent with the other checkout endpoints.
  • Documented that a LINE Pay order left unfinished when the customer closes the tab before returning to the site stays pending indefinitely, with no automatic reconciliation.

0.2.10

  • Added LINE Pay as a third payment gateway option (LINE Pay Online API v4, a redirect checkout — the customer authorizes on LINE Pay’s own site and is returned to yours once payment is confirmed). Supports USD, TWD and THB only; a checkout attempt in any other currency is rejected before contacting LINE Pay.
  • The capture/amount-verification logic PayPal and Stripe checkout already used is now shared with LINE Pay’s return handler, rather than duplicated, so all three gateways get the same integrity checks.

0.2.9

  • Added the missing readme.txt Description section, fixed the Installation walkthrough (it still referenced the per-product shipping field removed in 0.2.6, and never mentioned choosing a gateway or entering Stripe credentials), and restored a Notes and limitations section covering the single-active-gateway model, Stripe checkout charging the shipping fee without yet sending an address, the Taiwan-only shipping default, multisite inheritance being limited to PayPal, and shipping never applying to digital/service products.
  • Corrected the External services entry for Stripe (it claimed quantity is sent to Stripe; it is not) and expanded the Settings reference to cover the multisite inherit checkbox and the Network Admin screen.
  • Aligned the site-level Apple Pay domain-association field to use the same newline-preserving sanitizer as the network-level field, and removed an unused internal property. No behavior changes.

0.2.8

  • readme.txt: trimmed Tags to 5, added a Donate link, an External services disclosure section (PayPal, Stripe, Apple Pay), a setting-by-setting Settings reference, and a Frequently Asked Questions entry.
  • Added a dismissible “support the development” notice on the plugin’s settings screen, with a donate link in the plugin header.
  • Fixed a number of pre-existing code-standards findings: missing docblocks, unslashed $_POST/$_SERVER reads before sanitization, the Apple Pay domain-verification field now uses a newline-preserving sanitizer, and parse_url() replaced with wp_parse_url(). No behavior changes.

0.2.7

  • Fixed PayPal checkout sending an empty shipping address under SET_PROVIDED_ADDRESS when the “Collect a full delivery address” setting was off; the provided-address path is now only used once an address has actually been entered, otherwise physical products fall back to letting PayPal collect the address (GET_FROM_FILE).
  • Fixed the PayPal shipping address mapping: it previously mapped only the second-level administrative division (admin_area_2) from the city field and never populated the first-level division (admin_area_1), silently dropping the district field some destinations require. admin_area_1 is now mapped from city and admin_area_2 from district.
  • Removed the “Restrict countries” shipping setting: with it off, a submitted country code skipped format validation, and the checkout country selector was always built from the enabled delivery-country list regardless of the setting, so it had no effect either way. Delivery is now always limited to countries with an enabled rule.
  • A shipping-enabled site with zero enabled delivery countries now behaves the same as shipping being off, instead of showing an empty, unusable country selector.
  • Apple Pay no longer requests a separate delivery address/phone number when the checkout’s own shipping form is already collecting one, avoiding two potentially different delivery addresses on the same order.
  • The order-notification email now includes the delivery address when one was collected.

0.2.6

  • Added a country-based shipping system for physical products: an admin-configured allowlist of delivery countries and per-country fees (defaults to Taiwan only), server-side validated at checkout, with an optional full delivery-address collection step. Replaces the previous flat per-product shipping fee, which has been removed from the product editor.
  • PayPal checkout now passes the validated delivery address through as a provided shipping address (SET_PROVIDED_ADDRESS) for physical products, instead of relying on the buyer’s PayPal account address.
  • Stripe checkout’s charged total includes the shipping fee for physical products (via the shared server-side pricing calculation), but Stripe does not yet collect or receive a delivery address — that is planned for a future update.

0.2.5

  • Fixed the Stripe checkout to use Stripe’s deferred-payment-intent pattern: the Payment Element now mounts with a display-only estimate and the real order/PaymentIntent is only created when the buyer clicks Pay, using the quantity selected at that moment. Previously the order and PaymentIntent were created at page load with quantity fixed at 1, so a buyer who changed quantity before paying was charged for the original quantity instead of the displayed total, and an order/PaymentIntent was also created on every page view regardless of purchase intent.
  • Restricted the Stripe PaymentIntent to card payments only, matching this plugin’s card-only checkout scope and avoiding a redirect-based payment method failing with no return-URL handling page.
  • Fixed the capture amount-verification check incorrectly flagging a routine pending/processing Stripe payment for manual review; the check now only runs once a payment has actually completed.
  • Reduced the detail forwarded from Stripe API error responses to the public order-creation endpoint to buyer-actionable card/validation errors only, since Stripe error messages can otherwise include configuration or key-related detail.
  • Fixed the currently-active gateway setting being used to capture every order regardless of which gateway actually created it; capture now uses the gateway recorded on the order itself, so changing the active gateway mid-checkout can no longer route a capture to the wrong API.
  • Filled in missing gateway setting defaults on read so a saved settings option from before Stripe was added, or one missing individual fields, is completed with defaults instead of leaving them unset.
  • Generalized remaining PayPal-only wording in checkout/order messages and the plugin description now that Stripe is a second gateway option.

0.2.4

  • Added Stripe as a second payment gateway option (embedded card checkout via Stripe Elements and PaymentIntents). A new “Active Gateway” setting selects PayPal or Stripe; only one gateway is active per site. No Apple Pay/Google Pay through Stripe and no Stripe webhook in this version.
  • Settings storage restructured: gateway credentials now live under a nested “gateways” structure instead of top-level fields, to support more than one gateway.

0.2.3

  • Fixed the order of the capture amount-verification check so the expected order total/currency are read before any gateway-returned data is written, and reserved the post-meta keys this check owns so gateway data can never overwrite them.
  • Removed a leftover duplicate plugin bootstrap call left over from a prior internal file reorganization.
  • Fixed a rare race condition on first use of the internal checkout security secret.
  • Updated the uninstall instructions comment to mention the checkout security secret option.

0.2.2

  • Internal refactor: extracted all PayPal-specific code behind a new ELEOP_Gateway interface (ELEOP_Gateway_PayPal), so a future payment gateway can be added without changing checkout, settings, or order-management code. No user-visible change — checkout behavior, the admin UI, and stored settings are unaffected.
  • Replaced the wp_salt()-derived checkout security token with a dedicated, randomly generated secret stored in its own option, per this project’s standing rule against deriving plugin secrets from WordPress authentication material.

0.2.1

  • Renamed plugin identity from “EffortLess Paypal Online Payment” (ELPOP_) to “EffortLess Easy Online Payment” (ELEOP_): class, constants, option names, CPT slugs, REST namespace, shortcode tag, and asset identifiers all updated accordingly. No functional changes.

0.2.0

  • Added full WordPress Multisite support.
  • Added Network Admin shared PayPal / Apple Pay settings.
  • Added per-site inheritance control.
  • Kept products, orders and storefront settings isolated per site.
  • Shared network secrets remain hidden from subsite administrators.

0.1.0

  • Initial release.