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 Work Security Bundle Laravel Package

tourze/wechat-work-security-bundle

A Symfony bundle that integrates WeChat Work (企业微信) security features into your PHP application, handling message encryption and decryption, signature verification, and callback validation so you can safely receive and respond to WeChat Work events without writing the cryptography yourself.

View on GitHub
Deep Wiki
Context7

Getting Started

What this is. tourze/wechat-work-security-bundle is a Tourze-published package that wires WeChat Work (企业微信 / WeCom) authentication and security helpers into a PHP application. The -bundle suffix and the Tourze namespace convention indicate a Symfony bundle, not a native Laravel package — this matters a lot for how you consume it (see Gotchas).

Version 0.0.1 reality check. This is the first tagged release. The only release artifact is a changelog link with no described features, fixes, or upgrade notes. Treat the public API as unstable: expect namespace moves, constructor signature changes, and config key renames in 0.x. Pin the exact version ("tourze/wechat-work-security-bundle": "0.0.1") and read the source before relying on it.

Minimal steps.

  1. composer require tourze/wechat-work-security-bundle:0.0.1
  2. Start by reading composer.json (declared dependencies tell you whether it expects symfony/security-bundle, symfony/http-client, etc.) and then src/. In a Tourze bundle the two files that answer 90% of your questions are:
    • src/DependencyInjection/*Extension.php — the real config schema (service ids, env var names, defaults).
    • src/DependencyInjection/*Bundle.php / *Pass.php — what gets auto-registered and any compiler passes.
  3. Register the bundle in config/bundles.php if you are in Symfony, or, in Laravel, pull the underlying service classes manually (see Gotchas).
  4. Collect credentials: Corp ID (corp_id), the app's Secret (corp_secret / agent secret), and the Agent ID for the self-built app you are authenticating against.

First use case. The highest-value thing this class of package gives you is: given a WeChat Work OAuth code, resolve the employee's userid and profile. That is the single flow to get working first — a controller route that receives ?code=... from the WeChat Work authorization redirect, exchanges it, and hands you a stable employee identifier you can map to a local user row. Everything else (signature verification, JS-SDK tickets, department sync) is additive.

Implementation Patterns

Config-first, hardcoded-never. Register credentials through the bundle's extension config (or the equivalent Laravel config/services.php entry if you are wiring services by hand) reading from env: WECHAT_WORK_CORP_ID, WECHAT_WORK_CORP_SECRET, WECHAT_WORK_AGENT_ID. Never inline the secret — WeCom secrets leak via committed .env.example files constantly, and a leaked corp secret grants full API access to the corp's contacts.

OAuth login flow. The canonical shape:

/oauth/start    -> redirect to https://open.weixin.qq.com/connect/oauth2/authorize
                   ?appid=CORP_ID&redirect_uri=<encoded callback>&response_type=code
                   &scope=snsapi_base&state=<csrf nonce>#wechat_redirect
/oauth/callback -> validate `state` against the session nonce
                   exchange `code` -> access_token + userid
                   map userid -> local user, log in, redirect

Use snsapi_base (silent, returns userid only) for normal logins and snsapi_privateinfo only when you actually need avatar/mobile/email — the broader scope prompts the user and requires the app to have those permissions granted in the admin console.

Map userid to your own identity. Do not let the WeCom userid become your primary key or your users.email. Store it in a nullable, unique, indexed column (wecom_user_id) and resolve/create a local user from it. Employees leave, get renamed, and move departments; the external identifier should be an attribute, not the identity.

Wrap it in a service, not in controllers. Inject the package's client/exchange service into a thin WeComAuthenticator of your own. This is the single most useful pattern with a 0.0.1 dependency: when the upstream class is renamed in 0.0.2, you change one file instead of grepping controllers.

Cache access tokens centrally. WeCom access_token is corp-wide and rate-limited, and fetching it per-request will get you throttled. Cache it (Laravel Cache::remember, expiry ~7000s) under a single key, and use a lock around the refresh to avoid a thundering herd on cold cache.

Test with fakes. Point the HTTP client at a stub (Symfony MockHttpClient, or Laravel Http::fake() if you bypass the bundle's transport) returning a canned token/userinfo payload. Because docs are absent at 0.0.1, write a contract test asserting the exact JSON keys you depend on — it doubles as your upgrade canary.

Callback/message signature verification. If you also use this for the callback URL (event push, trusted-domain checks), verify signature before parsing the body, and make the route CSRF-exempt but signature-checked. Keep the verification in middleware so no future controller can forget it.

Gotchas and Tips

  • Symfony bundle ≠ Laravel package. There is no service provider or facade here. In Laravel you either (a) install symfony/security-bundle and hand-register the bundle in a minimal kernel — usually not worth it — or (b) bypass the bundle wiring and instantiate the few concrete client/service classes yourself in a small Laravel service provider. Option (b) is almost always the pragmatic choice, but it means the bundle's DI config is not your config, so read the extension class to learn the real constructor arguments.
  • 0.0.1 means no BC promise. Composer's default ^0.0.1 constraint resolves to <0.0.2, so you are safe by accident, but do not loosen it to ^0.1 or * without reading the diff. Vendor the class names you depend on into your own adapter.
  • Absent documentation is the main cost. There is no README-described config reference in the release notes. Budget an hour to read src/DependencyInjection/; that file is the documentation. If the extension has no Configuration tree, assume env vars are read directly with $_ENV/getenv and grep for them.
  • Trusted-domain / IP allowlist failures are silent-ish. WeCom web pages fail to render the JS-SDK when the current domain is not registered as a trusted domain in the admin console, and API calls fail with errcode 60020 (IP not in whitelist) if your server egress IP is not added. Both are console configuration, not code — check them before debugging the bundle.
  • Distinguish error shapes. WeCom returns HTTP 200 with a nonzero errcode on failure. Any client that only checks the HTTP status will treat a failed token exchange as success. Assert explicitly on errcode == 0 in your adapter, and log errcode + errmsg (never the secret or the raw token).
  • Token and ticket invalidation. WeCom can invalidate access_token early (e.g. secret rotation). Handle errcode 40001/42001 by clearing the cache and retrying exactly once — a retry loop without cache invalidation just burns rate limit.
  • Clock and encoding. Signature/nonce/timestamp verification is time-sensitive; ensure the host is NTP-synced. Also, WeCom payloads are UTF-8 with Chinese display names — verify your DB columns and json_encode flags (JSON_UNESCAPED_UNICODE) don't mangle them.
  • Extension points to watch. The bundle's compiler passes and any *Interface in src/ are your upgrade-stable seams. Prefer implementing/decorating those interfaces over subclassing concrete classes; Tourze packages frequently swap concrete implementations between patch releases.
  • Upgrade protocol for now. With no release notes beyond a changelog link, treat each 0.0.x bump as a review-required change: read git diff between tags, run your contract test, and check the DI extension for renamed config keys before deploying.
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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route