Push mailings in PHP (Android and IOS). Minimal turnkey solution
About Push notifications mailing list have been written many times on Habré, for example here and here , but there is still no direct guide to action. So, if interested, please, under cat.
Register device tokens
First of all, the application developer creates magic in which he indicates the registration address, it can be like this: htpp: //test.ru/secret/android? Token = value and htpp: //test.ru/secret/ios? Token = value .
The most remarkable thing is that there is simply no protection against left registrations, although the magic may have failed or it was not quite of high quality, if there is any protection, write in the comments, I will definitely add useful advice to the article.
At the input, we get the value of the token that comes when installing the application, there may be slight delays, but literally 10-20 seconds. Tokens are unique, but you can also make a check for uniqueness when writing to the database.
Example token for android:
APA91bFY-2CYrriS-Dt6y9_dGHhkPVwy7njqFpfgpzGYlDT4l0SQeqKr-lc1OM0a2DQ33S3EKwy2YJn-upKxOT6rNwgk3aqqfqggqgqgqgqgqgfgoqo
IOS:
628a3f4a28bb994bb7c9a4143950d240c6d5a1dab8621e9ed61a2109a074f832
At this step, with the registration of devices, we are done.
Notification mailing
Apple uses the APNS service , and Google GCM (C2DM is considered obsolete, keep this in mind), and after reading the documentation, you can move on to your favorite business, namely bicycle building, but the budget was limited and I started looking for ready-made solutions. The most suitable thing that met is ApnsPHP and GCMMessage , work on both 5.3+ and 5.4+.
When using libraries, the most important thing is to get the correct certificates and secret phrase in the case of APNS and a secret token for working with GCM.
An example of a ready-made code for sending notifications for GCM, tokens are advised to be sent in batches, it works quite quickly even with large quantities, the service returns invalid tokens (users deleted the application), they should be deleted right away.
function fnSendAndroid($tokens, $text, $config)
{
$sender = new CodeMonkeysRu\GCM\Sender($config['androidTokenAuth']);
$message = new CodeMonkeysRu\GCM\Message($tokens, array("message" => $text));
try {
$response = $sender->send($message);
if ($response->getFailureCount() > 0) {
$invalidRegistrationIds = $response->getInvalidRegistrationIds();
foreach($invalidRegistrationIds as $invalidRegistrationId) {
//Remove $invalidRegistrationId from DB
// на входе значение APS91bFY-2CYrriS-Dt6y9_dGHhkPVwy7njqFpfgpzGYlDT4l0SQeqKr-lc1OM0a2DQ33S3EKwy2YJn-upKxOT6rNwgk350xUM3g8VX65rkGocOQX80Ta34pwXo6fyn-usoaGUAm4lzsqbCL-gkzHZZXRX39kUQfnA
fnDeleteToken($invalidRegistrationId);
}
}
if ($response->getSuccessCount()) {
echo 'отправлено сообщений на ' . $response->getSuccessCount() . ' устройств';
}
} catch (CodeMonkeysRu\GCM\Exception $e) {
switch ($e->getCode()) {
case CodeMonkeysRu\GCM\Exception::ILLEGAL_API_KEY:
case CodeMonkeysRu\GCM\Exception::AUTHENTICATION_ERROR:
case CodeMonkeysRu\GCM\Exception::MALFORMED_REQUEST:
case CodeMonkeysRu\GCM\Exception::UNKNOWN_ERROR:
case CodeMonkeysRu\GCM\Exception::MALFORMED_RESPONSE:
fnLog('Ошибка отправления на андроид ' . $e->getCode() . ' ' . $e->getMessage());
break;
}
}
}
Everywhere they write that APNS is very easy to use, in principle, this is true, if you consider that there are certificates for the test and production, you should pay attention to the need for a certificate, a secret phrase and a root certificate, all this is obtained in the developer's personal account.
Users have the ability to remove particularly annoying applications, so you should remove dead tokens before sending.
function feedback($config)
{
$feedback = new ApnsPHP_Feedback(
ApnsPHP_Abstract::ENVIRONMENT_PRODUCTION, $config['apn']['sert']
);
$feedback->setProviderCertificatePassphrase($config['apn']['passphrase']);
$feedback->setRootCertificationAuthority($config['apn']['RootCertificat']);
$feedback->connect();
$aDeviceTokens = $feedback->receive();
if (!empty($aDeviceTokens)) {
foreach ($aDeviceTokens as $DeviceToken) {
/**
* формат
* [timestamp] => 1406040206
* [tokenLength] => 32
* [deviceToken] => 738d005a11bca268e2f1bffbfed88a456e261020b9277883cde14d9c8f47cde0
*/
//'DELETE LOW_PRIORITY FROM tokens WHERE token=:token';
fnLog('Feedback - Удален токен ' . $DeviceToken[deviceToken]);
}
}
$feedback->disconnect();
}
Then the sending itself:
function fnSendIos($tokens, $text, $config)
{
$push = new ApnsPHP_Push(
ApnsPHP_Abstract::ENVIRONMENT_PRODUCTION, $config['apn']['sert']);
// Set the Provider Certificate passphrase
$push->setProviderCertificatePassphrase($config['apn']['passphrase']);
$push->setRootCertificationAuthority($config['apn']['RootCertificat']);
$message = new ApnsPHP_Message();
$listTokens = array();
foreach ($tokens as $token) {
$message->addRecipient($token);
$listTokens[] = $token;
}
$push->connect();
$message->setText($text);
$push->add($message);
$push->send();
$push->disconnect();
$aErrorQueue = $push->getErrors();
if (!empty($aErrorQueue)) {
fnLog('Ошибка отправки ios - ' . print_r($aErrorQueue, true));
if (is_array($aErrorQueue)) {
foreach($aErrorQueue as $error) {
if (isset($error['ERRORS']) && is_array($error['ERRORS'])) {
foreach ($error['ERRORS'] as $m) {
if (isset($m['statusMessage']) && $m['statusMessage'] == 'Invalid token') {
$arrayID = $m['identifier'] - 1;
if (isset($listTokens[$arrayID])) {
//DELETE LOW_PRIORITY FROM tokens WHERE token=:token'
fnLog('Удален ошибочный токен ' . $listTokens[$arrayID]);
}
}
}
}
}
}
}
}
If you are not confused with the certificates, then the mailing will be successful.
Here is a condominium turned out.