Linux 软件免费装
Banner图

GSheet Membership

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

标签

membership stripe association google sheets branches

下载

4.6.8 4.5.8 4.5.9 4.6.1 4.6.10 4.6.6 4.6.7 4.6.9

详情介绍:

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. Credentials are stored securely in your WordPress database and are never exposed in the browser or source code. 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, PDF watermarks, PayPal checkout, gift purchases, editable membership levels, and admin refund/retry tools. 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.

安装:

  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 cache the sheet data locally (default: 300). Set 0 to disable. | | Warning Window (days) | Days before expiration to start showing members a renewal warning (default: 14) | | Grace Period (days) | Days of continued access after expiration before it's revoked (default: 10) | | 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 — only the Email and Membership columns matter to the plugin, but your sheet can carry whatever else you track alongside them (name, expiration date, address, phone, even international members).
  • Membership Expiration — Main Roster: warning window, grace period, and the message shown once access lapses.
  • 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 — only the Email and Membership columns matter to the plugin, required membership codes for that 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.
  • 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 — enable Stripe and/or PayPal for the purchase picker (PayPal requires the Pro add-on).
  • Recent Purchases — a live log of every sale, with refund and retry actions.
  • Sales general settings — currency code and the thank-you page shown after a successful purchase.
  • 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.

升级注意事项:

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.

常见问题:

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), protected by the same security as your WordPress installation. It is never sent to the browser or written to a file.

How quickly do membership changes take effect?

After the cache expires (default 5 minutes / 300 seconds). Reduce the cache duration in settings or click Clear Cache to force an immediate 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 send ALL plugin email — login verification codes, purchase confirmations, gift notices and group emails — from that account. Because mail truly originates from the mailbox, SPF/DKIM/DMARC align and messages stop landing in spam, with no separate SMTP plugin needed.

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 runs through the site's own batched mailer, or optionally through a connected Mailchimp account (the audience is synced to your membership filter before every send). Chapter sites always send to their own local roster only. Every send gets individual per-member delivery, unsubscribe links, throttled background sending, and a per-recipient send log with retry/cancel. 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), and any message from an authorized sender is queued to the roster through the exact same engine as the compose form — same audience rules, same per-member delivery, unsubscribe links, and send log with retry/cancel.

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 by anyone (spoofing) — an allowlist alone is not sufficient protection for something that can email your whole membership. The required subject keyword acts as a shared secret: only people who know it can trigger a send, even if they forge an authorized From: address. The keyword is stripped from the subject before delivery, so members never see it.

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 always send to the local chapter roster only — the code filter narrows within that roster.
  • Attachments are uploaded to the media library. Files up to 5 MB are attached to the outgoing email; larger files (and any additional attachments beyond the first) become download links in the message body.
  • Processed messages are marked read in the mailbox and their Message-IDs are recorded, so nothing is ever sent twice. Messages from unauthorized senders are marked read, logged (when WP_DEBUG is on) and never sent.

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. Leave any cell blank to mark that combination as not for sale: it is hidden / disabled in the picker and rejected server-side.
  • Stripe Checkout — redirect-style checkout (no card form on your site, lower PCI burden). Test mode and Live mode are stored side-by-side and toggled with one switch.
  • 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 + a per-row "Retry" button on the Recent Purchases page.
  • Buyer confirmation email — configurable subject and body with placeholders (first name, selection, amount, code, expiration, login URL, etc.).
  • 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.

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; 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/disable Stripe (and PayPal, with the Pro add-on); mode switch (Test / Live for Stripe, Sandbox / Live for PayPal); keys and secrets for each mode; webhook signing secret. The webhook URLs are shown here for paste-into-Stripe (and paste-into-PayPal with Pro).
  • Settings — currency, thank-you page picker, optional override of the access settings' expiration column, buyer confirmation email templates, and option labels.
  • Recent Purchases — the last 200 webhook deliveries with their outcome (gateway status + sheet status). Failed sheet writes show an inline Retry form; completed Stripe and PayPal rows show a Refund control.

Configuration: webhooks

Stripe:

  1. Developers → Webhooks → Add endpoint.
  2. Paste the Stripe Webhook URL shown on the plugin's 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_...) and paste it into Webhook signing secret on the plugin's Payments page.
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

Almost everything in this plugin can be exercised before you ever sign up for 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 (no real money)

  1. Sign up for a free Stripe account. No bank details are needed for test mode.
  2. On the plugin's Payments page, enable Stripe, switch Mode to "Test", paste your pk_test_... and sk_test_... keys, and save.
  3. Install the Stripe CLI on any laptop and run:
stripe listen --forward-to https://yoursite.example/wp-json/gsma-sales/v1/stripe-webhook The CLI prints a whsec_... signing secret — paste that into Webhook signing secret and save. 4. Visit the buy page, fill in any email/name, click Buy membership, and on the Stripe checkout page use the official test card:
  • Card number: 4242 4242 4242 4242
  • Expiry: any future date   CVC: any 3 digits   ZIP: any 5 digits
  • After the redirect, open Membership Sales → Recent Purchases in the admin. 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 until the next successful write. The buyer confirmation email is not sent for a failed write — only a successful upsert triggers it. You can manually rerun the upsert from the Recent Purchases page.

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. The sheet write being deferred (and retried) means the buyer's membership row catches up automatically.

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): the Pro add-on is commission-free — Pro sites use their own Stripe keys with a 0% platform fee, permanently. Deactivating Pro simply reverts the site to Connect mode without losing any 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.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