美文网首页
APNS有关于服务器端

APNS有关于服务器端

作者: __Lex | 来源:发表于2015-10-28 11:29 被阅读1290次

    如何制作apns证书在这里就不再说明了

    从导出证书开始

    首先导出两个 p12文件(cert.p12 key.p12) 把他们放在同一个文件夹(aaa)内

    a.先打开终端,切换文件夹aaa下执行

    openssl pkcs12 -clcerts -nokeys -out cert.pem -in cert.p12 
    

    b.在执行的时候 将会让输入密码, 输入生成p12文件时对应的密码

    openssl pkcs12 -nocerts -out key.pem -in key.p12
    

    此时要注意终端的提示 第一次输入的密码 是生成p.12时候的密码,第二次第三次输入的密码是设置key.pem的密码。

    c.如果需要对key不进行加密,执行下面语句

    openssl rsa -in key.pem -out key.unencrypted.pem 
    

    d.然后合并连个.pem文件,这个ck.pem就是服务端需要的证书了。

    cat cert.pem key.unencrypted.pem > ck.pem 
    

    此时,可以把生成的ck.pem 给服务器端的人员即可

    这里我们要自己实现服务端 给客户端发送信息

    下面我们生成php文件 ,这里不进行解释 直接上代码

    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="content-type" content="text/html;charset=utf-8">
        <title>APNS</title>
    </head>
    <body>
    <?php
    /**
     * @file apns.php
     * @synopsis  apple APNS class
     * @author Yee, <rlk002@gmail.com>
     * @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;
    }
    }
    
    ?>
    <?php
    date_default_timezone_set('PRC');
    echo "we are young,test apns.  -".date('Y-m-d h:i:s',time());
    
    $rootpath = 'entrust_root_certification_authority.pem';  //ROOT证书地址  
    $cp = 'ck.pem';  //provider证书地址  
    $apns = new APNS(1,$cp);
    try
    {
        //$apns->setRCA($rootpath);  //设置ROOT证书  
    $apns->connect(); //连接  
    $apns->addDT('输入你的deviceToken');  //加入deviceToken  
    $apns->setText('这是一条测试信息');  //发送内容  
    $apns->setBadge(1);  //设置图标数  
    $apns->setSound();  //设置声音  
    $apns->setExpiry(3600);  //过期时间  
    $apns->setCP('custom operation',array('type' => '1','url' => 'http://www.baidu.com'));  //自定义操作  
    $apns->send();  //发送  
    echo ' sent ok';
    }catch(Exception $e)
    {
        echo $e;
      }
     ?>
    
    </body>
    </html>  
    

    把生成好的apnsServer.php文件和ck.pem文件放到一个文件夹内

    打开终端 执行 php apnsServer.php

    php文件中需要更换成自己的deviceToken
    php文件中需要更换成自己的deviceToken
    php文件中需要更换成自己的deviceToken

    重要的事情说三遍

    这时候你的app将受到发来的推送

    开始调试吧 小伙伴们

    相关文章

      网友评论

          本文标题:APNS有关于服务器端

          本文链接:https://www.haomeiwen.com/subject/ongxhttx.html