Chrome Extensions接入Stripe最佳实践
Chrome Extensions接入Stripe最佳实践

Chrome Extensions接入Stripe最佳实践

URL
Tags
Node.js
Software Development
Published
March 8, 2024
Author
 
💡
经过长达八个小时以上的探索与实践,我成功在Manifest V3版本的Chrome Extensions中接入Striped的PricingTable功能。
 
先展示目前已成功实现的集成效果:
notion image

使用Plasmo搭建Chrome Extensions

 
搭建一个Extensions,我这里通过使用Plasmo快速搭建了我自己的Extensions程序。通过创建content.tsx 即可创建你自己的程序入口,我这里选择使用React进行开发。
 
关于CSUI的具体原理可以了解官方文档:How does Plasmo CSUI work? 这里大致说一下,CSUI主要通过Shadow DOM实现的,这个要关注一下,后续有关联。

搭建Server并部署到Vercel

 
在搭建Server上面,我直接参考官方提供的Checkout single subscription例子,然后结合Vercel的官方文档,自己实现了一版:
express
notion-niceUpdated Mar 7, 2024
。你可以参考该repo自行实现。
 
然后根据Using Express.js with Vercel进行部署即可。

入口文件api/index.js 源码解析

 
重点关注/pay/:customer/:theme? 路由中的实现,这是一个基于ejs实现的一个PricingTable页面,通过官方SDK生成Sessions并传递给PricingTable组件,对应大的ejs文件在views/pay.ejs。该路由请求呈现效果就是文章一开始演示的支付页面啦,源码中涉及的PRICING_TABLE_ID 参数,需要你自己在stripe后台创建对应的PricingTable 中获取并替换 。关于 PricingTable 更多信息可以查阅官方教程:Embeddable pricing table for SaaS businesses

把Server的页面嵌入到Chrome Extensions中

 
在集成方面,我写了一个组件进行操作,以下是部分实现代码:
// Upgrade.tsx import { useMount } from "ahooks" import React, { useContext, useState } from "react" import { Button } from "./ui/button" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, type DialogContentProps } from "./ui/dialog" export const Upgrade = ({ portalProps }: Pick<DialogContentProps, "portalProps">) => { const [paymentUrl, setPaymentUrl] = useState("") useMount(async () => { const user = {} // TODO: 获取用户信息 const { customerId } = await axiosStripe .post("/create-payment", { userId, email: user.email, name: user.name }) .then((r) => r.data) setPaymentUrl(`${baseURL}/pay/${customerId}`) }) return ( <Dialog> <DialogTrigger asChild> <Button variant="link">升级到Plus</Button> </DialogTrigger> <DialogContent portalProps={portalProps}> <DialogHeader> <DialogTitle>升级到Plus</DialogTitle> </DialogHeader> <div className="nf-w-full nf-h-[460px]"> {paymentUrl && ( <iframe src={paymentUrl} allowTransparency className="nf-w-full nf-h-full nf-border-none" /> )} </div> </DialogContent> </Dialog> ) }
组件使用了shadcn/uiTailwind CSS进行开发,在这里通过iframe嵌入了我们Server中的支付页面,把customer放到Url上面传递给服务器。

实现原理

目前Manifest V3版本不支持应用远程请求外部js,所以如果你直接使用官方SDK集成到你的Extensions里面,就会存在CSP问题,这里在stripe-js也有过讨论。
 
但是有一种情况是例外的:在沙盒化 iframe 中嵌入远程托管代码 ,而我们通过Plasmo创建的Extensions默认就已经通过Shadow DOM实现了,所以在Upgrade.tsx组件中可以直接通过iframe 嵌入我们自己搭建的Server页面啦~

 
本文内容使用 Notion Nice 排版。