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

Wechat Mini Program Bundle Laravel Package

tourze/wechat-mini-program-bundle

A PHP bundle that simplifies integrating WeChat Mini Program capabilities into backend applications. It provides service configuration and API wiring for mini program authentication, messaging, and related workflows, reducing boilerplate for developers building WeChat Mini Program-connected PHP serv...

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — that is the single most important thing to know before you install it. There is no ServiceProvider, no Facade, no php artisan vendor:publish. It ships a *Bundle class and a DependencyInjection/ extension intended to be registered in config/bundles.php of a Symfony app. In Laravel you will be wiring its services into the container by hand.

Confirm the baseline first:

composer show tourze/wechat-mini-program-bundle --all   # check PHP/Symfony constraints

2.0.0 is a major bump from 1.0.1 with an empty release body (just an auto-generated compare link), so treat namespaces, service IDs, and the configuration tree as unknown until you read them. Before writing any code:

  1. vendor/tourze/wechat-mini-program-bundle/src/ — find the bundle class and list the concrete API/service classes. These are what you will actually consume.
  2. src/DependencyInjection/Configuration.php — this is the authoritative list of config keys and their defaults. It is your replacement for a config/wechat.php stub.
  3. src/Resources/config/*.yaml (or PHP service definitions) — service IDs, constructor arguments, and which HTTP client is expected (symfony/http-client or PSR-18).
  4. composer.json of the package itself — note whether it pulls tourze/wechat-mini-program as the underlying SDK. If it does, you can often depend on that core library directly and skip the bundle wiring entirely.

First use case: the mini-program login handshake. wx.login() on the client yields a short-lived code; your server exchanges it via code2Session for openid + session_key. That single call is 90% of what most teams need on day one. Get that working through a thin adapter class, then add subscribe messages / QR codes / content-security checks on top.

Implementation Patterns

Bridge the bundle into Laravel explicitly. Register the underlying client as a singleton in AppServiceProvider, reading credentials from config/services.php:

$this->app->singleton(WeChatMiniProgramClient::class, fn () => new WeChatMiniProgramClient(
    appId: config('services.wechat_mp.app_id'),
    secret: config('services.wechat_mp.secret'),
));

Never new the client at the call site — the access-token cache and HTTP client must be shared.

Wrap it, don't sprinkle it. Put every call behind your own MiniProgramService with methods named for your domain (loginWithCode, sendSubscribeMessage, generateUnlimitedQr). A 1.0 → 2.0 major bump with no documented migration is exactly the scenario where leaking vendor class names into 30 controllers becomes a week of work. The wrapper is your upgrade seam.

Login → token issuance. The canonical flow:

$session = $this->miniProgram->code2Session($code);        // openid, session_key, unionid
$user = User::firstOrCreate(['openid' => $session->openid]);
Cache::put("wx:sk:{$user->id}", $session->session_key, now()->addDays(7));
return ['token' => $user->createToken('mp')->plainTextToken];

Persist session_key server-side only, in the cache, keyed per user. It is a symmetric key used to decrypt encryptedData / getPhoneNumber payloads — it must never reach the client.

Push anything network-bound to a queue. Subscribe messages, msgSecCheck, and QR generation are all remote calls with multi-second tails. Dispatch a job, use $tries = 3 with backoff(), and rely on Laravel's failed_jobs for the WeChat error code payload.

Test by faking HTTP, not by mocking the bundle. Since the bundle delegates to an HTTP client, Http::fake(['api.weixin.qq.com/*' => Http::response([...])]) gives you far more upgrade-resilient tests than mocking vendor classes whose names may change between majors.

Adapter per environment. Point at a local stub in local so a dev without WeChat credentials can still run the login flow; only production should hit api.weixin.qq.com.

Gotchas and Tips

  • 2.0.0 shipped with no notes. Do not blindly run composer update. Diff the tree between tags (git diff 1.0.1 2.0.0 -- src/ in the package repo, or diff vendor/ before and after) and pin ^2.0 only after the login flow passes. Assume renamed namespaces and changed service IDs until proven otherwise.
  • config:cache and secrets. Symfony-style bundles often read from a container parameter bag; Laravel's config() is a different mechanism entirely. Keep credentials in env() via config/services.php and verify with php artisan config:cache && php artisan tinker — a cached config is a very common "works locally, dead in prod" cause.
  • Access token is a global, rate-limited singleton. WeChat issues one access_token per app with ~2000 fetches/day. Cache it centrally with a TTL slightly shorter than the returned expires_in, and wrap in Cache::lock() — concurrent web workers otherwise burn the quota and get everyone throttled.
  • Token errors need refresh-and-retry, once. 40001, 42001, 40014 mean the cached token is stale or was invalidated by another process. Intercept these, flush the cache, retry exactly once. Retrying in a loop makes it worse.
  • session_key rotates. Every fresh wx.login() invalidates the prior key. Decryption failures are usually a stale key or a user who logged in on a second device — re-prompt rather than debugging crypto.
  • -1 / 45009 are not your bug. -1 is "system busy, try later" (retry with backoff); 45009 is API quota exhaustion. Log the raw errcode/errmsg — the bundle may normalize errors into exceptions and lose the code.
  • Request domains must be whitelisted in the MP admin console. Server-side calls are fine, but anything client-visible (download/upload domains, socket domains) fails silently in production if unlisted. This bites every team exactly once.
  • Extension point is the container, not the source. Bind an interface to your own implementation, or decorate the bundle's service, rather than editing vendor/. Composer will erase your edits on the next deploy.
  • Watch for a session_key-in-logs leak. Framework-neutral bundles often don't mark these values sensitive; Laravel's exception handler will happily serialize them into laravel.log. Sanitize at your wrapper boundary before you log the session object.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect