You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用Stripe PHP通过Card ID或Customer ID完成二次扣费?

解决Stripe二次支付复用已有Customer/Card ID的问题

我来帮你搞定这个二次支付复用客户和卡片的问题!核心问题在于你现在每次调用Stripe_Customer::create()都会生成新客户,咱们只要调整逻辑,先复用已有客户、绑定并存储支付方式,二次支付时直接用存储的信息发起扣费就行。下面分步骤给你讲具体实现:

一、首次支付时:创建/复用Customer,绑定并存储支付方式

1. 先检查数据库中是否已有当前用户的Stripe Customer ID

别每次都新建客户,先从你的数据库里查询当前登录用户(通过$_SESSION['userEmail']关联)是否已经有对应的Stripe Customer ID:

// 假设你的用户表是users,字段stripe_customer_id用来存储Customer ID
$userEmail = $_SESSION['userEmail'];
// 用你自己的数据库查询逻辑获取已有Customer ID
$existingCustomerId = $db->query("SELECT stripe_customer_id FROM users WHERE email = ?", [$userEmail])->fetchColumn();

2. 创建或复用Customer,绑定支付方式

如果没有已有Customer ID,再创建新的;如果有,直接用已有的。然后把用户选择的支付方式(Card/PaymentMethod)附加到这个Customer上:

// 接收前端从Stripe模态框传来的支付方式ID(新版是payment_method,旧版是source)
$paymentMethodId = $_POST['payment_method_id'];

if (!$existingCustomerId) {
    // 首次创建Customer并绑定支付方式
    $customer = Stripe_Customer::create([
        'email' => $userEmail,
        'payment_method' => $paymentMethodId,
        'invoice_settings' => [
            'default_payment_method' => $paymentMethodId, // 可选:设置默认支付方式
        ],
    ]);
    $existingCustomerId = $customer->id;
    // 把新的Customer ID保存到你的用户表中
    $db->query("UPDATE users SET stripe_customer_id = ? WHERE email = ?", [$existingCustomerId, $userEmail]);
} else {
    // 已有Customer,直接附加新的支付方式(如果用户绑定了新卡)
    Stripe_PaymentMethod::attach(
        $paymentMethodId,
        ['customer' => $existingCustomerId]
    );
    // 可选:将新绑定的卡片设为默认
    Stripe_Customer::update(
        $existingCustomerId,
        ['invoice_settings' => ['default_payment_method' => $paymentMethodId]]
    );
}

// 把支付方式的ID、卡片后四位等信息保存到数据库(方便用户后续选择)
$db->query("INSERT INTO user_payment_methods (user_email, stripe_customer_id, stripe_payment_method_id, card_last4) VALUES (?, ?, ?, ?)", [
    $userEmail,
    $existingCustomerId,
    $paymentMethodId,
    $_POST['card_last4'] // 前端传来的卡片后四位,比如"4242"
]);

二、二次支付时:用已有Customer/PaymentMethod发起扣费

当用户选择已绑定的卡片(比如你展示的visa****4242),从数据库取出对应的stripe_customer_idstripe_payment_method_id,然后发起支付:

方式1:用PaymentIntent(Stripe最新推荐方案)

// 从数据库取出用户选中的支付方式信息
$selectedPaymentMethod = $db->query("SELECT stripe_customer_id, stripe_payment_method_id FROM user_payment_methods WHERE user_email = ? AND card_last4 = ?", [$userEmail, '4242'])->fetch();

// 创建并确认支付Intent
$paymentIntent = Stripe_PaymentIntent::create([
    'amount' => 1000, // 金额单位为分,这里代表10美元
    'currency' => 'usd',
    'customer' => $selectedPaymentMethod['stripe_customer_id'],
    'payment_method' => $selectedPaymentMethod['stripe_payment_method_id'],
    'confirm' => true, // 直接确认支付
    'off_session' => true, // 如果是用户不在当前页面的无会话支付
]);

// 处理支付结果
if ($paymentIntent->status === 'succeeded') {
    // 支付成功,更新你的订单状态等业务逻辑
} else {
    // 处理支付失败,比如提示用户卡片过期、余额不足等
}

方式2:用Charge(旧版API,适配你当前的Stripe_Customer类)

如果你还在使用旧版Stripe API,可以用Charge接口:

$charge = Stripe_Charge::create([
    'amount' => 1000,
    'currency' => 'usd',
    'customer' => $selectedPaymentMethod['stripe_customer_id'], // 自动关联客户的默认支付方式
    // 或者指定具体的旧版Card ID(source)
    // 'source' => $selectedCardId,
]);

关键注意点

  • 禁止重复创建Customer:这是你之前的核心问题,一定要先查询数据库是否已有当前用户的Customer ID,避免每次支付都生成新客户。
  • 完整存储支付信息:把Customer ID、PaymentMethod/Card ID、卡片后四位都存在数据库,既方便用户选择卡片,也能确保二次支付时能准确调用。
  • API版本兼容:如果你的Stripe PHP库是较新版本,建议优先使用PaymentMethodPaymentIntent,这是Stripe目前推荐的标准方案。

内容的提问来源于stack exchange,提问作者Hashaam zahid

火山引擎 最新活动