tourze/wechat-mini-program-stats-bundle
A Symfony bundle that wires WeChat Mini Program statistics into your app, exposing the stats APIs through configurable services so you can pull usage and analytics data without boilerplate.
This is tourze/wechat-mini-program-stats-bundle at 0.0.1 — the first tagged release, so treat it as an unstable preview. The published release notes contain only a link to the commit list, meaning there is no documented feature set, no BC policy, and no migration guide. Your first job is discovery, not integration.
Practical order of operations:
composer require tourze/wechat-mini-program-stats-bundle:0.0.1 --prefer-source and inspect:
composer.json — check whether any illuminate/* or laravel/framework constraints exist. The -bundle suffix and the Tourze namespace strongly suggest a Symfony bundle, not a Laravel package.src/*Bundle.php and src/DependencyInjection/*Extension.php — if these exist, the package expects Symfony's kernel and will not be auto-discovered by Laravel.tourze/wechat-mini-program-bundle). The stats bundle is likely a thin layer over the datacube endpoints (getweanalysisappid*), so the access-token handling you actually care about lives in the dependency.If step 1 confirms there is no Laravel integration layer, decide immediately between (a) thin manual wiring of the underlying client in a service provider, or (b) dropping the package and calling the datacube HTTP endpoints directly. For a 0.0.1 with no changelog, (b) is a defensible choice.
Do not rely on container auto-wiring. With no service provider in the package, register the client yourself:
// app/Providers/WechatStatsServiceProvider.php
$this->app->singleton(MiniProgramStatsClient::class, function ($app) {
return new MiniProgramStatsClient(
appId: config('services.wechat_mini.app_id'),
secret: config('services.wechat_mini.secret'),
httpClient: $app->make(\GuzzleHttp\ClientInterface::class),
cache: $app->make(\Illuminate\Contracts\Cache\Repository::class),
);
});
Adjust constructor arguments to whatever the source actually declares — assume nothing.
Wrap the package behind your own contract. Because 0.0.1 can change shape in 0.0.2, define App\Contracts\MiniProgramStats with the two or three methods you need (dailySummary(), visitTrend(), retention()), implement it with an adapter that delegates to the package, and bind the interface. This costs an hour now and makes the next release a one-file change.
Schedule ingestion as a job, not a command body. A console command that dispatches one job per (appid, date) gives you retries, failed_jobs visibility, and RateLimited/WithoutOverlapping middleware for free:
Schedule::command('wechat:stats:pull')->dailyAt('08:30');
WeChat datacube data lands the following morning; scheduling before ~08:00 local often returns empty results for "yesterday."
Persist raw payloads alongside normalized rows. Keep a wechat_stats_raw table (appid, endpoint, date, payload JSON, fetched_at) plus your typed tables. When a metric turns out to mean something different than you assumed, you can re-derive without re-hitting a rate-limited API, and you get an audit trail.
Multi-tenant by appid. If you run more than one mini program, everything — token cache key, config, raw payload rows, models — must be keyed by appid. WeChat issues one access token per appid and invalidating it is a global side effect for that app.
Backfill deliberately. Datacube endpoints typically cap how far back you can query (commonly 30 days for several metrics). Write the backfill command with an explicit --from floor rather than --all, and log skipped dates.
"tourze/wechat-mini-program-stats-bundle": "0.0.1" — not ^0.0.1. In 0.x, ^0.0.1 still allows patch bumps with potential signature changes, and there is no changelog to diff against.Bundle class, php artisan package:discover will not find it and no config will be published. Expect to hand-write config and bindings.#[ORM\Entity] annotations on the package's models, you cannot reuse them as Eloquent models — either install Doctrine alongside (usually not worth it) or write a mapper into your own tables. There will be no Laravel migrations for the package's schema.{"errcode": 40013, "errmsg": "invalid appid"} with a 200 status. Any adapter must inspect and throw on non-zero errcode, otherwise your nightly job silently writes empty rows.src/.HttpClientInterface constructor argument (swap in a client with logging/retry middleware), an injectable cache or token provider (required to make token caching sane in Laravel), and any interface the stats client implements (decorate it rather than forking the package).Log::debug() around every call including the request URI and redacted payload — with no docs, production debugging depends entirely on what you logged. Never log the access token or secret.How can I help you explore Laravel packages today?