larva/laravel-wechat-notification-channel
A Laravel notification channel for sending notifications through WeChat. It integrates WeChat messaging into Laravel’s notification system, letting you deliver template or service messages to users alongside mail, SMS, and other channels.
The package plugs into Laravel's notification system as a wechat channel, typically routing through a WeChatChannel class that resolves a Laravel Socialite-style user identifier (usually openid) from your notifiable model and delegates outbound calls to EasyWeChat (overtrue/wechat) under the hood.
Minimal setup:
composer require larva/laravel-wechat-notification-channel.config/wechat.php (or config/services.wechat), with keys like app_id, secret, token, aes_key. If you already run EasyWeChat in the app, point the channel at the same app config to avoid duplicate auth flows.openid column or a routeNotificationForWeChat() method returning the WeChat openid.'wechat' to via() and implement toWeChat($notifiable).A working first notification:
public function via($notifiable) { return ['wechat']; }
public function toWeChat($notifiable) {
return (new WeChatTemplateMessage())
->template('ORDER_SHIPPED')
->url('https://shop.example/orders/'.$this->order->id)
->data([
'first' => '您的订单已发货',
'keyword1' => $this->order->number,
'keyword2' => $this->order->shipped_at->toDateTimeString(),
'remark' => '感谢您的购买',
]);
}
Look first at the package's src/Channel/ and src/Message/ directories — the message builder classes define exactly which template fields are supported, and that's where you'll spend most of your integration time.
Template-message dispatch is the dominant workflow. Almost everything you ship with this channel will be an official-account template message or a mini-program subscribe message. Structure your notifications around one template ID per notification class; don't try to multiplex multiple templates inside a single toWeChat() — the field mapping (first, keyword1..n, remark) is fixed per approved template in the WeChat console and gets brittle fast.
Keep the WeChat payload in the message object, not the notification. Build a small helper (e.g., an enum of template IDs constant class) and pass values through ->data(). This lets you unit-test the payload shape without touching EasyWeChat.
Batch or queued dispatch. WeChat's API is slow and rate-limited; always implement ShouldQueue on notifications that fan out to many users, and use Laravel's queue middleware (RateLimited) keyed on openid if you're sending bursts. The channel itself does not throttle — you own that.
Multi-app routing. If you have public accounts (服务号) plus mini programs plus 企业微信, register separate EasyWeChat app instances and inject the right one via constructor into your notification or a channel subclass. A common pattern is a WeChatChannel bound in a service provider per tenant/app, differentiated by config key.
Testing pattern. Swap the underlying EasyWeChat client with a fake in your test suite ($this->mock(...) or EasyWeChat's own test fakes) and assert on template_id and data fields. Since the channel is thin, most bugs surface at the payload layer, not the transport, so make that layer loudly testable.
Integration with Notification::route(). For one-off sends to a raw openid (without a model), use Notification::route('wechat', $openid)->notify(...) and make sure routeNotificationForWeChat() in your notifiable returns a scalar, not an array — the channel generally expects a single identifier.
overtrue/wechat moves fast and has had breaking major versions), and be prepared to fork if EasyWeChat bumps break compatibility.errcode in the response body rather than an exception. Add a channel-level wrapper that throws on non-zero errcode and logs the failing template + payload, otherwise failed notifications just vanish.access_token caching: EasyWeChat caches tokens, but in multi-server or ephemeral (serverless) deployments the cache store must be shared (Redis), or you'll hit WeChat's token-invalidation and 40001 errors intermittently. Set a stable cache driver in the EasyWeChat config.Notification::extend() or by overriding the wechat channel in the container.app_id/secret must match the official account (服务号) app, not the mini-program or open-platform app, when sending template messages. A very common 40013 (invalid appid) error comes from mixing these up.errmsg field is the only place WeChat tells you what's wrong with the payload.How can I help you explore Laravel packages today?