crxpaydocs

Migrate from ExtPay

Step-by-step guide to switch from ExtPay to crxpay.

Why migrate?

FeatureExtPaycrxpay
Offline subscription cacheNo — status disappears on network failureYes — HMAC-signed local cache
MV3 nativePartial — CORS workarounds neededYes — built for MV3 from day one
Subscription state machineAd-hoc string checksXState FSM — invalid states impossible
Payment processorExtPay's Stripe accountYour own Stripe account (Stripe Connect)
EntitlementsNo — boolean paid/unpaidYes — hasEntitlement('pro'), hasEntitlement('ai')
Platform fee5% (always, from dollar one)0% under $2,500 lifetime, then 2.5% — half the rate
Analytics dashboardBasicMRR, churn, trial conversion, per-customer timeline
Test modeLimitedFull test/live mode with separate Stripe keys

Migration steps

Step 1: Create a crxpay account

  1. Sign up at crxpay dashboard
  2. Register your extension (same Chrome Extension ID)
  3. Connect your Stripe account
  4. Create products, prices, and entitlements matching your ExtPay setup

Step 2: Install the crxpay SDK

npm uninstall extpay
npm install @crxpay/sdk

Step 3: Replace ExtPay code

Before (ExtPay):

// background.js
import ExtPay from 'extpay';
const extpay = ExtPay('your-extension-id');
extpay.startBackground();

extpay.onPaid.addListener((user) => {
  console.log('User paid!');
});

After (crxpay):

// background.js
import { CrxPay } from '@crxpay/sdk/background';

const client = CrxPay.configure({
  apiKey: 'crxpay_pub_YOUR_KEY',
});

client.onPaid.addListener((subscription) => {
  console.log('User paid!', subscription.status);
});

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.type?.startsWith('CRXPAY_')) {
    client.handleMessage(msg, sender).then(sendResponse);
    return true;
  }
});

Step 4: Replace subscription checks

Before (ExtPay):

const user = await extpay.getUser();
if (user.paid) {
  enablePremium();
}

After (crxpay):

import { CrxPay } from '@crxpay/sdk';

const result = await CrxPay.getSubscription();
if (result.ok && result.data.hasEntitlement('pro')) {
  enablePremium();
}

Step 5: Replace payment triggers

Before (ExtPay):

extpay.openPaymentPage();

After (crxpay):

await CrxPay.openCheckout('price_YOUR_PRICE_ID');
// or for the default offering:
await CrxPay.openCheckout();

Step 6: Replace login flow

Before (ExtPay):

extpay.openLoginPage();

After (crxpay):

// crxpay uses email identification instead of a login page
await CrxPay.identify('user@example.com');

Step 7: Update manifest.json

{
  "permissions": [
    "storage",
+   "alarms"
  ],
  "host_permissions": [
-   "https://extensionpay.com/*"
+   "https://api.crxpay.io/*"
  ]
}

Step 8: Handle existing paid users

Existing ExtPay users won't automatically appear in crxpay. You have two options:

Option A: Grant entitlements manually Use the crxpay dashboard to manually grant entitlements to existing paid users via Customers > Grant Entitlement.

Option B: Parallel check during transition Run both ExtPay and crxpay checks during a transition period:

// Transition period — check both systems
const extpayUser = await extpay.getUser();
const crxpayResult = await CrxPay.getSubscription();

const hasPaidAccess =
  extpayUser.paid ||
  (crxpayResult.ok && crxpayResult.data.hasEntitlement('pro'));

if (hasPaidAccess) {
  enablePremium();
}

API equivalents

ExtPaycrxpayNotes
ExtPay('id')CrxPay.configure({ apiKey })Config in background only
extpay.startBackground()Handled by configure()Automatic
extpay.getUser()CrxPay.getSubscription()Returns typed Result<Subscription>
user.paidsubscription.hasEntitlement('pro')More granular access control
extpay.openPaymentPage()CrxPay.openCheckout()Opens Stripe Checkout
extpay.openLoginPage()CrxPay.identify(email)Programmatic, no redirect
extpay.onPaidCrxPay.onPaidSame event pattern
N/ACrxPay.getOfferings()Dynamic pricing from dashboard
N/ACrxPay.setAttributes()Customer segmentation
N/ACrxPay.openBillingPortal()Stripe self-serve portal
N/ACrxPay.syncSubscription()Force refresh after checkout

Was this page helpful?

Your feedback shapes what we document next.