b0VIM 9.0`-eR;glenGlens-MacBook-Air-2.local~glen/code/extensionpay/ExtPay/README.mdutf-8 3210#"! UtpMaNUTad VMPOI9`ZWSR d ^ k )  gf^\G71/+*>=<  ica]\VU```js```} } "service_worker": "background.js" "background": {{```json### Manifest V3With either Manifest V3 or Manifest V2 you'll need to **[sign up and register an extension](https://extensionpay.com)**. When you register an extension you'll create an extension id that you'll use when initializing `ExtPay`. We'll use `sample-extension` as the extension id in the following examples.You need to put `ExtPay` in your background file, often named something like `background.js`. If you don't include `ExtPay` in your background file it won't work correctly. If you're using a bundler you can `import 'ExtPay'` or `require('ExtPay')` right in your `background.js`.## 3. Add `ExtPay` to `background.js` (required!)If you have a `"content_security_policy"` in your manifest or get a `Refused to connect to 'https://extensionpay.com...'` error, you'll have to add `connect-src https://extensionpay.com` to your extension's content security policy. See Mozilla's documentation for more details.ExtPay will not show a scary permission warning when users try to install your extension.```} ] "storage" "permissions": [{```jsonExtPay needs the following configuration in your `manifest.json` (for both manifest v2 and v3):## 2. Configure your `manifest.json````npm install extpay --save```bashCopy the [dist/ExtPay.js](dist/ExtPay.js) file into your project, or, if you're using a bundler (like Webpack or Rollup):## 1. InstallIf you like this library, please star it! ⭐️ It helps us out :)**Note**: ExtPay.js doesn't contain malware or track your users in any way. This library only communicates with ExtensionPay.com servers to manage users' paid status. 9. [Use `extpay.openLoginPage()` to let the user log in if they've paid already](#9-use-extpayopenloginpage-to-let-the-user-log-in-if-theyve-paid-already) 8. [Use `extpay.openTrialPage()` to let the user sign up for a free trial](#8-use-extpayopentrialpage-to-let-the-user-sign-up-for-a-free-trial) 7. [Use `extpay.openPaymentPage()` to let the user manage their subscription preferences](#7-use-extpayopenpaymentpage-to-let-the-user-manage-their-subscription-preferences) 6. [Use `extpay.onPaid.addListener()` to run code when the user pays](#6-use-extpayonpaidaddlistener-to-run-code-when-the-user-pays) 5. [Use `extpay.openPaymentPage()` to let the user pay](#5-use-extpayopenpaymentpage-to-let-the-user-pay) * [`user` object properties](#user-object-properties) 4. [Use `extpay.getUser()` to check a user's paid status](#4-use-extpaygetuser-to-check-a-users-paid-status) 3. [Add `ExtPay` to `background.js` (required!)](#3-add-extpay-to-backgroundjs-required) 2. [Configure your `manifest.json`](#2-configure-your-manifestjson) 1. [Install](#1-install)Below are directions for using this library in your browser extension. If you learn better by example, you can also view the code for a **[sample extension](sample-extension-mv3/)**. This library uses [Mozilla's webextension-polyfill library](https://github.com/mozilla/webextension-polyfill) internally for compatability across browsers which means it should work on almost all modern browsers.```}) } extpay.openPaymentPage() } else { // ... if (user.paid) {extpay.getUser().then(user => {extpay.startBackground();const extpay = ExtPay('your-extension-id');// your-extension/background.js// Example code```jsThe JavaScript library for [ExtensionPay.com](https://extensionpay.com), a service to easily add payments to browser extensions.# ExtPay.js — Payments in browser extensionsadSRBA04. `npm run dist` before committing changes.3. `npm run dev`2. Edit `ExtPay.dev.js`1. `npm install`## ContributingA page will open that will allow the user to enter the email they paid with to receive a magic login link. This page can also be accessed through the normal payment screen.adSRBA04. `npm run dist` before committing changes.3. `npm run dev`2. Edit `ExtPay.dev.js`1. `npm install`## ContributingA page will open that will allow the user to enter the email they paid with to receive a magic login link. This page can also be accessed through the normal payment screen.adRI`EA@~}wJ  V N L 8  Z Y p j S *   4 3 z<ED  ~ONfe  ## 7. Use `extpay.onPaid.addListener()` to run code when the user paysDepending on how you configure your extension, users that have paid before can log in to activate their paid features on different browsers, profiles, or after uninstalling/reinstalling.While testing, use your ExtensionPay email to test payments without entering credit card information. Reinstall the extension to reset back to an unpaid user.It is best to open the payment page when the user has a clear idea of what they're paying for.Note: `extpay.openPaymentPage()` can fail to open the popup if there is a network error. Please consider this possibility in your code.![popup screenshot](docs/popup_screenshot.png)The payment page looks like this:```extpay.openPaymentPage()```jsOpens a browser popup where the user can pay to upgrade their status.## 5. Use `extpay.openPaymentPage()` to let the user pay| `user.subscriptionCancelAt` | `null` or `Date()` object that the user's subscription is set to cancel or did cancel at. || `user.subscriptionStatus` | One of `active`, `past_due`, or `canceled`. `active` means the user's subscription is paid-for. `past_due` means the user's most recent subscription payment has failed (expire| `user.plan` | `null` or the `plan` the user is on. For example: `{unitAmountCents: 1000, currency: 'usd', nickname: null, intervalCount: 1, interval: 'month'}`. Unpaid users never have a plan. See `extpay.getPlans()` elsewhere in this README for more detail. || `user.trialStartedAt` | `null` or `Date()` object the user confirmed their free trial. || `user.installedAt` | `Date()` object the user installed the extension. || `user.email` | The user's email if there is one or `null`.|| `user.paidAt` | `Date()` object that the user first paid or `null`.|| `user.paid` | `true` or `false`. `user.paid` is meant to be a simple way to tell if the user should have paid features activated. For subscription payments, `paid` is only true if `subscriptionStatus` is `active`. || --- | --- || property | description |### `user` object propertiesThe `user` object returned from `extpay.getUser()` has the following properties:It is possible for `extpay.getUser()` to throw an error in case of a network failure. Please consider this possibility in your code e.g. `extpay.getUser().then(/* ... */).catch(/* handle error */)````} } // ... if (user.paid) { const user = await extpay.getUser();async function foo() {```jsor use `await`:```}) } // ... } else { // ... if (user.paid) {extpay.getUser().then(user => {```jsThis method makes a network call to get the extension user's paid status and returns a `user` object.## 4. Use `extpay.getUser()` to check a user's paid status```extpay.startBackground();const extpay = ExtPay('sample-extension')// background.js```js```} } "scripts": ["ExtPay.js", "background.js"] "background": {{```jsonIf you're not using a bundler, add `ExtPay.js` to `manifest.json`:### Manifest V2Make sure not to use `extpay.startBackground()` in callbacks — it should only be called once.```}) // ... var extpay = ExtPay('sample-extension');chrome.storage.local.get('foo', function() {```js**Note about service workers**: In the example above `extpay` will become undefined when accessed in service worker callbacks. To use `extpay` in service worker callbacks, redeclare it like so:```extpay.startBackground(); var extpay = ExtPay('sample-extension'); // Careful! See note belowimportScripts('ExtPay.js') // or `import` / `require` if using a bundler// background.jsadUb_[Zb;1+)%$ o n m   \ [ U < 8 7 { z    A@uU9a[XTS e[USON## 10. Use `extpay.openLoginPage()` to let the user log in if they've paid already```} ] } "run_at": "document_start" "js": ["ExtPay.js"], "matches": ["https://extensionpay.com/*"], { "content_scripts": [{```jsonYou can also use `extpay.onTrialStarted.addListener()` to run functions when the user's trial starts. Like `onPaid`, you need to include the following in your `manifest.json` to make it work:Note that `extpay.openTrialPage(displayText)` takes an optional string argument that is displayed to the user on the trial page. For example, `extpay.openTrialPage('7-day')` would change the trial prompt from `Enter an email to start your free trial` to `Enter an email to start your *7-day* free trial`. This is meant to give your users a better idea of what they're signing up for.```}) } // user's trial is not active } else { // user's trial is active if (user.trialStartedAt && (now - user.trialStartedAt) < sevenDays) { const sevenDays = 1000*60*60*24*7 // in milliseconds const now = new Date();extpay.getUser().then(user => {const extpay = ExtPay('sample-extension');```jsFor example, if you wanted a 7 day trial period, you could use a check like this:The user will be sent an email with a link that they can use to start their free trial. Once the user clicks the link, you can use the `trialStartedAt` property from `extpay.getUser()` in your extension to check if the trial has expired.Screenshot of trial page If you want to give your users a trial period of your extension, you can use `extpay.openTrialPage()`, which looks something like this:## 9. Use `extpay.openTrialPage()` to let the user sign up for a free trialNote: please read the **[detailed docs on subscriptions here](/docs/how_subscriptions_work.md)**.Screenshot of example subscription management page. The subscription management page looks something like this:```extpay.openPaymentPage()```jsIf your extension is configured for subscription payments, you can let the user manage their subscription from within the extension with the same function you used to let them pay:## 8. Use `extpay.openPaymentPage()` to let the user manage their subscription preferencesNote: `onPaid` callbacks will be called after a user pays as well as after a user "logs in" (e.g. activates their paid account on a different browser/profile/install). This may change in the future -- if you'd like this to work differently, please contact me with a detailed explanation of your use case :)You can add as many callback functions as you want.The content script is required to enable `extpay.onPaid` callbacks. It will add a permissions warning when installing your extension. If you're using a bundler, you can create a file called something like `ExtPay_content_script.js` that only contains `import 'ExtPay'` or `require('ExtPay')` and use that in the `"js"` field above.```} ] } "run_at": "document_start" "js": ["ExtPay.js"], "matches": ["https://extensionpay.com/*"], { "content_scripts": [{```jsonTo use this feature, you will need to include the following content script configuration in your `manifest.json`:```}) console.log('user paid!')extpay.onPaid.addListener(user => {```jsIf you want to run some code when your user pays, use `extpay.onPaid.addListener()`:adjD+ u t , & 0 /     U T   kT> ~zyL>+m_ -## 7. Use `extpay.onPaid.addListener()` to run code when the user pays| `plan.intervalCount` | `null` if `interval` is `'once'`, otherwise the number of intervals the plan is charged. For example: an `intervalCount` of `2` with an `interval` of `'month'` would mean the plan charges every 2 months. || `plan.interval` | The recurring interval the plan is charged. One of `'month'`, `'year'`, or `'once'`. || `plan.nickname` | An optional plan nickname for the developer to use in identifying plans. Can be editing in extension settings. || `plan.currency` | The ISO 4217 currency the unit amount is in. For example: `'usd'` || `plan.unitAmountCents` | The amount in cents that the user pays in one interval. || --- | --- || property | description |``` } intervalCount: number | null; interval: 'month' | 'year' | 'once'; nickname: string | null; currency: string; unitAmountCents: number; interface Plan {```typescriptThe specification for plans looks like this:``` ] } interval: 1 intervalCount: 'year', nickname: null, currency: 'usd', unitAmountCents: 9900, { }, interval: 1 intervalCount: 'month', nickname: null, currency: 'usd', unitAmountCents: 1000, { [ > await extpay.getPlans();```typescriptFor example, an extension with a $10 monthly and $99 yearly plan might look like this:## 6. Use `extpay.getPlans()` to list available payment plansDepending on how you configure your extension, users that have paid before can log in to activate their paid features on different browsers, profiles, or after uninstalling/reinstalling.While testing, use your ExtensionPay email to test payments without entering credit card information. Reinstall the extension to reset back to an unpaid user.It is best to open the payment page when the user has a clear idea of what they're paying for.You can optionally include your `planNickname` as an argument to `extpay.openPaymentPage()` to directly open the Stripe payment page for that plan. For example: `extpay.openPaymentPage('my_plan_nickname')`. Plan nicknames can be edited in the ExtensionPay.com extension settings page. Note: `extpay.openPaymentPage()` can fail to open the tab if there is a network error. Please consider this possibility in your code.![popup screenshot](docs/popup_screenshot.png)The payment page looks like this:```extpay.openPaymentPage()```jsOpens a new browser tab where the user can pay to upgrade their status.## 5. Use `extpay.openPaymentPage()` to let the user pay| `user.subscriptionCancelAt` | `null` or `Date()` object that the user's subscription is set to cancel or did cancel at. || `user.subscriptionStatus` | One of `active`, `past_due`, or `canceled`. `active` means the user's subscription is paid-for. `past_due` means the user's most recent subscription payment has failed (expired card, insufficient funds, etc). `canceled` means that the user has canceled their subscription and the end of their last paid period has passed. [You can read more about how subscriptions work here](/docs/how_subscriptions_work.md). || **subscription only**| |