agentleFS
thomaslimitedthomaslimited/chrome-extension-skills/skills/chrome-extension-payments/SKILL.md

chrome-extension-payments

Skill2 starsChanged 52 days agoMITView on GitHub

Add real payments to a Chrome MV3 extension — monthly/yearly subscriptions, a lifetime one-time purchase, PayPal (Subscriptions + Orders API) and USDT/BEP20 crypto payments, server-derived entitlements, plan changes, discount codes, an affiliate program, and an admin dashboard. Trigger for "add payments to chrome extension", "subscription extension", "paypal subscription", "accept USDT", "crypto payments", "lifetime license", "paywall", "pro plan", "monetize my extension". Ported from a shipped MV3 + Hono/Postgres backend: verified webhooks, idempotent settlement, exact-amount crypto invoices, reconciliation jobs — not a theoretical sketch.

  • Reads credentials

The file

We split this skill into the rules it gives an agent

1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Wire PayPal: create the product + plans once with a setup script, implement createCheckout / createOrder / captureOrder / verifyWebhook / …

    line 76

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Chrome Extension Payments

Monetize a Chrome MV3 extension with a real backend: subscriptions, a lifetime purchase, two payment rails (PayPal + USDT/BEP20), server-derived entitlements, and the admin/affiliate/discount machinery around them. Every pattern here shipped in production; alternatives are noted, not built out.

Scope — read this first

This skill does not cover:

  • Login / accounts — sessions, Google SSO, email/password. Use chrome-extension-auth first; this skill assumes requireAuth middleware and a users table already exist.
  • Chrome Web Store listing, permission justifications, screenshots — use chrome-web-store-listing.
  • Deploying the backend, TLS, CI/CD — use chrome-extension-deploy.
  • MV3 basics (WXT, messaging, storage/sync, build tooling) — use chrome-extension-dev.

Assumed stack: Hono (Node) API, raw pg (no ORM), Postgres, a WXT/React extension with a background script that is the only holder of the session token. Swap the framework; keep the shape.

1. Choose your payment providers

ProviderFeeMerchant of record (tax)ChargebacksWorks where Stripe doesn'tSetup cost
PayPal (Subscriptions + Orders API)~4.4% + $0.30No — you owe your own sales tax/VATYes, PayPal-mediatedYesLow — product/plan API + one webhook
USDT (BEP20)Network gas only (~$0.10–0.30), no processor feeNo — you are the merchantNo — on-chain is finalYes, anywhere crypto is legalMedium — RPC reads, address-activity webhook
Stripe~2.9% + $0.30NoYesNo — blocked/unavailable in many countries, and Chrome Web Store extension billing has its own restrictionsLow, best DX
Paddle / Lemon Squeezy~5% flatYes — they collect and remit tax as merchant of recordHandled by themYesLow, but you give up direct control of checkout UI and payout timing

Decision: this skill implements PayPal + USDT — the proven path when Stripe is unavailable or undesirable and you want to keep 100% of a crypto sale with no chargeback risk. If you have US/EU customers and want tax handled for you, evaluate Paddle or Lemon Squeezy instead (their hosted-checkout docs cover that path; do not hand-roll it here). If Stripe is available in your market and you don't need a crypto rail, Stripe's Billing + Checkout Session APIs are simpler than PayPal's — this skill does not template it, but the entitlement/webhook-idempotency patterns below transfer directly.

2. Entitlement model

  • Tiers are free | pro (or your tier set). One column, users.tier, is the fast-read projection — never the source of truth.
  • Source of truth is derived server-side from three places, in this priority: users.lifetime_at (set, never unset except on refund) OR users.comp_access (admin-granted) OR the newest row in subscriptions with status = 'active' AND current_period_end > now().
  • Never trust the client for entitlement. GET /v1/me returns { tier, lifetime, subscription }; the extension caches this response and gates features off the cache, but every privileged API call re-checks the database, not the cached flag.
  • The extension caches /me in storage.local, refreshes it on a daily alarms tick (re-armed on onStartup — Chrome can drop alarms across a browser restart), and immediately after any checkout, claim, or cancel action resolves.
  • Client-side "is this still Pro" also compares the cached current_period_end against Date.now() so a lapsed plan doesn't read as Pro for up to a day between refreshes.
  • Graceful downgrade: losing Pro never deletes data. Existing saved items stay readable and editable; only the "create new" action is gated behind the entitlement check.

Full code (types, isProFromMe, useEntitlement, alarm wiring, message-passing contract) in references/entitlements-and-checkout.md.

3. Data model

Postgres, raw SQL, no ORM. Every CREATE TABLE/ALTER TABLE is IF NOT EXISTS so the same script runs safely on every boot — this is your only migration system. Money as NUMERIC(10,2) (USD) or NUMERIC(20,8) (USDT); every purchase row carries created_at, and cancellable rows carry cancelled_at + cancelled_by. See references/data-model.md and assets/schema-template.sql.

4. Numbered workflow

  1. Define the catalog — plan codes, prices, tiers, one lifetime item — in one server-side module (plans.ts). The client never sends a price; it sends a plan code.
  2. Apply the schema (assets/schema-template.sql) — users, subscriptions, webhook_events, one_time_purchases, crypto_invoices, crypto_transfers, discount_codes, affiliate tables.
  3. Wire PayPal: create the product + plans once with a setup script, implement createCheckout / createOrder / captureOrder / verifyWebhook / parseWebhook, mount the webhook route. See references/paypal.md.
  4. Wire USDT/BEP20: exact-amount invoices, a minimal JSON-RPC reader with failover, the Alchemy address-activity webhook, and the manual tx-hash claim fallback. See references/usdt-bep20.md.
  5. Build the in-popup checkout UX: plan picker → PayPal approval opens a new tab (never an embedded SDK) → static return/cancel pages served by the API → popup polls invoice/subscription status. See references/entitlements-and-checkout.md.
  6. Apply billing events idempotently: claim the webhook event id before processing, release the claim on failure so the provider's retry gets a real attempt, mark it processed only after every side effect (tier write, discount redemption, commission) has committed.
  7. Add plan changes: upgrade-only in an MVP (bigger interval/tier), prorate on PayPal, no proration on the crypto rail (a new full-price pass stacks onto the end of the current one). See references/plan-changes-discounts-affiliate.md.
  8. Add discount codes and affiliate: first-charge-only discounts with redemption limits; referral codes discount the referee and pay the referrer a commission held for N days before payout. Rates live in a app_settings DB row, editable at runtime, not in env vars.
  9. Build the admin API: overview/revenue/users/orders/withdrawals endpoints behind a single shared secret compared in constant time. Never behind the same auth as customers.
  10. Run maintenance jobs: a scheduler tick that matures commissions, expires lapsed subscriptions (with a grace check so cancellation never revokes an already-paid period), sweeps confirmed crypto invoices, expires stale ones, and reconciles any invoice that reached paid but never got its entitlement applied (crash recovery).
  11. Test before going live: a paypal:check style script that verifies credentials, webhook subscriptions, and plan pricing without charging anything; a crypto:simulate script against a faked chain and a scratch database; manual webhook replay. See references/testing-and-operations.md.

5. Plan-change quick table

From → ToSame providerCross-provider
Month → Year (PayPal)Prorated new subscription, charged the difference nown/a
Month → Year (crypto)New full-price pass stacks onto the end of the current one — no prorationn/a
Year → MonthNot supported in an MVP — no clean way to apply it without re-billing or a manual revise call; let it run outSame
Any plan → LifetimeAlways allowed. Buying Lifetime auto-cancels every live subscription so the customer is never billed again for something Lifetime already coversSame
Lifetime → anythingBlocked — no further purchase is offered once Lifetime is granted—

6. Security checklist

  • Verify every webhook signature before parsing the body as trusted: PayPal via /v1/notifications/verify-webhook-signature, Alchemy (or your chain provider) via HMAC-SHA256 over the raw body with timingSafeEqual. An unverified webhook is a free-tier endpoint.
  • Never trust a client-supplied amount or price. The client sends a plan code; the server looks up the price. A discount is priced server-side from the code, not from a client-sent percentage.
  • Idempotency everywhere money moves: webhook event id claimed via INSERT ... ON CONFLICT, capture/settle writes guarded by a conditional UPDATE ... WHERE status <> 'paid', and any insert that could double-credit backed by a real unique constraint (not just an application check).
  • Secrets stay server-side only — API keys, webhook signing keys, the admin secret. Nothing payment-related belongs in the extension bundle; it is publicly downloadable.
  • Compare secrets in constant time (crypto.timingSafeEqual over a hash, not ===) for the admin secret and any webhook HMAC check.
  • Grant access only after money actually moved. PayPal order approval is not payment — capture it and check the capture's own status is COMPLETED before granting anything.
  • Rate-limit checkout, discount lookup, and crypto claim endpoints — a discount/claim endpoint is a guessing oracle otherwise.
  • Log every refund/chargeback and act on repetition — disable the account outright on a chargeback; flag after N ordinary refunds.
  • Refuse to boot in production with placeholder secrets (default session secret, missing admin secret, missing allowed-origins list, .env.example values still in place).

7. References

  • references/entitlements-and-checkout.md — tier model, caching, alarms, feature gating, popup checkout flow, message-passing contract.
  • references/paypal.md — catalog setup script, Subscriptions + Orders API, webhook verification and idempotent event handling, reconciliation, sandbox vs live.
  • references/usdt-bep20.md — exact-amount invoices, RPC reader with failover, Alchemy webhook, manual claim, confirmations/expiry, stacking, crypto discount, simulation.
  • references/plan-changes-discounts-affiliate.md — upgrade/downgrade rules, discount code validation, affiliate rates/attribution/payouts, admin auth.
  • references/data-model.md — schema walkthrough, money representation, audit fields, key relationships.
  • references/testing-and-operations.md — verification scripts, webhook replay, maintenance jobs, production checklist.
  • assets/schema-template.sql — generic, trimmed, idempotent Postgres schema to start from.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.