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

tourze/wechat-mini-program-express-bundle

A Symfony bundle that integrates WeChat Mini Program express delivery features into your PHP application, providing ready-made services and configuration for WeChat logistics APIs, order and shipping workflows, and faster setup of mini program delivery functionality.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is tourze/wechat-mini-program-express-bundle (0.1.0, previously 0.0.2). Name and versioning tell you most of what you need before you install it:

  • express → WeChat Mini Program 物流/发货 APIs: querying delivery companies, uploading shipping info for an order, and receiving logistics state callbacks.
  • bundle → this is a Symfony Bundle, not a Laravel package. There is no ServiceProvider, no config/*.php, and Composer auto-discovery will not register anything. Confirm by checking "type": "symfony-bundle" and a DependencyInjection/*Extension.php in composer.json/src.

Minimal steps

  1. composer require tourze/wechat-mini-program-express-bundle:0.1.0 — pin the exact version while it is pre-1.0.
  2. Register the bundle in config/bundles.php only if you are in a Symfony app. For a Laravel app, see the Gotchas section before going further — this is likely a dealbreaker.
  3. Find the configuration tree first: read src/DependencyInjection/Configuration.php and *Extension.php. That file is the authoritative list of what you must supply (app id, app secret, and typically certificate paths for sensitive endpoints).
  4. Then look at the service classes under src/Service/ (or src/Api/) — that is where the actual WeChat HTTP calls live, and where the request/response shape is defined.

First use case to validate the package against: fetch the list of delivery companies (delivery_list / getAllDelivery), then call the shipping-info upload for one test order. If those two calls work end-to-end, the package is doing its job; if you find yourself writing raw HTTP anyway, stop and use the underlying WeChat SDK directly.

Implementation Patterns

Wrap, don't call from controllers. The bundle gives you a service; inject it into one application-level class (e.g. App\Services\Shipping\WechatExpress) that speaks your domain language (markShipped(Order $order, string $trackingNo, string $companyCode)). Everything downstream — queueing, retries, logging, idempotency — then lives in one place instead of being sprinkled across controllers.

Persist the tracking mapping yourself. Do not let a third-party bundle own your order state. Store company_code, tracking_no, and an upload status on your own model, and keep the bundle's response as a reference blob (raw JSON column) for debugging.

Queue the upload. WeChat API latency is variable and the call is a network dependency in your fulfilment flow. Dispatch a job after the "shipped" state transition, with a small backoff, and make the job idempotent by guarding on your own uploaded_at / upload_status column rather than trusting the remote call.

Handle the callback path explicitly. Express state changes arrive as a push notification. Route it to a controller that (a) verifies the signature, (b) acknowledges fast with the expected success body, and (c) pushes the actual processing onto a queue. WeChat will retry aggressively if you return anything else, so an unhandled exception in that controller turns into duplicate callbacks.

Test with a mocked HTTP client, not the real API. If the bundle is built on Symfony HttpClient (check the constructor signature of the service), MockHttpClient lets you assert the request payload without a Mini Program account. Build fixtures for success, errcode != 0, and timeout.

Configuration via env, not YAML literals. Certificates and secrets belong in .env and get injected into the bundle config. Anything committed to config/packages/ should be a %env(...)% reference.

Gotchas and Tips

The changelog is empty. 0.1.0 ships with nothing but a compare link (0.0.2...0.1.0). You must read the diff yourself before upgrading. On a 0.x package there is no BC promise — a minor bump from 0.0.2 to 0.1.0 can rename services, change method signatures, or alter the config tree with no deprecation path. Pin "tourze/wechat-mini-program-express-bundle": "0.1.0" and review the diff deliberately.

Laravel integration is the main risk. There is no realistic path to dropping a Symfony Bundle into a Laravel app without a bridge (binding services manually, replicating the extension's config into config/). Before committing, check whether the package's classes are plain services you can new up yourself — if so, instantiate them directly and skip the bundle. If they are wired through a container with compiler passes and tagged services, treat this as "Symfony-only" and budget accordingly.

Expect a large transitive tree. Tourze packages are typically split into many micro-packages (*-contract, *-enum, *-entity, *-doctrine-*). Run composer why on anything that surprises you after install, and expect Doctrine ORM to arrive as a dependency.

Doctrine entities mean schema coupling. If the bundle ships doctrine entities/repositories, you are inheriting a schema, not just an API client. Check whether migrations are provided or whether you are expected to map the entities onto your existing tables. In a Laravel app with Eloquent, this is usually the point where the package stops being worth it.

access_token is per-app and global. WeChat issues one token per app id with a ~2h TTL and strict rate limits on the fetch endpoint. If the bundle fetches a fresh token per request, you will hit 45009/40001 errors under load. Verify it uses a PSR-6/PSR-16 cache pool, and that the pool is shared across workers — an in-memory pool in a multi-process PHP-FPM setup is effectively broken.

Errors arrive with HTTP 200. WeChat returns failures as errcode/errmsg in the JSON body. If your code only checks $response->getStatusCode(), every failure will look like a success and you will discover it in production order data. Assert on errcode explicitly in your wrapper, and log the raw body on non-zero.

Certificates for sensitive endpoints. Refund/transfer-adjacent APIs need apiclient_cert.pem + apiclient_key.pem. Never commit them; mount via a secret and reference by path in config. A common failure is a relative path that resolves correctly in local dev and breaks in the container.

Debugging: log the full outbound request and inbound response at the wrapper boundary (masked secrets), and keep a Mini Program test account/sandbox for the callback flow — you cannot trigger real logistics state changes on a production app id on demand.

Extension points: in Symfony, decorate the bundle's service rather than forking it (services.yaml → decorates:), and listen on the dispatcher if it emits events for request/response. That keeps you upgrade-safe against the next 0.x bump.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
cgv/localized-resource