Skip to Content
LaunchExt | Chrome 扩展开发平台 (Next.js + Plasmo) 🚀 Read more → 
文档Stripe 集成指南

使用 Stripe 快速开始

介绍

Stripe 是一个支付处理平台。用例包括:

  • 通过昂贵 API 调用获利
  • 通过高级扩展功能获利
  • 销售主题、商品、实体和数字商品等

场景

您是一家 SaaS 公司,希望通过扩展向客户提供高级 API 服务。您希望用户在扩展可以访问此高级功能之前每月支付 5 美元。

设置 Stripe 产品链接

由于 Manifest v3 对远程代码执行的限制 ,将符合 PCI 标准的支付系统集成到扩展中的选项有限。最简单的方法是设置 Stripe 产品链接。

要设置 Stripe 产品链接,您必须创建一个 Stripe 产品。前往 Stripe 产品仪表板 页面,点击添加产品,然后填写信息:

Stripe 添加产品

然后,转到产品页面并点击 创建支付链接 按钮:

Stripe 创建支付

以上操作应该会为您提供 Stripe 支付链接。对于后端授权,请前往 Stripe 仪表板主页 获取密钥:

Stripe 开发密钥

使用环境变量

假设您已经设置了一个基本的 Plasmo 项目,第一件事是设置我们的环境变量

env.development
PLASMO_PUBLIC_STRIPE_LINK=https://buy.stripe.com/test_XXXXXXXX STRIPE_PRIVATE_API_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxx

要启用 TypeScript IntelliSense,创建一个 index.d.ts 文件:

.index.d.ts

访问 Chrome 身份 API

要将订阅与用户关联,我们可以使用他们的电子邮件地址。一种快速方法是利用 Chrome 扩展的身份 API 。为了防止未经授权的访问,我们需要设置 OAuth2 认证方案,其工作原理如下:

  • 我们的扩展生成 OAuth2 访问令牌
  • 扩展使用令牌向我们的后端发送请求
  • 后端验证令牌以获取用户的电子邮件地址
  • 后端查询用户的订阅状态

要启用此功能所需的权限,请将以下内容添加到 package.json 文件的 manifest 字段中:

package.json
{ ... "manifest": { ... "permissions": ["identity", "identity.email"] } }
🚨

... 表示如果您已经有任何内容,请保留它。您将在我们的许多代码示例中看到这一点。

然后,我们需要使用 Google Cloud Platform (GCP) 设置 OAuth2 客户端 ID。按照本指南 在 GCP 中快速创建一个新项目,然后导航到凭据页面:https://console.cloud.google.com/apis/credentials?referrer=search&project=<YOUR_PROJECT_ID>。它将显示类似以下内容:

GCP 凭据页面

点击 创建凭据,然后选择 OAuth 客户端 ID

创建 OAuth 客户端 ID

在下一页,选择 Chrome 应用。表单将要求输入 应用程序 ID

创建 Chrome 应用客户端 ID

这将是您的扩展 ID - 下一节是关于如何获取它。

为开发设置固定扩展 ID

您会希望为开发固定您的扩展 ID。如果您不小心从浏览器中删除了开发扩展,扩展 ID 将丢失,您的 OAuth2 客户端将失效。

由于 Chromium 从公钥派生扩展 ID,您可以通过生成自己的 key 来固定它。您可以在 package.jsonmanifest 覆盖中指定它。我们可以按照这个 Stack Overflow 答案 生成此密钥:

  1. 生成私钥:
openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -out key.pem
  1. 从上面的私钥生成公钥:
openssl rsa -in key.pem -pubout -outform DER | openssl base64 -A

然后,我们可以通过在清单覆盖中利用环境变量来使用此密钥:

.env.development
... CRX_PUBLIC_KEY=v47xxx
package.json
{ "manifest": { ... "key": "$CRX_PUBLIC_KEY" } }

运行开发服务器然后将扩展加载到浏览器中。然后,复制扩展 ID:

复制扩展 ID

将 ID 粘贴到 OAuth 表单的应用程序 ID 字段中,然后提交。您将收到您的 OAuth2 客户端 ID:

OAuth 客户端 ID

将其添加到您的环境变量中:

.env.development
... OAUTH_CLIENT_ID=<YOUR_OAUTH_CLIENT_ID>

并在我们的清单覆盖中使用它:

package.json
{ ... "manifest": { ... "oauth2": { "client_id": "$OAUTH_CLIENT_ID", "scopes": [ "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" ] } } }

我们现在准备好生成 OAuth 访问令牌来授权和处理用户的订阅!

访问用户信息

我们可以使用 chrome.identity.getProfileUserInfo 来了解我们的用户是谁。为了缓存这些数据并在我们的应用程序中重用,我们可以创建一个快速的 React 上下文 。最简单的方法是使用 puro - Plasmo 的上下文实用程序库。通过将库添加到您的 package.json 文件并运行 pnpm i 来安装它:

package.json
{ ... "dependencies": { ... "puro": "0.3.4" } }

然后,我们可以创建我们的提供者:

core/user-info.tsx

core/user-info.tsx
import { createProvider } from "puro" import { useContext, useEffect, useState } from "react" const useUserInfoProvider = () => { const [userInfo, setUserInfo] = useState<chrome.identity.UserInfo>(null) useEffect(() => { chrome.identity.getProfileUserInfo((data) => { if (data.email && data.id) { setUserInfo(data) } }) }, []) return userInfo } const { BaseContext, Provider } = createProvider(useUserInfoProvider) export const useUserInfo = () => useContext(BaseContext) export const UserInfoProvider = Provider

并在我们的弹出窗口中使用它:

popup.tsx

popup.tsx
import { UserInfoProvider, useUserInfo } from "~core/user-info" const EmailShowcase = () => { const userInfo = useUserInfo() return ( <div> 您的邮箱是: <b>{userInfo?.email}</b> </div> ) } function IndexPopup() { return ( <UserInfoProvider> <div style={{ display: "flex", flexDirection: "column", padding: 16 }}> <h1> 欢迎使用您的 <a href="https://www.plasmocn.org">Plasmo</a> 扩展! </h1> <EmailShowcase /> </div> </UserInfoProvider> ) } export default IndexPopup

将 Stripe 链接集成到弹出页面

为了将 Stripe 支付链接与身份 API 流线化,我们可以通过他们的 API 参数 预先填写 Stripe 托管表单上的电子邮件,使用从上面的 UserInfoProvicer 获取的电子邮件。在将用户重定向到 Stripe 支付之前,让我们还调用 OAuth 流程以确保客户同意我们使用他们的电子邮件地址。这也将启动我们扩展的访问令牌缓存,允许将来的调用是非交互式的。

popup.tsx

popup.tsx
<button disabled={!userInfo} onClick={async () => { chrome.identity.getAuthToken( { interactive: true }, (token) => { if (!!token) { window.open( `${process.env.PLASMO_PUBLIC_STRIPE_LINK}?client_reference_id=${ userInfo.id }&prefilled_email=${encodeURIComponent(userInfo.email)}`, "_blank" ) } } ) }}> 订阅付费功能 </button>

验证订阅并启用一些高级功能

我们现在将设置我们的后端来验证用户的订阅。我们可以通过利用 NextJS 与 Plasmo 的互操作性来简化这个过程。我们将首先安装 NextJS 和一些实用程序库:

package.json
{ "scripts": { "start": "next start", "dev": "run-p dev:*", "dev:plasmo": "plasmo dev", "dev:next": "next dev --port 8472", "build": "run-p build:*", "build:plasmo": "plasmo build", "build:next": "next build" }, ... "dependencies": { ... "next": "12.1.6", "google-auth-library": "8.0.2", "swr": "1.3.0", "stripe": "9.8.0" }, "devDependencies": { ... "@plasmohq/rps": "1.3.4", } }
📝

@plasmohq/rps 是来自 Plasmo 的辅助库,用于促进并行或顺序运行脚本。它是 npm-run-all  的现代化分支。

一旦我们设置了依赖项,让我们创建一些实用函数:

然后,我们创建我们的 2 个 API 路由:一个用于检查用户的订阅,一个用于调用高级功能。两个 API 路由都必须首先解析授权标头以获取访问令牌,然后使用令牌独立获取用户配置文件,然后使用配置文件的数据获取用户的订阅。

要从我们的扩展调用开发服务器,我们可以使用环境变量存储 API URI 并在我们的清单主机中引用它:

.env.development
PLASMO_PUBLIC_API_URI=http://localhost:8472 ...
package.json
{ ... "manifest": { ... "host_permissions": [ "$PLASMO_PUBLIC_API_URI/*", "https://*/*" ] } }

终止并重新运行 pnpm dev 以启动我们的后端和扩展的开发服务器。在我们调用我们的 API 之前,让我们设置更多客户端助手:

现在,我们可以使用 swr 在我们的弹出窗口中调用和重新验证 check-subscription API:

popup.tsx
import useSWR from "swr" import { callAPI } from "~core/premium-api" ... const { data, error } = useSWR<{ active: boolean }>( "/api/check-subscription", callAPI ) if (!!error || !data?.active) { // 没有有效订阅,显示支付按钮 } // 有有效订阅,显示高级功能按钮

然后,调用我们的高级功能:

popup.tsx
<button onClick={async () => { const data = await callAPI("/api/premium-feature", { method: "POST" }) alert(data.code) }}> 调用 Awesome 高级功能 </button>

完整示例

有关完整示例,请查看示例 GitHub 仓库中的 with-stripe 

最后更新于