You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Stripe Connect测试模式生成Token未完成交易及调用Charge方法问询

问题分析

你目前的代码只完成了前端生成Stripe Token的环节,但Stripe的Charge(支付扣款)操作必须在后端执行——前端不能直接调用Charge接口,一来会泄露你的Secret Key,二来Connect场景下的资金流向逻辑也需要后端来处理。这就是为什么你在控制台只能看到v1/token请求,却没有实际支付记录的核心原因。

解决方案步骤

下面分前后端两部分帮你完成完整的支付流程:

1. 前端修改:把Token和自定义数据传给后端

当前前端在生成Token后只是展示token,需要改成通过AJAX把token、课程信息、价格等数据发送到你的后端接口,让后端发起扣款请求。

修改前端的setOutcome函数和表单提交逻辑:

function setOutcome(result) {
  var successElement = document.querySelector('.success');
  var errorElement = document.querySelector('.error');
  successElement.classList.remove('visible');
  errorElement.classList.remove('visible');

  if (result.token) {
    // 收集表单里的自定义数据
    var formData = new FormData(document.querySelector('form'));
    // 把Stripe Token加入表单数据
    formData.append('stripeToken', result.token.id);
    // 可选:把持卡人姓名也传过去(token里也包含这个信息,后端也可以直接取)
    formData.append('cardholderName', result.token.card.name);

    // 发送请求到后端的扣款接口
    fetch('/create-charge', {
      method: 'POST',
      body: formData
    })
    .then(response => response.json())
    .then(data => {
      if (data.success) {
        successElement.textContent = `支付成功!你的订单ID:${data.chargeId}`;
        successElement.classList.add('visible');
      } else {
        errorElement.textContent = data.error;
        errorElement.classList.add('visible');
      }
    })
    .catch(error => {
      errorElement.textContent = '网络连接异常,请稍后重试';
      errorElement.classList.add('visible');
    });
  } else if (result.error) {
    errorElement.textContent = result.error.message;
    errorElement.classList.add('visible');
  }
}

// 表单提交逻辑保留,只是把后续处理交给setOutcome
document.querySelector('form').addEventListener('submit', function(e) {
  e.preventDefault();
  var form = document.querySelector('form');
  var extraDetails = {
    name: form.querySelector('input[name=cardholder-name]').value,
  };
  stripe.createToken(card, extraDetails).then(setOutcome);
});

2. 后端实现扣款接口(PHP示例)

你需要用Stripe的Secret Key(测试环境用sk_test_xxx,生产环境用sk_live_xxx)在后端调用Stripe的Charge API,同时根据你的Connect场景选择对应的逻辑:

场景1:平台直接收取费用(资金进入平台账户)

如果是平台自己收取课程费用,直接创建Charge即可:

<?php
// 先引入Stripe PHP SDK,你可以通过Composer安装:composer require stripe/stripe-php
require_once('vendor/autoload.php');

// 设置你的Stripe Secret Key
\Stripe\Stripe::setApiKey('sk_test_你的测试密钥');

try {
  // 从前端请求中获取数据
  $stripeToken = $_POST['stripeToken'];
  // 注意:Stripe金额是最小货币单位(比如美元是分,人民币是分),所以要乘以100
  $amount = (int)($_POST['selectedAppointment'] * 100);
  $tutorName = $_POST['selectedTutor'];
  $subject = $_POST['slectedSubject'];
  $bookingDates = $_POST['selectedAppointment'];

  // 创建Charge扣款请求
  $charge = \Stripe\Charge::create([
    'amount' => $amount,
    'currency' => 'usd', // 根据你的业务修改货币代码,比如人民币填cny
    'source' => $stripeToken,
    'description' => "课程预约:{$tutorName} - {$subject}",
    'metadata' => [ // 存储自定义数据,在Stripe控制台可以查看
      'tutor_name' => $tutorName,
      'subject' => $subject,
      'booking_dates' => $bookingDates
    ]
  ]);

  // 向前端返回成功响应
  echo json_encode([
    'success' => true,
    'chargeId' => $charge->id
  ]);
} catch(\Stripe\Exception\CardException $e) {
  // 卡片相关错误(比如余额不足、卡片过期)
  echo json_encode([
    'success' => false,
    'error' => $e->getMessage()
  ]);
} catch(\Exception $e) {
  // 其他未知错误
  echo json_encode([
    'success' => false,
    'error' => '支付失败,请稍后重试'
  ]);
}
?>

场景2:通过Connect转账给讲师账户(平台代收后分账)

如果需要把钱转到讲师的Stripe Connect账户,需要添加destination参数:

<?php
require_once('vendor/autoload.php');

\Stripe\Stripe::setApiKey('sk_test_你的测试密钥');

try {
  $stripeToken = $_POST['stripeToken'];
  $amount = (int)($_POST['selectedAppointment'] * 100);
  // 讲师的Stripe Connect账户ID,你需要提前存储在数据库中
  $tutorStripeAccountId = 'acct_xxx';
  $tutorName = $_POST['selectedTutor'];

  $charge = \Stripe\Charge::create([
    'amount' => $amount,
    'currency' => 'usd',
    'source' => $stripeToken,
    'description' => "课程预约:{$tutorName}",
    'metadata' => [
      'tutor_name' => $tutorName
    ],
    'destination' => [
      'account' => $tutorStripeAccountId, // 资金会转入这个账户
      // 可选:平台收取手续费,比如抽成10%,这里填给讲师的金额(总金额的90%)
      // 'amount' => (int)($amount * 0.9)
    ]
  ]);

  echo json_encode([
    'success' => true,
    'chargeId' => $charge->id
  ]);
} catch(\Stripe\Exception\CardException $e) {
  echo json_encode([
    'success' => false,
    'error' => $e->getMessage()
  ]);
} catch(\Exception $e) {
  echo json_encode([
    'success' => false,
    'error' => '支付失败,请稍后重试'
  ]);
}
?>

3. 测试环境验证

  • 使用Stripe提供的测试卡号(比如4242 4242 4242 4242,过期日期填未来任意月份/年份,CVC随便填3位)进行支付
  • 支付成功后,你可以在Stripe控制台的Payments页面看到完整的Charge记录,而不是只有Token
  • 如果是Connect场景,讲师的Stripe控制台也会显示入账记录

4. 生产环境注意事项

  • 替换Secret Key为sk_live_xxx
  • 确保网站使用HTTPS(Stripe强制要求生产环境必须用HTTPS)
  • 配置Stripe Webhook(比如监听charge.succeeded、charge.failed事件),用来同步你的订单状态,避免前端回调失败导致状态不一致
  • 绝对不要在前端代码中暴露任何Secret Key,所有敏感操作必须通过后端完成
关键提醒
  • 禁止前端直接调用Charge API:前端只能生成Token,核心的扣款逻辑必须放在后端,否则会泄露密钥导致安全风险
  • 金额单位转换:Stripe API的金额是最小货币单位,比如人民币要把元转成分,所以必须乘以100
  • Connect账户ID:如果要分账给讲师,需要先让讲师完成Stripe Connect的账户注册,获取他们的account_id并存在你的数据库中

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:44:52