
本文详解 Stripe 支付流程中“创建客户并立即扣款”的正确实现方式,重点解决因重复设置支付源(token)导致的 Customer does not have a linked source 错误。核心在于:客户创建时绑定 token 即可,后续扣款无需、也不应再次调用 SetSource() 指定同一 token。
本文详解 stripe 支付流程中“创建客户并立即扣款”的正确实现方式,重点解决因重复设置支付源(token)导致的 `customer does not have a linked source` 错误。核心在于:**客户创建时绑定 token 即可,后续扣款无需、也不应再次调用 `setsource()` 指定同一 token**。
在使用 Stripe 构建支付系统时,一个常见且易被忽视的误区是:在创建客户(Customer)后,又试图将同一个一次性 token 作为支付源(source)显式传给 ChargeParams。这不仅多余,更会直接触发 404 invalid_request_error —— 错误信息明确指出:“Customer does not have a linked source with ID tok_...”,看似矛盾,实则源于 Stripe 的底层设计逻辑。
? 问题根源解析
Stripe 的 token(如 tok_123)是一次性、临时性凭证,仅用于安全地将卡信息从客户端传递至服务端。当它被用于创建客户(通过 customerParams.SetSource())时,Stripe 会:
- 将该 token 转换为一个持久化的
card_xxx或payment_method_xxx对象; - 自动将其关联到新创建的客户下;
- 立即作废原始 token(使其不可重用)。
因此,在后续发起扣款时,若再对 ChargeParams 执行 cp.SetSource("tok_123"),Stripe 会尝试查找该已失效的 token —— 此时它既不在客户下(已被转换),也不再是有效源,故返回 404。
✅ 正确做法:单次绑定,自动继承
只要客户创建时已通过 SetSource() 绑定了 token,Stripe 即默认使用该客户下最新添加的支付源进行扣款。你只需在 ChargeParams 中指定 Customer: cus.ID,无需、也不应再设置 source 字段。
以下是修正后的 Go 后端代码(基于 stripe-go v75+):
stripe.Key = "sk_test_################"
// 1. 创建客户,并绑定前端传来的 token
customerParams := &stripe.CustomerParams{
Description: stripe.String("Customer for xyz.com"),
Email: stripe.String("user@example.com"),
}
customerParams.SetSource("tok_####################") // ✅ 关键:仅此处绑定 token
cus, err := customer.New(customerParams)
if err != nil {
return nil, fmt.Errorf("failed to create customer: %w", err)
}
// 2. 发起扣款:仅指定 Customer ID,不设置 Source!
chargeParams := &stripe.ChargeParams{
Amount: stripe.Int64(100), // $1.00
Currency: stripe.String("usd"),
Description: stripe.String("some description"),
Customer: stripe.String(cus.ID), // ✅ 自动使用客户默认支付源
}
ch, err := charge.New(chargeParams)
if err != nil {
return nil, fmt.Errorf("failed to create charge: %w", err)
}⚠️ 注意事项:
SetSource()只能调用一次,且必须在customer.New()之前完成;ChargeParams中绝对不要对同一 token 再次调用SetSource();- 若需指定客户下的特定卡(例如客户有多个卡),应使用
Source: stripe.String("card_abc123")(即card_xxxID),而非原始tok_xxx;- 现代 Stripe 推荐使用
PaymentMethod+PaymentIntent流程替代旧版Charge,但上述原则在ChargeAPI 中依然严格适用。
? 总结
Stripe 的客户-支付源模型遵循“创建即绑定、扣款即继承”的简洁设计。错误地重复使用一次性 token 是导致 missing source 错误的最主要原因。牢记:Token 是入场券,只用一次;客户是账户,扣款自动走默认卡。遵循这一逻辑,即可稳定实现客户创建与即时扣款的无缝集成。

















