Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Jpush Notification Channel Laravel Package

medz/laravel-jpush-notification-channel

A Laravel notification channel for JPush (JiGuang Push). Send push notifications to Android, iOS, and other clients through Laravel's built-in notification system with a simple, fluent API and full support for JPush audience targeting and payload options.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire it up

composer require medz/laravel-jpush-notification-channel

Laravel 5.5+ auto-discovers the service provider, but on Lumen or with dont-discover you must register Medz\Laravel\Notifications\JPush\JPushServiceProvider in config/app.php (or bootstrap/app.php) and alias the channel if you plan to reference it by short name.

Publish the config and set credentials from the JPush console:

php artisan vendor:publish --provider="Medz\Laravel\Notifications\JPush\JPushServiceProvider"
JPUSH_APP_KEY=xxxxxxxxxxxxxxxxxxxxxxxx
JPUSH_MASTER_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx

Where to look first

  1. vendor/medz/laravel-jpush-notification-channel/src/ — confirm the exact namespace, channel class (JPushChannel), message class (JPushMessage), and whether the message proxies to the underlying jpush/jpush PushPayload. The public API has shifted across releases; read the source before copy-pasting docs.
  2. config/jpush.php — check whether it expects app_key/master_secret keys directly or an options array.
  3. Your User model — decide how you'll route. The channel resolves the audience via routeNotificationFor('jpush'), which calls routeNotificationForJpush() on the notifiable. Return a registration ID, an array of IDs, or an alias/tag.

First use: a single push

use Illuminate\Notifications\Notification;
use Medz\Laravel\Notifications\JPush\JPushChannel;
use Medz\Laravel\Notifications\JPush\JPushMessage;

class OrderShipped extends Notification
{
    public function via($notifiable)
    {
        return [JPushChannel::class]; // or 'jpush'
    }

    public function toJPush($notifiable)
    {
        return (new JPushMessage)
            ->setPlatform('all')
            ->setNotification([
                'alert'  => 'Your order has shipped',
                'android' => ['alert' => 'Your order has shipped', 'title' => 'Shipped'],
                'ios'     => ['alert' => 'Your order has shipped', 'sound' => 'default', 'badge' => 1],
            ])
            ->setExtras(['order_id' => 123]);
    }
}
$user->notify(new OrderShipped);

If the message class forwards unknown methods to the SDK payload builder, anything in the JPush REST API (setAudience, setOptions, setMessage, addTag, bigPushDuration, …) is reachable through the same fluent object.

Implementation Patterns

Route by alias for logged-in users, registration ID for logged-out ones. Storing a jpush_registration_id per device row is the most reliable route, but alias routing (routeNotificationForJpush() returning ['alias' => (string) $user->id] or the audience set directly on the message) survives app reinstalls and avoids stale IDs. Use registration IDs for targeted, ephemeral pushes (e.g. a chat message to the current device), aliases for user-scoped campaigns.

Multi-channel notifications. Combine the push channel with database/mail in via(). Guard the push so it doesn't fire for users who disabled push:

public function via($notifiable)
{
    return array_filter([
        $notifiable->push_enabled ? JPushChannel::class : null,
        'database',
    ]);
}

Queue the notification, not the channel. implements ShouldQueue on the notification is the right level — JPush calls are HTTP round-trips and the channel has no internal batching. Set tries/backoff and implement failed() for visibility, since the channel throws on API errors.

Platform-specific payloads. Build android and ios blocks explicitly rather than relying on alert alone; JPush's default behavior across platforms is inconsistent. For Chinese Android OEMs, set third_party_channel / vendor passthrough fields in the android block if you need delivery off the JPush long-connection channel.

Direct channel use outside notifications. For broadcast/admin tooling, resolve the channel from the container and call send() with a notifiable stub, or just use jpush/jpush directly. The channel is a thin adapter — for complex segmentation (addTag, addAllAudience, setSmsg), the underlying PushPayload is often clearer.

Testing. Notification::fake() asserts the notification was sent, not that JPush accepted it, which is what you normally want in tests. For channel-level tests, bind a fake client into the container (the service provider resolves JPush\Client — check the binding in source) and assert on setPlatform/setAudience calls. Never hit the real JPush API in CI.

Config-driven environments. Keep a jpush.php config that reads apns_production from an env var so staging can send to the iOS sandbox APNs while production sends to the real one. Default the message's setOptions(['apns_production' => config('jpush.apns_production')]) in a base notification class rather than per-notification.

Gotchas and Tips

  • Archived since 2019 — treat it as frozen. Pin an exact version in composer.json. It targets Laravel 5.5–6.x conventions; on Laravel 9+/10+ you'll likely hit method-signature and type-hint mismatches. For anything long-lived, fork it or skip the wrapper and inject jpush/jpush into a small custom channel — it's ~40 lines of code.
  • Config cache bites silently. After adding JPUSH_APP_KEY/JPUSH_MASTER_SECRET, run php artisan config:cache (and config:clear in dev). A cached empty config surfaces as an auth error from JPush, not a Laravel error.
  • Null audience = failed send. If routeNotificationForJpush() returns null or [] and the message has no explicit setAudience, you'll get a JPush validation error. Always set a fallback audience or short-circuit via().
  • Errors are exceptions, not return values. The SDK throws APIRequestException, APIConnectionException, and AuthenticationException. Catch them inside queued notifications and log the JPush error.code/error.message; otherwise a single bad registration ID fails the whole job. Registration IDs that are no longer valid come back in the response body under error, not as an exception — inspect the response if you care about cleanup.
  • iOS sandbox vs production is a per-request flag. In dev, set apns_production => false via setOptions(). Forgetting this on staging produces "push succeeded but never arrived" — the most common JPush debugging dead-end.
  • Android 8+ notification channels. Without an android.notification.channel_id matching a channel created client-side, notifications silently downgrade (no heads-up, no sound). Set it in the android payload block.
  • via() naming matters. 'jpush' (short name) requires the channel to be registered under that alias; JPushChannel::class always works. Pick one and be consistent — mixed usage causes "class not found" for the alias.
  • Don't reuse a JPushMessage instance. It's mutable and fluent; sharing one across notifications leaks payload settings between sends. Build a fresh instance in each toJPush().
  • Quotas and rate limits are invisible until you hit them. JPush's free tier caps daily pushes and per-app throughput; a runaway broadcast shows up as error.code 1000-series responses. Gate bulk sends behind an explicit admin action and log the response sendno/msg_id for reconciliation.
  • Auto-discovery and package metadata. If php artisan package:discover doesn't list the package, the extra.laravel.providers key is missing or your composer.json has a stale dont-discover entry. On Lumen, register the provider manually — discovery isn't supported there.
  • Debugging tip: dump the constructed payload ((array) $payload or the SDK's getPayload()) before the request when a push silently no-ops. Nine times out of ten the audience or apns_production flag is wrong, not the payload body.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator