tourze/wechat-official-account-mass-bundle
A Symfony bundle for sending mass messages through WeChat Official Accounts, wrapping the WeChat mass-send API in configurable services so you can broadcast news, text, images, and other content to subscribers from your application. It integrates with the Tourze bundle ecosystem and helps keep messa...
tourze/wechat-official-account-mass-bundle is a Symfony bundle (not a Laravel package) that wraps the WeChat Official Account 群发消息 (mass-send) endpoints — /cgi-bin/message/mass/sendall, /mass/send, /mass/preview, /mass/get, /mass/delete. Version 0.0.1 is the initial public tag, and the only release note is a link to the commit range, so treat this as pre-alpha: read the source before trusting any method signature.
First steps:
composer require tourze/wechat-official-account-mass-bundle:0.0.1 — pin the exact version, there is no stability guarantee at 0.0.x.src/ (usually *Bundle.php), the service class that actually issues HTTP calls, and config/services.yaml (or config/*.php). The service definition file tells you what arguments the mass-send service needs — that is your integration surface.config/services.php + .env, and add your server's egress IP to the WeChat 后台 IP whitelist — mass-send calls fail with 40164 otherwise.Your first use case should be a preview send, not a real send: /mass/preview targets a single OpenID, is not rate-limited like a broadcast, and is the only safe way to verify payload shape, media IDs, and error handling end-to-end.
Wiring a Symfony bundle into Laravel. There is no package auto-discovery for this. Register the bundle's services yourself in a dedicated provider, mapping the bundle's constructor arguments to Laravel config:
$this->app->singleton(\Tourze\WechatOfficialAccountMassBundle\Service\MassMessageService::class, function ($app) {
return new \Tourze\WechatOfficialAccountMassBundle\Service\MassMessageService(
$app->make(\Tourze\WechatKernel\AccessTokenProvider::class),
// ...remaining constructor args per config/services.yaml
);
});
Prefer manual singleton bindings over trying to boot the Symfony kernel — most Tourze bundles have few services and no compiler passes you need.
Preview → send → poll. The documented happy path is three distinct calls, and your code should mirror it:
media_id vs mediaId that WeChat reports as an opaque 40007.sendall (by tag or all subscribers) or send (by OpenID list, max 100 per call).msg_id and poll /mass/get — the send call returns before delivery completes.Queue everything. Mass sends are slow and quota-metered. Wrap the call in a queued job with $tries = 1 and a manual-review failure path. Never let a generic retry policy sit in front of a broadcast endpoint.
Targeting. Prefer sendall with filter: {is_to_all: false, tag_id: N} for segment sends over maintaining OpenID lists — it keeps your payload small and avoids the 100-recipient cap on /mass/send. Cache tag IDs in config; they're stable and rarely change.
Media is a separate concern. media_id values for image/voice/video/mpnews come from the upload endpoints, which likely live in a sibling bundle. Upload once, store the media_id alongside the asset, reuse it — WeChat media for mass-send is valid for 3 days, so expire your cache accordingly.
Testing. Inject a fake HTTP client (Symfony MockHttpClient or a Laravel Http::fake() adapter behind your own thin wrapper) and assert the exact JSON body. There is no sandbox for mass send, so payload assertions are your only regression net.
0.0.1 with a changelog-only release note. The tag tells you nothing about API stability. Diff the commits before every bump, and pin 0.0.1 exactly in composer.json.Extension/Configuration classes), and event dispatching are all Symfony conventions. Do not expect config/mass-message.php to be published — there is nothing to publish./mass/send does not mean the send failed. Check /mass/get for the msg_id before considering a re-send, or you will double-bill your monthly quota.45009 (rate limit), 45028 (no quota left), 48001 (API unauthorized for this account type) all require human intervention — map them to distinct exceptions and alert, don't retry.40001 failures under load./mass/delete recalls; it does not edit. Model any "edit and resend" flow as a new send with new quota consumption.errcode even on HTTP 200. WeChat returns 200 OK with {"errcode": 40003, "errmsg": "invalid openid"}. Wrap the service response in a normalizer that throws on non-zero errcode — the bundle may or may not do this for you, verify it explicitly.0.0.2 lands.How can I help you explore Laravel packages today?