Showing posts with label Laravel 5.2. Show all posts
Showing posts with label Laravel 5.2. Show all posts

Thursday, August 20, 2020

AWS PHP SDK - Create an Entry in Route53 - Laravel

 Hello,

In this blog I will explain you how to you can create an entry in Route53 hosted zone using AWS PHP SDK. Solution I mentioned here is particularly for Laravel app, but you can still use it in any of the PHP project. 

This solution is pretty much useful when you want to make a dynamic entry in your hosted. For example a dynamic sub domain creation. 

First of all your need install couple of packages using composer. Following are the packages. 

"aws/aws-sdk-php": "^3.148",

"aws/aws-sdk-php-laravel": "~3.0",

You can either install it by adding it in composer.json file or you can install it using composer require. 

Once the installation is done, follow the steps mentioned in below URL. 

https://github.com/aws/aws-sdk-php-laravel

Once installation is done. You need to add following keys in your env file.

AWS_ACCESS_KEY_ID

AWS_SECRET_ACCESS_KEY

AWS_REGION (default = us-east-1)

Set the values in above keys from your AWS account. That's it your AWS SDK is ready. Now add following line your controller where you want to have logic for adding value in Route53

use Aws\Route53\Route53Client;

use Aws\Common\Credentials\Credentials;

Now next step is to create a client

$client = Route53Client::factory(array(

            'credentials' => config('aws.credentials'),

            'region' => config('aws.region'),

            'version' => config('aws.version'),

)); 

After client is created we will use changeResourceRecordSets to create an entry.

$result = $client->changeResourceRecordSets(array(

            // HostedZoneId is required

            'HostedZoneId' => 'YOUR_HOSTED_ZONE_ID',

            // ChangeBatch is required

            'ChangeBatch' => array(

                'Comment' => 'string',

                // Changes is required

                'Changes' => array(

                    array(

                        // Action is required

                        'Action' => 'CREATE',

                        // ResourceRecordSet is required

                        'ResourceRecordSet' => array(

                            // Name is required

                            'Name' => 'YOUR_VALUE',

                            // Type is required

                            'Type' => 'CNAME', //A, CANME

                            'TTL' => 600,

                            'ResourceRecords' => array(

                                array(

                                    // Value is required

                                    'Value' => 'YOUR_VALUE', //IP address or load balancer.

                                ),

                            ),

                        ),

                    ),

                ),

            ),

        ));

That's it and it will create an entry in Route53 hosted zone. 

Tuesday, December 11, 2018

Laravel Check if SMTP Connection is valid

Hello,

While working with Laravel we often add SMTP credentials to send mail. It's important to check SMTP connection before sending mail or else it may give you error and throw run time exception. Here in this blog I am going to explain how to check SMTP connection before sending mail.

Below is the code you can use to check.

try {
$security = ($request->get('mail_encryption') != 'None') ? request()->get('mail_encryption') : null;
$transport = new \Swift_SmtpTransport($request->get('mail_host'), $request->get('mail_port'), $security);
$transport->setUsername($request->get('mail_username'));
$transport->setPassword($request->get('mail_password'));
$mailer = new \Swift_Mailer($transport);
$mailer->getTransport()->start();
}
catch (\Swift_TransportException $e) {
return redirect('mailSettings')->withInput()->with(array('message'=>'Can not connect to SMTP with given credentials.'));
}

As you can see in above code, first we are setting security config and create Swift_SmtpTransport class. After this we add add username and password. After that we create Swift_Mailer class and check it, if it throws an exception that means credentials are wrong or else credentials are correct.

Laravel Create Custom Validator

As we all know that Laravel comes with in built set of custom validators like required, unique etc using which we can do form or request validations on server side. In this blog I am going to explain how to create custom validator.

Custom validator is required when you have some special logic validations. For example a field should be minimum of 12 characters, it should start with special prefix etc.

To do this Laravel provides way to create custom field validator. You have to extend Validator in boot method of AppServiceProvider. Here is the complete code.

use Validator;

public function boot()
{
        Validator::extend('VALIDATOR_NAME', function($attribute, $value, $parameters, $validator) {
               //validation logic
               //should return true or false
        });

       Validator::replacer('greater_than_field', function($message, $attribute, $rule, $parameters) {
  return $attribute."MESSAGE".$parameters[0];
});
}

As you can see in above code, first we define validator with Validator::extend and then using Validator::replacer we can define the message to be displayed.

This way you can create your own validators and then use it with Validator class.

$this->validate($request, [
          'field'=>'VALIDATOR_NAME'
]);

Wednesday, August 1, 2018

Laravel Allow Single Login Only

Hello,

Recently in one of my project we need functionality to allow only single session for user. So if I am logged in with one user account then I can not use it on other device. If they try to do so, it will log you out from first last session and will continue with current session.

So here is the trick I have used is to store active session id to users table and then check it with new session id on login. If both are not same then destroy the old session.

So first of all create migration and add session id column in users table.

Schema::table('users', function($table)
        {       
            $table->string('session_id')->nullable();
        });

Now in your AuthController or LoginController add following function after user is authenticated.

$user = \Auth::user();
$currentSessionId = $request->session()->getId();
if($lastSessionId != null){
if($currentSessionId != $lastSessionId){
//destroy last session
\Session::getHandler()->destroy($lastSessionId);
}
}
$user->session_id = $currentSessionId;
$user->save();

So here it will destroy old session and create new one. Please note this is one way to achieve single login. There could be better trick, in that case please share here.lara

Friday, April 20, 2018

Laravel ValidationException Handling

This is the creepiest thing I have ever fixed in Laravel. I can't even imagine that in Laravel we can have such creepy problem. But anyways other than this I really like Laravel framework.

First let me explain the problem. In our Laravel 5.5 application we have added exception handling in app/Exceptions/Handler.php file

public function render($request, Exception $exception)
{
    Redirect::to('admin/errorPage')->send();
}

Now the problem was in case of form validations it was throwing ValidationException so in case of returning back to form it always took me to the error page and I am not able to see what are the validation issues. Now that was really strange. So there were two options . First, I have to remove server side validations so it does not throw ValidationException and we shall do all client side validations. Or find out some other way to handle this.

So after 3 to 4 hours of struggle of going though framework code and documentation and online help I finally figure out the solution. Here are steps to add it.

1) Step 1 : Add  ValidationException in dontReport field in app/Exceptions/Handler.php

protected $dontReport = [
   //
   \Illuminate\Validation\ValidationException::class
];

2) Step 2 : Update the render method declaration

public function render($request, Exception $exception)
{
    if($this->shouldReport($exception)){
       Redirect::to('admin/errorPage')->send();
    }else{
       return $this->convertValidationExceptionToResponse($exception, $request);
    }
}

So here first we are checking if the current exception to be reported or not by checking shouldReport function

If not to be reported then we are using convertValidationExceptionToResponse method of super class to generate the response and send it back.

Please note that this solution will only work

Friday, February 2, 2018

Amazon EC2 Laravel Not Live After " php artisan up " Command

Hello,

This blog post is about quick tip for the users who have deployed Laravel application on Amazon EC2 instance.

Recently we had Laravel application deployed on Amazon EC2 instance where we put site on maintenance mode with command

php artisan down

Worked properly, site was in maintenance mode and displayed

Be Right Back screen.

After sometime we tried to make site up and running by

php artisan up

Didn't work as site was still displaying

Be Right Back screen

Tried to clear the cache and config with

php artisan cache:clear
php artisan config:clear

But still it didn't worked. After 5 to 10 mins to struggle, found out an issue. It was because of file permission issue.  When you put site to maintenance mode, it creates

storage/framework/down folder

When you run

php artisan up

This folder should be removed. However in my case I was not using root user hence this file was not deleted.

So solution is

go to storage/framework folder and run command

rm -rf down

and that's it, your site is up and live.

Hope this helps you. 

Friday, August 25, 2017

Laravel Dynamic Mail Configuration With Values From Database

In Laravel we have config folder, where we have different files like app.php and mail.php etc where we can configure settings. For example for sending mail from Laravel application, we have to configure mail.php file with configs like mail driver, mail user name etc. This will work good for static information. But what if you want to override and use your own settings from database at run time.

For example you have different mail configurations for each users and you want to set it when user is logged in. I this blog I am going to show you how you can do this in Laravel 5.x

For example you have mail_settings table where you are saving mails settings for each user. Now when user is logged in we have to get settings of logged in user and set it in config. This is how you can do that.

We know that all laravel controller extends the Controller. So what you can do is in constructor of Controller.php file, you can set the mail settings.

Here is how you can do this.
public function __construct()
{
$this->middleware(function ($request, $next) {
if(Auth::user()){
//So user is logged in.
if(Auth::user()->parent_id != null){
//Get the mail settings.
$settings = MailSettings::where('user_id',Auth::user()->parent_id)->first();

if(isset($settings)){
//settting up mail config for the logged in user.
config( ['mail' => ['from' => ['address' => $settings->from_email, 'name' => $settings->from_name], 'host'=>$settings->mail_host, 'port'=>$settings->mail_port, 'username'=>$settings->mail_username,  'password'=>$settings->mail_password, 'encryption'=>$settings->mail_encryption, 'driver'=>$settings->mail_driver]]);
}
}
}
return $next($request);
});

}

So as you can see we are getting mail settings from table for logged in user and setting up it in config. This way you can override anything in the default config and set it run time.

Monday, August 7, 2017

Integrating GetStream with Laravel using stream-laravel for Real Time Notifications

Hello,

After a long time I am publishing a blog post. I am sorry to all my readers for not publishing blog for longer time. In this blog I am going to explain how you can have real time notifications in your laravel application using GetStream.io.

I will not go in installation details as it's very well documented on their Github page. You can refer it here.

GetStream/steam-laravel

After you have installed it and configured service provider. First thing you have to do is create table for notifications. For that create migration add following code to it.

Schema::create('notifications', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->index();
$table->string('name');
$table->string('message');
$table->string('link');
$table->timestamps();
});

Now create a model with name Notifications and add following code to it.


namespace App\Http\Models;

use App\User;
use Illuminate\Database\Eloquent\Model;

class Notifications extends Model
{
    //
    use \GetStream\StreamLaravel\Eloquent\ActivityTrait;
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $table = 'notifications';

    protected $fillable = ['name', 'message','link'];
   
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'user_id' => 'int',
    ];
    /**
     * Get the user that owns the task.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
    /**
     * Stream: Add extra activity data - task name, and user's display name:
     */
    public function activityExtraData()
    {
        return array('name'=>$this->name, 'message' => $this->message, 'link'=> $this->link);
    }
   /**
    * Stream: Change activity verb to 'created':
    */
    public function activityVerb()
    {
        return 'created';
    }

}


Now open your user model and add following code to it.

public function notifications()
    {
        return $this->hasMany(Notifications::class);
    }

So now we have notifications table setup and it's linked to user with hasMany relationship. Now next we will show how you can create notification.

$userObject->notifications()->create([
'name' => "NOTIFICATION_NAME",
'message' => 'NOTIFICATION_MESSAGE',
'link' => 'NOTIFICATION_LINK'           
]);

Here userObject is the object of user for whom you want to create notification. Now next we will show how to get all the notifications and show it user. For this we are going to use AngularJs. 

We are using client side library of GetStream.io you can download it from following link.


For this first of all we have to get token and that can be generated only from server side code. So create an API and call it from AngularJs controller. Here is the API code.

public function getStreamToken(){
$feed = \FeedManager::getUserFeed(Auth::user()->id);
$token = $feed->getToken();

return Response::json(array("success"=>true,"token"=>$token,"user_id"=>Auth::user()->id));
}

Now as soon as we get token, next you have to connect to client and get user feeds and register for push notifications. Here is the code for the same.

var client = stream.connect('YOUR_API_KEY', null, 'YOUR_APP_ID');
$scope.user = client.feed('user', $scope.user_id, $scope.token);

function successCallback() {
console.log('now listening to changes in realtime');
}

function failCallback(data) {
console.log(data);
}

$scope.user.subscribe($scope.gotNotification).then(successCallback, failCallback);    

$scope.user.get({limit:10, offset:$scope.offset}, $scope.gotUserActivities);

So above code will register you for the push notification and will get all your notifications. Now you have to display it using HTML and CSS as per your wish. 

For showing new notification, you can use below code in gotNotification function.

$.bootstrapGrowl(data.new[0].name + ' ' + data.new[0].message, { type: 'success' });

It will show nice pop up on screen.


 

Monday, April 3, 2017

Beginning Laravel Video Course

Here is something unusual I did apart from programming. My first ever video course "Beginning Laravel" with Packt Publishing



In this course you will learn about basics of Laravel Development. First section is about installation of Laravel. This section will start with introduction of Laravel and installation of Laravel in Mac, Windows and Linux. Then we will cover, basics of Laravel including, understanding of Framework Structure, basics of Artisan Commands, Composer, Core Concepts of Laravel, MVC structure, Database Migrations, Laravel Controllers, Models and Views etc. In last section
We will finish this course by creating simple Web application with Laravel which will have CRUD operations and basic validations in final section, this will help you getting started with Laravel Development. If you are interested in learning Laravel then this is the course you are looking for. You can buy it at following link.


Beginning Laravel Video Course



Hope you will like this course. Let me know your feedback in comments.

Sunday, January 8, 2017

.htaccess Doesn't Work in Amazon AWS EC2 Instance with Ubuntu

Recently I was configuring Laravel application in Amazon AWS EC2 instance which was having Ubuntu and Apache installed. The problem was htacess file was not working so Laravel routes were not working. Instead of parsing laravel routes it always shows error URL not found.

The problem is by default in apache installed on ubuntu doesn't have .htaccess enabled so first you have to manually enable it in config file and restart apache.

Here are the steps.

1) Login to your EC2 instance with SSH.

ssh -i "Yourkey.pem" ubuntu@yourpublicip

2) Enable Mode Rewrite, this is just incase if it's not enabled.

sudo a2enmod rewrite

3) Go to following directory.

cd /etc/apache2/sites-available

If you use LS command here you will see following file.

000-default.conf

That's the file with default apache configuration which are applied to your sites in /var/www/html folder.

4) Open this file for editing.

sudo nano 000-default.conf

5) Add following lines after DocumentRoot /var/www/html line.

<Directory />
     Options FollowSymLinks
     AllowOverride All
</Directory>
<Directory /var/www/html>
     Options Indexes FollowSymLinks MultiViews
     AllowOverride All
     Order allow,deny
     allow from all
</Directory>

6) Save the file and restart the apache.

sudo service apache2 restart

that's it and now your .htaccess file will work and your laravel application will start working.

Thursday, December 8, 2016

Amazon RDS Connection Limit Exhausted

Recently in one of our project we built laravel application and deployed it on Amazon AWS and database was on Amazon RDS. In start there was no issue but after some months we had problems with database connection. After sometime laravel app could not connect to Amazon RDS.

So I checked RDS and dashboard and found out that number of database connection was beyond allowed limits. It means connection open to RDS was not closed after sometime and there were lots of half opened connections. That eventually crashing RDS sever and then connection was not established till we restart the RDS server.

So next step was to check database queries and find the queries which are taking time to execute and get data. After looking into all the queries I got the query which is taking long time to execute and that query was responsible half closed or non closed database connections and which is ultimately crashing Amazon RDS server.

So how I fixed that. Well we have a only one solution to speed up database queries and that is

INDEXING


Yes, that 's right indexing solved my issue. There was a table in my database which has 100K records and executing query from it was taking lots of time as there was no indexing. So I created an index on columns which are used mostly for querying that table and after creating index query was working blazing fast.

If you are facing the same issue, better check your database queries and optimize it with indexing to make it faster.

Saturday, October 1, 2016

Laravel 5.x Store Uploaded Files to Amazon S3

Recently in one of my Laravel 5.2 project, we used Amazon s3 to store static files and user uploaded files. So here in this blog I am going to explain how to do this.

1) First of all install following plugin through composer.

composer require league/flysystem-aws-s3-v3 ~1.0

2) Now add your S3 credentials to your environment (.env file)

S3_KEY=YOUR_KEY
S3_SECRET=YOUR_SECRET
S3_REGION=YOUR_REGION
S3_BUCKET=YOUR_BUCKET

3) Open config.filesystems.php and configure s3 driver as follow.

's3' => [
            'driver' => 's3',
            'key'    => env('S3_KEY'),
            'secret' => env('S3_SECRET'),
            'region' => env('S3_REGION'),y.
            'bucket' => env('S3_BUCKET'),
        ]

4) Now open controller where you have code to manage uploaded file and add following dependency.

use Illuminate\Contracts\Filesystem\Filesystem;

5) Use following code to store your file to S3.

$image = $request->file('user_uploaded_image');
$imageFileName = time() . '.' . $image->getClientOriginalExtension();
$s3 = \Storage::disk('s3');
$filePath = '/mypath'/.$imageFileName;
$s3->put($filePath, file_get_contents($image), 'public');
$uploadedFileS3Path = 'https://'.env('S3_BUCKET').'/'.$filePath;

Please note in my case I configured S3 bucket to be direct URL of uploaded file. In case your case if you have not configured it then your path will be as follow.

$uploadedFileS3Path = 'http://s3-'.env('S3_REGION').'.amazonaws.com/'.env('S3_BUCKET').'/'.$filePath;

This path you can use to display file and you can store it to database as well.


Special Case 

If you are using it in localhost using XAMPP in your windows system. You have to do following few steps.

Download certificate pem file from this link. https://curl.haxx.se/ca/cacert.pem and store it to some where in your C drive or whatever drive you have your xampp installed.

For example I put it in  C:\code\cacert.pem

Now open your php.ini file and bottom of the file add following line.

curl.cainfo = C:\code\cacert.pem

That's it and it will work in your local environment too. Hope this helps you.

Saturday, September 10, 2016

Laravel 5.3 Run Artisan Command Through Routes

Recently for one my project we installed Laravel 5.3 on shared server where we were not having SSH or route access.

As we know general practice with Laravel is to create database tables with migrations and for that we have to run artisan commands through terminal and SSH.

But in our case we were not having SSH access, we have only FTP and database access so we have to figure out a way to run this commands through web. In this blog I am going to explain how to do this.

After reading Laravel 5.3 document I came to know that Laravel gives you Artisan class to run artisan command. So what I did is I created two routes, one for creating migration and other to run migration.

To create migration

Route::get('/create-migration-command', function () {
    Artisan::call('make:migration', ['name' => 'migration_name']);
});

As you can see here the command is make:migration and parameter passed is name of migration. 

Virtually it is equivalent to following SSH command.

php artisan make:migration migration_name

This will generate migration file in database folder, you can open it through FTP and add necessary code of migration.

Run Migration

Route::get('/run-migration-command', function () {
    Artisan::call('migrate', []);
});

Virtually it is equivalent to following SSH command.

php artisan migrate

Hope this helps you.

Laravel 5.3 Internal Server Error After Installation

Recently for one of my project I have installed Laravel 5.3 on server but after installation when I tried to run it in web it was showing 500 Internal Server Error so I had to spend few hours in resolving it so here in this blog I am going to explain what was the issue and how I solved it.

1) Find out the Error.

I looked into to server logs from cPanel and found out following error.

SoftException in Application.cpp:429: Mismatch between target UID (501) and UID (99) of file "/path/larravel/public/index.php"


After searching for sometime about this error I figured out that the apache or web user was not owner for the files because I created laravel project through SSH so the logged in SSH user was the owner of the files and folders.

So when apache or web user tried to access the files it was not working. So the solution was to change the ownership of files and folders to apache user.

2) Find out the username of apache user.

In most cases user name of apache user should be www-data or apache or apache2 but in my case since I was using VPS the username was different. So run following command in terminal through SSH

ls -l

It will give you file list with user and group owner. That's your web username. Now change the ownership of folder to this username.


chown -R username:username laravel

That's it. Now run your laravel project and it shall display following screen.

That means your laravel project is working fine on the server. Hope this helps you.

Saturday, August 13, 2016

Paypal Create Recurring Payment Profile From Laravel

Recently one of our Laravel project we have subscriptions management with recurring payment options with Paypal. It took a while for me to integrate it with my Laravel project so here in this blog I am going to explain how to do this. Please note example given here is using sandbox account.

First of all we need Paypal Merchant SDK.

You can find it here from this link https://github.com/paypal/merchant-sdk-php

Import it with composer. Add following line to your composer.json file in require section and run composer update command.

"paypal/merchant-sdk-php":"3.8.*"

Once the composer is updated your local vendor folder will have paypal directory with all the classes. Please note fort this SDK your will need PHP version 6 and on words.

Now first of all we will need a Paypal token to initiate recurring profile creation.

Go to your Laravel controller and add following classes of Paypal merchant SDK.

use PayPal\Service\PayPalAPIInterfaceServiceService;
use PayPal\EBLBaseComponents\PaymentDetailsType;
use PayPal\CoreComponentTypes\BasicAmountType;
use PayPal\EBLBaseComponents\SetExpressCheckoutRequestDetailsType;
use PayPal\EBLBaseComponents\BillingAgreementDetailsType;
use PayPal\PayPalAPI\SetExpressCheckoutRequestType;
use PayPal\PayPalAPI\SetExpressCheckoutReq;
use PayPal\EBLBaseComponents\RecurringPaymentsProfileDetailsType;
use PayPal\EBLBaseComponents\BillingPeriodDetailsType;
use PayPal\EBLBaseComponents\ScheduleDetailsType;
use PayPal\EBLBaseComponents\CreateRecurringPaymentsProfileRequestDetailsType;
use PayPal\PayPalAPI\CreateRecurringPaymentsProfileRequestType;
use PayPal\PayPalAPI\CreateRecurringPaymentsProfileReq;


Now lets first get token. Add following code to your controller function.

        $config = array (
            'mode' => 'sandbox' ,
            'acct1.UserName' => 'yourusername,
            'acct1.Password' => 'yourpassword',
            'acct1.Signature' => 'yourapisignature'
        );
        $paypalService = new PayPalAPIInterfaceServiceService($config);
        $paymentDetails= new PaymentDetailsType();

        $orderTotal = new BasicAmountType();
        $orderTotal->currencyID = 'USD';
        $orderTotal->value = '10.00';//your own value

        $paymentDetails->OrderTotal = $orderTotal;
        $paymentDetails->PaymentAction = 'Sale';

        $setECReqDetails = new SetExpressCheckoutRequestDetailsType();
        $setECReqDetails->PaymentDetails[0] = $paymentDetails;
        $setECReqDetails->CancelURL = 'http://yourcancelurl/cancel-paypal-payment';
        $setECReqDetails->ReturnURL = 'http://yoursuccessurl/qt/success-paypal-payment';

        $billingAgreementDetails = new BillingAgreementDetailsType('RecurringPayments');
        $billingAgreementDetails->BillingAgreementDescription = 'Recurring Billing';
        $setECReqDetails->BillingAgreementDetails = array($billingAgreementDetails);

        $setECReqType = new SetExpressCheckoutRequestType();
        $setECReqType->Version = '104.0';
        $setECReqType->SetExpressCheckoutRequestDetails = $setECReqDetails;

        $setECReq = new SetExpressCheckoutReq();
        $setECReq->SetExpressCheckoutRequest = $setECReqType;

        $setECResponse = $paypalService->SetExpressCheckout($setECReq);

        if($setECResponse->Ack == 'Success'){
            $token = $setECResponse->Token;
            return Redirect::to('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='.$token);
        }else{
            return Redirect::to('error')->with('message', 'There is a problem in payment processing.');
        }

As you can see in above code. As soon as we got token we are sending user to Paypal for authorization. Once it is authorized from Paypal you will get payer id and you will return back to your website on the URL specified in above code.

Now we get Payer id we have to create recurring profile.

        $profileDetails = new RecurringPaymentsProfileDetailsType();
        $profileDetails->BillingStartDate = date(DATE_ISO8601, strtotime(date('Y-m-d').' +1 day'));
        //Since date start should be greater than current date.

        $paymentBillingPeriod = new BillingPeriodDetailsType();
        $paymentBillingPeriod->BillingFrequency = 1;//your own value
        $paymentBillingPeriod->BillingPeriod = "Month";//your own value
       

        $paymentBillingPeriod->Amount = new BasicAmountType("USD", "10.00");//your own value

        $scheduleDetails = new ScheduleDetailsType();
        $scheduleDetails->Description = "Recurring Billing";
        $scheduleDetails->PaymentPeriod = $paymentBillingPeriod;

        $createRPProfileRequestDetails = new CreateRecurringPaymentsProfileRequestDetailsType();
        $createRPProfileRequestDetails->Token = $token;

        $createRPProfileRequestDetails->ScheduleDetails = $scheduleDetails;
        $createRPProfileRequestDetails->RecurringPaymentsProfileDetails = $profileDetails;

        $createRPProfileRequest = new CreateRecurringPaymentsProfileRequestType();
        $createRPProfileRequest->CreateRecurringPaymentsProfileRequestDetails = $createRPProfileRequestDetails;

        $createRPProfileReq = new CreateRecurringPaymentsProfileReq();
        $createRPProfileReq->CreateRecurringPaymentsProfileRequest = $createRPProfileRequest;

        $config = array (
            'mode' => 'sandbox' ,
            'acct1.UserName' => 'yourusername,
            'acct1.Password' => 'yourpassword',
            'acct1.Signature' => 'yourapisignature'
        );
        $paypalService = new PayPalAPIInterfaceServiceService($config);
        $createRPProfileResponse = $paypalService->CreateRecurringPaymentsProfile($createRPProfileReq);

Now we have to check if the recurring profile successfully created.

if($createRPProfileResponse->Ack == 'Success'){
            $profileId = $createRPProfileResponse->CreateRecurringPaymentsProfileResponseDetails->ProfileID;
            //your own logic to save details in database.

}else{
            return Redirect::to('error')->with('message', 'There is a problem in payment processing.');
        }

That's it and your recurring payment profile is created.

Hope this helps you.

Sunday, April 24, 2016

Laravel 5.x Dispaly Custom Error Page on Exception and Error

In this quick and small blog I am going to explain how to create custom error page for your Laravel 5.x project.

Laravel 5.x have custom exception handler class which you will find in app/Exceptions/Handler.php

If you open this file, you will see below code.

/**
* Render an exception into an HTTP response.
*
* @param  \Illuminate\Http\Request  $request
* @param  \Exception  $e
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
return parent::render($request, $e);
}

This code renders exceptions on your HTTP response and your end users will actually see following pages.


That's really embarrassing for your end users as they don't understand what is this all about. So best practice is to hide this types of errors and show custom error page to users. For that add a error page view in your project and render it on exception. Modify above function as follow.

/**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $e
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $e)
    {

        return response()->view('errors.index');
    } 

That's it and now you will have custom error page in your laravel app.

Laravel Swagger Integration for API and Code Documentation

I know, I know, all developers hate documentation. Even I also don't like it but it's an industry practice and we have to follow this. In this blog I am going to explain how you can integrate swagger most popular framework for API with Laravel for creating API docs. Swagger is an incredible way to easily document and test your APIs. So here is the step by step guides.

1) Go to your laravel project on Terminal and include Swagger PHP package with composer.

composer require zircote/swagger-php

This will install swagger php package to laravel and will update your vendor folder. Now we have to create documentation.

2) There is standard syntax for creating docs with swagger. For each API functions and classes you have to add swagger config and config have all the standard keys to define what kind of information you will include in docs. You can check this on following URL.


Hover mouse on left side object and it will give you information on right side.


This you have to add in add in your controllers and models in your laravel project. So lets define some basic info. For example see following swagger config we have added. This we have added a comments to top of the controller function.

@SWG\Swagger(
     *     basePath="",
     *     schemes={"http"},
     *     @SWG\Info(
     *         version="1.0",
     *         title="Sample API",
     *         @SWG\Contact(name="Hiren Dave", email="hdave10@gmail.com"),
     *     ),
     *   @SWG\Get(
     *     path="/",
     *     description="Returns basic information",
     *     produces={"application/json"},
     *     @SWG\Response(
     *         response=200,
     *         description="Application Overview"
     *     )
     *   )
     * )

And following is my API function.

        public function index()
{
              return Response::json(array('success'=>false,'message'=>'This is Basic Info of API'));
}

It have basic info like API info and API path and output information.

3) Build Swagger Docs.

Go to your laravel project in terminal and run following command.

./vendor/bin/swagger ./app/Http

It will generate swagger.json file in your root folder with all the swagger config you have added in your controller. 

4) Add swagger UI to project to show this docs.

Go to following link to download swagger UI.


Download it and copy all the files from dist folder to your public/docs folder. Now open public/docs/index.html page and update path of your swagger.json file in following code.

if (url && url.length > 1) {
        url = decodeURIComponent(url[1]);
      } else {
        url = "http://petstore.swagger.io/v2/swagger.json";
      }

Change URL to url your own swagger.json URL, for example in my case it was http://localhost/laravel-swagger/swagger.json

5) Read the Docs. Now go to public docs folder. In my case URL was

http://localhost/laravel-swagger/public/docs/index.html

When you run, you will see following output page.


That's it and you have your API docs minimum efforts. Hope this helps you.

Wednesday, April 20, 2016

Laravel Add Date Text in PNG and JPEG Image

In our recent project we have a requirement to add date as text in all the uploaded image. For example, check below image.


In this blog I am going to explain how you can do this.

First of open image from the path.

$publicPath = public_path();
$imagePath = $publicPath."/image/myImage.png"; //replace it with your own path

Create a date text.

$text = date('d-m-Y');

Setup font

$font = $publicPath."/fonts/RobotoCondensed-Bold.ttf"; //replace it with your own path

Now while working on this I faced two issues

1) PHP GD functions like imagecreatefrompng was not woking.
2) PNG image was having JPEG mime type.

To resolve first issue, first check your phpinfo(). It should have PNG support enabled.


If it's not enabled, enable it.

To solve second issue check mime type of image with file info function and use respective function to get image resources.

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $imagePath);

$image = null;
     
if($mime == "image/png"){

            $image = imagecreatefrompng($imagePath);
        
}else{

            $image = imagecreatefromjpeg($imagePath);       
}

Now we have image resource, we have to add text in image and save image.

$black = imagecolorallocate($image, 0, 0, 0);
imagettftext($image, 20, -45, 600, 20, $black, $font, $text);
imagepng($image,$imagePath);
imagedestroy($image);

That's it. Please note in my case all the images were of fixed width and height so I gave fix X = 600 and y = 20 coordinate for text. If you have variable width and height calculate it dynamically.

Hope this helps you.

Thursday, April 14, 2016

Laravel Share Some Variable with All Views

Hello,

Recently in one of my laravel project we have a requirement create side menu in app with some dynamic stats numbers like

Users   (12)
Managers  (10)
Questions  (25)

This menu is included in all the views and to set dynamic values in that we have to share this numbers globally. In this blog I am going to mention how to so this.

1) Create a BaseController class and extend it with controller and add a constructor.

class BaseController extends Controller {
       public function __construct() {
     
       }
}

2) Inside that constructor get all the numbers and share it with view

$users = DB::table('users')->count();
$managers = DB::table('managers')->count();
$questions = DB::table('questions')->count();

View::share('users',$users);
View::share('managers',$managers);
View::share('questions',$questions);

after adding this code your base controller should look like following.

class BaseController extends Controller {
       public function __construct() {
             $users = DB::table('users')->count();
             $managers = DB::table('managers')->count();
             $questions = DB::table('questions')->count();

            View::share('users',$users);
            View::share('managers',$managers);
            View::share('questions',$questions);
       }
}


3) Now extend this base controller to all other controllers.

class MyConttoller extends BaseController {

}

That's it now any view which you render from controller will have those variables by default. Now you just have to use those variables in views.

<ul>
       <li> Users  ({{$users}}) <li/>
       <li> Managers  ({{$managers}}) <li/>
       <li> Questions  ({{$questions}}) <li/>
<ul/>

Hope this helps you.


Saturday, March 26, 2016

Laravel LinkedIn Verification - Laravel LinkedIn Login

Recently in one of the laravel project we have to add LinkedIn verification. It's like we have to auto check if user is signing up on our app should have LinkedIn profile with same name and email. In this blog I am going to explain how to do this. First of all we will need one LinkedIn application. Go to following URL to create new LinkedIn application.

https://www.linkedin.com/developer/apps/

Once you create application it should look like below screenshot.


Now you have to copy client Id and client secret to your laravel app, that you can do in env file.

LINKEDIN_CLIENT_ID = your_client_id
LINKEDIN_CLIENT_SECRET = your_client_secret

Now in your laravel view you have to add a link, so user can click on it and go to LinkedIn for authentication.

Add following to your routes.

    Route::get('/user/linkedin-verification','AdminController@viewLinkedinVerification');

Following should be function of your controller.

        $user_id = Auth::user()->id;
        $user = User::find($user_id);
        $redirect_uri = env('LINKEDIN_REDIRECT_URL', '');
        $client_id = env('LINKEDIN_CLIENT_ID', '');
        $client_secret = env('LINKEDIN_CLIENT_SECRETE', '');
        return view('linkedinverification.index')-              >with(['user'=>$user,'redirect_uri'=>$redirect_uri,'client_id'=>$client_id,'client_secret'=>$client_secret]);

Where user is currently logged in user and redirect URL is the URL that will be invoked on successful LinkedIn verification,

Your view should have a link like below.

                        <p>Please verify your LinkedIn account. <a href="https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id={{$client_id}}&redirect_uri={{$redirect_uri}}&state=ab234aatdssda">Click Here</a></p>

When user click on this link they will see below screen of your LinkedIn application.


Once you are logged in with your LinkedIn account it will redirect back you website with specified redirect url with access code.

Add following to your laravel route.

Route::get('/user-dashboard/linkedin-response','AdminController@linkedinVerification');

In my case I used above URL, you can have different URL as per your requirement.

Now in linkedinVerification function first we will get access code which is generated by LinkedIn and get oAuth access token first. following is the code to get access token.

            $redirect_uri = env('LINKEDIN_REDIRECT_URL', '');
            $client_id = env('LINKEDIN_CLIENT_ID', '');
            $client_secret = env('LINKEDIN_CLIENT_SECRET', '');

            $code = Input::get('code');
            
            /// for get accesstoken
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL,"https://www.linkedin.com/uas/oauth2/accessToken");
            curl_setopt($ch, CURLOPT_POST, 5); // number of post parameters
            curl_setopt($ch, CURLOPT_POSTFIELDS,
                        "code=".$code."&client_id=".$client_id."&redirect_uri=".$redirect_uri."&grant_type=authorization_code&client_secret=".$client_secret);
            
            // receive server response ...
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            
            $server_output = curl_exec ($ch);
            curl_close ($ch);

Now you get access token, use that to get user profile information.

                $result = json_decode($server_output, true);
                
                $access_token = $result['access_token'];
                
                if($access_token != '')
                {
                    // for get customer email
                    $datach = curl_init();  
                    $authorization = 'Authorization: Bearer '.$access_token;
                    curl_setopt($datach,CURLOPT_URL,'https://api.linkedin.com/v1/people/~:(id,email-address,first-name,last-name)?format=json');
                    curl_setopt($datach,CURLOPT_RETURNTRANSFER,true);
                    curl_setopt($datach, CURLOPT_HTTPHEADER, array($authorization));
                 
                    $output=curl_exec($datach);
                 
                    curl_close($datach);
              }

Above call will give you basic user profile, now we just get email and name from it and compare it with credentials registered with us.

Hope this helps you.