• 技术文章 >php教程 >php手册

    PHP实现APNS推送

    2016-06-06 20:07:50原创1900

    参考http://code.google.com/p/apns-php/作为修改 上面的项目实现很完全,其中包括了队列。服务端实现等,但是功能过于复杂。简单的使用觉得不顺手! 用了几个小时,参考其过程,写了一个class文件,直接使用即可。简单且好理解 闲话少说,上代码 ?php/*** @

    参考http://code.google.com/p/apns-php/作为修改
    上面的项目实现很完全,其中包括了队列。服务端实现等,但是功能过于复杂。简单的使用觉得不顺手!

    用了几个小时,参考其过程,写了一个class文件,直接使用即可。简单且好理解
    闲话少说,上代码

    
    * @version 1.0
    * @date 2012-09-17 11:27:59
    */
    
        class APNS
        {
            const ENVIRONMENT_PRODUCTION = 0;
            const ENVIRONMENT_SANDBOX = 1;
            const DEVICE_BINARY_SIZE = 32;
            const CONNECT_RETRY_INTERVAL = 1000000;
            const SOCKET_SELECT_TIMEOUT = 1000000;
            const COMMAND_PUSH = 1;
            const STATUS_CODE_INTERNAL_ERROR = 999;
            const ERROR_RESPONSE_SIZE = 6;
            const ERROR_RESPONSE_COMMAND = 8;
            const PAYLOAD_MAXIMUM_SIZE = 256;
            const APPLE_RESERVED_NAMESPACE = 'aps';
            protected $_environment;
            protected $_providerCertificateFile;
            protected $_rootCertificationAuthorityFile;
            protected $_connectTimeout;
            protected $_connectRetryTimes = 3;
            protected $_connectRetryInterval;
            protected $_socketSelectTimeout;
            protected $_hSocket;
            protected $_deviceTokens = array();
            protected $_text;
            protected $_badge;
            protected $_sound;
            protected $_customProperties;
            protected $_expiryValue = 604800;
            protected $_customIdentifier;
            protected $_autoAdjustLongPayload = true;
            protected $asurls = array('ssl://gateway.push.apple.com:2195','ssl://gateway.sandbox.push.apple.com:2195');
            protected $_errorResponseMessages = array
                                (
                                    0   => 'No errors encountered',
                                    1 => 'Processing error',
                                    2 => 'Missing device token',
                                    3 => 'Missing topic',
                                    4 => 'Missing payload',
                                    5 => 'Invalid token size',
                                    6 => 'Invalid topic size',
                                    7 => 'Invalid payload size',
                                    8 => 'Invalid token',
                                    self::STATUS_CODE_INTERNAL_ERROR => 'Internal error'
                                );
            function __construct($environment,$providerCertificateFile)
            {
                if($environment != self::ENVIRONMENT_PRODUCTION && $environment != self::ENVIRONMENT_SANDBOX) 
                {
                    throw new Exception(
                        "Invalid environment '{$environment}'"
                    );
                }
                $this->_environment = $environment;
                if(!is_readable($providerCertificateFile)) 
                {
                    throw new Exception(
                        "Unable to read certificate file '{$providerCertificateFile}'"
                    );
                }
                $this->_providerCertificateFile = $providerCertificateFile;
                $this->_connectTimeout = @ini_get("default_socket_timeout");
                $this->_connectRetryInterval = self::CONNECT_RETRY_INTERVAL;
                $this->_socketSelectTimeout = self::SOCKET_SELECT_TIMEOUT;
            }
            public function setRCA($rootCertificationAuthorityFile)
            {
                if(!is_readable($rootCertificationAuthorityFile)) 
                {
                    throw new Exception(
                        "Unable to read Certificate Authority file '{$rootCertificationAuthorityFile}'"
                    );
                }
                $this->_rootCertificationAuthorityFile = $rootCertificationAuthorityFile;
            }
            public function getRCA()
            {
                return $this->_rootCertificationAuthorityFile;
            }
            protected function _connect()
            {
                $sURL = $this->asurls[$this->_environment];
                $streamContext = stream_context_create(
                    array
                        (
                            'ssl' => array
                            (
                                'verify_peer' => isset($this->_rootCertificationAuthorityFile),
                                'cafile' => $this->_rootCertificationAuthorityFile,
                                'local_cert' => $this->_providerCertificateFile
                            )
                        )
                    );
                $this->_hSocket = @stream_socket_client($sURL,$nError,$sError,$this->_connectTimeout,STREAM_CLIENT_CONNECT, $streamContext);
                if (!$this->_hSocket) 
                {
                    throw new Exception
                    (
                        "Unable to connect to '{$sURL}': {$sError} ({$nError})"
                    );
                }
                stream_set_blocking($this->_hSocket, 0);
                stream_set_write_buffer($this->_hSocket, 0);
                return true;
            }
            public function connect()
            {
                $bConnected = false;
                $retry = 0;
                while(!$bConnected) 
                {
                    try 
                    {
                        $bConnected = $this->_connect();
                    }catch (Exception $e) 
                    {
                        if ($nRetry >= $this->_connectRetryTimes) 
                        {
                            throw $e;
                        }else 
                        {
                            usleep($this->_nConnectRetryInterval);
                        }
                    }
                    $retry++;
                }
            }
            public function disconnect()
            {
                if (is_resource($this->_hSocket)) 
                {
                    return fclose($this->_hSocket);
                }
                return false;
            }
            protected function getBinaryNotification($deviceToken, $payload, $messageID = 0, $Expire = 604800)
            {
                $tokenLength = strlen($deviceToken);
                $payloadLength = strlen($payload);
                $ret  = pack('CNNnH*', self::COMMAND_PUSH, $messageID, $Expire > 0 ? time() + $Expire : 0, self::DEVICE_BINARY_SIZE, $deviceToken);
                $ret .= pack('n', $payloadLength);
                $ret .= $payload;
                return $ret;
            }
            protected function readErrorMessage()
            {
                $errorResponse = @fread($this->_hSocket, self::ERROR_RESPONSE_SIZE);
                if ($errorResponse === false || strlen($errorResponse) != self::ERROR_RESPONSE_SIZE) 
                {
                    return;
                }
                $errorResponse = $this->parseErrorMessage($errorResponse);
                if (!is_array($errorResponse) || empty($errorResponse)) 
                {
                    return;
                }
                if (!isset($errorResponse['command'], $errorResponse['statusCode'], $errorResponse['identifier'])) 
                {
                    return;
                }
                if ($errorResponse['command'] != self::ERROR_RESPONSE_COMMAND) 
                {
                    return;
                }
                $errorResponse['timeline'] = time();
                $errorResponse['statusMessage'] = 'None (unknown)';
                if (isset($this->_aErrorResponseMessages[$errorResponse['statusCode']])) 
                {
                    $errorResponse['statusMessage'] = $this->_errorResponseMessages[$errorResponse['statusCode']];
                }
                return $errorResponse;
            }
            protected function parseErrorMessage($errorMessage)
            {
                return unpack('Ccommand/CstatusCode/Nidentifier', $errorMessage);
            }
            public function send()
            {
                if (!$this->_hSocket) 
                {
                    throw new Exception
                    (
                        'Not connected to Push Notification Service'
                    );
                }
                $sendCount = $this->getDTNumber();
                $messagePayload = $this->getPayload();
                foreach($this->_deviceTokens AS $key => $value)
                {
                    $apnsMessage = $this->getBinaryNotification($value, $messagePayload, $messageID = 0, $Expire = 604800);
                    $nLen = strlen($apnsMessage);
                    $aErrorMessage = null;
                    if ($nLen !== ($nWritten = (int)@fwrite($this->_hSocket, $apnsMessage))) 
                    {
                        $aErrorMessage = array
                        (
                            'identifier' => $key,
                            'statusCode' => self::STATUS_CODE_INTERNAL_ERROR,
                            'statusMessage' => sprintf('%s (%d bytes written instead of %d bytes)',$this->_errorResponseMessages[self::STATUS_CODE_INTERNAL_ERROR], $nWritten, $nLen)
                        );
                    }
                }
            }
            public function addDT($deviceToken)
            {
                if (!preg_match('~^[a-f0-9]{64}$~i', $deviceToken)) 
                {
                    throw new Exception
                    (
                        "Invalid device token '{$deviceToken}'"
                    );
                }
                $this->_deviceTokens[] = $deviceToken;
            }       
            public function getDTNumber()
            {
                return count($this->_deviceTokens);
            }
            public function setText($text)
            {
                $this->_text = $text;
            }
            public function getText()
            {
                return $this->_text;
            }
            public function setBadge($badge)
            {
                if (!is_int($badge)) 
                {
                    throw new Exception
                    (
                        "Invalid badge number '{$badge}'"
                    );
                }
                $this->_badge = $badge;
            }
            public function getBadge()
            {
                return $this->_badge;
            }
            public function setSound($sound = 'default')
            {
                $this->_sound = $sound;
            }
            public function getSound()
            {
                return $this->_sound;
            }
            public function setCP($name, $value)
            {
                if ($name == self::APPLE_RESERVED_NAMESPACE) 
                {
                    throw new Exception
                    (
                        "Property name '" . self::APPLE_RESERVED_NAMESPACE . "' can not be used for custom property."
                    );
                }
                $this->_customProperties[trim($name)] = $value;
            }
            protected function _getPayload()
            {
                $aPayload[self::APPLE_RESERVED_NAMESPACE] = array();
                if (isset($this->_text)) 
                {
                    $aPayload[self::APPLE_RESERVED_NAMESPACE]['alert'] = (string)$this->_text;
                }
                if (isset($this->_badge) && $this->_badge > 0) 
                {
                    $aPayload[self::APPLE_RESERVED_NAMESPACE]['badge'] = (int)$this->_badge;
                }
                if (isset($this->_sound)) 
                {
                    $aPayload[self::APPLE_RESERVED_NAMESPACE]['sound'] = (string)$this->_sound;
                }
                if (is_array($this->_customProperties)) 
                {
                    foreach($this->_customProperties as $propertyName => $propertyValue) 
                    {
                        $aPayload[$propertyName] = $propertyValue;
                    }
                }
                return $aPayload;
            }
            public function setExpiry($expiryValue)
            {
                if (!is_int($expiryValue)) 
                {
                    throw new Exception
                    (
                        "Invalid seconds number '{$expiryValue}'"
                    );
                }
                $this->_expiryValue = $expiryValue;
            }
            public function getExpiry()
            {
                return $this->_expiryValue;
            }
            public function setCustomIdentifier($customIdentifier)
            {
                $this->_customIdentifier = $customIdentifier;
            }
            public function getCustomIdentifier()
            {
                return $this->_customIdentifier;
            }       
            public function getPayload()
            {
                $sJSONPayload = str_replace
                (
                    '"' . self::APPLE_RESERVED_NAMESPACE . '":[]',
                    '"' . self::APPLE_RESERVED_NAMESPACE . '":{}',
                    json_encode($this->_getPayload())
                );
                $nJSONPayloadLen = strlen($sJSONPayload);
                if ($nJSONPayloadLen > self::PAYLOAD_MAXIMUM_SIZE)
                {
                    if ($this->_autoAdjustLongPayload) 
                    {
                        $maxTextLen = $textLen = strlen($this->_text) - ($nJSONPayloadLen - self::PAYLOAD_MAXIMUM_SIZE);
                        if ($nMaxTextLen > 0)
                        {
                            while (strlen($this->_text = mb_substr($this->_text, 0, --$textLen, 'UTF-8')) > $maxTextLen);
                            return $this->getPayload();
                        }else
                        {
                            throw new Exception
                            (
                                "JSON Payload is too long: {$nJSONPayloadLen} bytes. Maximum size is " .
                                self::PAYLOAD_MAXIMUM_SIZE . " bytes. The message text can not be auto-adjusted."
                            );
                        }
                    }else
                    {
                        throw new Exception
                        (
                            "JSON Payload is too long: {$nJSONPayloadLen} bytes. Maximum size is " .
                            self::PAYLOAD_MAXIMUM_SIZE . " bytes"
                        );
                    }
                }
                return $sJSONPayload;
            }   
        }
    ?>


    使用办法:

        include 'apns.php';
        $rootpath = 'entrust_root_certification_authority.pem';  //ROOT证书地址
        $cp = 'production_push_certificates.pem';  //provider证书地址
        $apns = new APNS(0,$cp);
        try
        {
            $apns->setRCA($rootpath);  //设置ROOT证书
            $apns->connect(); //连接
            $apns->addDT('b9d98721b5586b61a00fbfa0d61a033954e1bfb8faaae3dfc5a1382xxxxxx');  //加入deviceToken
            $apns->setText('这是一条测试信息');  //发送内容
            $apns->setBadge(1);  //设置图标数
            $apns->setSound();  //设置声音
            $apns->setExpiry(3600);  //过期时间
            $apns->setCP('fljt',array('type' => '1','url' => 'http://www.google.com.hk'));  //自定义操作
            $apns->send();  //发送
        }catch(Exception $e)
        {
            echo $e;
        }

    下载文件:apns

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:【转】漫谈社区PHP 业务开发 下一篇:简单的PHP邮件发送类
    20期PHP线上班

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• Sajax融合服务器端的PHP和JS• Apache下禁止php文件被直接访问的方法• PHP更新购物车数量(表单部分/PHP处理部分)• php中突破基于HTTP• 使用PHP4.2.0及以后版本的注意事项
    1/1

    PHP中文网