Here I will explain step by step process how PHP Paypal SDK works in terms payment and our app e-commerce app. Let's take a look at the constructor function.
public function __construct()
{
$paypal_conf = Config::get('paypal');
$this->_api_context = new \PayPal\Rest\ApiContext(new OAuthTokenCredential(
$paypal_conf['client_id'],
$paypal_conf['secret'])
);
$this->_api_context->setConfig($paypal_conf['settings']);
}
In the PayPal PHP SDK, an API context is a configuration object that contains information required to make API calls to PayPal servers, such as client ID, client secret, API endpoints, authentication tokens, and other settings.
When making an API call, the SDK needs an API context object to authenticate the client and authorize the transaction. The API context manages the authentication and authorization details so that the developer doesn't need to include them in every API call.
The __construct()
function in the provided code snippet creates a new API context object and initializes it with the client ID, secret, and other settings from the paypal
configuration file. The API context object is then stored in the $this->_api_context
property, which can be used to make API calls to PayPal throughout the lifetime of the object.
See the diagram below
Let's see our payWithpaypal() function
public function payWithpaypal(Request $request)
{
$order = Order::with(['details'])->where(['id' => session('order_id')])->first();
$tr_ref = Str::random(6) . '-' . rand(1, 1000);
$payer = new Payer();
$payer->setPaymentMethod('paypal');
$items_array = [];
$item = new Item();
$number = sprintf("%0.2f", $order['order_amount']);
$item->setName(session('f_name'))
->setCurrency(Helpers::currency_code())
->setQuantity(1)
->setPrice($number);
array_push($items_array, $item);
$item_list = new ItemList();
$item_list->setItems($items_array);
$amount = new Amount();
$amount->setCurrency(Helpers::currency_code())
->setTotal($number);
\session()->put('transaction_reference', $tr_ref);
$transaction = new Transaction();
$transaction->setAmount($amount)
->setItemList($item_list)
->setDescription($tr_ref);
$redirect_urls = new RedirectUrls();
$redirect_urls->setReturnUrl(URL::route('paypal-status'))
->setCancelUrl(URL::route('payment-fail'));
$payment = new Payment();
$payment->setIntent('Sale')
->setPayer($payer)
->setRedirectUrls($redirect_urls)
->setTransactions(array($transaction));
try {
$payment->create($this->_api_context);
/**
* Get redirect url
* The API response provides the url that you must redirect
* the buyer to. Retrieve the url from the $payment->getLinks() method
*
*/
foreach ($payment->getLinks() as $key => $link) {
if ($link->getRel() == 'approval_url') {
$redirectUrl = $link->getHref();
break;
}
}
//$status = OrderTrack::where('success', 'success')->first();
//dd($status);
DB::table('orders')
->where('id', $order->id)
->update([
'transaction_reference' => $payment->getId(),
'payment_method' => 'paypal',
'order_status' => 'success',
'failed' => now(),
//'status_id'=>$status->id,
'updated_at' => now()
]);
Session::put('paypal_payment_id', $payment->getId());
if (isset($redirectUrl)) {
return Redirect::away($redirectUrl);
}else{
dd("bye");
}
} catch (\Exception $ex) {
// dd($ex->getData()["error_description"]);
Toastr::error(trans($ex->getData()));
//Toastr::error(trans('messages.your_currency_is_not_supported',['method'=>trans('messages.paypal')]));
return back();
}
Session::put('error', trans('messages.config_your_account',['method'=>trans('messages.paypal')]));
return back();
}
This code is a PHP function that processes a payment through PayPal using the PayPal REST API.
The payWithpaypal()
function begins by retrieving the order details from the database based on the order_id
saved in the session data. It then generates a unique transaction reference number using the Str::random()
and rand()
functions.
Next, the function creates a new instance of the Payer
class and sets the payment method to "paypal". It then creates an array of Item
objects representing the items being purchased and sets the price and currency for each item.
The function then creates an Amount
object representing the total amount of the payment, sets the transaction description using the transaction reference number generated earlier, and creates a Transaction
object using the Amount
and ItemList
objects.
The function then creates a RedirectUrls
object with URLs for PayPal to redirect the user after payment is complete or if the payment is cancelled. It then creates a Payment
object with the intent of "Sale" and the Payer
, RedirectUrls
, and Transaction
objects.
The function then tries to create the payment using the _api_context
object, which is an instance of the ApiContext
class that contains the PayPal API credentials and settings. If the payment is created successfully, the function retrieves the redirect URL from the payment's links and redirects the user to PayPal to complete the payment.
If an exception is thrown during the payment creation process, the function catches the exception and displays an error message to the user. If the payment creation is unsuccessful for any other reason, the function displays a generic error message to the user.
See the diagram
Let's see getPaymentStatus()
public function getPaymentStatus(Request $request)
{
$payment_id = Session::get('paypal_payment_id');
if (empty($request['PayerID']) || empty($request['token'])) {
Session::put('error', trans('messages.payment_failed'));
return Redirect::back();
}
$payment = Payment::get($payment_id, $this->_api_context);
$execution = new PaymentExecution();
$execution->setPayerId($request['PayerID']);
/**Execute the payment **/
$result = $payment->execute($execution, $this->_api_context);
$order = Order::where('transaction_reference', $payment_id)->first();
if ($result->getState() == 'approved') {
$order->transaction_reference = $payment_id;
$order->payment_method = 'paypal';
$order->payment_status = 'paid';
$order->order_status = 'confirmed';
$status = OrderTrack::where('order_status', $order->order_status)->first();
$order->status_id=$status->id;
$order->confirmed = now();
$order->save();
/*try {
Helpers::send_order_notification($order);
} catch (\Exception $e) {
} */
return redirect('&status=success');
/*if ($order->callback != null) {
return redirect($order->callback . '&status=success');
}else{
return \redirect()->route('payment-success');
}*/
}
$order->order_status = 'failed';
$status = OrderTrack::where('order_status', $order->order_status)->first();
$order->status_id=$status->id;
$order->failed = now();
$order->save();
return redirect('&status=fail');
/*if ($order->callback != null) {
return redirect($order->callback . '&status=fail');
}else{
return \redirect()->route('payment-fail');
}*/
}
The code is for a function named getPaymentStatus
that accepts an HTTP request object as a parameter. The purpose of this function is to handle the response from PayPal after the user completes the payment process.
The function first retrieves the paypal_payment_id
from the session and checks if the PayerID
and token
parameters are present in the request object. If either of these parameters is missing, the function sets an error message in the session and redirects the user back to the previous page.
If the PayerID
and token
parameters are present, the function uses the PayPal PHP SDK to execute the payment and retrieve the payment status. It retrieves the order object with the transaction reference ID from the database and updates its payment and order status accordingly.
If the payment is approved, the function updates the order's payment status, order status, and sets the confirmed timestamp. It also sets a status ID by retrieving the first order track with the same order status as the updated order. Finally, it redirects the user to a success page.
If the payment is not approved, the function updates the order status to 'failed', sets the failed timestamp, and redirects the user to a fail page.
There are some commented out lines of code that seem to be related to sending a notification or redirecting the user to a callback URL, but they are not currently being used in the function.