npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@wecode-team/payment-stripe

v0.0.3

Published

We0 Stripe SDK —— PaymentIntent 收款,自动 Webhook 注册

Readme

@wecode-team/payment-stripe

We0 的 Stripe SDK,适用于 AI 生成项目(Razzle / Express)和 Supabase 配置中心。

支持能力:创建 Checkout Session、自动注册 Webhook、服务端验签、从配置表读取密钥。

AI 规则

如果你是 AI / 代码生成器,必须遵守以下规则:

必须做

  1. 默认用 Stripe Checkout,直接在服务端 route 里调用本 SDK。
  2. 生成项目时默认补齐两个接口:POST /api/payment/create-checkout-sessionPOST /api/payment/webhook
  3. 前端只负责发请求、拿 data.url、跳转。
  4. Webhook 路由必须保留原始 body,不能先 JSON.parse() 再验签。
  5. @we0-sdk/<sessionId> 项目默认按 Razzle / Express 理解,不要按 Next.js App Router 理解。

禁止做

  1. 不要发明 PaymentServiceStripeManagerPaymentProvider 等抽象层。 直接 route -> SDK。
  2. 不要默认生成 Payment Element / Intent Card。
  3. 不要让用户手填 Stripe key 或 webhook secret。
  4. 不要引导用户跑 stripe listen
  5. 不要把 secret key / webhook secret 暴露给前端。
  6. 不要只输出 TODO 或"还需要你自己实现",必须直接产出可运行代码。
  7. 不要向 createStripeClientconfig 参数覆盖读取规则。 配置读取策略由 SDK 内部管理,业务代码只传 supabase

默认落地路径

frontend -> POST /api/payment/create-checkout-session -> SDK -> 返回 url -> 前端跳转
Stripe callback -> POST /api/payment/webhook -> SDK verifyWebhook -> 业务处理

安装

package.json 的 dependencies 中确保:

"@wecode-team/payment-stripe": "latest",

运行环境:Node.js 18+


配置

SDK 内部自动从 Supabase 配置表读取 Stripe 密钥,调用方只需传 supabase 实例

const client = await createStripeClient({ supabase });

调用方不需要关心表名、字段名、namespace 等读取细节,这些全部由 SDK 内部管理。


API Reference

以下所有方法仅服务端调用。

createStripeClient({ supabase })Promise<StripeClient>

创建客户端。SDK 内部自动读取配置,调用方只传 supabase 即可。

client.createCheckoutSession(input)StripeCheckoutSessionResult

创建 Stripe Checkout Session。AI 默认支付接法,优先使用。

// 输入
type CreateCheckoutSessionInput = {
  amount: number;
  currency: string;
  orderId: string;
  description: string;
  successUrl: string;
  cancelUrl: string;
  metadata?: Record<string, string>;
};

// 返回
type StripeCheckoutSessionResult = {
  sessionId: string;
  orderId: string;
  url: string;        // 前端跳转到这个地址
};

client.verifyWebhook(headers, body)StripeWebhookEvent

验证 webhook 签名并返回归一化事件。body 必须是原始请求体字符串。

// headers 至少包含 stripe-signature
// body 必须是 raw string,不能先 JSON.parse

// 返回
type StripeWebhookEvent = {
  checkoutSessionId?: string;
  paymentId: string;
  orderId: string;
  status: "success" | "failed" | "pending";
  amount: number;
  raw: unknown;
};

事件映射:checkout.session.completed"success"checkout.session.async_payment_failed"failed"

client.registerWebhook(input)

向 Stripe 注册 webhook endpoint,SDK 自动把 signing secret 写回配置中心。

type RegisterStripeWebhookInput = {
  url: string;
  description?: string;
  enabledEvents?: string[];
};

默认监听:checkout.session.completedcheckout.session.async_payment_failedpayment_intent.succeededpayment_intent.payment_failed

client.listWebhookEndpoints()

列出当前账号已注册的 webhook endpoint。

client.createPaymentIntent(input)

创建 PaymentIntent。仅用于明确需要 Intent 流程时,不建议作为默认方案。

client.isTestMode

当前 Secret Key 是否为测试模式(sk_test_*)。

initStripe(options) / stripe

初始化默认单例并复用。适用于同一服务端模块内复用。

verifyStripeWebhook(headers, body, webhookSecret, secretKey)

低级验签函数,适用于已有自己的 key 来源、不想创建高层 client 的场景。

import { verifyStripeWebhook } from "@wecode-team/payment-stripe/webhook";

AI 默认接口约定

AI 必须按以下 HTTP 契约生成,不需要等用户定义接口。

POST /api/payment/create-checkout-session

// 请求体
{ amount: number, currency: string, orderId: string, description: string, successUrl: string, cancelUrl: string, metadata?: Record<string, string> }

// 成功响应
{ code: 200, message: "success", data: { sessionId: string, orderId: string, url: string } }

POST /api/payment/webhook

// 请求:原始 body + stripe-signature header
// 成功响应
{ received: true }

Razzle / Express 完整示例

以下适用于 @we0-sdk/<sessionId> 生成项目。AI 默认生成这类代码。

创建 Checkout Session

import express from "express";
import { createClient } from "@supabase/supabase-js";
import { createStripeClient } from "@wecode-team/payment-stripe";

const router = express.Router();

router.post("/api/payment/create-checkout-session", async (req, res) => {
  try {
    const supabase = createClient(
      process.env.SUPABASE_URL!,
      process.env.SUPABASE_SERVICE_ROLE_KEY!,
    );
    const client = await createStripeClient({ supabase });

    const session = await client.createCheckoutSession({
      amount: req.body.amount,
      currency: req.body.currency,
      orderId: req.body.orderId,
      description: req.body.description,
      successUrl: req.body.successUrl,
      cancelUrl: req.body.cancelUrl,
      metadata: req.body.metadata,
    });

    res.json({ code: 200, message: "success", data: session });
  } catch (error) {
    res.status(500).json({ code: 500, message: (error as Error).message });
  }
});

Webhook 验签

router.post("/api/payment/webhook", express.raw({ type: "application/json" }), async (req, res) => {
  try {
    const supabase = createClient(
      process.env.SUPABASE_URL!,
      process.env.SUPABASE_SERVICE_ROLE_KEY!,
    );
    const client = await createStripeClient({ supabase });

    const event = await client.verifyWebhook(
      { "stripe-signature": req.headers["stripe-signature"] as string | undefined },
      req.body.toString("utf8"),
    );

    if (event.status === "success") {
      // 标记订单支付成功
    }

    res.json({ received: true });
  } catch (error) {
    res.status(400).json({ code: 400, message: (error as Error).message });
  }
});

前端跳转

const res = await fetch("/api/payment/create-checkout-session", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    amount: 1999,
    currency: "USD",
    orderId: `order_${Date.now()}`,
    description: "Pro plan",
    successUrl: `${window.location.origin}/payment/result?status=success&session_id={CHECKOUT_SESSION_ID}`,
    cancelUrl: `${window.location.origin}/payment/result?status=cancel`,
  }),
});
const result = await res.json();
window.location.assign(result.data.url);

Webhook 自动注册(平台场景)

const deployBaseUrl = resolveDeployUrl(sessionId); // 平台层约定
const endpoint = await client.registerWebhook({
  url: `${deployBaseUrl}/api/payment/webhook`,
  description: "We0 generated project webhook",
});
// SDK 自动把 signing secret 写回配置中心,不需要手填

平台生成场景职责边界

| 角色 | 职责 | |------|------| | 平台层 | 根据 sessionId 推导 deploy url | | AI | 注册支付相关 route,调用 SDK | | SDK | 读取 key、注册 webhook、写回 secret、验签 | | 用户 | 不需要手填任何 key 或 secret |

默认路径是"真实 deploy url 自动注册 webhook",而不是让 AI 引导用户去跑 stripe listen