关于 whop
whop 是面向 Whop 平台开发者的技能指南,涵盖数字产品、会员、课程与社区访问的销售和管理。它以 API v5 示例说明结账、会员权限、支付、Webhook 与 OAuth 集成。
主要功能
- 01创建产品、计划与结账配置
- 02查询和管理会员资格
- 03检查访问权限与许可证
- 04查询支付并处理退款
- 05管理课程、章节与课时
- 06配置 Webhook 与 OAuth 应用
适用场景
- 01搭建会员订阅产品
- 02接入 Whop 结账与支付
- 03按会员状态限制内容访问
- 04处理支付事件并管理课程
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ raintree-technology/ claude-starter --skill whop安装后在 Claude Code 中输入/whop确认已加载。
详细介绍
Whop 平台专家
Whop 是一个用于销售数字产品、会员服务、课程和社群访问权限的平台。
适用场景
- 构建会员制/订阅制产品
- 集成 Whop 结账和支付
- 管理课程和教育内容
- 根据会员状态控制内容访问权限
- 处理支付事件的 Webhook
- 使用 OAuth 构建 Whop 应用
快速入门
身份验证
const headers = {
Authorization: `Bearer ${process.env.WHOP_API_KEY}`,
"Content-Type": "application/json",
};
const response = await fetch("https://api.whop.com/api/v5/me", { headers });
API 密钥类型:
- 公司 API 密钥 - 访问你自己的公司数据(Dashboard → Settings → API Keys)
- 应用 API 密钥 - 用于多租户应用(Dashboard → Developer → Your App)
核心操作
创建产品
const product = await fetch("https://api.whop.com/api/v5/products", {
method: "POST",
headers,
body: JSON.stringify({
title: "Premium Membership",
description: "Access to all content",
visibility: "visible",
}),
});
创建方案
const plan = await fetch("https://api.whop.com/api/v5/plans", {
method: "POST",
headers,
body: JSON.stringify({
product_id: "prod_xxx",
billing_period: 1,
billing_period_unit: "month",
price: 2999, // $29.99 in cents
currency: "usd",
}),
});
创建结账
const checkout = await fetch(
"https://api.whop.com/api/v5/checkout-configurations",
{
method: "POST",
headers,
body: JSON.stringify({
plan_id: "plan_xxx",
success_url: "https://yourapp.com/success",
cancel_url: "https://yourapp.com/cancel",
metadata: { user_id: "123" },
}),
}
);
const { url } = await checkout.json();
// Redirect user to url
会员管理
列出会员
const response = await fetch(
"https://api.whop.com/api/v5/memberships?valid=true",
{ headers }
);
const { data: memberships } = await response.json();
检查用户访问权限
async function checkAccess(userId: string, productId: string): Promise<boolean> {
const response = await fetch(
`https://api.whop.com/api/v5/memberships?user_id=${userId}&product_id=${productId}&valid=true`,
{ headers }
);
const { data } = await response.json();
return data.length > 0;
}
验证许可证密钥
async function validateLicense(licenseKey: string): Promise<boolean> {
const response = await fetch(
`https://api.whop.com/api/v5/memberships?license_key=${licenseKey}`,
{ headers }
);
const { data } = await response.json();
return data.length > 0 && data[0].valid;
}
取消会员资格
await fetch(
`https://api.whop.com/api/v5/memberships/${membershipId}/cancel`,
{
method: "POST",
headers,
}
);
支付
获取支付信息
const payment = await fetch(
`https://api.whop.com/api/v5/payments/${paymentId}`,
{ headers }
);
退款
await fetch(`https://api.whop.com/api/v5/payments/${paymentId}/refund`, {
method: "POST",
headers,
body: JSON.stringify({
amount: 1000, // Optional: partial refund in cents
}),
});
课程
创建课程
const course = await fetch("https://api.whop.com/api/v5/courses", {
method: "POST",
headers,
body: JSON.stringify({
product_id: "prod_xxx",
title: "Complete Web Development",
description: "Learn fullstack from scratch",
visibility: "visible",
}),
});
创建章节
const chapter = await fetch("https://api.whop.com/api/v5/course-chapters", {
method: "POST",
headers,
body: JSON.stringify({
course_id: "course_xxx",
title: "Introduction to JavaScript",
order: 1,
}),
});
创建课程
const lesson = await fetch("https://api.whop.com/api/v5/course-lessons", {
method: "POST",
headers,
body: JSON.stringify({
chapter_id: "chapter_xxx",
title: "Variables and Data Types",
content: "Lesson content in markdown...",
type: "video", // or 'text', 'quiz', 'assignment'
video_url: "https://youtube.com/watch?v=...",
order: 1,
}),
});
标记课程已完成
await fetch(
`https://api.whop.com/api/v5/course-lessons/${lessonId}/mark-as-completed`,
{
method: "POST",
headers: {
Authorization: `Bearer ${userAccessToken}`,
},
}
);
Webhook
设置端点
import crypto from "crypto";
export async function POST(req: Request) {
const body = await req.text();
const signature = req.headers.get("x-whop-signature");
// Verify signature
const hash = crypto
.createHmac("sha256", process.env.WHOP_WEBHOOK_SECRET!)
.update(body)
.digest("hex");
if (hash !== signature) {
return new Response("Invalid signature", { status: 401 });
}
const event = JSON.parse(body);
switch (event.action) {
case "payment.succeeded":
await handlePaymentSuccess(event.data);
break;
case "membership.activated":
await grantAccess(event.data);
break;
case "membership.deactivated":
await revokeAccess(event.data);
break;
case "dispute.created":
await handleDispute(event.data);
break;
}
return Response.json({ received: true });
}
关键 Webhook 事件:
| 事件 | 触发条件 |
|---|---|
payment.succeeded | 支付完成 |
payment.failed | 支付失败 |
membership.activated | 会员资格已生效 |
membership.deactivated | 会员资格已结束 |
invoice.paid | 定期付款成功 |
dispute.created | 已发起拒付 |
OAuth 应用
重定向至 Whop OAuth
const authUrl = new URL("https://whop.com/oauth");
authUrl.searchParams.set("client_id", process.env.WHOP_CLIENT_ID!);
authUrl.searchParams.set("redirect_uri", "https://yourapp.com/callback");
authUrl.searchParams.set("scope", "memberships:read payments:read");
// Redirect user
window.location.href = authUrl.toString();
处理回调
export async function GET(req: Request) {
const url = new URL(req.url);
const code = url.searchParams.get("code");
const response = await fetch("https://api.whop.com/api/v5/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
client_id: process.env.WHOP_CLIENT_ID!,
client_secret: process.env.WHOP_CLIENT_SECRET!,
code,
grant_type: "authorization_code",
redirect_uri: "https://yourapp.com/callback",
}),
});
const { access_token, refresh_token } = await response.json();
// Store tokens securely
}
中间件(访问控制)
// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export async function middleware(request: NextRequest) {
const token = request.cookies.get("whop_user_token")?.value;
if (!token) {
return NextResponse.redirect(new URL("/login", request.url));
}
const response = await fetch("https://api.whop.com/api/v5/me/memberships", {
headers: { Authorization: `Bearer ${token}` },
});
const { data } = await response.json();
const hasAccess = data.some((m: any) => m.status === "active" && m.valid);
if (!hasAccess) {
return NextResponse.redirect(new URL("/subscribe", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/dashboard/:path*", "/premium/:path*"],
};
TypeScript 类型
interface WhopMembership {
id: string;
user_id: string;
product_id: string;
plan_id: string;
status: "active" | "paused" | "canceled" | "expired";
valid: boolean;
license_key: string;
renews_at: string | null;
expires_at: string | null;
cancel_at_period_end: boolean;
}
interface WhopPayment {
id: string;
amount: number;
currency: string;
status: "succeeded" | "pending" | "failed";
user_id: string;
product_id: string;
}
错误处理
async function safeWhopRequest(url: string, options: RequestInit) {
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || "Whop API error");
}
return response.json();
}
| 错误 | 含义 |
|---|---|
401 Unauthorized | API 密钥无效 |
403 Forbidden | 权限不足 |
404 Not Found | 资源不存在 |
429 Too Many Requests | 请求频率超出限制 |
安全最佳实践
应该:
- 验证 Webhook 签名
- 加密存储令牌
- 在服务端检查会员状态
- 始终使用 HTTPS
不应该:
- 在客户端暴露 API 密钥
- 信任客户端发送的会员数据
- 跳过 Webhook 验证
- 记录敏感数据
实施检查清单
- 创建 Whop 账号和公司
- 从 Dashboard 获取 API 密钥
- 设置环境变量
- 创建产品和方案
- 实现结账流程
- 添加会员访问权限检查
- 设置 Webhook 端点
- 处理支付事件
- 测试端到端流程
资源
- Dashboard: https://whop.com/dashboard
- API 文档: https://docs.whop.com
- API 基础地址: https://api.whop.com/api/v5
评论
支持 Markdown