Server-side library for working with Expo using PHP

Overview

expo-server-sdk-php tests codecov GitHub

Server-side library for working with Expo using PHP.

If you have any problems with the code in this repository, feel free to open an issue or make a PR!

Table of Contents

Testing

You can run the test suite via composer:

composer test

Installation

You can install the package via composer:

composer require ctwillie/expo-server-sdk-php

Use Cases

This package was written with two main use cases in mind.

  1. Sending push notification messages to one or more recipients, then you're done! The most obvious use case.
  2. And channel subscriptions, used to subscribe one or more tokens to a channel, then send push notifications to all tokens subscribed to that channel. Subscriptions are persisted until a token unsubscribes from a channel. Maybe unsubscribing upon the end users request.

Keep this in mind as you decide which is the best use case for your back end.

Composing a message

Compose a push notification message to send using options from the Expo docs.

use ExpoSDK\ExpoMessage;

/**
 * Create messages fluently and/or pass attributes to the constructor
 */
$message = (new ExpoMessage([
    'title' => 'initial title',
    'body' => 'initial body',
]))
    ->setTitle('This title overrides initial title')
    ->setBody('This notification body overrides initial body')
    ->setData(['id' => 1])
    ->setChannelId('default')
    ->setBadge(0)
    ->playSound();

Sending a push notification

Compose a message then send to one or more recipients.

use ExpoSDK\Expo;
use ExpoSDK\ExpoMessage;

/**
 * Composed messages, see above
 * Can be an array of arrays, ExpoMessage instances will be made internally
 */
$messages = [
    [
        'title' => 'Test notification',
        'to' => 'ExponentPushToken[xxxx-xxxx-xxxx]',
    ],
    new ExpoMessage([
        'title' => 'Notification for default recipients',
        'body' => 'Because "to" property is not defined',
    ]),
];

/**
 * These recipients are used when ExpoMessage does not have "to" set
 */
$defaultRecipients = [
    'ExponentPushToken[xxxx-xxxx-xxxx]',
    'ExponentPushToken[yyyy-yyyy-yyyy]'
];

(new Expo)->send($messages)->to($defaultRecipients)->push();

Channel subscriptions

Subscribe tokens to a channel, then push notification messages to that channel. Subscriptions are persisted internally in a local file so you don't have to worry about this yourself. Unsubscribe the token from the channel at any time to stop messages to that recipient.

⚠️ If you are are running multiple app servers: Be very careful here! Channel subscriptions are stored in an internal local file. Subscriptions will not be shared across multiple servers. Database drivers coming in the near future to handle this use case.

/**
 * Specify the file driver to persist subscriptions internally.
 * More drivers coming soon, (database, redis, custom local file)
 */
use ExpoSDK\Expo;

$expo = Expo::driver('file');

// composed message, see above
$message;

$recipients = [
    'ExponentPushToken[xxxx-xxxx-xxxx]',
    'ExponentPushToken[yyyy-yyyy-yyyy]'
];

// name your channel anything you'd like
$channel = 'news-letter';
// the channel will be created automatically if it doesn't already exist
$expo->subscribe($channel, $recipients);

$expo->send($message)->toChannel($channel)->push();

// you can unsubscribe one or more recipients from a channel.
$expo->unsubscribe($channel, $recipients);

Expo responses

Get the data returned from successful responses from the Expo server.

$response = $expo->send($message)->to($recipients)->push();

$data = $response->getData();

Handling unregistered devices

Expo provides a macro for handling tokens that have DeviceNotRegistered error in the Expo response. You can register a callback before sending your messages to handle these unregistered tokens.

You only need to register the handler once as it will be applied to all Expo instances.

use ExpoSDK\Expo;

Expo::addDevicesNotRegisteredHandler(function ($tokens) {
    // this callback is called once and receives an array of unregistered tokens
});

$expo1 = new Expo();
$expo1->send(...)->push(); // will call your callback

$expo2 = new Expo();
$expo2->send(...)->push(); // will also call your callback

Retrieving push receipts

Retrieve the push receipts using the ticket ids from the Expo server.

$ticketIds = [
    'xxxx-xxxx-xxxx-xxxx',
    'yyyy-yyyy-yyyy-yyyy'
];

$response = $expo->getReceipts($ticketIds);
$data = $response->getData();

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

License

The MIT License (MIT). Please see License File for more information.

Credits

Comments
  • Feature/add db driver

    Feature/add db driver

    @ctwillie Here is the start of my pull request. It still obviously needs a lot of work and I haven't added any testing yet, but feel free to look and offer feedback.

    opened by neklein 9
  • Multiple messages per request, macros for handling tokens with DeviceNotRegistered errors, automatic instance building

    Multiple messages per request, macros for handling tokens with DeviceNotRegistered errors, automatic instance building

    This PR fixes #7 and adds next features:

    Ability to set a bunch of messages before making a request.

    $messages = [];
    
    $messages[] = (new ExpoMessage())
        ->setTitle('random title')
        ->setTo(['ExponentPushToken[vwskdcfnkal]', 'ExponentPushToken[kljmfwe32rklowm]']);
    
    $messages[] = (new ExpoMessage())
        ->setTitle('another notification')
        ->setTo('ExponentPushToken[single-recipient]');
    
    $messages[] = (new ExpoMessage())
        ->setTitle('notification with default recipients');
    
    (new Expo())->send($messages)->to(['ExponentPushToken[default-recipients-here]'])->push();
    

    Ability to pass array of data in both ExpoMessage constructor and Expo send() method, without creating instances manually.

    $messages = [];
    
    // ExpoMessage can be created automatiaclly
    $messages[] = [
        'title' => 'test title',
        'body' => 'test body',
        'to' => 'ExponentPushToken[kjsdnfjkasnekf]',
        'data' => ['some' => 'data'],
    ];
    // or be instantiated manually
    $messages[] = (new ExpoMessage([
        'title' => 'Test not123123',
        'body' => 'Test body123123123',
    ]))->setTitle('this title will override initial one'),
    
    (new Expo)->send($messages)->push();
    

    Introduces two macros for handling tokens with DeviceNotRegistered errors.

    You can register them somewhere in the beginning of request life cycle and its callbacks will be called for all invalid tokens.

    Expo::addDevicesNotRegisteredHandler(function ($tokens) {
        // this callback is called once and it recieves array of invalid tokens
    });
    Expo::addDeviceNotRegisteredHandler(function ($token) {
        // this callback is called for each token separately and only if previous macro is not registered
    });
    
    opened by dorkyboi 8
  • categoryIdentifier not received

    categoryIdentifier not received

    I am sending this data via the SDK. I receive everything except for the categoryId as categoryIdentifier. Is there anything that I am doing wrong?

    $messages = [
         'title'      => $notification['title'],
         'body'       => $notification['body'],
         'to'         => $notification['device_token'],
         'data'       => json_decode($notification['json_data'], true),
         'categoryId' => $notification['category_identifier'],
    ];
    

    I even tried sending categoryIdentifier and category_identifier but again was not able to consume it in react native.

    opened by raonikhil 5
  • allow DriverManager to be extended by changing properties to protected

    allow DriverManager to be extended by changing properties to protected

    @ctwillie would you be willing to allow the DriverManager properties to protected rather than private? That way I can create my own DriverManager that extends yours and also create additional drivers for personal use.

    opened by neklein 4
  • error 60: SSL certificate problem: certificate has expired

    error 60: SSL certificate problem: certificate has expired

    Currently getting :

    GuzzleHttp\Exception\RequestException : cURL error 60: SSL certificate problem: certificate has expired (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://exp.host/--/api/v2/push/send
    

    using the basic example from docs, looks like some problem for expo.

    using :

    • php 7.4
    • Latest version of your library

    I'll provide a PR to fix this.

    opened by Stevemoretz 2
  • Fix invalid error handling from Expo: error is not an int but a string

    Fix invalid error handling from Expo: error is not an int but a string

    Hello,

    Thanks for you SDK. I new with Expo and while I was accidently failing at trying to send a notification, I found this bug: when setting an empty array as data param, the API returns a 400 error:

    [
      "errors" => [
        0 => [
          "code" => "VALIDATION_ERROR"
          "message" => ""[0].data" must be of type object."
          "isTransient" => false
        ]
      ]
    ]
    

    However, the code was designed to handle a int, not a string. The documentation confirms this: https://docs.expo.dev/push-notifications/sending-notifications/#push-receipt-response-format

    Error returned:

    In ExpoErrorManager.php line 61:
    
      [TypeError]
      Exception::__construct(): Argument #2 ($code) must be of type int, string given
    

    I thought it would be a good idea to prepend the stringed code to the error message to have some more context.

    [ExpoSDK\Exceptions\ExpoException (400)]
      VALIDATION_ERROR: "[0].data" must be of type object.
    

    Thanks!

    opened by eexit 2
  • Allow lowest guzzle version

    Allow lowest guzzle version

    Your package doesn't need the latest version of Guzzle and this will easier the way to add your package in an old project.

    Thanks for this package, it's very useful.

    opened by karlyn33 1
  • use token from error details, if provided

    use token from error details, if provided

    @ctwillie I noticed that the ticket error details from the expo api now include expoPushToken at least when the type is DeviceNotRegistered. Thought it might be helpful to move in that direction.

    opened by neklein 2
Releases(v2.0)
Owner
Cedric Twillie
Cedric Twillie
多平台通知 SDK(Bark、Chanify、钉钉群机器人、飞书群机器人、Server 酱、企业微信群机器人、息知)。

notify 简体中文 | ENGLISH Multi platform notification SDK(Bark、Chanify、DingTalk、FeiShu、ServerChan、WeWork、XiZhi). - 多平台通知 SDK(Bark、Chanify、钉钉群机器人、飞书群机器人、Se

guanguans 439 Dec 31, 2022
Multiple channels of laravel exception notification(DingTalk、FeiShu、ServerChan、WeWork、XiZhi). - 多种通道的 laravel 异常通知(钉钉群机器人、飞书群机器人、Server 酱、企业微信群机器人、息知)。

laravel-exception-notify 简体中文 | ENGLISH Multiple channels of laravel exception notification(DingTalk、FeiShu、ServerChan、WeWork、XiZhi). - 多种通道的 laravel

guanguans 61 Dec 8, 2022
WebPush can be used to send notifications to endpoints which server delivers Web Push

WebPush can be used to send notifications to endpoints which server delivers Web Push notifications as described in the Web Push protocol. As it is standardized, you don't have to worry about what server type it relies on.

null 1.5k Jan 7, 2023
Send SMS with easy using BEEM

beem-sms-api Send SMS with easy using BEEM Installation You must be using composer to be able to use this library. If composer 1.x is installed, make

Hosanna Higher Technologies 4 Dec 24, 2021
Push Notifications using Laravel

laravel-push-notification Push Notifications using Laravel PushNotification::send(['deviceToken1', 'deviceToken2',..], 'Notification Message', 'Action

Webelight Solutions 26 Jul 22, 2022
Laravel SMS allows you to send SMS from your Laravel application using multiple sms providers, allow to add custom sms provider

Laravel SMS Laravel SMS allows you to send SMS from your Laravel application using multiple sms providers, allow to add custom sms provider Requiremen

Ayman Alaiwah 3 May 7, 2022
Get a realtime feed of your Laravel project’s most important events using Logsnag.

laravel-logsnag Get a realtime feed of your Laravel project’s most important events using Logsnag. Supports push notifications straight to your phone.

Marius 8 Oct 19, 2022
This package makes it easy to send notifications using RocketChat with Laravel 9.0+.

laravel-rocket-chat-notifications Introduction This package makes it easy to send notifications using RocketChat with Laravel 9.0+. Contents Installat

Team Nifty GmbH 25 Dec 1, 2022
Standalone PHP library for easy devices notifications push.

NotificationPusher Standalone PHP library for easy devices message notifications push. Feel free to contribute! Thanks. Contributors Cédric Dugat (Aut

Cédric Dugat 1.2k Jan 3, 2023
A PHP Library to easily send push notifications with the Pushwoosh REST Web Services.

php-pushwoosh A PHP Library to easily send push notifications with the Pushwoosh REST Web Services. First sample, creating a Pushwoosh message // Crea

gomoob 63 Sep 28, 2022
Push notifications Library for PHP

Push notifications Library for PHP Supported Protocols Protocol Supported Driver Options APNs (Token Based) ✓ APNs\Token APNs\Token\Option APNs (Certi

Norifumi SUNAOKA 3 Dec 14, 2022
Standalone PHP library for easy devices notifications push.

NotificationPusher Standalone PHP library for easy devices message notifications push. Feel free to contribute! Thanks. Contributors Cédric Dugat (Aut

Cédric Dugat 1.2k Jan 3, 2023
A very lightweight library to handle notifications the smart way.

NAMSHI | Notificator Notificator is a very simple and lightweight library to handle notifications the smart way. It took inspiration from other librar

Namshi 187 Nov 4, 2022
A Toast notification library for the Laravel TALL stack.

A Toast notification library for the Laravel TALL stack. You can push notifications from the backend or frontend to render customizable toasts with almost zero footprint on the published CSS/JS ????

John F 365 Jan 7, 2023
Bundle around the WebPush library

MinishlinkWebPushBundle This bundle provides a simple integration of the WebPush library. Usage Web Push sends notifications to endpoints which server

Louis Lagrange 35 Dec 22, 2022
:computer: Send notifications to your desktop directly from your PHP script

About JoliNotif JoliNotif is a cross-platform PHP library to display desktop notifications. It works on Linux, Windows or MacOS. Requires PHP >= 7.2 (

JoliCode 1.2k Dec 29, 2022
Takes care of Apple push notifications (APNS) in your PHP projects.

Notificato Notificato takes care of push notifications in your PHP projects. Italian: notificato è: participio passato English: notified Why use Notif

Mathijs Kadijk 223 Sep 28, 2022
Notifications in PHP (notify-send, growl, etc) like that.

#Nod Notifications in PHP (notify-send, growl, etc) like that. ##Examples Letting Nod figure out the best Adapter to use (not recommend ATM, only work

Filipe Dobreira 51 Mar 26, 2019
Bugsnag notifier for the Laravel PHP framework. Monitor and report Laravel errors.

The Bugsnag Notifier for Laravel gives you instant notification of errors and exceptions in your Laravel PHP applications. We support both Laravel and Lumen. Learn more about Laravel error reporting from Bugsnag.

Bugsnag 816 Dec 15, 2022