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 Group Chat Bundle Laravel Package

tourze/wechat-work-group-chat-bundle

Symfony bundle from Tourze that adds WeChat Work (企业微信) group chat support to PHP applications. It streamlines configuring and integrating enterprise group messaging so you can wire chat features into your service with minimal boilerplate, following standard bundle conventions.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Pin the version explicitly when requiring the package: composer require tourze/wechat-work-group-chat-bundle:0.0.1. At 0.0.1 there is no stability guarantee and Composer's default constraint resolution is not something you want deciding your API surface for you.
  • Before writing any code, read the repository root. Expect the Tourze conventions: a *Bundle.php class, a DependencyInjection/ directory with an extension and possibly compiler passes, Entity/ or Model/ classes, Attribute/ or Annotation/ markers, and a README.md that is usually thinner than the code. The composer.json require block is your fastest signal for what HTTP client and SDK layer it sits on top of.
  • Treat this as a Symfony bundle first, Laravel package second. There is no WechatWorkGroupChatServiceProvider and no publishable config. Your first task is not calling the API — it is deciding how to boot a Symfony-style bundle inside Laravel's container. In practice that means instantiating the bundle's service classes manually in a app/Providers/WechatWorkServiceProvider.php, or accepting the cost of pulling in symfony/dependency-injection and booting a minimal container just for this bundle.
  • First concrete use case: pull the customer group chat list for one corp and dump it to a command. Build php artisan wecom:group-chats that resolves the client, calls the list endpoint with the corp's access token, and dd()s the first page. That single command tells you whether the bundle handles token acquisition for you or expects you to inject it — the answer changes everything downstream.
// app/Providers/WechatWorkServiceProvider.php
public function register(): void
{
    $this->app->singleton(GroupChatClient::class, fn ($app) => new GroupChatClient(
        corpId: config('services.wecom.corp_id'),
        secret: config('services.wecom.group_chat_secret'),
        httpClient: $app->make(\Symfony\Contracts\HttpClient\HttpClientInterface::class),
    ));
}

Note the HttpClientInterface — Tourze bundles almost always type-hint Symfony contracts rather than PSR-18, so you will likely need symfony/http-client bound in the container even inside a Laravel app.

Implementation Patterns

  • Isolate the bundle behind your own adapter. Wrap the bundle's client in an App\Services\Wecom\GroupChatRepository that exposes plain arrays or your own DTOs. This is the only reliable way to survive a 0.0.1 → 0.0.2 bump, and it keeps Symfony types out of your controllers and jobs.
  • Config in config/services.php, not env calls. Read WECOM_CORP_ID, WECOM_GROUP_CHAT_SECRET, and any agent ID from config so config:cache works. Never call env() from inside a service class.
  • Access tokens are the real integration. WeChat Work tokens are per-corp (and per-agent for some endpoints) with a ~7200s TTL and a hard limit on acquisition frequency. Cache them with Cache::remember('wecom:token:'.$corpId, 7000, ...) and use a lock (Cache::lock) around the fetch so ten concurrent queue workers don't all hit the token endpoint and invalidate each other.
  • Sync on a schedule, not on request. Group chat lists and chat statistics are slow and rate-limited. Put the calls in a queued job triggered by Schedule::command(...)->hourly() and persist results to your own tables. Your UI then reads local rows and stays fast.
  • Chunk and paginate explicitly. Group chat list endpoints page by cursor/offset with small page sizes. Write the loop once in the repository with a max-page guard so a misbehaving API can't spin your worker forever:
$cursor = null;
do {
    $page = $this->client->listGroupChats($cursor, limit: 100);
    $this->upsert($page->items());
    $cursor = $page->nextCursor();
} while ($cursor && ++$i < 200);
  • Events for downstream concerns. Fire GroupChatSynced / GroupChatMemberJoined from your adapter, not from inside bundle callbacks. Symfony EventDispatcher hooks the bundle may expose won't be wired to Laravel's dispatcher automatically — bridge them explicitly if you need them.
  • Errors as a domain concern. WeChat Work returns HTTP 200 with a non-zero errcode. Depending on how thin the bundle is, it may or may not convert that into an exception. Wrap every call in a try/catch that inspects errcode and maps the common ones (40001 invalid secret, 42001 token expired, 45009 rate limit exceeded) before they reach your job's retry logic — otherwise 42001 retries forever instead of refreshing the token.

Gotchas and Tips

  • There are no release notes. The entire changelog for 0.0.1 is a link to a commit list. That means: no documented feature set, no migration guide, and no signal about what 0.0.2 will break. Budget an hour to read src/ end to end before committing to the dependency, and vendor-lock the version in composer.json with an exact constraint.
  • Symfony compiler passes do not run in Laravel. If the bundle uses a compiler pass to tag services, inject collections, or register handlers, none of that happens under Laravel's container. Look in DependencyInjection/ for CompilerPass classes early — they are the most common source of "it works in the bundle's tests but not in my app."
  • Two secrets, easily confused. WeChat Work has a corp secret and per-app (agent) secrets. Group chat / customer group endpoints generally want the external contact secret, not your internal app's. Symptom of getting it wrong: errcode 40001 or an empty list with no error.
  • Rate limits are per-corp and unforgiving. 45009 means you've exceeded the daily or per-minute quota; 45033 is concurrent-call throttling. If you fan out sync jobs per chat, serialize them or cap concurrency in the queue worker — parallelizing this API is how you get a 24-hour ban.
  • HTTP client wiring is the usual first failure. A BindingResolutionException for HttpClientInterface or LoggerInterface means the bundle expects Symfony's container defaults. Bind Symfony\Contracts\HttpClient\HttpClientInterface to Symfony\Component\HttpClient\HttpClient::create() (or a scoped PSR-18 adapter) in your service provider.
  • Extension points to look for when the bundle gets in your way: an interface for the token provider (swap in your cached one), an interface for the HTTP transport (swap in one with logging and retry middleware), and any Attribute-based mapping classes for response hydration. Overriding the token provider is usually the highest-value customization, since token handling is where 0.0.1-grade packages are most often naive.
  • Log request IDs. WeChat Work support asks for errmsg plus the request timestamp. Add a middleware or a small decorator on the transport that logs method, errcode, and errmsg at debug level; without it, debugging errcode 40003 (invalid openid/userid) in production is guesswork.
  • Do not depend on this for anything on the request path. At 0.0.1, treat it as a scaffold for the API calls and own the retry, caching, and persistence layers yourself.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package