I'm hoping someone here could throw their eye over my flow, to see if I'm doing things correctly and, if not, to advise me as to where to improve.
My scenario is a simple one:
Step 1
- Customer logs in with an email address and password, note that this could be their first visit, or a return visit
- Customer is presented with a list of products, makes their selection, clicks button to pay
- Customer is presented with a CC form, as per Stripe guidelines and utilising Stripe.js.
- Upon submission, the details are sent to Stripe and a response is received which I pass to my PHP script.
At this point I have, I believe, a response id and a source object containing the abstracted card details as well as a card id.
Step 2
I connect to the Stripe API:
Stripe::setApiKey($stripe_secret_key); // note this is a Connect account
Stripe::setApiVersion('2018-05-21');
I check to see if I already have a Stripe customer id stored for this email address. If so, I use that. Otherwise, I create a Stripe customer:
$customer = Stripe_Customer::create(
[
'description' => $u->user_email,
'email'=>$u->user_email
], $stripe_access_token
);
$customer_id = $customer->id;
I then fetch that customer's Stripe object:
$customer = Stripe_Customer::retrieve($customer_id);
and then I fetch the source object, using the response id
$source = Stripe_Token::retrieve($form_response_id);
Step 3
I want to make sure that the fee is taken from the card the Customer is using right now, irrespective of whether or not they have visited before or not, or used the same card before or not. So I save this source to the customer:
$customer->sources->create(['source' => $source->id]);
$customer->save();
... and, although the latest source is supposed to be the default source (i.e. the one that's used), I make sure of it:
$customer->default_source = $source->card->id;
$customer->save();
Step 4
I do some local work to get fee descriptions, calculate application fees, etc. I put this altogether as a charge array, using the inititial card id I received from Stripe.js as the 'source' parameter
$charge = [
'customer' => $customer->id,
'source' => $transaction_card_id,
'amount' => $total_gross_received_cents,
'currency' => 'EUR',
'description' => $transaction_desc,
'application_fee' => $application_fee
];
$charge_obj = Stripe_Charge::create($charge, $stripe_access_token);
$charge_id = $charge_obj->id;
I then save the $charge_id
in my transaction records.
Questions
My biggest concerns revolve around Step 3 - making sure that the right card is accepted and used. Note that:
- I don't store any card information (nor do I want to), so every transaction requires card details to be inputted by the customer and abstracted by Stripe.js.
- I've run into trouble before with cards that are renewed - i.e. the number is the same, but the expiry is different. I want to make sure this doesn't happen.
Can I save the card as a new source for the customer every time, even if it already exists and is assigned to them? It seems to be working, and overwriting duplicate source records, but I want to be sure.
Obviously, I'm nervous about rolling out something I feel I don't fully grok yet, so if someone could give me a thumbs up or thumbs down, I be very grateful.