Advertisement
Guest User

PushNotificationProvider.php

a guest
Mar 4th, 2015
287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.89 KB | None | 0 0
  1. <?php
  2.  
  3. namespace Spika\Provider;
  4.  
  5. use Spika\Db\CouchDb;
  6. use Spika\Db\MySql;
  7. use Silex\Application;
  8. use Silex\ServiceProviderInterface;
  9.  
  10. define('SP_TIMEOUT',10);
  11.  
  12. class PushNotificationProvider implements ServiceProviderInterface
  13. {
  14. public function register(Application $app)
  15. {
  16.  
  17. $self = $this;
  18.  
  19. $app['sendProdAPN'] = $app->protect(function($tokens,$payload) use ($self,$app) {
  20. $self->sendAPN($app['pushnotification.options']['APNProdPem'],$tokens,$payload,'ssl://gateway.push.apple.com:2195',$app);
  21. });
  22.  
  23. $app['sendDevAPN'] = $app->protect(function($tokens,$payload) use ($self,$app) {
  24. $self->sendAPN($app['pushnotification.options']['APNDevPem'],$tokens,$payload,'ssl://gateway.sandbox.push.apple.com:2195',$app);
  25. });
  26.  
  27. $app['sendGCM'] = $app->protect(function($payload) use ($self,$app) {
  28. $self->sendGCM($app['pushnotification.options']['GCM_API_Key'],$payload,$app);
  29. });
  30.  
  31. }
  32.  
  33. public function boot(Application $app)
  34. {
  35. }
  36.  
  37. public function connectToAPN($cert,$host,$app){
  38.  
  39. $app['monolog']->addDebug("connecting to APN cert : {$cert}");
  40.  
  41. $ctx = stream_context_create();
  42. stream_context_set_option($ctx, 'ssl', 'local_cert', $cert);
  43. $fp = stream_socket_client($host, $err, $errstr, 60, STREAM_CLIENT_CONNECT, $ctx);
  44.  
  45. if (!$fp) {
  46. $app['monolog']->addDebug("Failed to connect $err $errstr");
  47. $app['monolog']->addDebug("Try to recconect");
  48. return $this->connectToAPN($cert,$host);
  49. }
  50. else {
  51. //stream_set_blocking($fp, 0);
  52. //stream_set_timeout($fp,SP_TIMEOUT);
  53. }
  54.  
  55. return $fp;
  56. }
  57.  
  58. public function sendAPN($cert, $deviceTokens, $payload, $host, $app){
  59.  
  60. $apn_status = array(
  61. '0' => "No errors encountered",
  62. '1' => "Processing error",
  63. '2' => "Missing device token",
  64. '3' => "Missing topic",
  65. '4' => "Missing payload",
  66. '5' => "Invalid token size",
  67. '6' => "Invalid topic size",
  68. '7' => "Invalid payload size",
  69. '8' => "Invalid token",
  70. '255' => "unknown"
  71. );
  72.  
  73. if(count($deviceTokens) == 0) return;
  74.  
  75. $fp = $this->connectToAPN($cert,$host,$app);
  76. $size = 0;
  77.  
  78. foreach($deviceTokens as $index => $deviceToken){
  79.  
  80. $identifiers = array();
  81. for ($i = 0; $i < 4; $i++) {
  82. $identifiers[$i] = rand(1, 100);
  83. }
  84.  
  85. $msg = chr(1) . chr($identifiers[0]) . chr($identifiers[1]) . chr($identifiers[2]) . chr($identifiers[3]) . pack('N', time() + 3600)
  86. . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . pack("n",strlen($payload)) . $payload;
  87.  
  88. $size += strlen($payload);
  89.  
  90. $result = fwrite($fp, $msg);
  91.  
  92. if($size >= 5120){
  93. // if sent more than 5120B reconnect again
  94. $fp = $this->connectToAPN($cert,$host,$app);
  95. sleep(1);
  96. }
  97.  
  98.  
  99. if(!$result){
  100. $app['monolog']->addDebug("{$deviceToken} succeed");
  101.  
  102. }else{
  103.  
  104.  
  105. $read = array($fp);
  106. $null = null;
  107. $changedStreams = stream_select($read, $null, $null, 0, 1000000);
  108.  
  109. if ($changedStreams === false) {
  110. $app['monolog']->addDebug("Error: Unabled to wait for a stream availability");
  111.  
  112. } elseif ($changedStreams > 0) {
  113.  
  114. $responseBinary = fread($fp, 6);
  115.  
  116. if ($responseBinary !== false || strlen($responseBinary) == 6) {
  117. $response = unpack('Ccommand/Cstatus_code/Nidentifier', $responseBinary);
  118. $result = $apn_status[$response['status_code']];
  119. $app['monolog']->addDebug("{$deviceToken} failed {$result}");
  120.  
  121. } else {
  122.  
  123. $app['monolog']->addDebug("{$deviceToken} failed");
  124.  
  125. }
  126.  
  127. } else {
  128.  
  129. $result = 'succeed';
  130. $app['monolog']->addDebug("{$deviceToken} succeed");
  131.  
  132. }
  133.  
  134. if($result != 'succeed'){
  135. // if failed connect again
  136. $fp = $this->connectToAPN($cert,$host,$app);
  137. sleep(1);
  138. }
  139.  
  140.  
  141. }
  142.  
  143.  
  144. }
  145.  
  146.  
  147. fclose($fp);
  148.  
  149. return $result;
  150.  
  151. }
  152. function sendGCM($apiKey, $json, $app = null) {
  153. // API access key from Google API's Console
  154. define( 'API_ACCESS_KEY', '<INSERT-YOUR-API-KEY>' );
  155.  
  156. $headers = array
  157. (
  158. 'Authorization: key=' . API_ACCESS_KEY,
  159. 'Content-Type: application/json'
  160. );
  161.  
  162. $ch = curl_init();
  163.  
  164. curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' );
  165. curl_setopt( $ch,CURLOPT_POST, true );
  166. curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers);
  167. curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
  168. curl_setopt( $ch,CURLOPT_POSTFIELDS, $json);
  169. curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
  170.  
  171. $result = curl_exec($ch );
  172. curl_close( $ch );
  173.  
  174. return $result;
  175.  
  176. }
  177.  
  178. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement