mcpField
S
stripe-integration

stripe-integration

github.com/breverdbidder开发40 次安装
代码仓库

关于 stripe-integration

stripe-integration 是用于集成 Stripe 支付的开发技能,涵盖订阅和相关流程,并提供安全、Webhook、测试及客户生命周期管理指引。

主要功能

  1. 01支付与结账流程
  2. 02订阅计费模式
  3. 03Webhook 配置与事件处理
  4. 04安全与幂等性指引
  5. 05Stripe CLI 测试指引

适用场景

  1. 01为应用添加 Stripe 支付
  2. 02构建订阅计费
  3. 03配置并测试支付 Webhook

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/breverdbidder/life-os --skill stripe-integration

安装后在 Claude Code 中输入/stripe-integration确认已加载。

详细介绍

Stripe 集成

此技能可确保首次正确实现 Stripe 支付集成,并遵循安全性、可靠性和用户体验方面的最佳实践。

何时使用此技能

在以下情况下使用此技能:

  • 将 Stripe 添加到新应用程序
  • 实现订阅计费
  • 设置支付处理
  • 配置 Webhook
  • 管理客户生命周期
  • 处理退款或争议
  • 实现结账流程

核心原则

安全第一:

  • 绝不在客户端暴露密钥
  • 生产环境始终使用 HTTPS
  • 验证 Webhook 签名
  • 使用 Stripe 的客户端库处理卡片信息

幂等性:

  • 为 API 请求使用幂等键
  • 处理重复的 Webhook 事件
  • 确保设计可安全重试

用户体验:

  • 清晰的错误消息
  • 支付期间显示加载状态
  • 提供成功/失败反馈
  • 发送电子邮件确认

实现工作流

1. 环境设置

所需凭据:

STRIPE_PUBLISHABLE_KEY_TEST=pk_test_...
STRIPE_SECRET_KEY_TEST=sk_test_...
STRIPE_WEBHOOK_SECRET_TEST=whsec_...

STRIPE_PUBLISHABLE_KEY_PROD=pk_live_...
STRIPE_SECRET_KEY_PROD=sk_live_...
STRIPE_WEBHOOK_SECRET_PROD=whsec_...

切勿提交:

  • 添加到 .env 或密钥管理器
  • 使用 .gitignore 忽略环境文件
  • 为开发/预发布/生产环境使用不同的密钥

安装:

# Node.js
npm install stripe @stripe/stripe-js

# Python
pip install stripe
2. 基本支付流程

客户端(React 示例):

import { loadStripe } from '@stripe/stripe-js';
import { Elements, CardElement, useStripe, useElements } from '@stripe/react-stripe-js';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);

function CheckoutForm() {
  const stripe = useStripe();
  const elements = useElements();

  const handleSubmit = async (event) => {
    event.preventDefault();
    
    if (!stripe || !elements) return;

    // Create payment intent on backend first
    const { clientSecret } = await fetch('/api/create-payment-intent', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ amount: 5000 }) // $50.00
    }).then(r => r.json());

    // Confirm payment on client
    const { error, paymentIntent } = await stripe.confirmCardPayment(
      clientSecret,
      {
        payment_method: {
          card: elements.getElement(CardElement),
          billing_details: {
            name: 'Customer Name',
            email: '[email protected]'
          }
        }
      }
    );

    if (error) {
      console.error(error.message);
    } else if (paymentIntent.status === 'succeeded') {
      // Payment successful
      console.log('Payment succeeded!');
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <CardElement />
      <button type="submit" disabled={!stripe}>
        Pay
      </button>
    </form>
  );
}

服务端(Node.js 示例):

const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

app.post('/api/create-payment-intent', async (req, res) => {
  try {
    const { amount } = req.body;

    const paymentIntent = await stripe.paymentIntents.create({
      amount: amount,
      currency: 'usd',
      automatic_payment_methods: {
        enabled: true,
      },
      metadata: {
        userId: req.user.id, // Track in your DB
        orderId: req.body.orderId
      }
    });

    res.json({ clientSecret: paymentIntent.client_secret });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});
3. 订阅实现

创建订阅:

// Server-side
async function createSubscription(customerId, priceId) {
  const subscription = await stripe.subscriptions.create({
    customer: customerId,
    items: [{ price: priceId }],
    payment_behavior: 'default_incomplete',
    payment_settings: {
      save_default_payment_method: 'on_subscription'
    },
    expand: ['latest_invoice.payment_intent']
  });

  return {
    subscriptionId: subscription.id,
    clientSecret: subscription.latest_invoice.payment_intent.client_secret
  };
}

处理订阅生命周期:

  • 客户注册 → 创建客户和订阅
  • 支付成功 → 启用功能
  • 支付失败 → 通知客户并重试
  • 收到取消请求 → 在 period_end 处理
  • 续订 → Webhook 确认支付
4. Webhook 配置

重要:Webhook 是 Stripe 通知你事件的方式,必须正确实现。

端点设置:

const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

app.post('/webhook', express.raw({type: 'application/json'}), async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;

  try {
    // Verify webhook signature
    event = stripe.webhooks.constructEvent(
      req.body,
      sig,
      process.env.STRIPE_WEBHOOK_SECRET
    );
  } catch (err) {
    console.log(`Webhook signature verification failed: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  // Handle the event
  switch (event.type) {
    case 'payment_intent.succeeded':
      const paymentIntent = event.data.object;
      await handlePaymentSuccess(paymentIntent);
      break;

    case 'payment_intent.payment_failed':
      const failedPayment = event.data.object;
      await handlePaymentFailure(failedPayment);
      break;

    case 'customer.subscription.created':
      const subscription = event.data.object;
      await handleSubscriptionCreated(subscription);
      break;

    case 'customer.subscription.updated':
      const updatedSub = event.data.object;
      await handleSubscriptionUpdated(updatedSub);
      break;

    case 'customer.subscription.deleted':
      const deletedSub = event.data.object;
      await handleSubscriptionCanceled(deletedSub);
      break;

    case 'invoice.payment_succeeded':
      const invoice = event.data.object;
      await handleInvoicePaymentSucceeded(invoice);
      break;

    case 'invoice.payment_failed':
      const failedInvoice = event.data.object;
      await handleInvoicePaymentFailed(failedInvoice);
      break;

    default:
      console.log(`Unhandled event type ${event.type}`);
  }

  res.json({received: true});
});

需要处理的重要事件:

  1. payment_intent.succeeded - 一次性支付成功
  2. payment_intent.payment_failed - 支付失败
  3. customer.subscription.created - 新订阅
  4. customer.subscription.updated - 订阅已更改
  5. customer.subscription.deleted - 订阅已取消
  6. invoice.payment_succeeded - 定期支付成功
  7. invoice.payment_failed - 定期支付失败
5. 客户管理

创建客户:

const customer = await stripe.customers.create({
  email: user.email,
  name: user.name,
  metadata: {
    userId: user.id
  }
});

// Store customer.id in your database
await db.users.update(user.id, {
  stripeCustomerId: customer.id
});

关联支付方式:

const paymentMethod = await stripe.paymentMethods.attach(
  pm_id,
  { customer: customerId }
);

await stripe.customers.update(customerId, {
  invoice_settings: {
    default_payment_method: pm_id
  }
});
6. 测试

测试模式:

  • 使用测试密钥(pk_test_、sk_test_)
  • 测试卡号:
    • 成功:4242 4242 4242 4242
    • 被拒:4000 0000 0000 0002
    • 3D Secure:4000 0027 6000 3184
  • 使用 stripe CLI 测试 Webhook:
    stripe listen --forward-to localhost:3000/webhook
    stripe trigger payment_intent.succeeded
    

Webhook 测试:

# Install Stripe CLI
brew install stripe/stripe-cli/stripe

# Login
stripe login

# Forward webhooks to local server
stripe listen --forward-to localhost:3000/webhook

# Trigger events manually
stripe trigger customer.subscription.created
7. 错误处理

需要处理的常见错误:

try {
  const charge = await stripe.charges.create({...});
} catch (error) {
  switch (error.type) {
    case 'StripeCardError':
      // Card was declined
      console.log('Card declined:', error.message);
      break;
    case 'StripeInvalidRequestError':
      // Invalid parameters
      console.log('Invalid request:', error.message);
      break;
    case 'StripeAPIError':
      // Stripe API error
      console.log('API error:', error.message);
      break;
    case 'StripeConnectionError':
      // Network error
      console.log('Network error');
      break;
    case 'StripeAuthenticationError':
      // Authentication error
      console.log('Auth error');
      break;
    default:
      console.log('Unknown error:', error);
  }
}

生产环境检查清单

上线前:

  • 使用正式 API 密钥(pk_live_、sk_live_)
  • 所有位置均已启用 HTTPS
  • 已在 Stripe Dashboard 中配置 Webhook 端点
  • 已实现 Webhook 签名验证
  • 已处理所有关键事件
  • API 调用均使用幂等键
  • 客户创建与用户账户关联
  • 已为所有支付流程处理错误
  • 已设置电子邮件通知
  • 已记录退款流程
  • 已使用真实测试卡进行测试
  • 已通过 CLI 测试 Webhook 事件
  • 已测试订阅续订流程
  • 已测试取消流程
  • 已实现支付失败重试逻辑
  • 已完成安全审查

常见模式

订阅层级
const plans = {
  basic: 'price_basic123',
  pro: 'price_pro456',
  enterprise: 'price_enterprise789'
};

function subscribeToPlan(customerId, tier) {
  return stripe.subscriptions.create({
    customer: customerId,
    items: [{ price: plans[tier] }]
  });
}
按用量计费
// Record usage
await stripe.subscriptionItems.createUsageRecord(
  subscriptionItemId,
  {
    quantity: 100,
    timestamp: Math.floor(Date.now() / 1000),
    action: 'increment'
  }
);
按比例计算升级费用
await stripe.subscriptions.update(subscriptionId, {
  items: [{
    id: subscriptionItemId,
    price: newPriceId
  }],
  proration_behavior: 'create_prorations'
});

资源

官方文档:

测试:

安全:

提示

  1. 从简单功能开始:先确保基本支付功能正常,再实现订阅
  2. 使用 Stripe Checkout:托管页面可处理复杂流程
  3. 彻底测试 Webhook:使用 CLI 模拟所有事件
  4. 记录所有信息:在数据库中跟踪支付意向和事件
  5. 妥善处理故障:实现重试逻辑并通知用户
  6. 隔离测试和生产环境:切勿混用密钥或环境
  7. 监控 Stripe Dashboard:检查错误和争议
  8. 阅读 Stripe 文档:内容出色且详尽

评论

支持 Markdown