# Zend_Mobile_Push_Apns

Zend_Mobile_Push_Apns provides the ability to send push notifications to APNS generally in conjunction with Zend_Mobile_Push_Message_Apns; however there is a case when it would not be utilized is when getting feedback from the APNS server.

## Pushing Messages

Prior to pushing messages; you must follow the provisioning and deployment steps outlined by Apple.

When implementing APNS; you have a few components that you will utilize. Zend_Mobile_Push_Apns which contains the server components and Zend_Mobile_Push_Message_Apns which contains the message that you would like to send. Generally when sending push notifications to Apple you should do so in a batch.

The actual implementation of the code is fairly minimal; however, considerations to error handling must be taken.

    $message = new Zend_Mobile_Push_Message_Apns();
    $message->setAlert('Zend Mobile Push Example');
    $message->setBadge(1);
    $message->setSound('default');
    $message->setId(time());
    $message->setToken('ABCDEF0123456789');

    $apns = new Zend_Mobile_Push_Apns();
    $apns->setCertificate('/path/to/provisioning-certificate.pem');
    // if you have a passphrase on your certificate:
    // $apns->setCertificatePassphrase('foobar');

    try {
        $apns->connect(Zend_Mobile_Push_Apns::SERVER_SANDBOX_URI);
    } catch (Zend_Mobile_Push_Exception_ServerUnavailable $e) {
        // you can either attempt to reconnect here or try again later
        exit(1);
    } catch (Zend_Mobile_Push_Exception $e) {
        echo 'APNS Connection Error:' . $e->getMessage();
        exit(1);
    }

    try {
        $apns->send($message);
    } catch (Zend_Mobile_Push_Exception_InvalidToken $e) {
        // you would likely want to remove the token from being sent to again
        echo $e->getMessage();
    } catch (Zend_Mobile_Push_Exception $e) {
        // all other exceptions only require action to be sent
        echo $e->getMessage();
    }
    $apns->close();

Exceptions and Remediation Techniques

Exception | Meaning | Handling
--- | --- | ---
Zend_Mobile_Push_Exception | These types of exceptions are more generic in nature and are thrown either from APNS or internally on input validation | Read the message and determine remediation steps.
Zend_Mobile_Push_Exception_InvalidPayload | Generally the payload will not throw an exception unless the size of the payload is too large or it is missing required content. | Check the size of the payload is within the requirements of APNS
Zend_Mobile_Push_Exception_InvalidToken | Any form of an invalid token will be if the token is no longer registered; you are missing a token or it is in an invalid format. | You should remove the token and not attempt to send to it again.
Zend_Mobile_Push_Exception_InvalidTopic | An invalid topic simply means that the message id was too long or not an integer. | Ensure that the message ID is an integer.

When sending in batches and you are sending a large amount of push notifications out; you should ensure to usleep from time to time. This will ensure that your messages will be delivered and APNS will not simply hang up on you.

## Getting Feedback

APNS has a feedback service that you must listen to. Apple states that they monitor providers to ensure that they are listening to this service.

The feedback service simply returns an array of device tokens and the time. You can use the time to ensure that the device has not re-registered for push notifications since the last send.

    $apns = new Zend_Mobile_Push_Apns();
    $apns->setCertificate('/path/to/provisioning-certificate.pem');

    try {
        $apns->connect(Zend_Mobile_Push_Apns::SERVER_FEEDBACK_SANDBOX_URI);
    } catch (Zend_Mobile_Push_Exception_ServerUnavailable $e) {
        // you can either attempt to reconnect here or try again later
        exit(1);
    } catch (Zend_Mobile_Push_Exception $e) {
        echo 'APNS Connection Error:' . $e->getMessage();
        exit(1);
    }

    $tokens = $apns->feedback();
    while(list($token, $time) = each($tokens)) {
        echo $time . "\t" . $token . PHP_EOL;
    }
    $apns->close();

## Advanced Messages

APNS provides the ability for sending more advanced messages; for instance the examples above show the most basic implementation of a message. Zend_Mobile_Push_Message_Apns allows you to do far more advanced messaging outlined below.

### Alerts

Alerts can contain anything from a simple body message to having an action key and a launch image (iOS 4). You may only want to provide an action key when only a confirmation is necessary OR you are looking to localize the button with non-standard text (aka not "View").

The following code example shows alerts from the APNS payload examples.

        $message = new Zend_Mobile_Push_Message_Apns();

        // message with different button
        $message->setAlert('Bob wants to play poker', 'PLAY');
        // message using apps localized strings w/ string replacements
        $message->setAlert(null, null, 'GAME_PLAY_REQUEST_FORMAT', array('Jenna', 'Frank'));

### Custom Data

You can send your app custom data which allows you to make decisions based on the notifications; such as synchronizing data.

                    $message = new Zend_Mobile_Push_Message_Apns();
                    $message->addCustomData('foo', 'bar');
                    $message->addCustomData('foo', array('bar' => 1));
                    $message->addCustomData('bar', 'foo');

You may not use a custom key of 'aps' as it is reserved by Apple and leveraged for the main push data.