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 Auth Bundle Laravel Package

tourze/wechat-mini-program-auth-bundle

A Symfony bundle for integrating WeChat mini program authentication into PHP applications. It wires up the services and configuration needed to handle mini program login flows, so your app can resolve user sessions from WeChat credentials with minimal boilerplate. Suitable for projects already using...

View on GitHub
Deep Wiki
Context7

Getting Started

This bundle wraps the WeChat Mini Program session handshake: you hand it the code returned by wx.login() on the client, and it performs the server-side jscode2session exchange against api.weixin.qq.com, returning openid, session_key, and (when the app is bound to an Open Platform account) unionid — plus normalised error handling for WeChat's errcode responses.

Minimal path:

  1. composer require tourze/wechat-mini-program-auth-bundle. Pin deliberately — this release is 1.0.2 → 2.0.0, a major bump. Read the diff at the changelog link before you let Composer resolve ^2.0, and don't let a composer update silently cross the boundary.
  2. Configure credentials and add them to .env: the Mini Program AppID and AppSecret. These are a different credential set from your 公众号 (Official Account) and from your Open Platform component_appid — mixing them is the most common first-day failure.
  3. The Tourze ecosystem publishes Symfony bundles. Under Laravel you either use the matching Tourze Laravel adapter package for the same version line, or register the bundle's services manually in a ServiceProvider (bind the session/auth service as a singleton, pull config from config/services.php). Confirm which route you're on before writing application code against it — the adapter versions must move in lockstep with the bundle.
  4. First use case: a POST /api/auth/wechat route that accepts { "code": "..." }, calls the exchange service, upserts a User keyed on openid, and issues your token (Sanctum or Passport). The bundle authenticates against WeChat; it does not issue your application session.

Test with a real Mini Program dev/preview build. WeChat will not give you a valid code from curl, Postman, or a unit test — stub the HTTP client for tests and keep one manual smoke test on a device.

Implementation Patterns

Thin controller, service behind an interface. Resolve the bundle's session/auth service via constructor injection rather than app() lookups, so you can swap it for a fake in feature tests. Keep the controller to: validate code → call service → map result to your User → return token.

Separate the three identities. Store openid (per Mini Program), unionid (cross-app, may be absent), and session_key (ephemeral, rotates on every login) in distinct columns. openid is your lookup key; unionid is your cross-product link; session_key is a decryption secret, never an identity.

Session key is a decryptor, not a session. If you use wx.getUserProfile-era flows or encrypted payloads (phone number, some user info), you need the session_key to AES-decrypt the encryptedData/iv pair the client sends. Store it server-side with a short TTL (Redis, ~ the life of the login), keyed by openid, and overwrite on each fresh login.

Cache the exchange, not the result. code is single-use with a ~5 minute lifetime. If two requests race with the same code, the second gets an error. Treat the exchange as a one-shot and make the client retry with a fresh wx.login() on failure, not the same code.

Bind to your user model via a dedicated resolver. Put the "find-or-create user by openid/unionid" logic in one place (an action class or a WechatUserResolver) and let both the login endpoint and any webhook/decrypt flow call it. This is the piece most likely to need changing when you add a second Mini Program or move to unionid-based accounts.

Cross-check the code with your own token issuance. After a successful exchange, issue a Sanctum token scoped to the user and set the token expiry to something sensible. Do not persist session_key inside the token payload.

Queue-tolerant design. If you're calling the exchange from a queued job (e.g. an import or a batch re-auth), remember the code will be dead by the time the job runs — pass the code through synchronously, only the post-auth work should be queued.

Gotchas and Tips

The 2.0.0 release notes are a bare compare link. There is no summary of breaking changes, deprecations, or new features in the published notes. Before upgrading, actually open compare/1.0.2...2.0.0 and diff: look for constructor signature changes on the exchange service, renamed config keys, a bumped minimum PHP version, and any change to the returned DTO shape (array → object, or openid key renames). A major version on this package almost certainly touches at least the service API surface; assume nothing.

Credential scope. errcode 40013 (invalid appid) and 40125 (invalid appsecret) usually mean the credentials belong to a different app type. 40029 is an invalid/expired code, 45011 is rate limiting (the per-appid call ceiling — back off), and 40226 means the Mini Program account is restricted. Map these to distinct exceptions in your own code rather than surfacing raw WeChat messages, and never echo errmsg back to the client verbatim.

Do not log the secret or the session_key. Both routinely end up in exception traces. Scrub them in your logging config and redact the js_code/session_key fields before shipping to a log aggregator.

Symfony-in-Laravel friction is the real cost. Config loading, container aliasing, and event dispatching differ between the two. If the Laravel adapter for this version doesn't exist or lags, you'll be re-implementing bootstrapping. Check composer why output and confirm the adapter's composer.json allows the 2.0 constraint — dependency conflicts here are common and easy to misread as a bundle bug.

Error shapes may differ across the 2.0 boundary. If 1.x returned null or an array on failure and 2.x throws a typed exception (or vice versa), every if ($result) guard in your code is now either dead or a fatal. Grep your call sites before upgrading.

Time-outs and DNS. api.weixin.qq.com latency from non-CN regions is real and spiky. Set an explicit connect/read timeout (2–3s) and a retry-with-backoff on 45011/5xx only — never retry a 40029.

Mock the HTTP boundary, not the service, in tests. Stub the underlying HTTP client (Guzzle / Laravel Http::fake) with recorded WeChat responses for success, 40029, and 45011. That keeps your tests valid across 1.x→2.x service refactors.

Extension points to prefer. Custom UserProvider / resolver, event listener on login success, and a configurable token issuer. If the package doesn't expose one of these, wrap it rather than forking — the 2.0.0 jump shows the maintainers are willing to break things at the API level.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle