apns-http2-php,蘋果push升級到http2

來源:互聯網
上載者:User

標籤:

最近公司push推送升級,用蘋果http2進行推送,http2的好處就不說了,這些網上都可以查到,但是真正在項目中用的,用php寫的還是特別少,因此,寫出來跟大家分享,廢話不說了,直接上代碼:

pushMessage.php

<?php

class PushMessage {
//發送apns server時發送訊息的鍵
const APPLE_RESERVED_NAMESPACE = ‘aps‘;

/*
* 串連apns地址
* ‘https://api.push.apple.com:443/3/device/‘, // 生產環境
* ‘https://api.development.push.apple.com:443/3/device/‘ // 沙箱環境
*
**/
private $_appleServiceUrl;
//認證
private $_sProviderCertificateFile;
//要發送到的device token
private $_deviceTokens = array();
//額外要發送的內容
private $_customProperties;
//私密金鑰密碼
private $_passPhrase;
//要推送的文字訊息
private $_pushMessage;
//要推送的語音訊息
private $_pushSoundMessage;
//設定角標
private $_nBadge;
//發送的頭部資訊
private $_headers = array();
private $_errors;
//推送的逾時時間,如果超過了這個時間,就自動不推送了,單位為秒
private $_expiration;
//apple 唯一標識
private $_apns_topic;
//10:立即接收,5:螢幕關閉,在省電時才會接收到的。如果是螢幕亮著,是不會接收到訊息的。而且這種訊息是沒有聲音提示的
private $_priority;
//cURL允許執行的最長秒數
private $_timeout;
/**< @type integer Status code for internal error (not Apple). */
const STATUS_CODE_INTERNAL_ERROR = 999;

const ERROR_WRITE_TOKEN = 1000;
//apple server 返回的錯誤資訊
protected $_aErrorResponseMessages = array(
200 => ‘Sussess‘,
400 => ‘Bad request‘,
403 => ‘There was an error with the certificate‘,
405 => ‘The request used a bad :method value. Only POST requests are supported‘,
410 => ‘The device token is no longer active for the topic‘,
413 => ‘The notification payload was too large‘,
429 => ‘The server received too many requests for the same device token‘,
500 => ‘Internal server error‘,
503 => ‘The server is shutting down and unavailable‘,
self::STATUS_CODE_INTERNAL_ERROR => ‘Internal error‘,
self::ERROR_WRITE_TOKEN => ‘Writing token error‘,
);

public function __construct() {}

/*
* 串連apple server
* @params certificate_file 認證
* @params pass_phrase 私密金鑰密碼
* @params apple_service_url 要發送的apple apns service
* @params expiration 推送的逾時時間,如果超過了這個時間,就自動不推送了,單位為秒
* @params apns-topic apple標識
**/
public function connServer($params) {
if (empty($params[‘certificate_file‘])) {
return false;
}
$this->_sProviderCertificateFile = $params[‘certificate_file‘];
$this->_appleServiceUrl = $params[‘apple_service_url‘];
$this->_passPhrase = $params[‘pass_phrase‘];
$this->_apns_topic = $params[‘apns-topic‘];
$this->_expiration = $params[‘expiration‘];
$this->_priority = $params[‘priority‘];
$this->_timeout = $params[‘timeout‘];

$this->_headers = array(
‘apns-topic:‘. $params[‘apns-topic‘],
‘apns-priority‘. $params[‘priority‘],
‘apns-expiration‘. $params[‘expiration‘]
);

$this->_hSocket = curl_init();
if(!defined(CURL_HTTP_VERSION_2_0)) {
define(CURL_HTTP_VERSION_2_0, 3);
}
curl_setopt($this->_hSocket, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_setopt($this->_hSocket, CURLOPT_SSLCERT, $this->_sProviderCertificateFile);
curl_setopt($this->_hSocket, CURLOPT_SSLCERTPASSWD, $this->_passPhrase);
curl_setopt($this->_hSocket, CURLOPT_SSLKEYTYPE, ‘PEM‘);
curl_setopt($this->_hSocket, CURLOPT_TIMEOUT, $this->_timeout);

if (!$this->_hSocket) {
$this->_errors[‘connServer‘][‘cert‘] = $this->_sProviderCertificateFile;
$this->_errors[‘connServer‘][‘desc‘] = "Unable to connect to ‘{$this->_appleServiceUrl}‘: $this->_hSocket";
$this->_errors[‘connServer‘][‘nums‘] = isset($this->_errors[‘connServer‘][‘nums‘]) ? intval($this->_errors[‘connServer‘][‘nums‘]) : 0;
$this->_errors[‘connServer‘][‘nums‘] += 1;
return false;
}

return $this->_hSocket;
}

/*
* 斷連
*
**/
public function disconnect() {
if (is_resource($this->_hSocket)) {
return curl_close($this->_hSocket);
}
return false;
}

//設定發送文字訊息
public function setMessage($message) {
$this->_pushMessage = $message;
}
//設定發送語音訊息
public function setSound($sound_message = ‘default‘) {
$this->_pushSoundMessage = $sound_message;
}

//擷取要發送的文字訊息
public function getMessage() {
if (!empty($this->_pushMessage)) {
return $this->_pushMessage;
}
return ‘‘;
}

//擷取語音訊息
public function getSoundMessage() {
if (!empty($this->_pushSoundMessage)) {
return $this->_pushSoundMessage;
}
return ‘‘;
}

/*
* 接收device token 可以是數組,也可以是單個字串
*
**/
public function addDeviceToken($device_token) {
if (is_array($device_token) && !empty($device_token)) {
$this->_deviceTokens = $device_token;
} else {
$this->_deviceTokens[] = $device_token;
}
}

//返回要擷取的device token
public function getDeviceToken($key = ‘‘) {
if ($key !== ‘‘) {
return isset($this->_deviceTokens[$key]) ? $this->_deviceTokens[$key] : array();
}
return $this->_deviceTokens;
}

//設定角標
public function setBadge($nBadge) {
$this->_nBadge = intval($nBadge);
}
//擷取角標
public function getBadge() {
return $this->_nBadge;
}

/*
* 用來設定額外的訊息
* @params custom_params array $name 不能和 self::APPLE_RESERVED_NAMESPACE(‘aps‘)樣,
*
**/
public function setCustomProperty($custom_params) {
foreach($custom_params as $name=>$value){
if (trim($name) == self::APPLE_RESERVED_NAMESPACE) {
$this->_errors[‘setCustomProperty‘][] = $name.‘設定不成功,‘.$name.‘不可以設定成 aps.‘;
}
$this->_customProperties[trim($name)] = $value;
}
}

/*
* 用來擷取額外設定的值
* @params string $name
*
**/
public function getCustomProperty($name = ‘‘) {
if($name !== ‘‘){
return isset($this->_customProperties[trim($name)]) ? $this->_customProperties[trim($name)] : ‘‘;
}

return $this->_customProperties;
}

/**
* 組織發送的訊息
*
* @return @type array The payload dictionary.
*/
protected function getPayload() {
$aPayload[self::APPLE_RESERVED_NAMESPACE] = array();

if (isset($this->_pushMessage)) {
$aPayload[self::APPLE_RESERVED_NAMESPACE][‘alert‘] = $this->_pushMessage;
}
if (isset($this->_pushSoundMessage)) {
$aPayload[self::APPLE_RESERVED_NAMESPACE][‘sound‘] = (string)$this->_pushSoundMessage;
}
if (isset($this->_nBadge)) {
$aPayload[self::APPLE_RESERVED_NAMESPACE][‘badge‘] = (int)$this->_nBadge;
}

if (is_array($this->_customProperties) && !empty($this->_customProperties)) {
foreach($this->_customProperties as $sPropertyName => $mPropertyValue) {
$aPayload[$sPropertyName] = $mPropertyValue;
}
}

return json_encode($aPayload);
}

/*
* 推送訊息
*
**/
public function send() {
if (!$this->_hSocket) {
return false;
}
if (isset($this->_errors[‘connServer‘])) {
unset($this->_errors[‘connServer‘]);
}

if (empty($this->_deviceTokens)) {
$this->_errors[‘send‘][‘not_deviceTokens‘][‘desc‘] = ‘No device tokens‘;
$this->_errors[‘send‘][‘not_deviceTokens‘][‘time‘] = date("Y-m-d H:i:s",time());
return false;
}

if (empty($this->getPayload())) {
$this->_errors[‘send‘][‘not_message‘][‘desc‘] = ‘No message to push‘;
$this->_errors[‘send‘][‘not_message‘][‘time‘] = date("Y-m-d H:i:s",time());
return false;
}

$tmpfile = tmpfile();
foreach ($this->_deviceTokens as $token) {
$sendMessage = $this->getPayload();
curl_setopt($this->_hSocket, CURLOPT_URL, $this->_appleServiceUrl . $token);
curl_setopt($this->_hSocket, CURLOPT_POSTFIELDS, $sendMessage);
curl_setopt($this->_hSocket, CURLOPT_HTTPHEADER, $this->_headers);
curl_setopt($this->_hSocket, CURLOPT_FILE, $tmpfile);

$response_info = curl_exec($this->_hSocket);
$response_code = curl_getinfo($this ->_hSocket,CURLINFO_HTTP_CODE);

if(!$response_info) {
$this->_errors[‘send‘][‘exec_curl‘][‘desc‘] = "curl connect faild";
$this->_errors[‘send‘][‘exec_curl‘][‘time‘] = date("Y-m-d H:i:s", time());
}

$response_errors = array();
fseek($tmpfile, 0);
while(($line = fgets($tmpfile)) !== false) {
$response_errors[] = json_decode($line, true);
}

if ($response_code != 200) {
$this->_writeErrorMessage($response_errors, $response_code, $token);
}
}

fclose($tmpfile);
$this->_deviceTokens = array();
return true;
}

//擷取發送過程中的錯誤
public function getError() {
return $this->_errors;
}

/*
* 讀取錯誤資訊
*@params res_errors 發送失敗的具體資訊
*@params res_code 回應標頭返回的錯誤code
*@params token 發送失敗的device token
**/
protected function _writeErrorMessage($res_errors, $res_code, $token) {
if(isset($this->_aErrorResponseMessages[$res_code])) {
$this->_errors[‘send‘][‘response‘][] = array(
‘reason‘ => $res_errors,
‘response_code‘ => $res_code,
‘msg‘ => $this->_aErrorResponseMessages[$res_code],
‘token‘ => $token,
‘time‘ => date("Y-m-d H:i:s",time())
);
} else {
$this->_errors[‘send‘][‘response‘][] = array(
‘reason‘ => $res_errors,
‘response_code‘ => $res_code,
‘token‘ => $token,
‘time‘ => date("Y-m-d H:i:s")
);
}

$this->disconnect();
sleep(0.5);
$this->_resConnect();
}

//重新串連
protected function _resConnect() {
$conn_res = $this->connServer(array(
‘certificate_file‘ => $this->_sProviderCertificateFile,
‘apple_service_url‘ => $this->_appleServiceUrl,
‘pass_phrase‘=> $this->_passPhrase,
‘priority‘=> $this->_priority,
‘apns-topic‘=> $this->_apns_topic,
‘expiration‘=> $this->_expiration,
‘timeout‘=> $this->_timeout
));

if (!$conn_res) {
$this->_errors[‘connServer‘][‘res_conn_nums‘] = isset($this->_errors[‘connServer‘][‘res_conn_nums‘]) ? intval($this->_errors[‘connServer‘][‘res_conn_nums‘]) : 0;
$this->_errors[‘connServer‘][‘res_conn_nums‘] += 1;
if ($this->_errors[‘connServer‘][‘res_conn_nums‘] >=5) {
return false;
}

return $this->_resConnect();
}
if (isset($this->_errors[‘connServer‘])) {
unset($this->_errors[‘connServer‘]);
}
return true;
}

}

 

 

使用:

include "pushMessage.php";

$obj = new PushMessage();

$params = array(

  ‘certificate_file‘ =>憑證路徑 ,// .pem 檔案

  ‘apple_service_url‘ => // 生產環境: ‘https://api.push.apple.com:443/3/device/‘  沙箱環境 ‘https://api.development.push.apple.com:443/3/device/‘ 

  ‘pass_phrase‘ => //這個是認證的私密金鑰密碼
  ‘apns-topic‘  => //apple唯一標識,這個不是隨便的字串,應該是申請蘋果推送的時候有的吧,具體不清楚,這個要問負責人

  ‘expiration‘ =>0,  //推送的逾時時間,如果超過了這個時間,就自動不推送了,單位為秒, 一般預設為0

  ‘priority‘  => 10,//10:立即接收,5:螢幕關閉,在省電時才會接收到的。如果是螢幕亮著,是不會接收到訊息的。而且這種訊息是沒有聲音提示的,一般為10

  ‘timeout‘ => 30,//curl逾時時間,單位為秒

);

//設定發送的文字還是聲音或者角標什麼的按自己的需求調用

$obj->connServer($params);

$obj->setMessage = "要發送的文字";

$obj->setSound = "要發送的聲音";

$obj->addDeviceToken= array();//或者單個的device token, 要發送到的apple token

$obj->setBadge = 1;//設定角標

$obj->setCustomProperty = array(‘a‘=>‘b‘);//其他額外發送的參數

$obj->getPayload(); //組織發送

$obj->send();//發送

$obj->getError();//擷取發送過程中的錯誤

$obj->disconnect();//斷連

 

注意:轉載請註明出處,謝謝!

apns-http2-php,蘋果push升級到http2

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.