On my current datetime of writing this blog post I have shown the images of paypal dashboard. It may change on future. Paypal have changed many things on past.
Above image give us the idea how PayPal work on behind
Step 1 : Create a PayPal account.
select business on account creation.
Step 2 : got to developer dashboard from your business dashboard. See The Below Images.
Step 3 : now we are on developer dashboard
Step 3.1 : now create a rest API App buy clicking on My App and credential. see the image below.
when app is created PayPal also created two sandox account for us. Step-4 can be skip if we want use the default accounts
Step 4 : create sandbox account
Step: 5 accessing the accounts
After creating sandbox account we will have two user email
1 business email
2 personal email
we will use the business email to login to our PayPal merchant account.
And personal email to do purchase, order from our Laravel application.
watch the below images
from here we get the email pass. The modal open when we click the edit button on ....
I have shown on above image see click here
Going to the PayPal sandbox dasboard. which will give a real look of PayPal merchant Dashboard.
www.sandbox.paypal.com
Buyer/Payer/Personal Dashboard
Hurray we have completed all the PayPal account procedure and sandbox Utilities. Congratulations
https://developer.paypal.com/docs/business/get-started/
Note :
When we create our PayPal Rest Api App from the My app and Credential menu.
By Default PayPal give us two accounts One personal,
second business.
Now lets jump to the business logic and other essentials.
Step-6 : get the CLIENT_ID and CLIENT_SECRET from our created on
click the My Apps & Credentials menu on you dashboad and then click to the created app which will redirect to the below image pages
-
step-7 : puth the CLIENT_ID and CLIENT_SECRET on your laravel .env file
PAYPAL_MODE=sandbox
PAYPAL_SANDBOX_CLIENT_ID=
PAYPAL_SANDBOX_CLIENT_SECRET=
* step-8 : Install the [https://github.com/srmklive/laravel-paypal](https://github.com/srmklive/laravel-paypal)
`composer require srmklive/paypal`
> which a wrapper on PayPal SDK
[https://github.com/paypal/Checkout-PHP-SDK](https://github.com/paypal/Checkout-PHP-SDK)
* step-9 : now publish the config of our srmklive/laravel-paypal
php artisan vendor:publish --provider "Srmklive\PayPal\Providers\PayPalServiceProvider"
* step-10 : go to app config folder on paypal.php file
`config/paypal.php`
![config](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b6yybng9z8owo3nzp19h.png)
* Step-11 : add client_id, secret to paypal.php file
'mode' => env('PAYPAL_MODE', 'sandbox'), // Can only be 'sandbox' Or 'live'. If empty or invalid, 'live' will be used.
'sandbox' => [
'client_id' => env('PAYPAL_SANDBOX_CLIENT_ID'),
'client_secret' =>env('PAYPAL_SANDBOX_CLIENT_SECRET',),
],
* Step-11.1 : create route on api.php file
> we will be sending api request to our server side laravel app from our javascript paypal sdk. That's why we create route on api.php. benefit of doing these we don't need to send CSRF token to our laravel app when we make the fetch post request to our laravel server side application. In laravel api.php route don't work with session.so we will can not use the session() on this route. we can also write route on web.php file then we have to send csrf token with our post from our javascript.
* step-11.2 : creating route on api.php
```php
Route::group(['prefix'=>'paypal'], function(){
Route::post('/order/create',[\App\Http\Controllers\Front\PaypalPaymentController::class,'create']);
Route::post('/order/capture/',[\App\Http\Controllers\Front\PaypalPaymentController::class,'capture']);
});
- Step-11.2.1 : add the PayPal Javascript SDK on your blade file/page. where usually user want to pay. Example checkout page of our product. PayPal Javascript SDK
<body>
<!-- Set up a container element for the button -->
<div id="paypal-button-container"></div>
<!-- Include the PayPal JavaScript SDK -->
<script src="https://www.paypal.com/sdk/js?client-id=test¤cy=USD"></script>
<script>
// Render the PayPal button into #paypal-button-container
paypal.Buttons({
// Call your server to set up the transaction
createOrder: function(data, actions) {
return fetch('/api/paypal/order/create', {
method: 'POST',
body:JSON.stringify({
'course_id': "{{$course->id}}",
'user_id' : "{{auth()->user()->id}}",
'amount' : $("#paypalAmount").val(),
})
}).then(function(res) {
//res.json();
return res.json();
}).then(function(orderData) {
//console.log(orderData);
return orderData.id;
});
},
// Call your server to finalize the transaction
onApprove: function(data, actions) {
return fetch('/api/paypal/order/capture' , {
method: 'POST',
body :JSON.stringify({
orderId : data.orderID,
payment_gateway_id: $("#payapalId").val(),
user_id: "{{ auth()->user()->id }}",
})
}).then(function(res) {
// console.log(res.json());
return res.json();
}).then(function(orderData) {
// Successful capture! For demo purposes:
// console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
var transaction = orderData.purchase_units[0].payments.captures[0];
iziToast.success({
title: 'Success',
message: 'Payment completed',
position: 'topRight'
});
});
}
}).render('#paypal-button-container');
</script>
</body>
- Step-11.2.2 : when we importing the paypal javascirpt sdk at the bottom of our body tag replace client_id=test with client-id=<?php echo config('services.paypal.client_id') ?>
<script src="https://www.paypal.com/sdk/js?client-id=test¤cy=USD"></script>
client-id={{config('services.paypal.client_id')}}
- step-11.2 on Javascript SDK at createOrder we write /api/paypal/order/create url which send a post request to our larave app. ```js
createOrder: function(data, actions) {
return fetch('/api/paypal/order/create', {
method: 'POST',
body:JSON.stringify({
'course_id': "{{$course->id}}",
'user_id' : "{{auth()->user()->id}}",
'amount' : $("#paypalAmount").val(),
})
}).then
* step-11.3 : create the PaypalPaymentController
`php artisan make:controller PaypalPaymentController`
* step-11.4 : writhe the create method on PaypalPaymentController
* Step-11.5 : write logic and make request to paypal using the package we are using
```php
public function create(Request $request)
{
$data = json_decode($request->getContent(), true);
$this->paypalClient->setApiCredentials(config('paypal'));
$token = $this->paypalClient->getAccessToken();
$this->paypalClient->setAccessToken($token);
$order = $this->paypalClient->createOrder([
"intent"=> "CAPTURE",
"purchase_units"=> [
[
"amount"=> [
"currency_code"=> "USD",
"value"=> $data['amount']
],
'description' => 'test'
]
],
]);
$mergeData = array_merge($data,['status' => TransactionStatus::PENDING, 'vendor_order_id' => $order['id']]);
DB::beginTransaction();
Order::create($mergeData);
DB::commit();
return response()->json($order);
//return redirect($order['links'][1]['href'])->send();
// echo('Create working');
}
below code snippet setup the config and send a post request to paypal to get the access token
$this->paypalClient->setApiCredentials(config('paypal'));
$token = $this->paypalClient->getAccessToken();
$this->paypalClient->setAccessToken($token);
below code create a order on paypal on paypal gives us the order object which have a id
order id
$order = $this->paypalClient->createOrder([
"intent"=> "CAPTURE",
"purchase_units"=> [
[
"amount"=> [
"currency_code"=> "USD",
"value"=> $data['amount']
],
'description' => 'test'
]
],
]);
saving the order with the paypal order id on our database
$mergeData = array_merge($data,['status' => TransactionStatus::PENDING, 'vendor_order_id' => $order['id']]);
DB::beginTransaction();
Order::create($mergeData);
DB::commit();
return response()->json($order);
after creating the order a paypal payment modal open up.login as personal then paypal payment form will appear.
When we click on the paypment button on the paypal form model.
The javascript Paypal Sdk at onApprove we make a post request to our laravel app with the order which was provided by our laravel app from paypal on create order process.
onApprove: function(data, actions) {
return fetch('/api/paypal/order/capture' , {
method: 'POST',
body :JSON.stringify({
orderId : data.orderID,
payment_gateway_id: $("#payapalId").val(),
user_id: "{{ auth()->user()->id }}",
})
}).
the post goes to api/paypal/order/capture which lead to create us new method on PayPalPaymentController
public function capture(Request $request)
on that method we write our business logic
public function capture(Request $request)
{
$data = json_decode($request->getContent(), true);
$orderId = $data['orderId'];
$this->paypalClient->setApiCredentials(config('paypal'));
$token = $this->paypalClient->getAccessToken();
$this->paypalClient->setAccessToken($token);
$result = $this->paypalClient->capturePaymentOrder($orderId);
// $result = $result->purchase_units[0]->payments->captures[0];
try {
DB::beginTransaction();
if($result['status'] === "COMPLETED"){
$transaction = new Transaction;
$transaction->vendor_payment_id = $orderId;
$transaction->payment_gateway_id = $data['payment_gateway_id'];
$transaction->user_id = $data['user_id'];
$transaction->status = TransactionStatus::COMPLETED;
$transaction->save();
$order = Order::where('vendor_order_id', $orderId)->first();
$order->transaction_id = $transaction->id;
$order->status = TransactionStatus::COMPLETED;
$order->save();
DB::commit();
}
} catch (Exception $e) {
DB::rollBack();
dd($e);
}
return response()->json($result);
}
Again we make a post request to paypal to get the access token using the below snippet
$data = json_decode($request->getContent(), true);
$orderId = $data['orderId'];
$this->paypalClient->setApiCredentials(config('paypal'));
$token = $this->paypalClient->getAccessToken();
$this->paypalClient->setAccessToken($token);
then we make our payment using capturePaymentOrder()
$result = $this->paypalClient->capturePaymentOrder($orderId);
then do our database saving stuff
DB::beginTransaction();
if($result['status'] === "COMPLETED"){
$transaction = new Transaction;
$transaction->vendor_payment_id = $orderId;
$transaction->payment_gateway_id = $data['payment_gateway_id'];
$transaction->user_id = $data['user_id'];
$transaction->status = TransactionStatus::COMPLETED;
$transaction->save();
$order = Order::where('vendor_order_id', $orderId)->first();
$order->transaction_id = $transaction->id;
$order->status = TransactionStatus::COMPLETED;
$order->save();
DB::commit();
Happy coding. Thank you to read my post. Leave a comment for a feedback. Give a unicorn.
Reference
developer.paypal.com/docs/business/checkout/set-up-standard-payments
https://developer.paypal.com/docs/business/checkout/set-up-standard-payments/#1-add-payment-buttons
https://github.com/paypal/Checkout-PHP-SDK#code
https://github.com/srmklive/laravel-paypal/issues/407#issuecomment-864521831
https://www.youtube.com/watch?v=_7YBIRQfSN0&ab_channel=AndreMadarang
Top comments (5)
Hi will this work with re-occuring payments? What extra steps are needed?
No. You check out the Paypal docs for re-occurring.
Thank you so much !
this is so helping
Thank you.
you can show TransactionStatus controller ?