Skip to content
Open
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"php": "^7.1.3|^8.0",
"guzzlehttp/guzzle": "^6.3 || ^7.0.1",
"illuminate/support": "~5.8 || ^6.0 || ^7.0 || ^8.0 || ^9.0|^10.0",
"illuminate/notifications": "~5.8 || ^6.0 || ^7.0 || ^8.0 || ^9.0|^10.0"
"illuminate/notifications": "~5.8 || ^6.0 || ^7.0 || ^8.0 || ^9.0|^10.0",
"google/apiclient": "^2.15"
},
"require-dev": {
"phpunit/phpunit": "^7.5 || ^8.0 || ^9.0"
Expand Down
57 changes: 57 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This is an easy to use package to send push notification.

* GCM
* FCM
* FCMV1
* APN

## Installation
Expand Down Expand Up @@ -59,6 +60,28 @@ $push->setConfig([
]);
```

The default configuration parameters for **FCMV1** are :

* ```priority => 'normal'```
* ```dry_run => false```
* ```projectId => 'my-project-id'```
* ```jsonFile => __DIR__ . '/fcmCertificates/file.json'```

You can dynamically update those values or adding new ones calling the method setConfig like so:
```php
$push->setConfig([
'priority' => 'high',
'projectId' => 'my-real-project-id',
'jsonFile' => 'path/to/credentials.json'
]);
```

To generate a credentials json file for your service account:

* In the Firebase console, open **Settings** > [Service Accounts](https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk).
* Click **Generate New Private Key**, then confirm by clicking **Generate Key**.
* Securely store the JSON file containing the key.


The default configuration parameters for **APN** are:

Expand Down Expand Up @@ -117,6 +140,11 @@ For FCM Service:
$push = new PushNotification('fcm');
```

For FCMV1 Service:
```php
$push = new PushNotification('fcmv1');
```

Now you may use any method that you need. Please see the API List.


Expand All @@ -139,6 +167,11 @@ Now you may use any method that you need. Please see the API List.

- [sendByTopic](https://github.com/edujugon/PushNotification#sendbytopic)

### Only for Fcmv1

- [setProjectId](https://github.com/edujugon/PushNotification#setprojectid)
- [setJsonFile](https://github.com/edujugon/PushNotification#setjsonfile)

> Go to [Usage samples](https://github.com/edujugon/PushNotification#usage-samples) directly.

#### setService
Expand Down Expand Up @@ -173,6 +206,30 @@ object setMessage(array $data)
object setApiKey($api_key)
```

#### setProjectId

> Only for fcmv1

`setProjectId` method sets the Project ID of your App as a string.

**Syntax**

```php
object setProjectId($project_id)
```

#### setJsonFile

> Only for fcmv1

`setJsonFile` method sets the path of credentials json file of your App.

**Syntax**

```php
object setJsonFile($api_key)
```

#### setDevicesToken

`setDevicesToken` method sets the devices' tokens, which you pass the token through parameter as array or string if it was only one.
Expand Down
14 changes: 14 additions & 0 deletions src/Channels/FcmV1Channel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Edujugon\PushNotification\Channels;

class FcmChannel extends GcmChannel
{
/**
* {@inheritdoc}
*/
protected function pushServiceName()
{
return 'fcmv1';
}
}
10 changes: 10 additions & 0 deletions src/Config/config.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* @see https://github.com/Edujugon/PushNotification
*/
Expand All @@ -20,6 +21,15 @@
// See https://docs.guzzlephp.org/en/stable/request-options.html
'guzzle' => [],
],
'fcmv1' => [
'priority' => 'normal',
'dry_run' => false,
'projectId' => 'my-project-id',
'jsonFile' => __DIR__ . '/fcmCertificates/file.json',
// Optional: Default Guzzle request options for each FCM request
// See https://docs.guzzlephp.org/en/stable/request-options.html
'guzzle' => [],
],
'apn' => [
'certificate' => __DIR__ . '/iosCertificates/apns-dev-cert.pem',
'passPhrase' => 'secret', //Optional
Expand Down
Empty file.
154 changes: 154 additions & 0 deletions src/FcmV1.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?php

namespace Edujugon\PushNotification;

use Carbon\Carbon;
use Edujugon\PushNotification\Fcm;
use Exception;
use Google\Client as GoogleClient;
use Google\Service\FirebaseCloudMessaging;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;

class FcmV1 extends Fcm
{
const CACHE_SECONDS = 55 * 60; // 55 minutes

/**
* Fcm constructor.
* Override parent constructor.
*/
public function __construct()
{
$this->config = $this->initializeConfig('fcmv1');

$this->url = 'https://fcm.googleapis.com/v1/projects/' . $this->config['projectId'] . '/messages:send';

$this->client = new Client($this->config['guzzle'] ?? []);
}

/**
* Set the apiKey for the notification
* @param string $apiKey
*/
public function setApiKey($apiKey)
{
throw new Exception('Not available on FCM V1');
}

/**
* Set the projectId for the notification
* @param string $projectId
*/
public function setProjectId($projectId)
{
$this->config['projectId'] = $projectId;

$this->url = 'https://fcm.googleapis.com/v1/projects/' . $this->config['projectId'] . '/messages:send';
}

/**
* Set the jsonFile path for the notification
* @param string $jsonFile
*/
public function setJsonFile($jsonFile)
{
$this->config['jsonFile'] = $jsonFile;
}

/**
* Set the needed headers for the push notification.
*
* @return array
*/
protected function addRequestHeaders()
{
return [
'Authorization' => 'Bearer ' . $this->getOauthToken(),
'Content-Type' => 'application/json',
];
}

/**
* Send Push Notification
*
* @param array $deviceTokens
* @param array $message
*
* @return \stdClass GCM Response
*/
public function send(array $deviceTokens, array $message)
{
// FCM v1 does not allows multiple devices at once

$headers = $this->addRequestHeaders();
$jsonData = ['message' => $this->buildMessage($message)];

$feedbacks = [];

foreach ($deviceTokens as $deviceToken) {
try {
$jsonData['message']['token'] = $deviceToken;

$result = $this->client->post(
$this->url,
[
'headers' => $headers,
'json' => $jsonData,
]
);

$json = $result->getBody();

$feedbacks[] = json_decode($json, false, 512, JSON_BIGINT_AS_STRING);
} catch (ClientException $e) {
$feedbacks[] = ['success' => false, 'error' => json_encode($e->getResponse())];
} catch (\Exception $e) {
$feedbacks[] = ['success' => false, 'error' => $e->getMessage()];
}
}

$this->setFeedback($feedbacks);
}

/**
* Prepare the data to be sent
*
* @param $topic
* @param $message
* @param $isCondition
* @return array
*/
protected function buildData($topic, $message, $isCondition)
{
$condition = $isCondition ? ['condition' => $topic] : ['to' => '/topics/' . $topic];

return [
'message' => array_merge($condition, $this->buildMessage($message)),
];
}

protected function getOauthToken()
{
return Cache::remember(
Str::slug('fcm-v1-oauth-token-' . $this->config['projectId']),
Carbon::now()->addSeconds(self::CACHE_SECONDS),
function () {
$jsonFilePath = $this->config['jsonFile'];

$googleClient = new GoogleClient();

$googleClient->setAuthConfig($jsonFilePath);
$googleClient->addScope(FirebaseCloudMessaging::FIREBASE_MESSAGING);

$accessToken = $googleClient->fetchAccessTokenWithAssertion();

$oauthToken = $accessToken['access_token'];

return $oauthToken;
}
);
}
}
3 changes: 2 additions & 1 deletion src/PushNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class PushNotification
protected $servicesList = [
'gcm' => Gcm::class,
'apn' => Apn::class,
'fcm' => Fcm::class
'fcm' => Fcm::class,
'fcmv1' => FcmV1::class,
];

/**
Expand Down