轻松集成 Stripe:开发者代码示例

June 11, 2025

嘿,各位开发者同行们!如果你的应用曾经需要集成支付功能,那么 Stripe 很可能曾出现在你的视野中。它确实是个很棒的工具,但有时要把它所有东西都妥善配置好,感觉就像在和一只章鱼搏斗——触手太多,你都不知道下一步该抓哪条。

这正是这份指南的用武之地。我来这里不是为了重复官方文档(尽管它们很棒!)。我的目标是为你提供一条清晰、简洁的 Stripe 集成之路,其中包含一些常用编程语言的实用代码片段。你可以把它想象成和一位过来人朋友的轻松对话,他经历过你现在面临的困境,希望能帮你少走弯路。

为什么选择 Stripe?(以及为何正确集成至关重要)

在深入代码之前,我们先快速谈谈为什么 Stripe 是许多人的首选。它功能强大、安全可靠,并且提供了出色的开发者工具。但仅仅拥有强大的工具是不够的;你还需要有效地运用它。一个良好集成的支付系统不仅仅是收款那么简单;它关乎为你的用户提供流畅、值得信赖的体验,并为你的业务减少潜在的摩擦点。

核心要点:设置你的 Stripe 环境

首先,你需要一个 Stripe 账户。访问 stripe.com 并注册。成功注册后,你可以在开发者控制面板中找到你的 API 密钥。你有两套密钥:一套是“可发布”密钥(用于前端,可以安全地公开),另一套是“秘密”密钥(用于后端,务必保密!)。

对于本地开发,最好设置一个 .env 文件来存储你的秘密密钥。切勿将其硬编码!

.env 文件示例:

STRIPE_SECRET_KEY=sk_test_YOUR_SECRET_KEY
STRIPE_PUBLISHABLE_KEY=pk_test_YOUR_PUBLISHABLE_KEY

创建一个基本的支付会话

如今,使用 Stripe 处理支付最常见的方式是通过 Checkout Sessions。这能将大量的 PCI 合规性和用户界面样式的工作分流给 Stripe,这对于我们开发者来说是巨大的福音。

你的前端只需将用户重定向到 Stripe 托管的页面,支付完成后,用户将被重定向回你的网站。

以下是如何从后端发起一个支付会话:

Node.js 示例(使用 express):

// backend/server.js
const express = require('express');
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const app = express();

app.use(express.json()); // 用于解析 application/json

app.post('/create-checkout-session', async (req, res) => {
  try {
    const session = await stripe.checkout.sessions.create({
      payment_method_types: ['card'],
      line_items: [
        {
          price_data: {
            currency: 'usd',
            product_data: {
              name: 'Awesome Product',
            },
            unit_amount: 2000, // $20.00
          },
          quantity: 1,
        },
      ],
      mode: 'payment',
      success_url: 'http://localhost:3000/success?session_id={CHECKOUT_SESSION_ID}',
      cancel_url: 'http://localhost:3000/cancel',
    });
    res.json({ id: session.id });
  } catch (error) {
    console.error('Error creating checkout session:', error);
    res.status(500).json({ error: error.message });
  }
});

app.listen(4242, () => console.log('Node server listening on port 4242!'));

Python 示例(使用 Flask):

# backend/app.py
from flask import Flask, jsonify, request, redirect, url_for
import stripe
import os

app = Flask(__name__)

stripe.api_key = os.getenv('STRIPE_SECRET_KEY')

@app.route('/create-checkout-session', methods=['POST'])
def create_checkout_session():
    try:
        session = stripe.checkout.Session.create(
            payment_method_types=['card'],
            line_items=[
                {
                    'price_data': {
                        'currency': 'usd',
                        'product_data': {
                            'name': 'Awesome Product',
                        },
                        'unit_amount': 2000,
                    },
                    'quantity': 1,
                }
            ],
            mode='payment',
            success_url='http://localhost:3000/success?session_id={CHECKOUT_SESSION_ID}',
            cancel_url='http://localhost:3000/cancel',
        )
        return jsonify(id=session.id)
    except Exception as e:
        print(f'Error creating checkout session: {e}')
        return jsonify(error=str(e)), 500

if __name__ == '__main__':
    app.run(port=4242)

在前端,调用此端点后,你将重定向用户:

前端示例(使用 Stripe.js):

<!-- frontend/index.html -->
<!DOCTYPE html>
<html>
<head>
  <title>购买我的超赞产品</title>
  <script src="https://js.stripe.com/v3/"></script>
</head>
<body>
  <h1>购买我的超赞产品</h1>
  <button id="checkout-button">立即支付</button>

  <script type="text/javascript">
    const stripe = Stripe('pk_test_YOUR_PUBLISHABLE_KEY'); // 替换为你的公开密钥

    const checkoutButton = document.getElementById('checkout-button');

    checkoutButton.addEventListener('click', async () => {
      try {
        const response = await fetch('/create-checkout-session', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
        });
        const session = await response.json();

        if (session.id) {
          const result = await stripe.redirectToCheckout({
            sessionId: session.id,
          });

          if (result.error) {
            alert(result.error.message);
          }
        } else if (session.error) {
            alert(session.error.message);
        }

      } catch (error) {
        console.error('Error initiating checkout:', error);
        alert('无法发起支付。请重试。');
      }
    });
  </script>
</body>
</html>

处理支付后事件:Webhook 是你的好帮手

支付成功后,你的后端如何知道发生了什么?你不能仅仅依赖 success_url,因为用户可能会关闭浏览器。答案是 webhooks

每当发生重要事件(例如支付成功、退款、订阅更新等)时,Stripe 都会向你指定的 webhook 端点发送事件。你的服务器会监听这些事件并采取相应的行动。

设置 Webhook 端点

首先,你需要一个公共 URL,供 Stripe 向其发送事件。对于本地开发,ngrok 等工具非常宝贵。它们可以从公共 URL 到你的本地机器创建安全隧道。查阅 ngrok 的文档以进行设置。

ngrok 运行后,你通常会像 ngrok http 4242 这样启动它(假设你的服务器运行在 4242 端口)。它会给你一个公共 URL(例如 https://your-random-subdomain.ngrok-free.app)。

现在,在你的 Stripe 控制面板中,前往“开发者” > “Webhooks”并点击“添加端点”。粘贴你的 ngrok URL(例如 https://your-random-subdomain.ngrok-free.app/webhook),并选择你要监听的事件(checkout.session.completed 是支付事件的一个好的开始)。

验证 Webhook 签名

验证 webhook 签名绝对至关重要。这能确保事件确实来自 Stripe,并且未被篡改。

Stripe 在 Stripe-Signature 头部中包含了一个签名。你需要你的 webhook 秘密(在 Stripe 控制面板的 webhook 端点详细信息中可以找到)来验证它。

Node.js Webhook 示例:

// backend/server.js (添加到你现有的 server.js)

// 重要:确保此端点是专用的,并且在使用 body-parser 或 express.json 全局解析 JSON 之前,
// 因为 webhooks 需要原始的请求体。

app.post('/webhook', express.raw({type: 'application/json'}), async (req, res) => {
  const sig = req.headers['stripe-signature'];
  let event;
  const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET; // 从你的 Stripe webhook 设置中获取

  try {
    event = stripe.webhooks.constructEvent(req.body, sig, endpointSecret);
  } catch (err) {
    console.error(`Webhook Error: ${err.message}`);
    return res.status(400).send(`Webhook Error: ${err.message}`);
  }

  // 处理事件
  switch (event.type) {
    case 'checkout.session.completed':
      const checkoutSession = event.data.object;
      // 完成购买,更新你的数据库,发送确认邮件等。
      console.log(`Checkout session completed for: ${checkoutSession.id}`);
      // 从 checkoutSession 对象中访问客户、订单项等
      break;
    // ... 处理其他事件类型
    default:
      console.log(`Unhandled event type ${event.type}`);
  }

  // 返回 200 响应以确认收到事件
  res.send();
});

Python Webhook 示例:

# backend/app.py (添加到你现有的 app.py)

@app.route('/webhook', methods=['POST'])
def webhook_received():
    request_data = request.data.decode('utf-8')
    signature = request.headers.get('stripe-signature')
    webhook_secret = os.getenv('STRIPE_WEBHOOK_SECRET') # 从你的 Stripe webhook 设置中获取

    try:
        event = stripe.Webhook.construct_event(
            payload=request_data,
            sig_header=signature,
            secret=webhook_secret
        )
    except ValueError as e:
        # 无效的载荷
        print(f'Invalid payload: {e}')
        return jsonify({'error': 'Invalid payload'}), 400
    except stripe.error.SignatureVerificationError as e:
        # 无效的签名
        print(f'Invalid signature: {e}')
        return jsonify({'error': 'Invalid signature'}), 400

    # 处理事件
    if event['type'] == 'checkout.session.completed':
        checkout_session = event['data']['object']
        # 完成购买,更新你的数据库,发送确认邮件等。
        print(f'Checkout session completed for: {checkout_session.id}')
    # ... 处理其他事件类型

    return jsonify({'status': 'success'}), 200

几个需要牢记的快速最佳实践

  • 错误处理至关重要: 始终将你的 Stripe API 调用放在 try...catch 块中。支付是关键环节,你希望能够优雅地处理任何可能出错的情况。
  • 幂等性: 在进行 API 调用时(尤其是那些创建资源如收款的调用),使用幂等键。这确保了即使请求意外地多次发送(例如,由于网络故障),Stripe 也只会处理一次。大多数客户端库会为你处理这个问题,但了解一下是有好处的。
  • 测试模式与实时模式: 始终在 test 模式下进行充分的开发和测试。使用 Stripe 提供的测试卡号。仅在你完全准备好进行真实交易时,才切换到 live 模式密钥。
  • HTTPS 不可妥协: 对于实时应用,务必确保你的域名使用 HTTPS。这可以保护敏感的支付信息。
  • 仅存储你需要的信息: 避免在你的服务器上存储敏感的银行卡详细信息。让 Stripe 处理这些。如果你需要引用客户或支付方式,使用 Stripe 的客户 ID 或支付方式 ID。

总结

Stripe 是一个强大得令人难以置信的平台,集成它不一定是一项艰巨的任务。通过将其分解为可管理的步骤——设置密钥、创建支付会话以及至关重要的处理 Webhooks——你可以相当顺利地部署你的支付流程。

请记住,这只是一个开始。Stripe 提供了更多功能:订阅、发票、关联账户以及更复杂的支付流程。但有了这些基础知识,你就能很好地在应用程序中构建强大而可靠的支付处理功能。祝编程愉快!

分享本文