使用 Stripe 快速开始
介绍
Stripe 是一个支付处理平台。用例包括:
- 通过昂贵 API 调用获利
- 通过高级扩展功能获利
- 销售主题、商品、实体和数字商品等
场景
您是一家 SaaS 公司,希望通过扩展向客户提供高级 API 服务。您希望用户在扩展可以访问此高级功能之前每月支付 5 美元。
设置 Stripe 产品链接
由于 Manifest v3 对远程代码执行的限制 ,将符合 PCI 标准的支付系统集成到扩展中的选项有限。最简单的方法是设置 Stripe 产品链接。
要设置 Stripe 产品链接,您必须创建一个 Stripe 产品。前往 Stripe 产品仪表板 页面,点击添加产品,然后填写信息:

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

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

使用环境变量
假设您已经设置了一个基本的 Plasmo 项目,第一件事是设置我们的环境变量:
PLASMO_PUBLIC_STRIPE_LINK=https://buy.stripe.com/test_XXXXXXXX
STRIPE_PRIVATE_API_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxxx要启用 TypeScript IntelliSense,创建一个 index.d.ts 文件:
访问 Chrome 身份 API
要将订阅与用户关联,我们可以使用他们的电子邮件地址。一种快速方法是利用 Chrome 扩展的身份 API 。为了防止未经授权的访问,我们需要设置 OAuth2 认证方案,其工作原理如下:
- 我们的扩展生成 OAuth2 访问令牌
- 扩展使用令牌向我们的后端发送请求
- 后端验证令牌以获取用户的电子邮件地址
- 后端查询用户的订阅状态
要启用此功能所需的权限,请将以下内容添加到 package.json 文件的 manifest 字段中:
{
...
"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>。它将显示类似以下内容:

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

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

这将是您的扩展 ID - 下一节是关于如何获取它。
为开发设置固定扩展 ID
您会希望为开发固定您的扩展 ID。如果您不小心从浏览器中删除了开发扩展,扩展 ID 将丢失,您的 OAuth2 客户端将失效。
由于 Chromium 从公钥派生扩展 ID,您可以通过生成自己的 key 来固定它。您可以在 package.json 的 manifest 覆盖中指定它。我们可以按照这个 Stack Overflow 答案 生成此密钥:
- 生成私钥:
openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -out key.pem- 从上面的私钥生成公钥:
openssl rsa -in key.pem -pubout -outform DER | openssl base64 -A然后,我们可以通过在清单覆盖中利用环境变量来使用此密钥:
...
CRX_PUBLIC_KEY=v47xxx{
"manifest": {
...
"key": "$CRX_PUBLIC_KEY"
}
}运行开发服务器然后将扩展加载到浏览器中。然后,复制扩展 ID:

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

将其添加到您的环境变量中:
...
OAUTH_CLIENT_ID=<YOUR_OAUTH_CLIENT_ID>并在我们的清单覆盖中使用它:
{
...
"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 来安装它:
{
...
"dependencies": {
...
"puro": "0.3.4"
}
}然后,我们可以创建我们的提供者:
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并在我们的弹出窗口中使用它:
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 流程以确保客户同意我们使用他们的电子邮件地址。这也将启动我们扩展的访问令牌缓存,允许将来的调用是非交互式的。
<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 和一些实用程序库:
{
"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 并在我们的清单主机中引用它:
PLASMO_PUBLIC_API_URI=http://localhost:8472
...{
...
"manifest": {
...
"host_permissions": [
"$PLASMO_PUBLIC_API_URI/*",
"https://*/*"
]
}
}终止并重新运行 pnpm dev 以启动我们的后端和扩展的开发服务器。在我们调用我们的 API 之前,让我们设置更多客户端助手:
现在,我们可以使用 swr 在我们的弹出窗口中调用和重新验证 check-subscription API:
import useSWR from "swr"
import { callAPI } from "~core/premium-api"
...
const { data, error } = useSWR<{ active: boolean }>(
"/api/check-subscription",
callAPI
)
if (!!error || !data?.active) {
// 没有有效订阅,显示支付按钮
}
// 有有效订阅,显示高级功能按钮然后,调用我们的高级功能:
<button
onClick={async () => {
const data = await callAPI("/api/premium-feature", {
method: "POST"
})
alert(data.code)
}}>
调用 Awesome 高级功能
</button>完整示例
有关完整示例,请查看示例 GitHub 仓库中的 with-stripe 。