对于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。