Stripe 支付集成完整指南:从基础接入到订阅管理
Stripe 是目前全球最流行的在线支付处理平台之一,服务超过数百万家企业。无论是独立开发者还是大型企业,Stripe 都以简洁的 API、完善的文档和全球化的支付能力著称。本文将从零开始,带你完成 Stripe 支付的完整集成。
一套完整的支付接入通常包含四件事:注册账户并取得密钥、用 Checkout 或 Payment Elements 收单、为订阅类业务配置定价方案、以及用 Webhook 把支付结果同步回自己的系统。很多人把前三步做完就上线了,结果订单和账目对不上——问题往往出在遗漏了 Webhook 与对账环节。下面按顺序把这四件事逐一讲清楚。
一、Stripe 账户注册与准备
创建账户
访问 Stripe 官网 注册账户。Stripe 支持全球大多数国家和地区的商家注册,包括中国香港、新加坡等地。注册时需要提供:
- 企业或个人的基本信息
- 银行账户信息(用于收款结算)
- 身份验证材料
获取 API 密钥
注册完成后,在 Stripe Dashboard 的「开发者」→「API 密钥」页面可以获取两对密钥:
# 测试模式密钥(开发使用)
STRIPE_PUBLISHABLE_KEY=pk_test_xxxxxxxxxxxx
STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxx
# 生产模式密钥(上线使用)
STRIPE_PUBLISHABLE_KEY=pk_live_xxxxxxxxxxxx
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxx
重要提示:永远不要将 Secret Key 暴露在客户端代码或公开仓库中。
二、基础支付流程集成
前端集成(Checkout 模式)
Stripe Checkout 是最简单的集成方式,Stripe 托管支付页面,无需处理敏感支付信息:
<!-- 引入 Stripe.js -->
<script src="https://js.stripe.com/v3/"></script>
<!-- 创建支付按钮 -->
<button id="checkout-button">立即支付 $20.00</button>
<script>
const stripe = Stripe('pk_test_xxxxxxxxxxxx');
document.getElementById('checkout-button').addEventListener('click', async () => {
// 请求后端创建 Checkout Session
const response = await fetch('/api/create-checkout-session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
product: 'premium-plan',
quantity: 1
})
});
const session = await response.json();
// 跳转到 Stripe 托管支付页面
const result = await stripe.redirectToCheckout({
sessionId: session.id
});
});
</script>
后端创建 Checkout Session(Node.js 示例)
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
app.post('/api/create-checkout-session', async (req, res) => {
const session = await stripe.checkout.sessions.create({
line_items: [
{
price_data: {
currency: 'usd',
product_data: { name: '高级套餐' },
unit_amount: 2000, // $20.00 (单位为分)
},
quantity: 1,
},
],
mode: 'payment',
success_url: 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}',
cancel_url: 'https://example.com/cancel',
});
res.json({ id: session.id });
});
测试卡号与本地联调
Stripe 在测试模式提供一组固定的测试卡号,让你在不产生真实扣款的情况下验证整个流程:
| 测试卡号 | 场景 |
|---|---|
4242 4242 4242 4242 |
支付成功 |
4000 0000 0000 0002 |
余额不足,被发卡行拒绝 |
4000 0000 0000 9995 |
触发 3DS 验证流程 |
4000 0000 0000 3220 |
支付成功后产生拒付(dispute) |
本地联调时,推荐安装 Stripe CLI 把远端事件转发到开发机:
stripe listen --forward-to localhost:3000/webhook
运行后终端会输出一个 whsec_ 开头的 Webhook 签名密钥,把它填进环境变量 STRIPE_WEBHOOK_SECRET,本地服务就能收到 checkout.session.completed 等真实格式的事件,实现端到端联调。
支持的支付方式
Stripe 支持数十种支付方式,覆盖全球主要市场:
| 支付方式 | 适用地区 | 适用场景 |
|---|---|---|
| 信用卡/借记卡 | 全球 | 通用在线支付 |
| Apple Pay | 全球 | 移动端和 Safari 浏览器 |
| Google Pay | 全球 | Android 和 Chrome 浏览器 |
| Alipay | 中国 | 中国消费者 |
| WeChat Pay | 中国 | 中国消费者 |
| IDEAL | 荷兰 | 荷兰本地支付 |
| SEPA Direct Debit | 欧盟 | 欧洲银行转账 |
| BACS Direct Debit | 英国 | 英国银行转账 |
三、订阅管理集成
Stripe 的订阅管理功能强大,适用于 SaaS 产品和会员服务:
// 创建订阅产品
const product = await stripe.products.create({
name: '月度专业版',
description: '包含所有高级功能'
});
// 创建定价方案(月度 $29.99)
const price = await stripe.prices.create({
product: product.id,
unit_amount: 2999,
currency: 'usd',
recurring: { interval: 'month' }
});
// 创建订阅
app.post('/api/create-subscription', async (req, res) => {
const { customerId, priceId } = req.body;
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [{ price: priceId }],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent'],
});
res.json({ subscriptionId: subscription.id });
});
订阅业务通常还要处理试用期与价格变更。给新用户提供 14 天试用期是最常见的做法,在创建订阅时传入 trial_period_days 即可:
// 创建带 14 天试用的订阅
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [{ price: priceId }],
trial_period_days: 14,
payment_settings: { payment_method_types: ['card'] },
});
试用期结束后,Stripe 会自动生成第一张账单并向用户扣款;扣款失败会进入 incomplete 状态,并按照你配置的重试策略(例如 4 天内重试 3 次)继续尝试。调整价格也不用重建整个订阅,调用 stripe.subscriptions.update 修改 items 里的 price 即可,Stripe 会自动按比例计算剩余周期差价。要停用某个订阅,可以传 cancel_at_period_end: true,让它在当前计费周期结束时自然失效,而不是立即切断服务。
四、Webhook 事件处理
Webhook 是 Stripe 通知你的服务器支付状态变更的核心机制:
// Node.js Webhook 处理
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const sig = req.headers['stripe-signature'];
let event;
try {
event = stripe.webhooks.constructEvent(
req.body, sig, process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
return res.status(400).send(`Webhook Error: ${err.message}`);
}
switch (event.type) {
case 'checkout.session.completed':
const session = event.data.object;
// 处理支付成功逻辑(更新订单状态、发送确认邮件等)
console.log(`支付成功: ${session.id}`);
break;
case 'invoice.payment_succeeded':
// 订阅续费成功
break;
case 'customer.subscription.deleted':
// 订阅取消
break;
}
res.json({received: true});
});
五、跨境收款注意事项
使用 Stripe 进行跨境收款时需要注意以下几点:
- 货币转换:Stripe 支持 135+ 种货币,自动处理货币转换
- 结算周期:标准结算周期为 7 天(支持 2 天快速结算,需额外费用)
- 手续费结构:2.9% + $0.30(美国卡),国际卡额外 1.5%
- 退款处理:Stripe 收取的手续费不退,退款本身免费
- 防欺诈工具:Stripe Radar 提供机器学习驱动的欺诈检测
六、常见问题与排错
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 支付被拒绝 | 卡信息错误或余额不足 | 检查卡片信息,建议使用测试模式调试 |
| Webhook 验签失败 | Webhook Secret 不匹配 | 确保使用正确的 Signing Secret |
| Checkout 无法加载 | API 密钥配置错误 | 检查密钥是否与模式匹配(测试/生产) |
| 跨境交易失败 | 银行卡不支持跨境支付 | 建议用户联系发卡行 |
七、从下单到续费的完整场景
用一个典型的 SaaS 会员站来说明整条链路:用户在结算页选择“专业版,月付 $29.99”,点击支付后:
- 前端调用
/api/create-checkout-session,后端用mode: 'subscription'创建会话,并带上customer_creation: 'always',Stripe 会同时生成客户档案; - 用户跳转到 Stripe 托管的 Checkout 页面完成付款,Stripe 通过
checkout.session.completed事件通知你的服务器; - 服务端收到事件后把本地订单状态更新为“已支付”,并通过
customer.subscription.created记录订阅关系,把subscriptionId存进数据库; - 每月账单日,Stripe 自动扣款并推送
invoice.paid事件;扣款失败时推送invoice.payment_failed,你可以据此给用户发提醒邮件,避免因忘记扣款导致服务中断; - 用户在后台取消订阅后,会收到
customer.subscription.deleted,服务端据此关闭其高级功能。
这条链路里,本地数据库只负责“展示”订阅状态,真实状态以 Stripe 事件为准。哪怕中间漏收了一个事件,也可以在次日用 stripe.subscriptions.retrieve 补查对齐。
参考:Stripe Checkout 文档 https://docs.stripe.com/payments/checkout;订阅与计费 https://docs.stripe.com/billing;Webhook 签名校验 https://docs.stripe.com/webhooks/signatures
16IDC 观察
Stripe 是跨境建站的首选支付方案,尤其适合面向欧美用户的网站。对于中国市场为主的网站,建议同时集成支付宝和微信支付。如果你的网站流量较小,Stripe 的即用即付模式(无月费)非常适合起步阶段。对于高交易量的商家,可以与 Stripe 协商更低的费率。