Apple Push Notification – Android Google Cloud Messaging

Standard

Merhaba,

Bir çoğunuzun ihtiyacı olan push notification konusunda bugün bir makale yazma kararı aldım.

Hem ios hem android e notification gönderebileceğiniz bir sınıf yazdım. Kullanımı ile birlikte hızlıca ele alalım isterseniz.

Tabi herşeyden önce şunu belirtmek isterim; kullanımı hakkında daha detaylı bilgi ve kaynak kodlara Git üzerinden erişmek isterseniz: https://github.com/onurcanalp/pushNotification

Hadi başlayalım isterseniz..

<?php
/**
 * Onur Canalp - 13 Ekim 2014
 *
 * Mobil aygıtlara notification göndermek için..
 * GMC - Google Mobile Cloud Push Notification
 * APN - Apple Push Notification
 */

class pushNotification {

    private $gmcApiKey = 'xxxxxxxxxxxxx'; //GOOGLE
    private $apnPassPhrase = 'onur12345'; //Apple
    private $apnPemFile = 'APNS.pem';
    private $errorMessages = "";

    public function __construct() {
        $this->apnPemFile = dirname(__FILE__).'/'.$this->apnPemFile;

        if (!file_exists($this->apnPemFile)) {
            echo "PEM Not Found! "; exit();
        }

	}

    //Hazırlayalım ve gönderelim
    public function prepareAndSend($message = "", $devices =  array()){

        $data['d'] = $message['d'];
        $data['m'] = $message['m'];

        if(isset($message['i'])){
            $data['i'] = $message['i'];
        }

        //ayıklayalım aygıtları ios - android
        foreach($devices as $key => $device){
            if($device['type'] == 'ios'){
                $iosIDS[] = $device['id'];
            }
            else{
                $androidIDS[] = $device['id'];
            }
        }

        //android cihazlara gönderelim
        if (count($androidIDS) > 0){
            $return['android'] = $this->sendGoogleCloudMessage($data, $androidIDS);
        }

        //ios cihazlara gönderelim
        if (count($iosIDS) > 0){
            //sadece ios da badge kavramı var..
            if(isset($message['badge'])){
                $data['badge'] = $message['badge'];
            }

            $return['ios'] = $this->sendAPNS($data, $iosIDS);
        }

        return $return;
    }

    public function sendGoogleCloudMessage( $message, $ids )
    {

        $url = 'https://android.googleapis.com/gcm/send';

        $post = array(
            'registration_ids'  => $ids,
            'data'              => $message,
        );

        $headers = array(
            'Authorization: key=' . $this->gmcApiKey,
            'Content-Type: application/json'
        );

        $ch = curl_init();

        curl_setopt( $ch, CURLOPT_URL, $url );
        curl_setopt( $ch, CURLOPT_POST, true );
        curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
        curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $post ) );

        $result = curl_exec( $ch );

        if ( curl_errno( $ch ) )
        {
            $result['result'] = array('result' => false, 'hata' => 'GCM error: ' . curl_error( $ch ));
        }

        curl_close( $ch );

        return json_decode($result);
    }

    public function sendAPNS($message = "", $ids = array()){

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

        // Open a connection to the APNS server
        $fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err, $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

        if (!$fp){
            $this->errorMessages = "Failed to connect: $err $errstr" . PHP_EOL;
            return false;
        }


        //Body
        $body['aps']['alert'] = $message['m'];
        $body['aps']['d'] = $message['d'];
        if(isset($message['badge'])){
            $body['aps']['badge'] = $message['badge'];
        }
        if(isset($message['i'])){
            $body['aps']['i'] = $message['i'];
        }

        $apnsBodyContent = json_encode($body);
        $errorNum = 0;
        foreach($ids as $deviceToken){
            $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($apnsBodyContent)) . $apnsBodyContent;

            // Send it to the server
            $result = fwrite($fp, $msg, strlen($msg));

            if (!$result){
                $errorNum++;
                $errors[] = 'Message not delivered'. $deviceToken . PHP_EOL;
            }
        }

        // Close the connection to the server
        fclose($fp);

        if($errorNum > 0){
            //detaylı bilgi istenirse
            $this->errorMessages = $errors;

            $object = new stdClass();
            $object->success = 0;
            $object->failure = $errorNum;
            $object->results = $errors;
        }
        else{
            $object = new stdClass();
            $object->success = 1;
            $object->failure = 0;
        }

        return $object;
    }

    public function getAllDevices(){
        global $db;

        $devices = $db->fetchAll("SELECT device_id, device_type FROM mobile_devices GROUP BY device_id");
        foreach($devices as $device){
            $ret[] = array('id' => $device['device_id'], 'type' => $device['device_type']);
        }

        unset($devices);

        return $ret;
    }
}

APNS.pem dosyası dikkatinizi çekmiştir belki.. .cer formatında sertifikanız varsa ve .pem nereden çıktı diyorsanız buyrun çözümü:

http://www.onurcanalp.com/2014/12/04/linuxunix-ve-os-x-uzerinde-cer-p12-sertifikalarini-pem-yapmak/

Şimdi bu sınıfı kullanarak mesajı gönderen fonksiyonumu yazacağım..

<?php
 *
 * Push Notification
 *
 * m: mesaj
 * d: display(açılmasını istediğimiz ekran)
 *      0 - Kategoriler
 *      1 - Sepet
 *      2 - Son görüntülenen ürünler
 *      3 - Profil
 *      4 - Bilgi Merkezi
 *      5 - Sipariş Listesi
 *      6 - Hediye Çekleri
 *      7 - Kupon Kodları
 *      8 - Destek Listesi
 *      9 - Kampanya
 *      10 - Ürün
 *      11 - Sipariş
 *      12 - Destek Detayı
 * i: id (varsa id)
 * badge: ios için üstteki rakam
 */
function sendPushNotification($mesaj = "", $display = 0, $devices = array(), $id = 0, $badge = 0){

    require("includes/class.pushNotification.php");
    $pushObj = new pushNotification();

    //hatalı display geldi ise default profili açtıralım
    $display = (int)$display;
    if($display > 12){
        $display = 0;
        $id = 0;
    }

    //hatalı array(device_id - device_type) gönderildiyse tümüne gönderelim
    if (empty($devices) || !is_array($devices)){
        $devices = $pushObj->getAllDevices();
    }


    $parameters['m'] = $mesaj;
    $parameters['d'] = $display;

    if($id > 0){
        $parameters['i'] = $id;
    }

    //parametrelere ekleyelim, sonra prepareAndSend metodunda android ise temizliyoruz.
    if($badge > 0){
        $parameters['badge'] = $badge;
    }

    $result = $pushObj->prepareAndSend($parameters,$devices);

    $success = true;
    $failCount = 0;

    if(isset($result['android']) && $result['android']->failure > 0){
        $success = false;
        $failCount += $result['android']->failure;
    }

    if(isset($result['ios']) && $result['ios']->failure > 0){
        $success = false;
        $failCount += $result['ios']->failure;
    }


    unset($pushObj, $parameters);

    if($success){
        //Tümü başarılı
        return true;
    }
    else{
        //biri veya bir kaçı hatalı gitti.. Hatalı giden adeti döndürelim
        return $failCount;
    }
}

Yeterli olacağını umuyorum anlamanız için, kod aralarında yorumlarda yazdım..

Kolay gelsin

2 thoughts on “Apple Push Notification – Android Google Cloud Messaging

  1. Abdullah Dural

    Merhaba Onur Bey,

    .net tarafında bu kod üzerine bilgileriniz örnek verecbileceğiniz bir paylaşımınız var mı ?

    Teşekkürler
    İyi Çalışmalar

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir