Hi everybody, in my personal EU based project I want to have one time charges and posibly subscription billing in the future, I heard good things abut Stripe so I decided to use it in my projects.
But after the new EU SCA regulations becoming SCA compliant has made my sync charge workflow much harder to test. With paymentIntents confirmations now I have to take extra trips between client and server, using the same endpoint, having a method to generate different responses based on required action, it was much more easy before.
So I'm asking , is there an alternative to Stripe, SCA compliant with an easier dev workflow than Stripe, maybe Paypal does it easier?
Currently, for a one time charge my workflow looks like this, before it was much SHORTER and STRAIGHTFORWARD.
public function confirmPayment(Request $request)
{
//Check if customer was created and user is logged
$customer = Auth::check() && Auth::user()->stripeId ? Customer::retrieve(Auth::user()->stripeId) : false;
$user = Auth::user();
if(!$customer)
{
return response()->json([
'message' => 'Registrate para disfrutar de nuestros mejores descuentos.',
'customer' => null,
], 500);
}
//If request has a payment method then customer was just created and credit card introduced, 3d secure not completed yet
if ($request->input('paymentMethodId'))
{
$outOfStock = Discount::outOfStockItems($request->input('cartItems'));
if(!empty($outOfStock)){
return response()->json([
'message' => 'No nos quedan suficientes existencias de '.$outOfStock[0].'. Escoge una cantidad menor.',
], 500);
}
$amount = (int) ($request->input('cartTotal')*100);
/*
$receiptData =
[
'userId' => $user['id'],
'stripeCustomerId' => $customer->id,
'paymentIntentId' => $paymentIntent->id,
'cartItems' => $request->input('cartItems'),
'cartTotal' => $request->input('cartTotal'),
];
*/
$user->cartItems = $request->input('cartItems');
$user->cartTotal = $request->input('cartTotal');
$user->save();
$paymentIntent = PaymentIntent::create([
'payment_method' => $request->input('paymentMethodId'),
'customer' => $customer->id,
'amount' => $amount,
'currency' => 'eur',
'confirmation_method' => 'manual',
'payment_method_types' => ['card'],
'confirm' => true,
'setup_future_usage' => 'off_session',
'save_payment_method' => true,
],
[
"idempotency_key" => sha1(Carbon::now())
]);
}
//If request has paymentIntent object then 3d secure was completed
if ($request->input('paymentIntent'))
{
$paymentIntent = PaymentIntent::retrieve($request->input('paymentIntent')['id']);
$paymentIntent->confirm();
$this->completePayment($paymentIntent);
}
//After one of the two options is completed, generate the proper response to client
return $this->generatePaymentResponse($paymentIntent);
}
public function generatePaymentResponse($paymentIntent)
{
if ($paymentIntent->status == 'requires_source_action' && $paymentIntent->next_action->type == 'use_stripe_sdk')
{
# Tell the client to handle the action, this is completing 3D Secure Auth.
return response()->json([
'message' => 'El pago requiere confirmación',
'requires_action' => true,
'payment_intent_client_secret' => $paymentIntent->client_secret,
], 200);
}
else if ($paymentIntent->status == 'succeeded')
{
# The payment didn’t need any additional actions and completed succesfully!
$this->completePayment($paymentIntent);
return response()->json([
'message' => 'Completaste el pago con exito',
], 200);
}
else
{
# Invalid status, something wrong happened
return response()->json([
'message' => 'Intención de pago invalida, intentalo de nuevo.',
], 500);
}
}
public function completePayment($paymentIntent)
{
$user = Auth::user();
$orderData =
[
'userId' => $user['id'],
'paymentiIntent' => $paymentIntent['id'],
'cartItems' => $user->cartItems,
'cartTotal' => $user->cartTotal,
];
$order = Item::purchaseItems($orderData);
$item = new Item();
$item->sendMail1($order);
return response()->json([
'message' => '¡Exito! Pago completado con exito',
], 200);
}