diff --git a/common/framework/drivers/push/apns.php b/common/framework/drivers/push/apns.php
index 9d2ea0914..5257c86e3 100644
--- a/common/framework/drivers/push/apns.php
+++ b/common/framework/drivers/push/apns.php
@@ -42,11 +42,14 @@ class APNs extends Base implements \Rhymix\Framework\Drivers\PushInterface
*
* @param object $message
* @param array $tokens
- * @return bool
+ * @return object
*/
- public function send(\Rhymix\Framework\Push $message, array $tokens): bool
+ public function send(\Rhymix\Framework\Push $message, array $tokens)
{
- $status = true;
+ $output = new \stdClass;
+ $output->success = [];
+ $output->invalid = [];
+ $output->needUpdate = [];
// Set parameters
$local_cert = $this->_config['certificate'];
@@ -68,18 +71,17 @@ class APNs extends Base implements \Rhymix\Framework\Drivers\PushInterface
if(!$fp)
{
$message->addError('Failed to connect socket - error code: '. $err .' - '. $errstr);
- $status = false;
}
$msg = chr(0) . pack('n', 32) . pack('H*', $token) . pack('n', strlen($payload)) . $payload;
$result = fwrite($fp, $msg, strlen($msg));
if(!$result)
{
$message->addError('APNs return empty response.');
- $status = false;
}
+ $output->success[] = $token;
fclose($fp);
}
- return $status;
+ return $output;
}
}
diff --git a/common/framework/drivers/push/base.php b/common/framework/drivers/push/base.php
index 67718e834..23c2cb403 100644
--- a/common/framework/drivers/push/base.php
+++ b/common/framework/drivers/push/base.php
@@ -2,6 +2,8 @@
namespace Rhymix\Framework\Drivers\Push;
+use stdClass;
+
/**
* The base class for other Push drivers.
*/
@@ -86,10 +88,10 @@ abstract class Base implements \Rhymix\Framework\Drivers\PushInterface
*
* @param object $message
* @param array $tokens
- * @return bool
+ * @return object
*/
- public function send(\Rhymix\Framework\Push $message, array $tokens): bool
+ public function send(\Rhymix\Framework\Push $message, array $tokens)
{
- return false;
+ return new \stdClass;
}
}
diff --git a/common/framework/drivers/push/fcm.php b/common/framework/drivers/push/fcm.php
index e086ee977..67affb7c3 100644
--- a/common/framework/drivers/push/fcm.php
+++ b/common/framework/drivers/push/fcm.php
@@ -2,9 +2,6 @@
namespace Rhymix\Framework\Drivers\Push;
-use message;
-use stdClass;
-
/**
* The FCM (Google) Push driver.
*/
@@ -45,11 +42,14 @@ class FCM extends Base implements \Rhymix\Framework\Drivers\PushInterface
*
* @param object $message
* @param array $tokens
- * @return bool
+ * @return object
*/
- public function send(\Rhymix\Framework\Push $message, array $tokens): bool
+ public function send(\Rhymix\Framework\Push $message, array $tokens)
{
- $status = true;
+ $output = new \stdClass;
+ $output->success = [];
+ $output->invalid = [];
+ $output->needUpdate = [];
$url = 'https://fcm.googleapis.com/fcm/send';
$api_key = $this->_config['api_key'];
@@ -64,31 +64,48 @@ class FCM extends Base implements \Rhymix\Framework\Drivers\PushInterface
$notification['body'] = $message->getContent();
$notification['click_action'] = $message->getClickAction();
- foreach($tokens as $i => $token)
+ $chunked_token = array_chunk($tokens, 1000);
+ foreach($chunked_token as $token_unit)
{
$data = json_encode(array(
- 'registration_ids' => [$token],
+ 'registration_ids' => $token_unit,
'notification' => $notification,
'priority' => 'normal',
- 'data' => $message->getData() ?: new stdClass,
+ 'data' => $message->getData() ?: new \stdClass,
));
- $result = \FileHandler::getRemoteResource($url, $data, 5, 'POST', 'application/json', $headers);
- if($result)
+ $response = \FileHandler::getRemoteResource($url, $data, 5, 'POST', 'application/json', $headers);
+ if($response)
{
- $error = json_decode($result)->error_code;
- if($error)
+ $decoded_response = json_decode($response);
+ if(!$decoded_response)
{
- $message->addError('FCM error code: '. $error);
- $status = false;
+ $message->addError('FCM return invalid json : '. $response);
+ return $output;
+ }
+ $results = $decoded_response->results ?: [];
+ foreach($results as $i => $result)
+ {
+ if($result->error)
+ {
+ $message->addError('FCM error code: '. $result->error);
+ $output->invalid[$token_unit[$i]] = $token_unit[$i];
+ }
+ else if($result->message_id && $result->registration_id)
+ {
+ $output->needUpdate[$token_unit[$i]] = $result->registration_id;
+ }
+ else
+ {
+ $output->success[$token_unit[$i]] = $result->message_id;
+ }
}
}
else
{
$message->addError('FCM return empty response.');
- $status = false;
}
}
- return $status;
+ return $output;
}
}
diff --git a/common/framework/drivers/pushinterface.php b/common/framework/drivers/pushinterface.php
index d9bd78ecb..e15158536 100644
--- a/common/framework/drivers/pushinterface.php
+++ b/common/framework/drivers/pushinterface.php
@@ -52,7 +52,7 @@ interface PushInterface
*
* @param object $message
* @param array $tokens
- * @return bool
+ * @return object
*/
- public function send(\Rhymix\Framework\Push $message, array $tokens): bool;
+ public function send(\Rhymix\Framework\Push $message, array $tokens);
}
diff --git a/common/framework/push.php b/common/framework/push.php
index 9e86eedbb..b7834e0b2 100644
--- a/common/framework/push.php
+++ b/common/framework/push.php
@@ -2,9 +2,6 @@
namespace Rhymix\Framework;
-use BaseObject;
-use stdClass;
-
/**
* The Push class.
*/
@@ -16,12 +13,12 @@ class Push
protected $from = 0;
protected $to = array();
protected $subject = '';
- protected $content = '';
+ protected $content = '';
protected $click_action = '';
protected $data = [];
protected $errors = array();
protected $sent = false;
-
+
/**
* Static properties.
*/
@@ -286,19 +283,25 @@ class Push
try
{
- $tokens = $this->getDeviceTokens();
+ $tokens = $this->_getDeviceTokens();
// Android FCM
- if(count($tokens['android']))
+ if(count($tokens->android))
{
$fcm_driver = $this->getDriver('fcm');
- $this->sent = $fcm_driver->send($this, $tokens['android']);
+ $output = $fcm_driver->send($this, $tokens->android);
+ $this->sent = $output->invalid ? false : true;
+ $this->_deleteInvalidTokens($output->invalid);
+ $this->_updateDeviceTokens($output->needUpdate);
}
// iOS APNs
- if(count($tokens['ios']))
+ if(count($tokens->ios))
{
$apns_driver =$this->getDriver('apns');
- $this->sent = $apns_driver->send($this, $tokens['ios']);
+ $output = $apns_driver->send($this, $tokens->ios);
+ $this->sent = $output->invalid ? false : true;
+ $this->_deleteInvalidTokens($output->invalid);
+ $this->_updateDeviceTokens($output->needUpdate);
}
}
catch(\Exception $e)
@@ -319,21 +322,21 @@ class Push
/**
* Get the device token
*
- * @return array
+ * @return object
*
*/
- protected function getDeviceTokens(): array
+ protected function _getDeviceTokens()
{
$member_srl_list = $this->getRecipients();
- $result = [];
- $result['android'] = [];
- $result['ios'] = [];
+ $result = new \stdClass;
+ $result->android = [];
+ $result->ios = [];
- $args = new stdClass;
+ $args = new \stdClass;
$args->member_srl = $member_srl_list;
$args->device_type = [];
$driver_types = config('push.types') ?: array();
- if(count($driver_types))
+ if(!count($driver_types))
{
return $result;
}
@@ -354,12 +357,44 @@ class Push
foreach($output->data as $row)
{
- $result[$row->device_type][] = $row->device_token;
+ $result->{$row->device_type}[] = $row->device_token;
}
return $result;
}
+
+ /**
+ * Delete the device toekn
+ *
+ * @param array
+ */
+ protected function _deleteInvalidTokens(array $invalid_tokens): void
+ {
+ if(!count($invalid_tokens))
+ {
+ return;
+ }
+ $args = new \stdClass;
+ $args->device_token = $invalid_tokens;
+ executeQueryArray('member.deleteMemberDevice', $args);
+ }
+
+ /**
+ * Update the device toekn
+ *
+ * @param array
+ */
+ protected function _updateDeviceTokens(array $update_tokens): void
+ {
+ $args = new \stdClass;
+ foreach($update_tokens as $key => $value)
+ {
+ $args->old_token = $key;
+ $args->new_token = $value;
+ executeQueryArray('member.updateMemberDevice', $args);
+ }
+ }
/**
* Check if the message was sent.
diff --git a/modules/member/member.controller.php b/modules/member/member.controller.php
index 20654ba37..926b2c80d 100644
--- a/modules/member/member.controller.php
+++ b/modules/member/member.controller.php
@@ -100,10 +100,6 @@ class memberController extends member
$browserInfo = Rhymix\Framework\UA::getBrowserInfo();
$device_type = strtolower($browserInfo->os);
- if('android' !== $device_type && 'ios' !== $device_type)
- {
- return new BaseObject(-1, 'NOT_SUPPORTED_OS');
- }
if('ios' === $device_type)
{
@@ -134,7 +130,7 @@ class memberController extends member
$logged_info = Context::get('logged_info');
$random_key = Rhymix\Framework\Security::getRandom();
- $device_key = hash_hmac('sha256', $random_key, $device_token);
+ $device_key = hash_hmac('sha256', $random_key, $logged_info->member_srl . ':' . config('crypto.authentication_key'));
// Start transaction
$oDB = DB::getInstance();
@@ -179,8 +175,8 @@ class memberController extends member
Context::setResponseMethod('JSON');
// Check member_srl, device_token, device_key
$member_srl = Context::get('member_srl');
- $device_token = escape(Context::get('device_token'));
- $random_key = escape(Context::get('device_key'));
+ $device_token = Context::get('device_token');
+ $random_key = Context::get('device_key');
// Return an error when id, password and device_key doesn't exist
if(!$member_srl) return new BaseObject(-1, 'NULL_MEMBER_SRL');
@@ -190,7 +186,7 @@ class memberController extends member
$args = new stdClass;
$args->member_srl = $member_srl;
$args->device_token = $device_token;
- $args->device_key = hash_hmac('sha256', $random_key, $device_token);
+ $args->device_key = hash_hmac('sha256', $random_key, $member_srl . ':' . config('crypto.authentication_key'));
$output = executeQueryArray('member.getMemberDevice', $args);
if(!$output->toBool())
{
diff --git a/modules/member/queries/deleteMemberDevice.xml b/modules/member/queries/deleteMemberDevice.xml
new file mode 100644
index 000000000..1320b0df1
--- /dev/null
+++ b/modules/member/queries/deleteMemberDevice.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/member/queries/updateMemberDevice.xml b/modules/member/queries/updateMemberDevice.xml
new file mode 100644
index 000000000..60847a22e
--- /dev/null
+++ b/modules/member/queries/updateMemberDevice.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/ncenterlite/ncenterlite.controller.php b/modules/ncenterlite/ncenterlite.controller.php
index b653ebce0..324930590 100644
--- a/modules/ncenterlite/ncenterlite.controller.php
+++ b/modules/ncenterlite/ncenterlite.controller.php
@@ -1514,7 +1514,6 @@ class ncenterliteController extends ncenterlite
$oPush = new \Rhymix\Framework\Push();
$oPush->setSubject($content);
$oPush->setContent($args->extra_content);
- $oPush->setImage($args->extra_image);
$oPush->setData($args->extra_data);
$oPush->setURL($target_url);
$oPush->addTo($args->member_srl);