条带无效请求 - 多次使用令牌

时间:2017-09-12 11:22:02

标签: php stripe-payments

代码:

Stripe::setApiKey($stripe_secret_key);
Stripe::setApiVersion('2017-02-14');



// Either create a new customer object or retrieve the existing customer object

$db->query(" SELECT StripeCustomerToken FROM stripe_ids WHERE UPPER(UserEmail) = UPPER(:email) ");
$db->bind(':email', $user_email);
$db->execute();
$customer_token = $db->fetchSingleColumn();

if(!$customer_token)
{
    $customer = Stripe_Customer::create(
        [
            'card' => $stripe_card_token,
            'description' => $user_email,
            'email'=>$user_email
        ],
        $stripe_access_token
    );

    $customer_token = $customer->id;

    $db->query(" INSERT INTO stripe_ids (UserEmail, StripeCustomerToken) VALUES (:e, :custID) ");
    $db->bind(':e', $user_email);
    $db->bind(':custID', $customer_token);
    $db->execute();
}

if(!$customer_token)
    throw new Exception('No Stripe Customer Token detected. The payment could not be processed.');

$customer = Stripe_Customer::retrieve($customer_token);



// Using the token ID, retrieve the full token object and retrieve the fingerprint from the `card.fingerprint` attribute

$current_card = Stripe_Token::retrieve($stripe_card_token);
$current_card_fingerprint = $current_card->card->fingerprint;
$current_card_id = $current_card->card->id;



// Iterate through the list of the customer's saved sources and check if any has the same value for its `fingerprint`

$source_exists = false;
foreach($customer->sources->data as $i => $fingerprint)
{
    if($current_card_fingerprint === $fingerprint)
        $source_exists = true;
}



// If not, add the card to the customer object

if(!$source_exists)
    $customer->sources->create(['source' => $stripe_card_token]);

$customer->default_source = $current_card_id;
$customer->save();



// Create the charge using the customer ID and the card ID

$charge = [
    'customer' => $customer->id,
    'source' => $current_card_id,
    'amount' => $total_gross_received_cents,
    'currency' => 'EUR',
    'description' => $transaction_description_str,
    'application_fee' => $databiz_fee
];

$charge_obj = Stripe_Charge::create($charge, $stripe_access_token);

if(empty($charge_obj))
    throw new Exception('No Stripe Charge Object detected. The payment could not be processed.');

$charge_token = $charge_obj->id;

问题:

每次客户使用该应用程序时,他们都必须输入其CC细节。因此我想:

  1. 创建客户(如果尚不存在)
  2. 检查他们是否将当前卡作为来源,如果没有,则将其添加为来源
  3. 为当前使用的卡充电
  4. 我遇到了麻烦,即返回的客户的默认卡没有更新到当前使用的卡(导致资金来自默认值),所以我将卡ID添加到收费对象,并且将当前卡保存为客户的默认值。

    现在的问题是,在实时交易中,我收到InvalidRequest异常 - 我不能多次使用令牌。

    有人能指出我哪里出错了吗?

1 个答案:

答案 0 :(得分:1)

将卡添加到客户($customer->sources->create(...))时提供的令牌可能已被其他API请求使用。您应该检查您的集成,以确保$stripe_card_token包含由CheckoutElements创建的“新鲜”令牌。

我注意到的其他一些事情:

  • 您正在Connect使用direct charges。这意味着客户对象必须存在于已连接的帐户上,而不是平台的帐户上。当您检索客户时,您没有指定已连接帐户的API密钥,因此该请求将在您平台的帐户上发出并且将失败(因为该平台的帐户中不存在该客户ID)

  • 您正在使用Stripe's PHP library的旧版本(1.x)。您应该考虑升级到更新版本。这需要将代码更新为新语法(Stripe_Class - > \Stripe\Class

  • 当查看客户卡上是否已存在时,您会迭代$customer->sources->data。请注意,在检索客户对象时,此属性最多包含10个源。如果客户拥有10个以上的来源,则需要使用pagination来检索完整列表。

    请注意,如果您使用最新版本的Stripe的PHP库,则可以使用auto-pagination功能轻松处理此问题。