APNS有關于服務器端

如何制作apns證書在這里就不再說明了

從導出證書開始

首先導出兩個 p12文件(cert.p12 key.p12) 把他們放在同一個文件夾(aaa)內

a.先打開終端瞳收,切換文件夾aaa下執(zhí)行

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

b.在執(zhí)行的時候 將會讓輸入密碼阿趁, 輸入生成p12文件時對應的密碼

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

此時要注意終端的提示 第一次輸入的密碼 是生成p.12時候的密碼,第二次第三次輸入的密碼是設置key.pem的密碼处硬。

c.如果需要對key不進行加密,執(zhí)行下面語句

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

d.然后合并連個.pem文件拇派,這個ck.pem就是服務端需要的證書了荷辕。

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

此時,可以把生成的ck.pem 給服務器端的人員即可

這里我們要自己實現(xiàn)服務端 給客戶端發(fā)送信息

下面我們生成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('這是一條測試信息');  //發(fā)送內容  
$apns->setBadge(1);  //設置圖標數(shù)  
$apns->setSound();  //設置聲音  
$apns->setExpiry(3600);  //過期時間  
$apns->setCP('custom operation',array('type' => '1','url' => 'http://www.baidu.com'));  //自定義操作  
$apns->send();  //發(fā)送  
echo ' sent ok';
}catch(Exception $e)
{
    echo $e;
  }
 ?>

</body>
</html>  

把生成好的apnsServer.php文件和ck.pem文件放到一個文件夾內

打開終端 執(zhí)行 php apnsServer.php

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

重要的事情說三遍

這時候你的app將受到發(fā)來的推送

開始調試吧 小伙伴們

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末疮方,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子茧彤,更是在濱河造成了極大的恐慌骡显,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曾掂,死亡現(xiàn)場離奇詭異惫谤,居然都是意外死亡,警方通過查閱死者的電腦和手機珠洗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門溜歪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人许蓖,你說我怎么就攤上這事蝴猪〉魉ィ” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵自阱,是天一觀的道長嚎莉。 經(jīng)常有香客問我,道長动壤,這世上最難降的妖魔是什么萝喘? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮琼懊,結果婚禮上阁簸,老公的妹妹穿的比我還像新娘。我一直安慰自己哼丈,他們只是感情好启妹,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著醉旦,像睡著了一般饶米。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上车胡,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天檬输,我揣著相機與錄音,去河邊找鬼匈棘。 笑死丧慈,一個胖子當著我的面吹牛,可吹牛的內容都是我干的主卫。 我是一名探鬼主播逃默,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼簇搅!你這毒婦竟也來了完域?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤瘩将,失蹤者是張志新(化名)和其女友劉穎吟税,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姿现,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡肠仪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年建钥,在試婚紗的時候發(fā)現(xiàn)自己被綠了藤韵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虐沥。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖匹涮,靈堂內的尸體忽然破棺而出然低,到底是詐尸還是另有隱情吨灭,我是刑警寧澤喧兄,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布拯辙,位于F島的核電站蚯斯,受9級特大地震影響遭赂,放射性物質發(fā)生泄漏撇他。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一狈蚤、第九天 我趴在偏房一處隱蔽的房頂上張望困肩。 院中可真熱鬧貌嫡,春花似錦篙程、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽潭枣。三九已至比默,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盆犁,已是汗流浹背命咐。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谐岁,地道東北人醋奠。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像伊佃,于是被迫代替她去往敵國和親窜司。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理航揉,服務發(fā)現(xiàn)例证,斷路器,智...
    卡卡羅2017閱讀 134,664評論 18 139
  • 前言:現(xiàn)在第三方推送也很多 迷捧,比如極光织咧,融云,信鴿漠秋,其原理也是相同利用APNS推送機制 笙蒙,前段公司讓做自己的推送,...
    _方丈閱讀 21,360評論 15 133
  • 前言:現(xiàn)在第三方推送也很多 庆锦,比如極光捅位,融云,信鴿搂抒,其原理也是相同利用APNS推送機制 艇搀,前段公司讓做自己的推送,...
    OliviaZqy閱讀 2,959評論 0 5
  • 小的時候求晶,我們村里有個孩子王焰雕,村里的孩子都是他帶著玩。他鬼點子多芳杏,發(fā)明了一種暗號矩屁,用一種學狼叫的聲音來聚集村里的孩...
    莫名就有風閱讀 171評論 0 0
  • 這是一份遲到的總結,本以為2014的總結能夠在2014的最后幾個小時內完成爵赵;卻沒想到因為湊熱鬧想去外灘看個跨年燈光...
    17號冷鋒閱讀 208評論 0 2