ExtPay.js Documentation

repository·main·Indexed 19 days ago

https://github.com/glench/extpay

A JavaScript library for integrating payments into browser extensions via ExtensionPay.com without requiring a server. It provides tools for managing subscriptions, one-time payments, free trials, and discount codes via Stripe. Key features include user status tracking with extpay.getUser(), payment page redirection with extpay.openPaymentPage(), and event listeners for payment and trial activations. Supports Manifest V2 and V3.

Tokens
3.5K
Snippets
13
Records
17
Agent score
72%

What's inside extpay

  1. How subscription statuses work in ExtPay

    main

    ExtPay manages subscription lifecycles through the user object returned by extpay.getUser(). Understanding the relationship between user.paid, user.subscriptionStatus, and user.subscriptionCancelAt is critical for implementing access control.

    Subscription States

    Stateuser.paiduser.subscriptionStatususer.subscriptionCancelAtDescription
    ActivetrueactivenullUser has an active, ongoing subscription.
    Pending CancellationtrueactivedatetimeUser has canceled, but access remains until the end of the current billing cycle.
    Past Duefalsepast_duenullAutomatic payment failed. User needs to update payment method.
    CanceledfalsecanceleddatetimeThe billing cycle ended and the subscription is no longer active.
    Unpaidfalsenull / othernullUser has not purchased a subscription.
  2. Install the ExtPay sample extension on Chrome

    main

    To test the sample extension locally in Chrome, follow these steps:

    1. Open chrome://extensions/ in your browser.
    2. Enable Developer Mode using the toggle in the top right corner.
    3. Click the Load unpacked button.
    4. Select the directory containing the sample extension code.
    5. Once installed, click the extension icon (labeled "E") in the browser toolbar (or find it within the extensions "puzzle piece" menu) to view popup.html.
    1. Open chrome://extensions/
    2. Enable Developer Mode
    3. Click Load unpacked
  3. Create a coupon / promotion code in your Stripe settings

    main

    Follow these steps in your Stripe dashboard to enable discount codes:

    1. Navigate to Coupons: Go to your Stripe settings page for creation and management of coupons and promotion codes.
    2. Create a Coupon: Use the Stripe coupon creation form.
    3. Enable Promotion Codes: When configuring the coupon, you must enable the option labeled Use customer-facing coupon codes. This generates the short alphanumeric string (the promotion code) that users enter at checkout.

    User Experience: Once configured, customers will see an "add promotion code" button on the Stripe Checkout page, where they can enter their code to apply the discount.

  4. Manage subscriptions with openPaymentPage()

    main

    You can use extpay.openPaymentPage() to open a subscription management screen. This allows users to view their current plan, update payment methods, or manage their subscription status.

    It is recommended to provide a way for users to access this page from within your extension settings or profile area. In development mode, ExtPay provides a special version of this page that allows you to manually toggle subscription statuses for testing purposes.

    extpay.openPaymentPage();
  5. Initialize ExtPay in background.js

    main

    ExtPay must be added to your background script (e.g., background.js) to function correctly. You must first register your extension at ExtensionPay.com to obtain an extension ID.

    Manifest V3 (Service Worker)

    In Manifest V3, you use importScripts or a bundler to load ExtPay.

    Important: In Service Workers, the extpay instance may become undefined inside callbacks. To use it within a callback (like chrome.storage.local.get), you must re-initialize it inside that callback. However, only call extpay.startBackground() once in your script, not inside callbacks.

    Manifest V2

    In Manifest V2, add ExtPay.js to the scripts array in your background configuration before your main background script.

    // Manifest V3 example
    importScripts('ExtPay.js')
    
    var extpay = ExtPay('sample-extension');
    extpay.startBackground();
    
    // Inside a callback to avoid undefined errors
    chrome.storage.local.get('foo', function() {
        var extpay = ExtPay('sample-extension');
        // ...
    });
  6. How to Add Discount Codes to your Extensions

    main

    To enable discount codes for your browser extension, you must create coupons and promotion codes within your Stripe dashboard. This allows users to enter alphanumeric strings during the payment process to receive discounts.

    Prerequisites:

    • ExtPay must be installed in your extension.
    • You must have a connected Stripe account set up through ExtensionPay.com.
  7. Install ExtPay.js

    main

    You can install ExtPay.js via npm:

    npm install extpay --save

    If you are not using a bundler, you can manually copy the following files from the dist/ directory into your project:

    • ExtPay.js (Standard)
    • ExtPay.module.js (for ESM)
    • ExtPay.common.js (for CommonJS)
  8. Configure manifest.json for ExtPay

    main

    ExtPay requires the storage permission in your manifest.json for both Manifest V2 and V3.

    Firefox Note: You may need to include "https://extensionpay.com/*" in your extension's permissions.

    Content Security Policy (CSP): If you encounter a Refused to connect to 'https://extensionpay.com...' error, add connect-src https://extensionpay.com to your content_security_policy in the manifest.

    {
        "permissions": [
          "storage"
        ]
    }
  9. Handle all subscription states in your extension

    main

    When checking a user's access, you should account for active subscriptions, subscriptions that are set to expire (canceled but still within the billing cycle), and failed payments. Use the following pattern to handle these states:

    const extpay = ExtPay('my-extension-id');
    
    extpay.getUser().then(user => {
    
        if (user.paid && !user.subscriptionCancelAt) {
            // User is fully active
            console.log("You're paid!")
        } else if (user.paid && user.subscriptionCancelAt) {
            // User canceled, but still has access until the end of the cycle
            console.log("Your subscription will end at the next billing cycle")
        } else if (user.subscriptionStatus === 'past_due') {
            // Payment failed, prompt user to update card
            console.log("You need to update your card!");
            extpay.openPaymentPage();
        } else if (user.subscriptionStatus === 'canceled') {
            // Subscription has officially ended
            console.log("We hope you enjoyed your subscription!")
        } else {
            // User is not a paid subscriber
            console.log("You haven't paid yet :( ")
        }
    
    })
    const extpay = ExtPay('my-extension-id');
    
    extpay.getUser().then(user => {
    
        if (user.paid && !user.subscriptionCancelAt) {
            console.log("You're paid!")
        } else if (user.paid && user.subscriptionCancelAt) {
            console.log("Your subscription will end at the next billing cycle")
        } else if (user.subscriptionStatus === 'past_due') {
            console.log("You need to update your card!");
            extpay.openPaymentPage();
        } else if (user.subscriptionStatus === 'canceled') {
            console.log("We hope you enjoyed your subscription!")
        } else {
            console.log("You haven't paid yet :( ")
        }
    
    })
  10. Open the payment page with extpay.openPaymentPage()

    main

    Use extpay.openPaymentPage() to open a new browser tab where users can choose a plan and pay via Stripe.

    • Default: Opens the plan selection page.
    • Specific Plan: Pass a planNickname as an argument to go directly to the Stripe Checkout page for that specific plan (e.g., extpay.openPaymentPage('my_plan_nickname')).

    Note: This method may fail to open the tab if there is a network error.

    // Open general payment page
    extpay.openPaymentPage();
    
    // Open specific plan
    extpay.openPaymentPage('premium_monthly');
  11. Check a user's paid status with extpay.getUser()

    main

    The extpay.getUser() method performs a network call to retrieve the current user's status. It returns a user object and may throw an error if the network call fails.

    user object properties

    propertydescription
    user.paidtrue or false. For subscriptions, this is only true if subscriptionStatus is active.
    user.paidAtDate() object of first payment or null.
    user.emailUser's email or null.
    user.installedAtDate() object of extension installation.
    user.trialStartedAtDate() object of trial confirmation or null.
    user.planThe current Plan object, or null if unpaid.
    user.subscriptionStatusFor subscriptions: active, past_due, or canceled.
    user.subscriptionCancelAtDate() object of scheduled cancellation or null.
    // Using async/await
    async function checkStatus() {
        try {
            const user = await extpay.getUser();
            if (user.paid) {
                // User has access
            } else {
                // User is unpaid
            }
        } catch (err) {
            // Handle network errors
        }
    }