From 4dcb8d741bb25d65786ef213429dc0f22dcb1a7b Mon Sep 17 00:00:00 2001 From: choyeon Date: Fri, 19 Jun 2020 16:01:30 +0900 Subject: [PATCH] =?UTF-8?q?push=20=EB=AA=A8=EB=93=88=20=EC=A4=91=EA=B0=84?= =?UTF-8?q?=20=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/framework/drivers/push/apns.php | 44 +++++++++++- common/framework/drivers/push/base.php | 3 +- common/framework/drivers/push/fcm.php | 48 ++++++++++++- common/framework/drivers/pushinterface.php | 3 +- common/framework/push.php | 78 ++++++++++++++++++++-- 5 files changed, 162 insertions(+), 14 deletions(-) diff --git a/common/framework/drivers/push/apns.php b/common/framework/drivers/push/apns.php index 026319f0e..b70e47495 100644 --- a/common/framework/drivers/push/apns.php +++ b/common/framework/drivers/push/apns.php @@ -41,11 +41,49 @@ class APNs extends Base implements \Rhymix\Framework\Drivers\PushInterface * This method returns true on success and false on failure. * * @param object $message + * @param array $tokens * @return bool */ - public function send(\Rhymix\Framework\Push $message): bool + public function send(\Rhymix\Framework\Push $message, array $tokens): bool { - // TODO - return false; + $status = true; + + // Set parameters + $local_cert = $this->_config['certificate']; + $passphrase = $this->_config['passphrase']; + $alert = []; + $alert['title'] = $message->getSubject(); + $alert['body'] = $message->getContent(); + if($message->getImage()) + { + $alert['image'] = $message->getImage(); + } + + $body['aps'] = array('alert' => $alert,'sound' => 'default'); + $payload = json_encode($body); + + foreach($tokens as $token) + { + $ctx = stream_context_create(); + stream_context_set_option($ctx, 'ssl', 'local_cert', $local_cert); + stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase); + + $fp = stream_socket_client('ssl://gateway.push.apple.com:2195', $err, $errstr, 5, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); + 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; + } + fclose($fp); + } + + return $status; } } diff --git a/common/framework/drivers/push/base.php b/common/framework/drivers/push/base.php index 65d4012c8..67718e834 100644 --- a/common/framework/drivers/push/base.php +++ b/common/framework/drivers/push/base.php @@ -85,9 +85,10 @@ abstract class Base implements \Rhymix\Framework\Drivers\PushInterface * This method returns true on success and false on failure. * * @param object $message + * @param array $tokens * @return bool */ - public function send(\Rhymix\Framework\Push $message): bool + public function send(\Rhymix\Framework\Push $message, array $tokens): bool { return false; } diff --git a/common/framework/drivers/push/fcm.php b/common/framework/drivers/push/fcm.php index 6caa1307f..869bdf957 100644 --- a/common/framework/drivers/push/fcm.php +++ b/common/framework/drivers/push/fcm.php @@ -2,6 +2,9 @@ namespace Rhymix\Framework\Drivers\Push; +use message; +use stdClass; + /** * The FCM (Google) Push driver. */ @@ -41,11 +44,50 @@ class FCM extends Base implements \Rhymix\Framework\Drivers\PushInterface * This method returns true on success and false on failure. * * @param object $message + * @param array $tokens * @return bool */ - public function send(\Rhymix\Framework\Push $message): bool + public function send(\Rhymix\Framework\Push $message, array $tokens): bool { - // TODO - return false; + $status = true; + + $url = 'https://fcm.googleapis.com/fcm/send'; + $api_key = $this->_config['api_key']; + $headers = array('Authorization:key='.$api_key,'Content-Type: application/json'); + + // Set notification + $notification = []; + $notification['title'] = $message->getSubject(); + $notification['body'] = $message->getContent(); + if($message->getImage()) + { + $notification['image'] = $message->getImage(); + } + + // Set android options + $options = []; + $options['priority'] = 'normal'; + $options['notification']['click_action'] = 'RX_NOTIFICATION'; + + foreach($tokens as $i => $token) + { + $data = array('registration_ids' => $token, 'notification' => $notification, 'android' => $options, 'data' => $message->getData()); + $result = \FileHandler::getRemoteResource($url, $data, 5, 'POST', 'application/json', $headers); + if($result) + { + $error = json_decode($result)->error_code; + if($error) + { + $message->addError('FCM error code: '. $error); + $status = false; + } + } + else + { + $message->addError('FCM return empty response.'); + $status = false; + } + } + return $status; } } diff --git a/common/framework/drivers/pushinterface.php b/common/framework/drivers/pushinterface.php index 7b8b8278d..d9bd78ecb 100644 --- a/common/framework/drivers/pushinterface.php +++ b/common/framework/drivers/pushinterface.php @@ -51,7 +51,8 @@ interface PushInterface * This method returns true on success and false on failure. * * @param object $message + * @param array $tokens * @return bool */ - public function send(\Rhymix\Framework\Push $message): bool; + public function send(\Rhymix\Framework\Push $message, array $tokens): bool; } diff --git a/common/framework/push.php b/common/framework/push.php index cd0361325..c66b06caa 100644 --- a/common/framework/push.php +++ b/common/framework/push.php @@ -2,6 +2,9 @@ namespace Rhymix\Framework; +use BaseObject; +use stdClass; + /** * The Push class. */ @@ -14,8 +17,8 @@ class Push protected $to = array(); protected $subject = ''; protected $content = ''; - protected $image = ''; - protected $url = ''; + protected $image = ''; + protected $data = []; protected $errors = array(); protected $sent = false; @@ -215,6 +218,28 @@ class Push { return $this->image; } + + /** + * Set a data to associate with this push notification. + * + * @param array $data + * @return bool + */ + public function setData(array $data): bool + { + $this->data = $data; + return true; + } + + /** + * Get the data associated with this push notification. + * + * @return array + */ + public function getData(): array + { + return $this->data; + } /** * Set a URL to associate with this push notification. @@ -224,7 +249,7 @@ class Push */ public function setURL(string $url): bool { - $this->url = $url; + $this->data['url'] = $url; return true; } @@ -235,7 +260,7 @@ class Push */ public function getURL(): string { - return $this->url; + return $this->data['url']; } /** @@ -261,8 +286,14 @@ class Push try { - //$this->getDriver('fcm'); - //$this->getDriver('apns'); + $tokens = $this->getDeviceToken(); + // Android FCM + $fcm_driver = $this->getDriver('fcm'); + $this->sent = $fcm_driver->send($this, $tokens['android']); + + // iOS APNs + $apns_driver =$this->getDriver('apns'); + $this->sent = $apns_driver->send($this, $tokens['ios']); } catch(\Exception $e) { @@ -278,6 +309,41 @@ class Push return $this->sent; } + + /** + * Get the device token + * + * @return array + * + */ + protected function getDeviceToken(): array + { + $member_srl_list = $this->getRecipients(); + + $args = new stdClass; + $args->member_srl = $member_srl_list; + $output = executeQueryArray('member.getMemberDeviceByMemberSrl', $args); + if(!$output->toBool()) + { + return []; + } + + $device_tokens = []; + $device_tokens['android'] = array_map(function($device){ + if('android' === $device->device_type) + { + return $device->device_token; + } + }, $output->data); + $device_tokens['ios'] = array_map(function($device){ + if('ios' === $device->device_type) + { + return $device->device_token; + } + }, $output->data); + + return $device_tokens; + } /** * Check if the message was sent.