【问题标题】:Charge Separate Sources/Cards for Customer for Separate Sites Connected to One Stripe Account为连接到一个 Stripe 帐户的单独站点向客户收取单独的来源/卡费用
【发布时间】:2018-12-14 08:02:45
【问题描述】:

我有一个问题,即在将多个网站连接到一个 Stripe 帐户时,确保网站始终为特定网站上的特定客户收取正确的卡(或银行帐户)费用。

  • 站点 A - example1.com 通过 API 连接到 Stripe 帐户 1
  • 站点 B - example2.com 通过 API 连接到 Stripe 帐户 1

客户 1 使用他们的个人电子邮件帐户在站点 A 上使用信用卡 1(比如他们的名片)购买了一些东西。他们的电子邮件与他们的客户 ID 一起保存,并且他们的来源设置为名片。然后客户 1 到站点 B 并使用信用卡 2(他们的个人卡)在站点 B 上购物,但使用相同的电子邮件地址。

如何在不更新站点 A 使用的默认卡的情况下让站点 B 每次都使用特定卡?


基本上在创建帐户之前,我会检查以确保客户还没有使用该特定电子邮件的帐户。因此,如果在站点 B 上使用与站点 A 相同的电子邮件,则会为两个站点找到相同的客户帐户。 (出于解释目的简化了代码。)

<?php
// namespace statement
// use \Stripe statements    


function exists ($email) {

  $customers = Customer::all(['email' => $email]);
  $count = 0;
  if (isset ($customers['data'])) {
    $count = count($customers['data']);
  }
  if ($count == 1) {
    $c = current ($customers['data']);
    if ($c instanceof Customer) {
      return $c->id;
    }
  }
  return false;

}

function create_customer ($email) {

  // Try to get the customer id by email.
  $cid = exists ($email);

  // Customer not found create them.
  if (!$cid) {
    try {
      $c = Customer::create([
        'email' => $e->mail,
      ]);
      return $c->id;
    } catch(Exception $e) {
      return false;
    }
  }
  return $cid;
}

function set_source ($cid, $token) {
  try {
    // This updates the default card, if I am understanding the documentation correctly.
    Customer::update($customer_id, ['source' => $token]);
    return true;
  } catch(Exception $e) {
    _sec_set_error_messages ($e, $sandbox_message);
  }
  return false;
}

function charge ($cid, $amount) {

  try {

    // This charges the default card, if I am understanding the documentation correctly.
    $charge = Charge::create([
      'amount' => $amount, 
      'currency' => 'usd',
      'customer' => $cid
    ]);

    return $charge;

  } catch (Exception $e) {
    return false;
  }


}

// check_my_db_for_customer_id();

// Create customer if not found.
$email = 'personal@example.com';
$cid = create_customer ($email);
if ($cid) {
  // save_to_my_db($email, $cid);
  set_source ($cid, $token);
  charge ($cid, $amount);
}

?>

问题是,在向客户收费时,如何告诉每个站点使用特定的卡?我可以在我的 set_source 函数期间保存一个源,然后在为卡充电时为特定站点使用相同的源吗?

<?php

function set_source ($cid, $token) {
  try {
    // Need to add a source if one is found, not update the default.
    $get_source_id_somehow = Customer::update($customer_id, ['source' => $token]);
    return $get_source_id_somehow;
  } catch(Exception $e) {
    _sec_set_error_messages ($e, $sandbox_message);
  }
  return false;
}


function charge ($cid, $amount, $src) {

  try {

    $charge = Charge::create([
      'amount' => $amount, 
      'currency' => 'usd',
      'customer' => $cid,
      'source' => $src
    ]);

    return $charge;

  } catch (Exception $e) {
    return false;
  }

}

// check_my_db_for_customer_id_and_source_id();

// Create customer if not found.
$email = 'personal@example.com';
$cid = create_customer ($email);
if ($cid) {
  // save_to_my_db($email, $cid);
  $src = set_source ($cid, $token);
  // save_source_id_to_my_db ($src); ????
  charge ($cid, $amount, $src);
}

?>

或者是将每个站点连接到自己独立的 Stripe 帐户的唯一方法?谢谢。

编辑 - 附加问题

这也会带来安全风险吗?如果用户 1 在站点 A 上注册,然后用户 2 使用用户 1 的电子邮件在站点 B 上注册,他们肯定需要输入新的付款详细信息,以便在用户 2 注册时不会从用户 1 的卡上扣款。

编辑 2 - 其他想法

似乎需要以某种方式将客户帐户绑定到单个站点或应用程序。我不知道它是否会验证,但可能会在该站点上使用该域(及其用户 ID)标记电子邮件或客户,这样当您搜索匹配的客户时,您只会找到具有匹配电子邮件的客户域(并通过查找用户 ID 确保它尚未被使用)。否则,用户 2 可以使用用户 1 的电子邮件进行注册,并且根据站点的不同,可能允许在不先验证另一个电子邮件的情况下更改他们的电子邮件,在这种情况下,您无法在站点 B 上更新用户 2 的 Stripe 客户帐户不会为站点 A 上的用户 1 搞砸。

这可能会导致您的 Stripe 帐户中出现多次相同的客户电子邮件,但您可以按标签排序以至少找到各个域并查看用户 ID 正在使用哪些域。

现在,如果用户 1 在站点 A 上使用 personal@email.com 注册,它会创建一个带有站点 A 域及其用户 ID 标记的 Stripe 帐户。如果我们不将其与帐户 ID 相关联,则用户 1 可能能够将其站点的电子邮件切换到 somethingnew@email.com(如果 Stripe 未更新),然后如果用户 2 使用personal@email.com 注册在站点 A 上,该帐户现在会找到与 personal@email.com 绑定的 Stripe 帐户,并且两个帐户都将从同一个 Stripe 帐户运行。

在创建新客户之前尝试匹配客户似乎是一个严重的安全漏洞。或者 Stripe 帐户的电子邮件需要与网站保持同步,但仍需要添加额外的标签以防止用户 1 的 Stripe 帐户被劫持。

可能的解决方案 - 谁能确认?

每次有人注册时创建一个新的 Stripe 帐户并将其绑定到网站的域用户 ID 以供将来搜索是我能想到的唯一安全方法。

<?php

$customer = Customer::create([
    'email' => 'paying.user.3@example.com',
    'metadata' => [
      'site' => 'test/',
      'uid' => '6'
    ]
]);

然后您可以像这样搜索...这不是最优雅的方式,因为您失去了对搜索结果进行分页以换取更精细结果的本机方式,因为元数据无法通过 Customer::all() [我知道]。

<?php

$customers = Customer::all(['email' => $email]);
$matches = [];
foreach ($customers['data'] as $c) {
  if (
    $c->metadata && is_object ($c->metadata) && 
    $c->metadata->site && $c->metadata->site == 'test/' &&
    $c->metadata->uid && $c->metadata->uid == $uid
  ) {
    $matches[] = $c;
  }
}

【问题讨论】:

    标签: php security stripe-payments


    【解决方案1】:

    收到 Stripe 的答复:

    对于彼此独立运营的项目、网站或企业,您必须使用单独的 Stripe 帐户。当您激活一个新帐户时,它受 Stripe 的标准政策和定价的约束——它不会继承任何可能适用于您现有帐户的特殊状态或其他类似注意事项。

    话虽如此;您可以随时创建额外的 Stripe 账户,每个账户相互独立运作。在此过程中,您可以将新的或现有的帐户添加到一个配置文件中,并在仪表板中快速切换它们(而不必记住任何其他电子邮件和密码组合),而不是创建具有不同电子邮件地址的多个用户帐户。

    以下是有关管理多个帐户的支持文档: https://stripe.com/docs/multiple-accounts

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-13
      • 2014-08-23
      • 2017-08-06
      • 2017-06-17
      • 2018-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多