Linux 软件免费装
Banner图

GSheet Membership

开发者 gsheetplugins
更新时间 2026年10月9日 03:24
PHP版本: 7.4 及以上
WordPress版本: 7.1
版权: GPL-2.0-or-later
版权网址: 版权信息

标签

membership stripe association google sheets branches

下载

4.10.16 4.6.8 4.8.1 4.5.8 4.5.9 4.6.1 4.6.10 4.6.6 4.6.7 4.6.9 4.6.11 4.6.12 4.10.8 4.9.0

详情介绍:

Access — the login and page gate GSheet Membership lets you use a private Google Sheet as your membership database. How it works The plugin authenticates using a Google Service Account — a special non-human Google account your server uses to read and update the sheet. You share the spreadsheet with it; no one else can access the sheet. With OpenSSL available, the saved service-account JSON is encrypted at rest; the roster cache is only written when it can be encrypted. The two use separate keys derived from this WordPress installation's security salts. They are not exposed in the browser or source code. The entire cached roster is decrypted in server memory when it is read; this does not encrypt old backups made before the upgrade. Signing in There's no separate account-creation step for members. A member already on the roster enters their email on your sign-in page: the first time, a 6-digit verification code is emailed to them and they're prompted to create a password after entering it; after that, they sign in with the password directly. See the FAQ entry below for the full flow. Optional Pro add-on GSheet Membership Pro adds authenticated mailbox sending, Group Email (including Mailchimp campaign delivery), Email-in, File Delivery links and optional PDF watermarks, PayPal checkout, gift purchases, editable membership levels, and admin tools to retry failed sheet writes and refund supported purchases. Pro can also sync roster contacts to Mailchimp and EmailOctopus without sending a campaign; EmailOctopus is a sync option, not a campaign-delivery gateway. The Access and Sales admin screens show read-only previews of relevant Pro features and a direct upgrade button. After purchasing, install and activate the Pro add-on, then complete its license activation; the free plugin's existing settings stay in place. Compose's Sync Roster action syncs its filtered recipients to the connected providers and can supply a selected attachment through a personalized GDLINK1 field. The separate Mailchimp and EmailOctopus settings-card buttons save the card and sync the full roster only to that provider. Pro and Chapters check the required Free features before loading their modules, so an add-on update arriving first through Freemius can keep working with compatible older Free versions. Unsupported combinations pause with an admin notice, preserve saved settings, and resume automatically after a compatible Free update. New optional functionality can require a newer Free version without pausing an otherwise compatible add-on.

安装:

  1. Upload the membership-google-sheets folder to /wp-content/plugins/ (or upload the ZIP under Plugins → Add New → Upload Plugin).
  2. Activate the plugin through the Plugins screen.
  3. Follow the Google setup steps below.
  4. Go to Membership Access (top-level menu in the WordPress admin sidebar) and configure the plugin.
  5. Click Save & Test Main Roster to verify the service account can read your sheet.
Google setup (~5 minutes)
  1. Go to https://console.cloud.google.com/ and create or select a project.
  2. Enable the Google Sheets API (APIs & Services → Library → search "Sheets").
  3. Create a Service Account (IAM & Admin → Service Accounts → Create).
  4. Generate a JSON key for the service account (Keys tab → Add Key → JSON). Download the file.
  5. Open your Google Sheet → Share → add the service account email (looks like name@project.iam.gserviceaccount.com) as an Editor (required for the Sales feature and the Pro add-on's Group Email; Viewer is enough if you only use page protection). The sheet stays private to everyone else.
  6. In Membership Access (top-level menu in the WordPress admin sidebar), paste the full contents of the JSON key file and enter your Spreadsheet ID.
When you click Save & Test Main Roster, the result identifies the exact service-account email in use and checks authentication, spreadsheet access, available tabs, the selected tab, row reading, and required column mappings in order. If a check fails, the result names the Main roster and gives a specific correction without displaying the private key, access token, raw JSON, or Google response body. For the Sheet (Tab) Name, leave the field blank to use the spreadsheet's first tab automatically. If an explicit tab name is missing, the connection result lists the available tab names and tells you to choose one or clear the field. Restricting pages
  1. Edit any page or post in WordPress.
  2. Find the Membership Access panel in the editor sidebar.
  3. Enter the required membership code(s), comma-separated (e.g. GOLD, PLATINUM).
  4. Save the page.
Codes are compared according to the Access Control Match Mode setting (exact match by default, or "letters mode" — see Configuration reference below). Leave the field blank for unrestricted access. Configuration reference | Setting | Description | |---------------------------|-------------------------------------------------------------------------------| | Service Account JSON | Full contents of the JSON key file downloaded from Google Cloud Console | | Spreadsheet ID | The ID from the spreadsheet URL (between /d/ and /edit) | | Sheet (Tab) Name | Optional. Leave blank to use the spreadsheet's first tab automatically. | | Email Column | Column letter containing email addresses (default: A) | | Membership Code Column | Column letter containing membership codes (default: B) | | Header Row Number | Row number of the header; data starts on the next row (default: 1) | | Cache Duration (seconds) | How long to keep the encrypted whole-roster cache in WordPress options (default: 300). Set 0 to disable roster caching. | | Expiration Mode | Daily (individual dates), Monthly, or Annual (covered-to year). | | Warning Window (days) | Days before expiration to start showing members a renewal warning (default: 14) | | Grace Period | Continued access after expiration: days in Daily mode; calendar months in Monthly and Annual modes. | | Expired-Access Message | Message shown once a membership has expired and the grace period has passed | | Login Redirect URL | Where to send unauthenticated visitors trying to access a restricted page | | Access-Denied Redirect URL| Where to redirect logged-in users without the required membership | | Access-Denied Message | Message to display instead of redirecting (if no redirect URL is set) | | Access Control Match Mode | Exact match, or "letters mode," where the member's code must contain every letter in the required set | | Custom Login Page | The WordPress page containing [gsma_login_form]; leave on Auto-detect to let the plugin find it, or fall back to WordPress's default login page |

屏幕截图:

  • Main Roster — the organisation's spreadsheet ID and column mapping (email, membership code, name, cache duration).
  • A private Google Sheet roster — email and membership-code columns support access checks; additional columns can supply expiration dates, member details, and purchase information.
  • Membership Expiration — Main Roster: choose Daily, Monthly, or Annual expiration updates, then set the warning window, mode-specific grace period, and expired-access message. Chapter sites can set separate local-roster rules.
  • Extra User-Info Fields — map additional sheet columns (address, phone, region) for members to view and verify on the front end.
  • The Membership Access panel in the page editor sidebar — set the membership codes required to view this page.
  • The login gate turning away a visitor whose email is not on the roster.
  • Login Flow — pick the page that hosts your custom sign-in form.
  • Front-end Appearance — force the login form and status panel to keep their original colors and resize their text.
  • Access Control Behaviour — exact vs. letters-mode code matching, and the message shown when access is denied.
  • Signing in — a member enters their email to get started.
  • First-time sign-in — a 6-digit verification code is emailed and entered here.
  • After the code, a first-time member is prompted to create a password.
  • Membership status confirmed after sign-in — shown here right after a purchase, but the same confirmation appears for any member signing in.
  • Sales settings — the Pricing Matrix with Delivery, Duration and Postage pricing; `0` offers a free membership and a blank cell is unavailable.
  • The membership purchase picker a buyer sees, with live price updates.
  • The confirmation email a buyer receives after purchase.
  • The Membership Code Matrix — the stored code for every level and delivery-method combination.
  • Payments with Pro active — Stripe Connect account details and the optional PayPal gateway; free-only sites use Stripe Connect without PayPal.
  • Recent Purchases — purchase outcomes and available actions; sheet-write retry needs Pro, while refundable Stripe Connect sales can be refunded on free sites.
  • General Settings — currency, thank-you page, expiration-column override and the new-member bonus cutoff used in Annual mode.
  • Membership Level Names — map raw membership codes to the human-readable names members see.
  • Email Verification (OTP) — code expiry and sender details for the verification email.

升级注意事项:

4.10.14 Checks fresh roster data before refusing a login for a missing email. Pro 1.15.10 and Chapters 1.18.8 remain unchanged. 4.10.13 Adds a 60-second login-code resend delay with reassurance messages. Suppressed requests do not count toward the send limit. Chapters 1.18.8 and Pro 1.15.10 remain compatible. 4.10.12 Fixes an incorrect "selected membership record has changed" refusal for unchanged chapter members. Keep Chapters 1.18.8 and Pro 1.15.10 installed. Previously failed paid purchases and existing duplicate rows still require reconciliation. 4.10.11 Improves roster-read timeout recovery. Install Chapters 1.18.8 for same-payment chapter recovery and Pro 1.15.10 for the unsafe-retry safeguard. Existing duplicate rows require manual reconciliation. 4.10.10 Adds safe existing-member destination support for Chapters 1.18.7; purchases complete independently of optional new-email approval. 4.10.9 Refreshes feature and compatibility documentation; Free runtime behavior is unchanged. 3.1.0 The plugin folder and text domain changed to membership-google-sheets. Deactivate and delete the old copy after installing this one; settings and data are preserved automatically.

常见问题:

How do I close a failed sandbox test purchase?

In Recent Purchases, choose Reconcile and then "Abandon a sandbox test purchase". Verify the original transaction in the payment provider's test or sandbox environment, confirm that no real funds were charged, and confirm that any test roster changes have been removed or reversed without deleting a legitimate membership. Record a short note and mark it reconciled. This permanently prevents another fulfillment attempt for that payment without claiming a refund or a completed membership, and does not approve an email addition. Known live transactions cannot use this shortcut: a real-money purchase made for testing still needs a completed full refund or the correct fulfilled membership. Original errors and email-status notes remain available in expandable details instead of an active failure warning.

Does the Google Sheet need to be shared publicly?

No — never. You only share it with the service account email address. It remains completely private to all other users.

What PHP extensions are required?

The OpenSSL extension is needed to sign the JWT for authentication. It is enabled by default on virtually all shared and managed WordPress hosts (including WP Engine, Kinsta, SiteGround, Flywheel, and others).

Are administrators ever blocked?

No. Users with the manage_options capability always bypass all membership checks.

Where is the Service Account JSON stored?

It is stored in your WordPress database (the wp_options table). With OpenSSL available, the plugin encrypts it using this installation's security salts; if encryption is unavailable, the credential-saving routine can retain plaintext rather than replace a working credential with unusable ciphertext. Check the encryption status on the Access settings screen. It is never sent to the browser or written to a file by the plugin. Keep the salts and database backups secure.

How quickly do membership changes take effect?

After the encrypted whole-roster cache expires (default 5 minutes / 300 seconds), the next read fetches fresh data and writes a newly encrypted payload. Reduce the cache duration in settings or click Clear Cache to force the next read to refresh.

What happens if the Sheets API is unreachable?

The plugin logs an error and denies access as a safe default. Use Save & Test Main Roster in settings to verify connectivity.

Signing in: verification code, then password

This works for any member already on the roster, whether they got there through the plugin's own purchase pathway or not — a name typed in manually, imported from a spreadsheet, added after a mailed-in check, however your roster is maintained. The sign-in flow doesn't care how someone became a member, only that their email is on the sheet. It's part of the free plugin. There's no separate account-creation step. A member enters their email, and what happens next depends on whether they've signed in before:

  • First time signing in? A 6-digit verification code is emailed to them. They enter the code and are prompted to create a password. From then on, that password signs them in directly.
  • Already have a password? The code step is skipped entirely — they go straight to a normal password sign-in.
(Pro's Authenticated mailbox sending, below, improves deliverability of these verification codes — it doesn't add the sign-in flow itself.)

Authenticated mailbox sending (Pro add-on)

With the GSheet Membership Pro add-on, you can connect a real mailbox (Google sign-in or an App Password) on the main settings page and route login verification codes, purchase confirmations and gift notices through it. A rejected verification code falls back to the site's normal mailer. Group Email can also use the authenticated mailbox for batched sending, or use Mailchimp for campaign delivery. Correctly configured mailbox authentication can improve deliverability; it does not guarantee that messages avoid spam filters.

Group Email: message your roster (Pro add-on)

With the GSheet Membership Pro add-on, the Group Email page in Membership Access lets you compose a message and send it to your roster — everyone, or a subset filtered by membership code. Delivery can use the site's batched mailer (including an authenticated mailbox) or a connected Mailchimp audience. Mailchimp can sync the filtered audience before a classic-mode send or target a segment of the synced full roster. Chapter sites send Group Email to their local chapter roster only, even if their access checks also include the main roster. Direct delivery and Mailchimp campaigns have different unsubscribe and reporting behavior; Pro includes send history and delivery reports. There are two ways to trigger a send: filling out the compose form yourself, or Email-in — forwarding a single email to a dedicated mailbox, covered next.

Email-in: trigger a group email by forwarding a message (Pro add-on)

Email-in is the second way to send a Group Email: instead of the compose form, you forward a message to a dedicated mailbox (e.g. blast@example.org). The plugin checks that mailbox on a schedule (IMAP); a message from an authorized sender that meets the subject-keyword rule is queued under the same audience rules as the compose form. The configured delivery method determines whether it goes through site mail or Mailchimp.

Setting it up

  1. Create a dedicated mailbox for intake (a Gmail / Google Workspace account works well). Don't reuse a personal inbox — every unread message is examined.
  2. For Gmail / Google Workspace: enable IMAP (Gmail Settings → Forwarding and POP/IMAP), turn on 2-Step Verification for the account, and create an App Password (Google Account → Security → App passwords). The regular account password will NOT work over IMAP.
  3. In Membership Access → Group Email, fill in the Email-in card: host imap.gmail.com, port 993, the mailbox address as username, and the App Password.
  4. Add the email addresses allowed to trigger a send (one per line) and — strongly recommended — a required subject keyword.
  5. Enable polling, click Test connection, then send yourself a trial: forward a message from an allowlisted address (with the keyword in the subject) and click Check mailbox now.

Why the subject keyword matters (spoofing)

The From: address of an email can be forged (spoofing) — an allowlist alone is not sufficient protection for something that can email your whole membership. The required subject keyword adds a second check; keep it private and choose a non-obvious phrase. The keyword is stripped from the subject before delivery. This does not replace mailbox security or prevent an attacker who learns the keyword from sending a forged message.

Audience & attachments

  • Embed a code filter in the subject to target membership levels: Meeting notes [codes: GOLD,SILVER]. The tag is removed before delivery. Without a tag, the membership code filter saved on the Group Email page is applied; if that filter is blank, all members receive the message. Works on both main and chapter sites.
  • Chapter sites send to the local chapter roster only — the code filter narrows within that roster, regardless of whether access checks also use the main roster.
  • Email-in attachments are uploaded to the media library. With Pro's File Delivery link mode, every attachment becomes an expiring, recipient-bound link that opens without a login; PDFs may also be watermarked for the recipient. With link mode off, the first file is attached to site mail (or converted to a link if over 5 MB), while additional files use shared login-gated links. Mailchimp link mode supports up to five personalized file links per campaign; additional files are omitted with a notice.
  • Accepted and permanently skipped authorized messages are marked read and recorded to avoid duplicate sends. Unauthorized or unrelated messages are ignored and left unread, with their IDs recorded so they are not repeatedly processed.

Sales — sell memberships

The Sales half of GSheet Membership puts a configurable buy-membership picker on any page and, on a successful payment, writes (or updates) the buyer's row in your private Google Sheet so they can immediately log in on your site.

  • Three-dimensional picker — buyers choose Delivery (Electronic / Print / Both) × Duration (1-Year and Lifetime included by default; the Pro add-on adds custom levels and multi-year durations) × Postage (Regular, First Class, Canada/Mexico, Other International), and the price updates live as they change selections.
  • Discrete pricing matrix — you set the exact price for every saleable combination in the admin. Enter 0 for a free membership that skips the gateway; leave a cell blank to make that combination unavailable.
  • Stripe Checkout — the free plugin uses Connect with Stripe and hosted onboarding, with no API keys to paste; Pro can use your own Stripe keys instead. Card details stay on Stripe's hosted checkout page. Pro's own-key settings provide a Test/Live switch; free Connect has no separate mode switch in WordPress.
  • PayPal Standard Checkout (requires the Pro add-on) — buyers can optionally pay via PayPal instead of (or in addition to) Stripe. Both gateways share the same sheet-upsert pipeline, purchase log, and retry UI.
  • Sheet upsert — on a verified webhook the plugin first tries to update the row that matches the buyer's email; if there is no row, it appends one. Renewals extend an existing future expiration date instead of overwriting it.
  • Reliable webhook pipeline — per-event and per-email atomic locks prevent duplicate writes from concurrent webhook redeliveries; a sheet-write failure returns HTTP 500 so Stripe retries, and the admin sees a notice. The Pro add-on adds an admin retry control for failed sheet writes.
  • Buyer confirmation email — configurable subject and body with placeholders (first name, selection, amount, code, expiration, login URL, etc.). Integrations can enrich purchase variables with gsms_purchase_email_vars and adjust the rendered confirmation body with gsms_confirmation_body.
  • Roster-aware checkout and contact collection — checkout distinguishes the signed-in purchaser's own verified email from another entered email or a gift recipient. Add-ons can collect contact fields independently of local sheet-write columns using the same field list for rendering and paid-checkout validation. With Chapters, this supports international State / Province / Region, Country, and Zone for main-organization reporting without local mappings. Electronic-delivery buyers can select the international-address checkbox when international fields are collected, even without a local ZIP column; administrator direct-apply still uses only local mappings.
  • Admin direct-apply — a separate [gsms_admin_picker] shortcode lets a site administrator apply a membership directly to the sheet without taking a payment, perfect for comp memberships, cheque / cash-in-hand orders, or back-filling an old purchase.
  • Membership Level Names — map the raw membership codes stored in your sheet to human-readable names, so a member who's denied access sees a name like "Gold Member" instead of the raw code. Pro adds a level editor; copying Pro levels to free-only storage requires an explicit administrator action.

Requirements

  • PHP 7.4+ with the standard openssl, hash, and mbstring extensions (already enabled on every major WordPress host).
  • WordPress 5.9+.
  • The access features (above) configured with a working Service Account — the sales pipeline reuses the same sheet-writer.
  • A Stripe account for live or test payments (a PayPal developer account too, if you use the Pro add-on's PayPal checkout).

Selling setup

  1. Configure the Access settings first (see Installation above) and confirm the Save & Test Main Roster button succeeds.
  2. Go to Membership Sales in the WordPress admin sidebar. Every sub-page shows a "Setup" notice at the top reminding you which shortcode to put on which page.
  3. Fill in the Pricing Matrix, Code Matrix, and Payments sub-pages (see Configuration below).
  4. Create a page containing only the shortcode [gsma_membership_purchase] — that is the buy page.
  5. Create (or pick) a thank-you page and put [gsma_user_info] on it (that shortcode shows the buyer's status with an inline login form when they're not yet signed in). Select that page on the Settings sub-page under Thank-you page.

Shortcodes

  • [gsma_login_form] — renders the sign-in form (email, then a first-time verification code or a returning password) on the page you choose as the Custom Login Page. Independent of the Sales feature — every site can use it.
  • [gsma_membership_purchase] — renders the full picker (Delivery × Duration × Postage) with live total and the Buy membership button. Place this on the page where you want to take payments.
  • [gsms_admin_picker] — admin-only variant of the picker that applies a membership directly to the sheet without any payment. Only site administrators (manage_options) see it; everyone else sees a polite notice.
  • [gsma_user_info] — place it on the thank-you page so buyers see their membership status (and an inline login form when they aren't logged in).

Admin sub-pages

  • Pricing Matrix — one row per Delivery, one column per Postage, repeated for each Duration. Type a price into a cell to make it saleable, including 0 for a free membership; leave it blank to make that combination unavailable. The Membership Levels block above the grid lets you choose which levels are currently offered for purchase.
  • Code Matrix — the membership code written into the buyer's sheet row for each combination. Every membership level gets its own row of codes. Levels beyond the built-in 1-Year and Lifetime, including multi-year durations, can be added with the Pro add-on; each new level gets its own Code Matrix row automatically. A warning is shown if any saleable cell is missing a code.
  • Payments — enable Stripe and use Connect with Stripe in the free plugin (no API keys or Stripe webhook secret to paste). With Pro, use your own Stripe keys instead and optionally enable PayPal, which has its own credentials and webhook setup.
  • General Settings (sidebar label Settings) — currency, thank-you page picker, optional override of the access settings' expiration column, annual new-member bonus cutoff, buyer confirmation email templates, and option labels.
  • Recent Purchases — the last 200 purchase events with gateway and sheet status. Reconcile guides administrators through the original-payment, intended-membership and correction checks, with a shorter path for a completed full refund and a missing-record review when an entry is no longer retained. It records the verified outcome without charging, refunding or editing the roster, prevents another renewal from that payment, and clears the warning only when no unresolved failures remain. Pro adds an inline Retry form for failed sheet writes and refunds for supported purchases; refundable Stripe Connect sales can also be refunded in the free plugin.

Configuration: webhooks

Stripe Connect (free plugin): On the Payments page, click Connect with Stripe and complete Stripe's hosted onboarding. No Stripe API keys or direct webhook signing secret are entered in the free plugin; payment confirmations are relayed through the hosted Connect service. Direct Stripe API keys (Pro add-on only): If you choose Pro's own-key mode instead of Connect, configure separate Test/Live keys on the Payments page and register its direct webhook:

  1. Developers → Webhooks → Add endpoint.
  2. Paste the Stripe Webhook URL shown on the Pro Payments page (ends in /wp-json/gsma-sales/v1/stripe-webhook).
  3. Subscribe to a single event: checkout.session.completed.
  4. Copy the resulting Signing secret (whsec_...) into Pro's matching webhook field for that mode.
PayPal (requires the Pro add-on):
  1. In the PayPal developer dashboard → My Apps & Credentials → your app → Add webhook.
  2. Paste the PayPal Webhook URL shown on the plugin's Payments page (ends in /wp-json/gsma-sales/v1/paypal-webhook).
  3. Subscribe to CHECKOUT.ORDER.APPROVED and PAYMENT.CAPTURE.COMPLETED.
  4. Copy the resulting Webhook ID into the matching field on the plugin's Payments page.

How to test without real money

The picker can be exercised without a payment gateway. A price of 0 also completes a free membership without sending the buyer to Stripe or PayPal.

  1. Picker UI / pricing layout (no gateway at all)

  • Fill in just the Pricing Matrix (real prices) and the Code Matrix (any short string like TEST).
  • Visit your buy page. The picker renders, the cheapest combination is preselected, and clicking different options updates the live total.
  • Leave a cell blank in the Pricing Matrix and reload — that postage / duration is greyed-out and unselectable, and the Buy membership button is disabled if the current selection has no price.

  1. End-to-end with Stripe in TEST mode (Pro own-key setup)

  1. Sign up for a free Stripe account. No bank details are needed for test mode.
  2. Activate Pro, enable Stripe on Payments, select Test under Your own Stripe keys (Pro), save your pk_test_... and sk_test_... keys, and register the test-mode direct webhook as described above. The free Connect setup does not offer a Test/Live switch in the WordPress settings; do not use a test card against a live connected account.
  3. Visit the buy page, fill in a test email/name, click Buy membership, and on the Stripe checkout page use the official test card:
  4. Card number: 4242 4242 4242 4242
  5. Expiry: any future date   CVC: any 3 digits   ZIP: any 5 digits
  6. After the redirect, open Membership Sales → Recent Purchases in the admin. Once the payment confirmation is delivered, you should see a new entry with paid from Stripe and inserted (or updated) for the sheet.

What happens if Stripe or PayPal sends the same event twice?

The first delivery is processed normally. Any duplicate of the same event is identified and returns HTTP 200 with status: duplicate without writing to the sheet. Two concurrent deliveries for the same event are serialized via an atomic per-event lock; the loser receives HTTP 409 so the gateway retries it. From 1.7.13 each processed event is stored as its own wp_options row with a 72-hour TTL — there is no fixed-size eviction window that could cause old-but-recent events to fall off and be reprocessed.

What happens if the Google Sheet write fails?

The plugin returns HTTP 500 to the gateway (so it retries delivery automatically), records a "failed" entry on the Recent Purchases page, and shows a persistent admin notice while failures remain unresolved. The buyer confirmation email is not sent for a failed write — only a successful upsert triggers it. Pro offers a manual retry for safe failures. If the result of an earlier write is uncertain, use Reconcile to compare the original payment and intended membership before confirming an already-corrected outcome; do not renew again blindly. Reconciliation itself does not send a receipt, charge, refund, approve an email change or write the roster.

Is the buyer's payment ever lost if the sheet write fails?

No. The gateway has captured the payment regardless of what happens on your site. Recoverable sheet failures can catch up through retries, but an uncertain prior write is deliberately blocked to avoid renewing twice and needs administrator review through Reconcile.

Can lifetime memberships and renewals coexist?

Yes. Renewals extend the existing expiration date forward, so an early renewal never shortens the buyer's coverage. A lifetime purchase clears the expiration cell entirely.

What if a buyer clicks Cancel at PayPal and then tries to pay again?

The cancelled checkout row is kept visible in Recent Purchases for auditing, but it never blocks a retry. If the gateway somehow delivers a capture event for an order the cancel handler already marked cancelled, the finalisation pipeline now detects and recovers that row automatically rather than treating it as already-done.

Does the free plugin charge a fee on sales?

It depends on how you take card payments:

  • Stripe Connect (free, the default since 3.5.0): click Connect with Stripe on the Payments screen — no API keys to paste, Stripe hosts the onboarding. A 2% platform commission is deducted from each card sale (in addition to Stripe's own standard processing fees). The current rate is always shown on the Payments screen before you connect.
  • Your own API keys (Pro add-on): when Pro's own Stripe keys are saved for the active mode, direct-key checkout has a 0% platform fee. Activating Pro alone does not switch a connected site away from Connect or remove its commission; deactivating Pro returns a connected site to Connect without losing its saved settings.
  • Legacy free installs that saved their own Stripe keys before 3.5.0 keep working with no commission; the keys remain a supported deprecation path until you choose to connect.
  • PayPal (a Pro feature) carries no platform commission either.
The commission is applied server-side by the plugin's hosted Stripe Connect service when the Checkout Session is created; the plugin itself never computes or transmits the fee amount.

更新日志:

4.10.16 4.10.15 4.10.14 4.10.13 4.10.12 4.10.11 4.10.10 4.10.9 4.10.8 4.10.7 4.10.6 4.10.5 4.10.4 4.10.3 4.10.2 4.10.1 4.10.0 4.9.0 4.8.1 4.8.0 4.7.0 4.6.13 4.6.12 4.6.11 4.6.10 4.6.9 4.6.8 4.6.7 4.6.6 4.6.5 4.6.4 4.6.3 4.6.2 4.6.1 4.6.0 4.5.9 4.5.8 4.5.7 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.2 4.4.1 4.3.6 4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.17 4.2.16