crxpay

Browsers · Chrome (MV3)

Built for Chrome Manifest V3, from the service worker up.

No CORS drama. No fetch-from-popup bugs. No dead subscriptions when the service worker sleeps. Drop the SDK in, wire one handler, ship.

✓MV3 service worker–native✓Offline-signed entitlements✓10-line setup
chrome-extension://…/popup.html
Y
YourApp
PRO
Everything unlocked.

Offline-signed — status verified 4s ago.

→ sub.hasEntitlement('pro') → true
MV3 native
Service Worker
Zero CORS errors

MV3, done right

Four things every MV3 billing SDK gets wrong. We got them right.

SW-aware

No CORS errors in the service worker

MV3 moved network calls out of the popup. Most SDKs never adapted. crxpay routes every request through chrome.runtime.sendMessage, so billing traffic never touches a cross-origin pre-flight.

Offline-first

Status survives a sleeping worker

Service workers evict memory after 30 seconds. We persist a signed entitlement blob in chrome.storage.local — so your paywall disappears when the user cancels, not when Chrome garbage-collects.

TypeScript

One-line init, typed everywhere

No manifest hacks, no background.js gymnastics. Import the SDK, call init() with your public key, and get typed entitlement checks in content scripts, popups, and the worker itself.

Framework-free

Works with React, Vue, Svelte, or vanilla

The subscription state is a plain observable. Wire it to React hooks, Vue refs, Svelte stores, or a raw callback — crxpay does not care how you render your popup.

Quickstart

Ship a paywall in four steps.

Real code. Copy-paste ready. This is the entire MV3 integration — we do not hide the rest in “advanced configuration” docs.

01

Install the SDK

Add @crxpay/sdk to your extension project. It ships as ESM and works with Vite, webpack, or esbuild out of the box.

02

Initialise in the service worker

One call in background.ts. The SDK wires message handlers so popups and content scripts never have to do their own fetch.

03

Check entitlements anywhere

Pop-up, content script, options page — one async call, typed return, zero network round-trip on the happy path.

04

Open the hosted checkout

crxpay opens a new tab to Stripe-hosted checkout, listens for the webhook, then signs a fresh cache entry. No redirect gymnastics required.

your-extension/src
01 · bash
pnpm add @crxpay/sdk
02 · ts
// background.ts — MV3 service worker
import { crxpay } from '@crxpay/sdk';

crxpay.init({
  apiKey: 'crxpay_pub_live_…',
  // the SDK uses chrome.storage.local
  // for the offline-signed entitlement cache
});
03 · tsx
// popup.tsx
import { crxpay } from '@crxpay/sdk';

const sub = await crxpay.checkSubscription();

if (sub.hasEntitlement('pro')) {
  unlockPro();
} else {
  showPaywall();
}
04 · ts
// on "Upgrade" click
await crxpay.openCheckout({
  priceId: 'price_1Pqk…',
  successUrl: 'chrome-extension://…/success.html',
});

Compatibility

One build. Every Chromium browser.

If it speaks MV3, crxpay works. The same zip you upload to the Chrome Web Store runs unmodified on Edge, Brave, Opera, Arc, and Vivaldi.

C
Chrome
MV3 · 121+
Primary
E
Edge
Chromium 121+
Supported
B
Brave
Chromium 121+
Supported
O
Opera
Chromium 111+
Supported
A
Arc
Chromium 126+
Supported
V
Vivaldi
Chromium 120+
Supported
F
Firefox
MV3 · V1
Coming V1
S
Safari
Web Ext · V2
V2

Pitfalls

The three MV3 traps — and how crxpay avoids them.

×The trapfetch() inside popup.html

Triggers CORS pre-flight every time. Breaks when the host blocks cross-origin.

✓crxpay doeschrome.runtime.sendMessage → service worker

crxpay marshals the call through the worker. The pop-up never touches the network.

×The trapStore sub status in memory

The service worker evicts after 30s of idle. Your Pro badge disappears.

✓crxpay doesSigned cache in chrome.storage.local

HMAC-signed blob survives eviction, restarts, and offline mode. Verified by the SDK on read.

×The trapHardcode price IDs in the extension

Every price change requires a full re-submission to the Chrome Web Store.

✓crxpay doesFetch offerings from crxpay

Ship once. Change prices, trials, and paywall copy from the dashboard.

Ready to grow?

Our entire suite of features comes standard — and your first $2,500 in tracked revenue is free.