Codeigniter APN.where将.pem文件放在php代码中

时间:2016-11-21 16:43:27

标签: php ios codeigniter apns-php

我正在开发一个codeigniter项目,该项目需要将推送通知发送到ios设备。 在导入eapn库时,我无法弄清楚从ios app项目导出的.pem文件的放置位置。 而且我也无法弄清楚如何引用它的路径。

这是Pushnotification.php库

<?php

class APN
{

protected $server;
protected $keyCertFilePath;
protected $passphrase;
protected $pushStream;
protected $feedbackStream;
protected $timeout;
protected $idCounter = 0;
protected $expiry;
protected $allowReconnect = true;
protected $additionalData = array();
protected $apnResonses = 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',
    255 => 'None (unknown)',
);

private $connection_start;

public $error;
public $payloadMethod = 'simple';

/**
* Connects to the server with the certificate and passphrase
*
* @return <void>
*/
protected function connect($server) {

    $ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'local_cert', $this->null);
    stream_context_set_option($ctx, 'ssl', 'passphrase', $this->null);

    $stream = stream_socket_client($server, $err, $errstr, $this->timeout, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
    log_message('debug',"APN: Maybe some errors: $err: $errstr");


    if (!$stream) {

        if ($err)
            show_error("APN Failed to connect: $err $errstr");
        else
            show_error("APN Failed to connect: Something wrong with context");

        return false;
    }
    else {
        stream_set_timeout($stream,20);
        log_message('debug',"APN: Opening connection to: {$server}");
        return $stream;
    }
}



/**
* Generates the payload
* 
* @param <string> $message
* @param <int> $badge
* @param <string> $sound
* @return <string>
*/
protected function generatePayload($message, $badge = NULL, $sound = NULL, $newstand = false) {

   $body = array();

   // additional data
        if (is_array($this->additionalData) && count($this->additionalData))
        {
            $body = $this->additionalData;
        }

    //message
        $body['aps'] = array('alert' => $message);

    //badge
        if ($badge)
            $body['aps']['badge'] = $badge;

        if ($badge == 'clear')
            $body['aps']['badge'] = 0;

     //sound
        if ($sound)
            $body['aps']['sound'] = $sound;

    //newstand content-available
        if($newstand)
            $body['aps']['content-available'] = 1;


   $payload = json_encode($body);
   log_message('debug',"APN: generatePayload '$payload'");
   return $payload;
}



/**
 * Writes the contents of payload to the file stream
 * 
 * @param <string> $deviceToken
 * @param <string> $payload
 */
protected function sendPayloadSimple($deviceToken, $payload){

    $this->idCounter++;     

    log_message('debug',"APN: sendPayloadSimple to '$deviceToken'");

    $msg = chr(0)                                   // command
        . pack('n',32)                                  // token length
        . pack('H*', $deviceToken)                      // device token
        . pack('n',strlen($payload))                    // payload length
        . $payload;                                     // payload

    log_message('debug',"APN: payload: '$msg'");
    log_message('debug',"APN: payload length: '".strlen($msg)."'");
    $result = fwrite($this->pushStream, $msg, strlen($msg));

    if ($result)
        return true;
    else
        return false;
}


/**
 * Writes the contents of payload to the file stream with enhanced api (expiry, debug)
 * 
 * @param <string> $deviceToken
 * @param <string> $payload
 */
protected function sendPayloadEnhance($deviceToken, $payload, $expiry = 86400) {

    if (!is_resource($this->pushStream))
        $this->reconnectPush();

    $this->idCounter++;     

    log_message('debug',"APN: sendPayloadEnhance to '$deviceToken'");

    $payload_length = strlen($payload);

    $request = chr(1)                                       // command
                    . pack("N", time())                     // identifier
                    . pack("N", time() + $expiry) // expiry
                    . pack('n', 32)                             // token length
                    . pack('H*', $deviceToken)      // device token
                    . pack('n', $payload_length)    // payload length
                    . $payload;

    $request_unpacked = @unpack('Ccommand/Nidentifier/Nexpiry/ntoken_length/H64device_token/npayload_length/A*payload', $request); // payload

    log_message('debug', "APN: request: '$request'");
    log_message('debug', "APN: unpacked request: '" . print_r($request_unpacked, true) . "'");
    log_message('debug', "APN: payload length: '" . $payload_length . "'");
    $result = fwrite($this->pushStream, $request, strlen($request));

    if ($result)
    {
        return $this->getPayloadStatuses();
    }

    return false;
}


protected function timeoutSoon($left_seconds = 5)
{
    $t = ( (round(microtime(true) - $this->connection_start) >= ($this->timeout - $left_seconds)));
    return (bool)$t;
}




 * Connects to the APNS server with a certificate and a passphrase
 *
 * @param <string> $server
 * @param <string> $keyCertFilePath
 * @param <string> $passphrase
 */
function __construct() {

    $this->_ci = get_instance();

    $this->_ci->config->load('apn',true);


    if(!file_exists($this->_ci->config->item('PermissionFile','apn')))
    {
        show_error("APN Failed to connect: APN Permission file not found");
    }

    $this->pushServer = $this->_ci->config->item('Sandbox','apn') ? $this->_ci->config->item('PushGatewaySandbox','apn') : $this->_ci->config->item('PushGateway','apn');
    $this->feedbackServer = $this->_ci->config->item('Sandbox','apn') ? $this->_ci->config->item('FeedbackGatewaySandbox','apn') : $this->_ci->config->item('FeedbackGateway','apn');

    $this->keyCertFilePath = $this->_ci->config->item('PermissionFile','apn');
    $this->passphrase = $this->_ci->config->item('PassPhrase','apn');
    $this->timeout = $this->_ci->config->item('Timeout','apn') ? $this->_ci->config->item('Timeout','apn') : 60;
    $this->expiry = $this->_ci->config->item('Expiry','apn') ? $this->_ci->config->item('Expiry','apn') : 86400;
}




/**
 * Public connector to push service
 */
public function connectToPush()
{
    if (!$this->pushStream or !is_resource($this->pushStream))
    {
        log_message('debug',"APN: connectToPush");

        $this->pushStream = $this->connect($this->pushServer);

        if ($this->pushStream)
        {
            $this->connection_start = microtime(true);
            //stream_set_blocking($this->pushStream,0);
        }
    }

    return $this->pushStream;
}

/**
 * Public connector to feedback service
 */
public function connectToFeedback()
{
    log_message('info',"APN: connectToFeedback");
    return $this->feedbackStream = $this->connect($this->feedbackServer);
}

/**
 * Public diconnector to push service
 */
function disconnectPush()
{
    log_message('debug',"APN: disconnectPush");
    if ($this->pushStream && is_resource($this->pushStream))
    {
        $this->connection_start = 0;
        return @fclose($this->pushStream);
    }
    else
        return true;
}

/**
 * Public disconnector to feedback service
 */
function disconnectFeedback()
{
    log_message('info',"APN: disconnectFeedback");
    if ($this->feedbackStream && is_resource($this->feedbackStream))
        return @fclose($this->feedbackStream);
    else
        return true;
}

function reconnectPush()
{
    $this->disconnectPush();

    if ($this->connectToPush())
    {
        log_message('debug',"APN: reconnect");
        return true;
    }
    else
    {
        log_message('debug',"APN: cannot reconnect");
        return false;
    }
}

function tryReconnectPush()
{
    if ($this->allowReconnect)
    {
        if($this->timeoutSoon())
        {
            return $this->reconnectPush();
        }
    }

    return false;
}


/**
 * Sends a message to device
 * 
 * @param <string> $deviceToken
 * @param <string> $message
 * @param <int> $badge
 * @param <string> $sound
 */
public function sendMessage($deviceToken, $message, $badge = NULL, $sound = NULL, $expiry = '', $newstand = false)
{
    $this->error = '';

    if (!ctype_xdigit($deviceToken))
    {
        log_message('debug',"APN: Error - '$deviceToken' token is invalid. Provided device token contains not hexadecimal chars");
        $this->error = 'Invalid device token. Provided device token contains not hexadecimal chars';
        return false;
    }

    // restart the connection
    $this->tryReconnectPush();

    log_message('info',"APN: sendMessage '$message' to $deviceToken");

    //generate the payload
    $payload = $this->generatePayload($message, $badge, $sound, $newstand);

    $deviceToken = str_replace(' ', '', $deviceToken);

    //send payload to the device.
    if ($this->payloadMethod == 'simple')
        $this->sendPayloadSimple($deviceToken, $payload);
    else
    {
        if (!$expiry)
            $expiry = $this->expiry;

        return $this->sendPayloadEnhance($deviceToken, $payload, $expiry);
    }
}


/**
 * Writes the contents of payload to the file stream
 * 
 * @param <string> $deviceToken
 * @param <string> $payload
 * @return <bool> 
 */
function getPayloadStatuses()
{

    $read = array($this->pushStream);
    $null = null;
    $changedStreams = stream_select($read, $null, $null, 0, 2000000);

    if ($changedStreams === false)
    {    
        log_message('error',"APN Error: Unabled to wait for a stream availability");
    }
    elseif ($changedStreams > 0)
    {

        $responseBinary = fread($this->pushStream, 6);
        if ($responseBinary !== false || strlen($responseBinary) == 6) {

            if (!$responseBinary)
                return true;

            $response = @unpack('Ccommand/Cstatus_code/Nidentifier', $responseBinary);

            log_message('debug','APN: debugPayload response - '.print_r($response,true));

            if ($response && $response['status_code'] > 0)
            {
                log_message('error','APN: debugPayload response - status_code:'.$response['status_code'].' => '.$this->apnResonses[$response['status_code']]);
                $this->error = $this->apnResonses[$response['status_code']];
                return false;
            }
            else
            {
                if (isset($response['status_code']))
                    log_message('debug','APN: debugPayload response - '.print_r($response['status_code'],true));
            }

        }
        else
        {
            log_message('debug',"APN: responseBinary = $responseBinary");
            return false;
        }
    }
    else
        log_message('debug',"APN: No streams to change, $changedStreams");

    return true;
}



/**
* Gets an array of feedback tokens
*
* @return <array>
*/
public function getFeedbackTokens() {

    log_message('debug',"APN: getFeedbackTokens {$this->feedbackStream}");
    $this->connectToFeedback();

    $feedback_tokens = array();
    //and read the data on the connection:
    while(!feof($this->feedbackStream)) {
        $data = fread($this->feedbackStream, 38);
        if(strlen($data)) {    
            //echo $data;       
            $feedback_tokens[] = unpack("N1timestamp/n1length/H*devtoken", $data);
        }
    }

    $this->disconnectFeedback();

    return $feedback_tokens;
}


/**
* Sets additional data which will be send with main apn message
*
* @param <array> $data
* @return <array>
*/
public function setData($data)
{
    if (!is_array($data))
    {
        log_message('error',"APN: cannot add additional data - not an array");
        return false;
    }

    if (isset($data['apn']))
    {
        log_message('error',"APN: cannot add additional data - key 'apn' is reserved");
        return false;
    }

    return $this->additionalData = $data;
}



/**
* Closes the stream
*/
function __destruct(){
    $this->disconnectPush();
    $this->disconnectFeedback();
}

}//end of class

1 个答案:

答案 0 :(得分:0)

您可以将此密钥文件(.pem)放在项目的任何位置。但是将此文件放入/library文件夹的最佳方法是创建一个新文件夹keys

现在,在您的库文件中,您必须添加real path

function __construct() {
    $this->keyCertFilePath = APPPATH.'library/keys/'.$this->_ci->config->item('PermissionFile','apn');

这是最好的方法,如果它不起作用,请告诉我。