【问题标题】:In Braintree is it possible to verify duplicate payment method for just one customer instead of entire vault?在 Braintree 中,是否可以仅验证一个客户而不是整个保险库的重复付款方式?
【发布时间】:2016-03-29 09:03:20
【问题描述】:

对于Braintree_PaymentMethod::create() 函数,选项之一是:

'failOnDuplicatePaymentMethod', bool

如果通过此选项并且付款方式已添加到保险柜,则请求将失败。此选项不适用于 PayPal 付款方式。

这似乎是一个全局比较。即如果信用卡信息存在于保险库中,无论客户 ID 是什么,这都会失败。

有没有办法检查特定客户的重复项?

【问题讨论】:

  • 我在大约 2 年前就此事联系了支持人员,答案是否定的,但它当然值得再次研究。
  • 所以我不能有两个带有 41111111111111111 的测试帐户?这种情况对我来说毫无意义。保险库应该是个人帐户唯一的。如果共用一张信用卡的两个人有不同的帐户怎么办。这有什么意义。
  • 值得注意的是,它说这不适用于 PayPal。这实际上很棒。如果您尝试添加代表已添加付款方式的 PayPal 随机数,您只需取回与该付款方式对应的令牌(对于该客户,该令牌永远不会更改)。不幸的是,信用卡不是这样运作的。

标签: php braintree


【解决方案1】:

这是一个 .NET 版本。不是 100% 完成,但对于有相同情况的人来说是一个很好的开始。如果您发现任何问题或建议,请编辑此答案。

        try
        {
            // final token value (unique across merchant account)
            string token;

            // PaymentCreate request
            var request = new PaymentMethodRequest
            {
                CustomerId = braintreeID,
                PaymentMethodNonce = nonce,
                Options = new PaymentMethodOptionsRequest()
            };

            // try to create the payment without allowing duplicates
            request.Options.FailOnDuplicatePaymentMethod = true;
            var result = await gateway.PaymentMethod.CreateAsync(request);

            // handle duplicate credit card (assume CC type in this block)
            if (result.Errors.DeepAll().Any(x => x.Code == ValidationErrorCode.CREDIT_CARD_DUPLICATE_CARD_EXISTS))
            {
                // duplicate card - so try again (could be in another vault - ffs)

                // get all customer's existing payment methods (BEFORE adding new one)
                // don't waste time doing this unless we know we have a dupe
                var vault = await gateway.Customer.FindAsync(braintreeID);


                // fortunately we can use the same nonce if it fails
                request.Options.FailOnDuplicatePaymentMethod = false;

                result = await gateway.PaymentMethod.CreateAsync(request);
                var newCard = (result.Target as CreditCard);

                // consider a card a duplicate if the expiration date is the same + unique identifier is the same
                // add on billing address fields here too if needed
                var existing = vault.CreditCards.Where(x => x.UniqueNumberIdentifier == newCard.UniqueNumberIdentifier).ToArray();
                var existingWithSameExpiration = existing.Where(x => x.ExpirationDate == newCard.ExpirationDate);

                if (existingWithSameExpiration.Count() > 1)
                {
                    throw new Exception("Something went wrong! Need to decide how to handle this!");
                }
                else
                {
                    // delete the NEW card 
                    await gateway.PaymentMethod.DeleteAsync(newCard.Token);

                    // use token from existing card
                    token = existingWithSameExpiration.Single().Token;
                }
            }
            else
            {
                // use token (could be any payment method)
                token = result.Target.Token;
            }

            // added successfully, and we know it's unique
            return token;
        }
        catch (BraintreeException ex)
        {
            throw;  
        }
        catch (Exception ex)
        {
            throw;
        }

【讨论】:

    【解决方案2】:

    @Raymond Berg,我对您的代码进行了一些更改,这是更新后的代码:
    1.用foreach代替in_array
    2.如果发现重复,也删除添加的卡

    $customer = Braintree_Customer::find('your_customer');
    $unique_ids = array_map(extractUniqueId,$customer->creditCards);
    
    $result = Braintree_PaymentMethod::create(array(
        'customerId' => 'your_customer',
        'paymentMethodNonce' => 'fake-valid-discover-nonce',
    ));
    
    if ($result->success) {
        $cardAlreadyExist = false;
    $currentPaymentMethod = $this->extractUniqueId($result->paymentMethod);
    //The in_array function was not working so I used foreach to check if     card identifier exist or not
        foreach ($unique_ids as $key => $uid) {
            if( $currentPaymentMethod  == $uid->uniqueNumberIdentifier)
            {
                $cardAlreadyExist = true;
    //Here you have to delete the currently added card
                $payment_token = $result->paymentMethod->token;
                Braintree_PaymentMethod::delete($payment_token);
            }
    }
    
    
        if($cardAlreadyExist) {
            echo "Do your duplicate logic";
        } else {
            echo "Continue with your unique logic";
        }
    
    }
    

    【讨论】:

    • @harishsharma 请启用您的 php 错误报告,您可以修复语法错误。也可以在评论中发布语法错误。我没有看到语法错误?
    • 谢谢@harishsharma 我怎么错过了:(
    【解决方案3】:

    全面披露:我在 Braintree 工作。如果您还有任何问题,请随时联系support

    您和 Evan 是对的:这是唯一在重复创建时失败的预构建方法,无论客户创建如何。但是,您可以通过自己的自动化来实现您想要做的事情。

    为此,只需从the customer object 收集已经存在的credit card unique ids。然后当你create the new payment method时,和现有的卡片对比一下:

    function extractUniqueId($creditCard){ 
        return $creditCard->uniqueNumberIdentifier;
    }
    
    $customer = Braintree_Customer::find('your_customer');
    $unique_ids = array_map(extractUniqueId,$customer->creditCards);
    
    $result = Braintree_PaymentMethod::create(array(
        'customerId' => 'your_customer',
        'paymentMethodNonce' => 'fake-valid-discover-nonce',
    ));
    
    if ($result->success) {
        if(in_array(extractUniqueId($result->paymentMethod), $unique_ids)) {
            echo "Do your duplicate logic";
        } else {
            echo "Continue with your unique logic";
        }
    } 
    

    根据您的需要,您可以删除新的付款方式或您需要的任何其他方式。

    【讨论】:

    • 感谢您的完整回答!任何关于为什么不存在每个客户的见解?
    • 不,只是说有很多方法可以解决这些问题。在发布新功能时,我们总是希望得到 Braintree 支持的反馈。请继续给它! :)
    • 感谢雷蒙德的回答!那么这uniqueNumberIdentifier 只是信用卡号上的某种散列吗?还是包括过期在内的所有数据?它是特定于商家的吗?
    • 关于 uniqueNumberIdentifier 的更多信息:security.stackexchange.com/questions/63248/…
    • @Revent 绝对是商家特定的!但我可以确认哈希不考虑到期日期。你必须自己做。我添加了一堆测试卡(到 Braintree 保险库)并使用“查找客户”检索它们。返回的结果显示不同的到期日期(但显然从来没有不同的卡类型)。 Visa 03/2021 80988f0eaaff19cd36ea5ab99a4fb90dVisa 12/2018 80988f0eaaff19cd36ea5ab99a4fb90dVisa DEFAULT 03/2021 80988f0eaaff19cd36ea5ab99a4fb90dDiscover 01/2019 b8389212b5076ddbd08f2736eca7b6e3
    【解决方案4】:

    已通过 Braintree 支持进行检查 - 仍然没有开箱即用:

    如果您使用 failOnDuplicatePaymentMethod 任何将重复付款方式信息添加到保险柜的请求都将失败。

    我们目前没有阻止客户在他们的个人资料中添加重复卡的功能,但仍允许在多个个人资料下添加重复卡。如果您对此感兴趣,则必须构建自己的逻辑。

    【讨论】:

      猜你喜欢
      • 2015-09-16
      • 2016-12-17
      • 2018-05-20
      • 2018-03-05
      • 2017-11-18
      • 2014-12-29
      • 1970-01-01
      • 2020-02-04
      • 2016-05-04
      相关资源
      最近更新 更多