I am trying to setup paypal payment authorization in my laravel app so the seller has the option to review the offer and reject payment if he wants on his paypal business dashboard rather than receive the complete payment right away and unnecessarily be charged for transaction fee from paypal if he does not want to receive the funds.
I use srmklive/paypal package for handling paypal payment method and right now my code makes immediate capture on order confirmation from user. Those things were so much easier to setup on Stripe…
This is my current paypal portion of code in checkout controller:
if ($request->input('payment_option') === 'paypal'){
$provider = new PayPalClient();
$provider->setApiCredentials(config('paypal'));
// $provider->setCurrency('EUR');
$paypalToken = $provider->getAccessToken();
$response = $provider->createOrder([
"intent" => "CAPTURE",
"application_context" => [
"return_url" => route('payment.success'),
"cancel_url" => route('payment.cancel'),
],
"purchase_units" => [
[
'description' => "Globus Transfers - " . strtoupper($vehicle) . " taxi transfer reservation from $departureLocationName to $destinationLocationName.",
"amount" => [
"currency_code" => "EUR",
"value" => $price
],
]
]
]);
if(isset($response['id']) && $response['id'] != 'null') {
// Store the order ID in the session
session(['paypal_order_id' => $response['id']]);
foreach($response['links'] as $link){
if($link['rel'] === 'approve'){
return redirect()->away($link['href']);
}
}
} else {
return redirect()->route('payment.cancel');
}
And this is my success method in PaymentController:
if($routeAndReservationData['payment_option'] === 'paypal'){
$provider = new PayPalClient();
$provider->setApiCredentials(config('paypal'));
$paypalToken = $provider->getAccessToken();
$orderId = session('paypal_order_id');
$response = $provider->showOrderDetails($request->token);
// Capture the payment
$captureResponse = $provider->capturePaymentOrder($orderId);
if(isset($captureResponse['status']) && $captureResponse['status'] == 'COMPLETED'){
// Update the reservation with the PayPal transaction ID
$reservation->update(['paypal_order_id' => $orderId]);
// Send confirmation email to the user
Mail::to($routeAndReservationData['email'])->send(new UserReservationCreation($routeAndReservationData));
Mail::to('[email protected]')->send(new CompanyReservationCreation($routeAndReservationData));
session()->flush();
return view('payment.success');
} else {
return view('payment.cancel');
}
What methods i need to use to make the described functionality?
2
Answers
I already tried "intent" => "AUTHORIZE" but it didn't work. The paypal portion of code in success method should be modified too. There should be probably some other method then "$captureResponse = $provider->capturePaymentOrder($orderId);" and the condition "if(isset($captureResponse['status']) && $captureResponse['status'] == 'COMPLETED'){.." should be probably like "if(isset($captureResponse['status']) && $captureResponse['status'] == 'PROCESSED')". I need more help with this since the documentation is very vague to me, thank you!
Use
"intent" => "AUTHORIZE"
for that behavior.For more information see: Authorize a payment and capture funds later. (The part about being a partner and using the purchase_units.payee object to specify a receiver does not apply to first-party integrations with the receiver’s own API credentials.)
Edit with more details:
You also need to change what happens in your "success" method after approval. Instead of doing an orders /capture on the order, you need to call the /authorize endpoint.
Also your database should not be recording the PayPal Order ID. The Order ID is temporary and only used for the payer’s approval; it is not the PayPal transaction ID, and does not serve any accounting purpose. Instead, save
purchase_units[0]->payments->authorizations[0].id