I'm sure I'm missing something obvious here, but I can't get my head around how to check for an existing card against a customer.
I'm using the stripe connect api within an laravel app to manage payments on behalf of others, and the basic process is as follows:
token
is created via stripe.js
and submitted with the payment formstripe_id
, otherwise a new customer is created using the token as the source/cardcharge
is then created using the retrieved or new customer stripe_id
Currently, if the customer returns and uses a different card, as the charge only includes a customer, not source, it'll be charged against their default card regardless.
What I'd like to do is:
token
customer
against local database etccard
fingerprint against customer's cardscard
on customer's recordcustomer
and card
idsSimply put: I can't see where in the process a persistent card_id
is generated; both those used in the stripe.js
response, and when created in the stripe dashboard, appear to be unique, meaning every charge creates a brand-new card object in stripe.
I know I can retrieve a list of cards stored against a customer's account - but where do I get the initial card_id
from to search against?
I've seen a question that touches on this here - Can I check whether stripe a card is already existed before going to create new one? - but I don't know Ruby, so can't make head nor tail of it.
EDIT:
Simpler version - is there a way to get the fingerprint
as described in the stripe docs here - https://stripe.com/docs/api/php#card_object - without having to first create a card object ?
Each fingerprint is unique to a card, so before storing additional cards for a customer, you can simply search the user's cards by fingerprint.
Card verification code check (CVC)You can perform CVC verification by providing the CVC value either when you create a payment with a new card payment method, or when you attach a new card payment method to a customer. To re-verify the CVC on a previously saved card, refer to the integration guide on CVC recollection.
Automatic card updatesStripe works with card networks and automatically attempts to update saved card details whenever a customer receives a new card (for example, replacing an expired card or one that was reported lost or stolen).
So the idea here would be to use the fingerprint
on the Card object or the Token object and not the id itself as those would be different if you add the same card multiple times.
When you get a new card token you can retrieve it through the Retrieve Token API and look for the fingerprint
in the card
hash.
You would keep a list of known fingerprints in your database associated with a specific customer and/or card so that you can detect duplicate cards.
NOTE: make sure you are using the secret keys to get those information. otherwise if you are using the publishable key, you might not get the fingerprint value.
I created a function to do this:
$customer
is the stripe customer object$stripe_account
is either your account's stripe ID or the connected account's stripe ID$token
comes from stripe.js elements$check_exp
allows you to decide if you want to check the card's expiration date as well, because the fingerprint does not change if the card's number is the samestripe PHP API 7.0.0
function check_duplicate_card($customer, $stripe_account, $token, $check_exp) {
$loc = "check_duplicate_card >> ";
$debug = true;
if ($debug) {
// see here for an explanation for logging: http://php.net/set_error_handler >> Examples
trigger_error("$loc started", E_USER_NOTICE);
}
try
{
// get token data
$response = \Stripe\Token::retrieve(
$token,
["stripe_account" => $stripe_account]
);
$token_fingerprint = $response->card->fingerprint;
$token_exp_month = $response->card->exp_month;
$token_exp_year = $response->card->exp_year;
if ($debug) {
trigger_error("$loc token_fingerprint = $token_fingerprint; token_exp_month = $token_exp_month; token_exp_year = $token_exp_year", E_USER_NOTICE);
}
// check for duplicate source
if ($debug) {
trigger_error("$loc customer sources = " . json_encode($customer->sources), E_USER_NOTICE);
}
$duplicate_found = false;
foreach ($customer->sources->data as &$value) {
// get data
$fingerprint = $value->fingerprint;
$exp_month = $value->exp_month;
$exp_year = $value->exp_year;
if ($fingerprint == $token_fingerprint) {
if ($check_exp) {
if (($exp_month == $token_exp_month) && ($exp_year == $token_exp_year)) {
$duplicate_found = true;
break;
}
} else {
$duplicate_found = true;
break;
}
}
}
if ($debug) {
trigger_error("$loc duplicate_found = " . json_encode($duplicate_found), E_USER_NOTICE);
}
} catch (Exception $e) {
if ($e instanceof \Stripe\Exception\ApiErrorException) {
$return_array = [
"status" => $e->getHttpStatus(),
"type" => $e->getError()->type,
"code" => $e->getError()->code,
"param" => $e->getError()->param,
"message" => $e->getError()->message,
];
$return_str = json_encode($return_array);
trigger_error("$loc $return_str", E_USER_WARNING);
http_response_code($e->getHttpStatus());
echo $return_str;
} else {
$return_array = [
"message" => $e->getMessage(),
];
$return_str = json_encode($return_array);
trigger_error("$loc $return_str", E_USER_ERROR);
http_response_code(500); // Internal Server Error
echo $return_str;
}
}
if ($debug) {
trigger_error("$loc ended", E_USER_NOTICE);
}
return $duplicate_found;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With