在Braintree,可以只验证一个客户的重复付款方式,而不是整个保险库


In Braintree is it possible to verify duplicate payment method for just one customer instead of entire vault?

对于Braintree_PaymentMethod::create()函数,其中一个选项是:

'failOnDuplicatePaymentMethod', bool

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

这似乎是一个全球性的比较。即,如果信用卡信息存在于保险库中而与客户id无关,则这将失败。

有没有一种方法可以检查特定客户的重复项?

全面披露:我在Braintree工作。如果您有任何进一步的问题,请随时联系支持人员

您和Evan是正确的:无论客户创建如何,这都是重复创建失败的唯一预构建方式。然而,你可以通过自己的自动化来实现你想要做的事情。

要做到这一点,只需从客户对象中收集已经存在的信用卡唯一ID。然后,当你创建新的支付方式时,将其与现有卡进行比较:

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支持--仍然无法开箱即用:

如果使用failOnDuplicatePaymentMethod,则向Vault中添加重复付款方式信息的任何请求都将失败。

我们目前没有阻止客户在其配置文件中添加重复卡的功能,同时允许在多个配置文件下添加重复卡。如果这是你感兴趣的事情,你必须建立自己的逻辑。

@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";
    }
}

这是一个.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;
        }

如这里所述,现在可用于卡片。不适用于Paypal、Gpay和其他支付方式。但这需要我们发送大脑树客户ID。