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

Open Ecommerce Laravel Package

ibrand/open-ecommerce

ibrand/open-ecommerce is a modular Laravel e-commerce package for building customizable online stores. It provides product catalog, cart, checkout, order, payment, and promotion components with an extensible admin backend, helping PHP developers launch and extend commerce applications quickly.

View on GitHub
Deep Wiki
Context7

Getting Started

Assumptions to verify first: this package sits at the API layer of the iBrand e-commerce stack — it is the Open API (routes + controllers + resources) over a set of sibling packages (ibrand/laravel-shopping-cart, address, settings, repository, tag). It is not a batteries-included storefront. v2.0.3 also ships an admin-side mall settings + micro-page (微页面) editor whose output is consumed by a WeChat mini-program client, so treat this as "storefront API + lightweight CMS" rather than a pure headless catalog. Read composer.json and routes/ before anything else to confirm which Laravel and which ibrand/* versions it pins — v2.0.3 explicitly bumped third-party packages, so do not carry over assumptions from 1.x.

Minimal bring-up:

git clone https://github.com/guojiangclub/ecommerce-open-api
composer install
cp .env.example .env && php artisan key:generate
# configure DB in .env, then:
php artisan migrate --seed
php artisan passport:install     # OAuth2 clients for the API
php artisan vendor:publish --all # settings + micro-page assets/migrations, check --tag
php artisan serve

Where to look, in this order:

Path Why
routes/ (usually api.php / routes/v1) The actual product surface — every endpoint is a feature
config/ (ecommerce.php, ibrand.php) Currency, payment drivers, image/upload, order expiry
src/Contracts + src/Repositories The seams you are meant to override
database/migrations + seeders The real schema; treat it as the spec
src/Http/Controllers/Admin + micro-page module registry New in 2.0.3 — the module catalogue (幻灯片/优惠券/快捷导航/魔方) and how pages are composed
tests/ Often the only working documentation of the checkout flow

First use case to target: read-only catalog → cart → order. Hit GET /api/products unauthenticated, then obtain a token (POST /oauth/token, password grant), add to cart, and place one order end-to-end with a cash/fake payment driver. Then repeat via the new direct-buy path (商品支持直接下单) — the two flows should converge on the same order-creation service; if they don't, that divergence is the first thing to fix. If both paths work, the rest of the domain is mostly variations. Do not start by reading models — start by tracing one request from route → controller → repository → model.

Implementation Patterns

Use it as a service, not a library, if you can. Running it as a separate API process (its own DB or a read replica) and talking to it over HTTP keeps the upgrade blast radius contained. If you need it in-process, pin the exact commit/tag in composer.json and vendor it under a namespace you control. The 2.x line is still moving (2.0.3 added schema-bearing features), so an unpinned dev-master is a guaranteed surprise.

Override through the container, not by editing models. The packages are repository-driven; the intended extension point is binding your own implementation to an ibrand.* contract in a service provider:

// app/Providers/CommerceServiceProvider.php
$this->app->bind(
    \iBrand\EC\Open\Core\Contracts\OrderContract::class,
    \App\Commerce\Orders\OrderRepository::class
);

Confirm the exact FQCNs from src/Contracts — they moved between releases and 2.0.3 is a minor release on top of a major, so re-check after upgrading. Keep your overrides in app/, never in vendor/, so a composer update on a fork stays mergeable.

Treat order placement as one transaction with explicit locking. Stock decrement plus cart conversion is the classic race here, and the new direct buy path adds a second entry point into it. Funnel both through one service:

DB::transaction(function () use ($items, $payload) {
    $locked = $this->stock->lockForUpdate($items); // re-validate price + stock from DB
    $order  = $this->orders->create($payload, $locked); // never trust the cart/request snapshot
    event(new OrderPlaced($order));
});

The cart is a quote, not a reservation — re-price server-side at submit time. If direct-buy reuses the cart table internally, confirm it uses a distinct/disposable cart so a "buy now" doesn't silently mutate the user's saved cart. This is where most integrations with this package go wrong.

Model the micro-page as a versioned document, not rows. 2.0.3 stores page composition as module blocks (slideshow, coupon, quick-nav, cube grid). You will get JSON-ish structures whose shape is only implied by the admin editor. Snapshot the schema, put a schema_version on it, and render it server-side into a stable, deliberately-shaped payload for your mini-program rather than dumping the stored blob. When the package adds a module, you add a renderer — you don't touch the client.

Add your own module via the registry, not by patching the editor. Find the module map/config that enumerates the block types and register a new class implementing the same render + admin-form surface. That keeps you on the supported extension path; editing the admin controllers is a permanent fork.

Drive post-order work off events, not controller edits. Order paid / shipped / cancelled events are the stable seam for email, inventory sync, ERP push, and analytics. A listener keeps you off the update treadmill — especially relevant given 2.0.3's "支付问题修复", which likely touched the paid transition.

Write a thin anti-corruption layer on the client side. The API returns framework-shaped payloads (Laravel resources over Eloquent). Map them into your own DTOs immediately so a schema drift in the package is one file to fix, not fifty. This applies doubly to micro-page payloads.

Money: check whether the schema stores integer minor units or decimal. If decimal, cast to integer cents at your boundary and never do arithmetic on the API's floats. Same for currency — there is a single configured currency, so multi-currency means a schema change, not a config change.

Testing: use the package's own factories for fixtures, but write your integration tests against the HTTP surface ($this->postJson('/api/cart', ...), $this->postJson('/api/orders/buy-now', ...)) with a fresh migrated DB per test. Mock the payment driver rather than the repository — the driver boundary is narrower and more stable. Cover cart-checkout and direct-buy with the same assertions; that's your regression net for the duplicated-logic risk.

Gotchas and Tips

  • Re-baseline the version ceiling on upgrade, don't assume it. v2.0.3's "更新第三方包版本" may have moved the Laravel/PHP floor up — or may have only patched within the old one. Read composer.json constraints before planning. The 1.x-era facts (Laravel 5.7/5.8, str_slug, array_get, Passport-not-Sanctum, possibly Dingo) are worth re-verifying line by line; if 2.x genuinely modernised, your port budget shrinks a lot, and if it didn't, nothing changed. Upgrading 1.x → 2.x is a major-version jump: expect migrations, config keys, and contract FQCNs to have moved, and treat it as a port with a test plan, not a composer update.
  • Payment changes are the highest-risk item in this release. "修复支付问题" is unqualified. Whatever changed, re-test the full state machine (pending → paid → refunded), the async notify/callback endpoint, idempotency on duplicate callbacks, and refunds — against your actual driver, not just the bundled China-centric ones.
  • Payment drivers are China-centric (WeChat Pay / Alipay). There is no Stripe/PayPal path. Plan for a custom driver implementing the payment contract; the driver interface is small, the surrounding state machine is what you must respect.
  • "修复数据回滚异常" — re-audit migrations before relying on rollbacks. If down() was previously broken, earlier migrations may be squashed or effectively irreversible. Validate migrate:refresh and RefreshDatabase in CI early; don't discover this mid-sprint.
  • Direct-buy duplicate orders. "Buy now" is usually a single POST — client retries, double taps, and network replays all create duplicate orders. Enforce an idempotency key or a short-lived server-side lock, and don't rely on the client to guard it.
  • Abandoned-upstream risk is lower but not gone. Active feature shipping in 2.0.x is a good sign; Dependents: 0 still means no ecosystem, no Stack Overflow answers, and no CVE triage on your behalf. Fork it, own the security patches, and note the exit cost in your ADR. Chinese-language issues and docs remain the only support channel.
  • Micro-page content is schema-less by contract. No validation layer will stop a malformed block, and the admin editor may allow states your renderer doesn't expect. Validate on read, degrade gracefully (skip unknown modules), and never json_decode straight into your client.
  • Auth is OAuth2 client + password grants. Tokens are per-client; scope handling is minimal. If you need SPA/mobile flows, terminate auth in front of this service rather than bending its Passport config.
  • Debugging: php artisan route:list is your map. Turn on DB::listen / APP_DEBUG and log the query log — repository layers hide N+1s badly, and product listing and micro-page assembly endpoints are the usual culprits. If it uses Dingo, API_DEBUG=true and API_STRICT=true in .env will surface the real exception instead of a generic JSON error.
  • Migrations and config are publishable but not published by default — check --tag options on vendor:publish. Seeding is required (settings, payment methods, shipping rules, mall settings) or checkout silently fails at the shipping step; micro-pages likewise have no content until seeded, which reads as "broken editor".
  • Timezone and locale: set APP_TIMEZONE and currency explicitly before seeding; order timestamps and price formatting are baked into seeded settings rows, and changing them later means data migration. 2.0.3's new mall-settings surface widens what gets baked in — set it before you seed, not after.
  • Extension points, in order of safety: config values → events/listeners → container bindings for contracts → module registry entries (micro-page blocks) → your own controllers reusing repositories → forking a model. Anything below "module registry" should be treated as a permanent fork.
  • Don't expose the stock schema to clients. The API's product payloads are verbose; build a presentation layer so you can change field names and pagination without breaking your mobile app.
  • Have an exit plan. Structure the integration so the domain (products, carts, orders, page content) lives in your schema and the package is a backend you can replace. The micro-page editor is the stickiest new coupling — store your own page documents and treat the package's editor as one possible authoring UI, or migrating away means rebuilding the CMS and the frontend.
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
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core