initial commit
This commit is contained in:
162
app/Controller/Component/NotificationComponent.php
Normal file
162
app/Controller/Component/NotificationComponent.php
Normal file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
App::uses('Component', 'Controller');
|
||||
App::uses('CakeEmail', 'Network/Email');
|
||||
require_once(APP . 'Controller' . DS . 'Traits' . DS . 'ApiCallTrait.php');
|
||||
use Google\Auth\Credentials\ServiceAccountCredentials;
|
||||
class NotificationComponent extends Component
|
||||
{
|
||||
use ApiCallTrait;
|
||||
/**
|
||||
* @var AppModel|bool|mixed|Model|object|string|null
|
||||
*/
|
||||
private $PushToken;
|
||||
public function initialize(Controller $controller)
|
||||
{
|
||||
$this->PushToken = ClassRegistry::init('PushToken');
|
||||
}
|
||||
public function sendEmail($data) {
|
||||
$default = array(
|
||||
'host' => Configure::read('expensecount.email.smtp.host'),
|
||||
'port' => 587,
|
||||
'auth' => 'plain',
|
||||
'username' => Configure::read('expensecount.email.smtp.username'),
|
||||
'password' => Configure::read('expensecount.email.smtp.password'),
|
||||
'tsl' => false,
|
||||
'transport' => 'Smtp',
|
||||
'from' => array(Configure::read('expensecount.email.smtp.from') => 'ExpenseCount'),
|
||||
'returnPath' => Configure::read('expensecount.email.smtp.from'),
|
||||
'layout' => false,
|
||||
'emailFormat' => 'html',
|
||||
'charset' => 'utf-8',
|
||||
'headerCharset' => 'utf-8',
|
||||
);
|
||||
|
||||
try {
|
||||
$Email = new CakeEmail($default);
|
||||
$Email->to($data["email_to"]);
|
||||
$Email->emailFormat('html');
|
||||
$Email->template($data["template"], null)->viewVars(array('data' => $data));
|
||||
$Email->subject($data["subject"]);
|
||||
$Email->replyTo($data["email_from"]);
|
||||
$Email->from(array(Configure::read('expensecount.email.smtp.from') => "ExpenseCount.com"));
|
||||
$Email->delivery = 'Smtp';
|
||||
return $Email->send();
|
||||
}catch (Exception $e) {
|
||||
CakeLog::write(LOG_ERR, 'Email sending failed: ' . $e->getMessage());
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private function getAccessToken()
|
||||
{
|
||||
$cacheFile = TMP . 'fcm_token.cache';
|
||||
|
||||
if (file_exists($cacheFile)) {
|
||||
$cached = json_decode(file_get_contents($cacheFile), true);
|
||||
if (!empty($cached['token']) && $cached['expires_at'] > time()) {
|
||||
return $cached['token'];
|
||||
}
|
||||
}
|
||||
|
||||
$scopes = ['https://www.googleapis.com/auth/firebase.messaging'];
|
||||
|
||||
$credentials = new ServiceAccountCredentials(
|
||||
$scopes,
|
||||
json_decode(file_get_contents(FIREBASE_SECRET), true)
|
||||
);
|
||||
|
||||
$token = $credentials->fetchAuthToken();
|
||||
|
||||
if (!isset($token['access_token'])) {
|
||||
throw new \Exception('Unable to get access token');
|
||||
}
|
||||
|
||||
// Google tokens expire in 3600s; cache for 55 minutes to stay safely within that.
|
||||
file_put_contents($cacheFile, json_encode([
|
||||
'token' => $token['access_token'],
|
||||
'expires_at' => time() + 3300,
|
||||
]));
|
||||
|
||||
return $token['access_token'];
|
||||
}
|
||||
|
||||
public function sendPushNotification($tokens, $message, $async = false)
|
||||
{
|
||||
$projectId = FIREBASE_PROJECT_ID;
|
||||
if (empty($projectId)) {
|
||||
CakeLog::write(LOG_ERR, 'Push notification: Firebase project_id not configured');
|
||||
return ['error' => 'Firebase project_id not configured'];
|
||||
}
|
||||
$url = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send";
|
||||
|
||||
try {
|
||||
$accessToken = $this->getAccessToken();
|
||||
} catch (\Exception $e) {
|
||||
CakeLog::write(LOG_ERR, 'Push notification: Failed to get access token: ' . $e->getMessage());
|
||||
return ['error' => 'Failed to get access token: ' . $e->getMessage()];
|
||||
}
|
||||
|
||||
$responses = [];
|
||||
|
||||
foreach ($tokens as $key => $token) {
|
||||
$payload = [
|
||||
"message" => [
|
||||
"token" => $token['token'],
|
||||
"data" => $message,
|
||||
"apns" => [
|
||||
"payload" => [
|
||||
"aps" => [
|
||||
"alert" => [
|
||||
"title" => $message['title'],
|
||||
"body" => $message['body']
|
||||
],
|
||||
"sound" => "default",
|
||||
"badge" => 1,
|
||||
"mutable-content" => 1,
|
||||
"content-available" => 1
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
$apiResponse = $this->fireAndForget($url, $payload, $accessToken);
|
||||
$responses[] = ['request' => [$token['user_id'], $token['device_id']], 'response' => $apiResponse];
|
||||
}
|
||||
|
||||
return $responses;
|
||||
}
|
||||
|
||||
public function send($users,$message){
|
||||
|
||||
$tokens = array();
|
||||
if(!empty($users)){
|
||||
$filter = array('status' => 1,'user_id' => $users);
|
||||
$db_token = $this->PushToken->getToken($filter);
|
||||
|
||||
if(!empty($db_token)) {
|
||||
foreach ($db_token as $token) {
|
||||
$tokens[] = ['user_id'=>$token['PushToken']['user_id'],
|
||||
'device_id'=>$token['PushToken']['device_id'],
|
||||
'token'=> $token['PushToken']['push_token']];
|
||||
}
|
||||
}
|
||||
if(!empty($tokens)) {
|
||||
|
||||
$response = $this->sendPushNotification($tokens, $message, true);
|
||||
|
||||
}else{
|
||||
$response["status"] = "-99";
|
||||
$response["status_desc"] = "Push Token Not Found!";
|
||||
$response["input"] = $users;
|
||||
}
|
||||
|
||||
}else{
|
||||
$response["status"] = "-99";
|
||||
$response["status_desc"] = "User Not Found!";
|
||||
$response["input"] = $users;
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user