Send Push Notification to Android and iOS app [Part 1]


RESTFUL API IMPLEMENTATION FOR PUSH NOTIFICATION USING FCM & LARAVEL/PHP

 

Firebase Cloud Messaging(FCM)is a google cloud messaging service it is used for sending notification and messages in cross-platform for android, web application and ios application, which is available at no cost.

 

Firebase is a mobile development platform built by the Google to help the developers quickly develop high-quality apps, grow the user base, and earn extra cash by displaying ads.

 

Firebase comes with everything that mobile developers need to build, maintain and scale a mobile app on all platforms including iOS: from Storage, Hosting and Databases to innovative tools like Remote Config and Test Lab.

 

Firebase Cloud Messaging (FCM) platform is another important service based on the precedent Google Cloud Messaing (GCM) service. FCM inherits core infrastructure of GCM but simplifies the client development. FCM integration can be completed with just lines of code instead of writing own registration or subscription retry complex logic as you did for GCM.

 

In this blog, we’re going to see server side integration of Firebase Cloud Messaging (FCM) in android app using laravel/php. If you want to use this service in your application please just follow below simple steps and then you can send notification using google FCM(Firebase Cloud Messaging) service.

ABOUT FCM SERVER

The server side of FCM consists of two main components:

  • FCM connection servers provided by Google. These servers take messages from an app server and send them to a client app running on a device. Google provides connection servers for HTTP and XMPP.

  • An app server that you must implement in your environment. This app server sends data to a client app via the chosen FCM connection server, using the appropriate XMPP or HTTP protocol.

A full FCM implementation requires both a client implementation and a server implementation to work perfectly.

 

APP SERVER IMPLEMENTATION IN PHP

We can send FCM push notification from our PHP app server to all users by using Firbase Cloud Messaging HTTP Protocol. It provides following HTTP end-point that can be used to route all notifications requests:

https://fcm.googleapis.com/fcm/send

For a complete list of targets,options and payloads available to send message from server visit this link.

OK, So let’s start the actual work, PHP coding to send FCM notification. Here is a code that you can add into your PHP project to send push notification to intended user or a group of users. Be sure to replace the SERVER_KEY with a proper one from the Firebase Console page.

sample snapshot:

console

Send push notification in IOS:

public function sendNotification()
{
 $url = "https://fcm.googleapis.com/fcm/send";
 $registrationIds = array( $_GET['id'] );
 $serverKey ='YOUR_SERVER_KEY';
 $title = "Push Notification";
 $body = "This is body.";
 $notification = array('title' =>$title , 'text' => $body, 'sound' => 'default', 'badge' =>'1');

 $arrayToSend = array('registration_ids' => $registrationIds, 'notification'=>$notification,'priority'=>'high');
 $json = json_encode($arrayToSend);
 $headers = array();
 $headers[] = 'Content-Type: application/json';
 $headers[] = 'Authorization: key='. $serverKey;

 $ch = curl_init();
 curl_setopt($ch, CURLOPT_URL, $url);
 curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"POST");
 curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
 curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

 //Send the request
 $result = curl_exec($ch);
 if ($result === FALSE) 
 {
    die('FCM Send Error: ' . curl_error($ch));
 }

 curl_close( $ch );
 return $result;
}

Send push notification in Android:

public function sendNotification()
{
define('SERVER_KEY', 'YOUR-SERVER-KEY-GOES-HERE' );
$registrationIds = array( $_GET['id'] );
// prep the bundle
$msg = array
(
	'message' 	=> 'here is a message. message',
	'title'		=> 'This is a title. title',
	'subtitle'	=> 'This is a subtitle. subtitle',
	'vibrate'	=> 1,
	'sound'		=> 1,
	'largeIcon'	=> 'large_icon',
	'smallIcon'	=> 'small_icon'
);

$fields = array
(
	'to ' => $registrationIds //for single user  
		(OR)
	'registration_ids' => $registrationIds, //  for  multiple users
	'data'	=> $msg
);
	 
$headers = array
(
	'Authorization: key=' . SERVER_KEY',
	'Content-Type: application/json'
); 
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
if ($result === FALSE) 
{
       die('FCM Send Error: ' . curl_error($ch));
}
curl_close( $ch );
return $result;
}

Response Data:

{
	"multicast_id":4679427854122301046,
	"success":1,
	"failure":0,
	"canonical_ids":0,
	"results":[{"message_id":"0:1463757518309261%31bd1c96f9fd7ecd"}]
}

NOTE: while executing this code, you may get ssl certificate error… this can be resolved by downloading the cacert. pem file(https://curl.haxx.se/docs/caextract.html), put is somewhere and reference it in your php.ini file.

sample snapshot:

Capturew

COMPLETE CODE TO SEND NOTIFICATION IN BOTH ANDROID AND IOS

1) Create table ‘FCMToken’ to store mobile token details into databse.
Run this command on your terminal to crate the table:

php artisan make:migration create_FCMToken_table  --create=FCMToken

 

add the following fields in your migration table and then run the command “php artisan migrate”.

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUserFcmTokenTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('user_fcm_token', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->nullable();
            $table->string('token',512)->nullable();
            $table->string('apns_id',512)->nullable();
            $table->timestamps();
        });
    }
   /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('user_fcm_token');
    }
}

2) Write the validation rule for UserFcmTokenController class to validate the input.

To create the validation class, run this command in your terminal and add the following code to your class.

 php artisan make:request FCMTokenRequest
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class FCMTokenRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'token' => 'required',
            'device_type' => 'sometimes|required|in:ios'
        ];
    }
}

3) Create the controller class ‘ UserFcmTokenController ‘.In this controller class we will write the functionality to store user mobile token into database.

Run this command in your terminal to crate UserFcmTokenController and add the following code to your controller

 php artisan make:controller UserFcmTokenController
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\FCMToken as UserFcmTokenModel;
use App\Http\Requests\FCMTokenRequest;
use Auth;
class UserFcmTokenController extends Controller
{
    /**
     * Instance of FCMToken class
     * 
     * @var incident
     */
    protected $userFcmToken;

   
    /**
     * Constructor
     * 
     * @param App\FCMToken $userFcmToken
     */
    public function __construct(UserFcmTokenModel $userFcmToken)
    {
        return $this->userFcmToken = $userFcmToken;

    }
    
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(FCMTokenRequest $request)
    {
	$data = $request->all();
	$userId = Auth::id();

	if(array_key_exists('device_type', $data))
   	 {
        	$FCMTokenData = ['user_id' => $userId,
                                'apns_id' => $data['token']];
        	// Add the IOS device token to dbs
        	$FCMTokenData =$this->userFcmToken->create($FCMTokenData)
        	if ($FCMTokenData) 
        	{
 			return response()->json(['message' => 'Token added successfully','data'=>[$FCMTokenData ]],200);       
       		}       
        	else 
        	{
            		 return response()->json(['error' => 'Something went wrong!!'], 400);                        
        	}
    	}
    	else
    	{
        	$FCMTokenData = ['user_id' => $userId,
                                'token' => $data['token']];
        	// Add the android device token to dbs
        	$FCMTokenData = $this->userFcmToken->create($FCMTokenData))
        	if ($FCMTokenData) 
        	{
            		return response()->json(['message' => 'Token added successfully','data'=>[$FCMTokenData ]],200);
        	} 
       		 else 
        	{
            		 return response()->json(['error' => 'Something went wrong!!'], 400);;                   
        	}
   	 }  
	        
    }
   
}

4) Create SendPushNotificationController class

In this controller we will write the functionality to send push notification on both IOS and Android apps. Run the bleow command to create the SendPushNotificationController and write the following code in the controller class.

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\User;
use App\FCMToken;
class UserFcmTokenController extends Controller
{
    /**
     * 
     * @var user
     * @var FCMToken
     */
    protected $user;
    protected $fcmToken;

    /**
     * Constructor
     * 
     * @param 
     */
    public function __construct(User $user, FCMToken $fcmToken)
    {
        $this->user = $user;  
        $this->fcmToken = $fcmToken;      
    }

     /**
     * Functionality to send notification.
     * 
    */

    public function sendNotification(Request $request)
    {

        $tokens = [];
        $apns_ids = [];
        $responseData = [];
	$data= $request->all();
	$users= $data['user_ids']; 
        
	// for Android
	
        if ($FCMTokenData = $this->fcmToken->whereIn('user_id',$users)->where('token','!=',null)->select('token')->get()) 
        {
            foreach ($FCMTokenData as $key => $value) 
            {
                $tokens[] = $value->token;
              
            }

            define('YOUR_SERVER_KEY', 'YOUR_SERVER_KEY' );

            $msg = array
                  (
                'body'  => 'This is body of notification',
                'title' => 'Notification',
                'subtitle => 'This is a subtitle',
                  );

            $fields = array
                    (
                        'registration_ids'  => $tokens,
                        'notification'  => $msg
                    );
            
            
            $headers = array
                    (
                        'Authorization: key=' . YOUR_SERVER_KEY,
                        'Content-Type: application/json'
                    );
   
            $ch = curl_init();
            curl_setopt( $ch,CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send' );
            curl_setopt( $ch,CURLOPT_POST, true );
            curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
            curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
            curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
            curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
            $result = curl_exec($ch );

            if ($result === FALSE) 
            {
                die('FCM Send Error: ' . curl_error($ch));
            }
            $result = json_decode($result,true);

            $responseData['android'] =[
                       "result" =>$result
                    ];
          
            curl_close( $ch );
           
        }
	
	// for IOS

        if ($FCMTokenData = $this->fcmToken->whereIn('user_id',$users)->where('apns_id','!=',null)->select('apns_id')->get()) 
        {
           foreach ($FCMTokenData as $key => $value) 
            {
                $apns_ids[] = $value->apns_id;
            }

            $url = "https://fcm.googleapis.com/fcm/send";
           
            $serverKey = 'YOUR_SERVER_KEY';
            $title = "Thsi is title";
            $body = 'This is body';
            $notification = array('title' =>$title , 'text' => $body, 'sound' => 'default', 'badge' => '1');
            $arrayToSend = array('registration_ids' => $apns_ids, 'notification' => $notification,'priority'=>'high');
            $json = json_encode($arrayToSend);
            $headers = array();
            $headers[] = 'Content-Type: application/json';
            $headers[] = 'Authorization: key='. $serverKey;

            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"POST");
            curl_setopt($ch, CURLOPT_POSTFIELDS, $json);
            curl_setopt($ch, CURLOPT_HTTPHEADER,$headers);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

            //Send the request
            $result = curl_exec($ch);

            if ($result === FALSE) 
            {
                die('FCM Send Error: ' . curl_error($ch));
            }
            $result = json_decode($result,true);
            $responseData['ios'] =[
                        "result" =>$result
                    ];

            //Close request
            curl_close($ch);
        }
    
         return $responseData;

     }

}