我正在开发一个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
答案 0 :(得分:0)
您可以将此密钥文件(.pem)放在项目的任何位置。但是将此文件放入/library
文件夹的最佳方法是创建一个新文件夹keys
现在,在您的库文件中,您必须添加real path
。
function __construct() {
$this->keyCertFilePath = APPPATH.'library/keys/'.$this->_ci->config->item('PermissionFile','apn');
这是最好的方法,如果它不起作用,请告诉我。