lizhipay/acg-faka
ACG Faka is a Laravel-based card-key (faka) storefront for selling virtual goods, accounts, and activation codes with automatic delivery. It ships with Alipay, WeChat, and QQ payment support, multi-merchant management, coupon and order handling, and swappable storefront themes, making it a fast way...
First, calibrate what this is. lizhipay/acg-faka (异次元发卡 / ACG Faka) is not a Composer package you require into an existing Laravel app — it is a complete self-hosted storefront application for selling digital goods (card secrets / 卡密, license keys, accounts, downloads) with automatic delivery after payment. Your day-to-day relationship with it is deploy, configure, theme, and integrate around it, not import and call it. Confirm the framework version in the repo before assuming Laravel conventions (Eloquent, service providers, Blade) — several distributions of this family are built on ThinkPHP-style MVC, and the directory layout and ORM will not match what you expect.
Minimal path to a working store:
public/ (never the repo root), set PHP version + extensions per the README, create a MySQL database.Where to look first: the payment driver/adapter directory, the order state handling (search for the callback/notify controller), the card-inventory model and import logic, and the theme directory. Those four places determine 90% of what you'll be asked to change.
Best first use case: selling a fixed-price digital key with instant on-page delivery and an email copy. It exercises inventory, payment, delivery, and notification in one flow — if that works, everything else is variation.
Treat card inventory as the core resource, not an afterthought. Inventory is the thing that actually costs money when it goes wrong. Standard patterns:
available / locked / sold states rather than a simple counter — a raw stock integer will drift the first time an order is refunded or a delivery fails mid-transaction.Payment integration follows a driver/adapter shape. Each gateway is a class handling: build-payment-request, verify-signature, parse-notify, and return a normalized result. When adding a new gateway, implement it against that shape rather than branching inside the order controller — it keeps the state machine clean and makes gateways swappable per product or per currency.
Model the order as an explicit state machine: pending → paid → delivering → delivered, plus failed and refunded. Every notify handler should be idempotent and safe to receive twice, since gateways will replay callbacks. Delivery should be a separate step triggered by the paid transition, so a replayed notify doesn't ship a second card.
Delivery modes to support from day one:
Theme and extension work: fork a theme into your own directory and keep upstream changes mergeable. Never edit core files for a feature — the upgrade story becomes a manual diff every time. If the app exposes hooks/plugins, use them; if not, put custom logic in a separate Laravel service that talks to the store over its order webhook and database/API, rather than patching the monolith.
If you already run a Laravel app, integrate rather than merge. Run the store as its own service and bridge it: SSO or a shared signed token for identity, a webhook into your app's queue on order.paid, and a read replica or API for product catalog. This keeps your domain logic in code you control and lets you replace the storefront later without a rewrite.
Ops patterns that pay off: scheduled job to expire unpaid orders and release locked cards, nightly DB backup that explicitly includes the card table, and structured logging of raw gateway notify payloads for disputes.
License is NOASSERTION. This is the highest-risk item on the list. There is no clear OSI license, and this family of projects often ships under a Chinese copyright notice with restrictions on removing branding or reselling. Read the actual LICENSE file and any 授权/授权协议 text before commercial deployment, and get a decision in writing from whoever owns the risk.
Upgrades are git pull + conflict resolution, not composer update. Pin to a tag, keep your customizations in themes/plugins/a sidecar service, and diff before pulling. Last release dates on these projects can be misleading — check the commit log for actual activity.
Duplicate delivery is the classic bug. Two concurrent notifies, or a notify plus a manual "re-deliver" click, can hand out two cards for one order. Guard the card-selection step with a transaction and a row lock (SELECT ... FOR UPDATE on an available card), and key delivery on a unique order id.
Card secrets are frequently stored in plaintext or with weak symmetric encryption. A DB dump or a SQL-injection bug equals total inventory loss. Encrypt at rest with a key held outside the DB, restrict DB access to the app host, and consider rotating/voiding unsold stock after any suspected exposure.
Callback debugging workflow: log the raw notify body and headers before signature verification, then replay the stored payload at the notify endpoint to re-trigger delivery. Nine times out of ten the failure is a signature mismatch from a trailing space in the merchant key, or a gateway sending the notify to an http:// URL that redirects and drops the POST body.
Security hardening is non-optional. These systems are popular enough to be actively scanned. Remove the installer, change the admin path and credentials, disable directory listing, hide the exact version, put the admin behind IP allowlisting or basic auth, and subscribe to the repo's issues for disclosed vulnerabilities. Assume default config is unsafe.
Email is the flakiest delivery channel. Use authenticated SMTP from a reputable provider, set SPF/DKIM, and queue sends. If buyers report "no email," check spam before assuming the store is broken — the on-page reveal should always be treated as the source of truth.
Extension points drift. Theme hooks and plugin registries in projects like this are often undocumented and change between minor versions. Verify any hook you depend on after each upgrade, and prefer the stable seams (payment driver interface, order webhook, DB schema) over template-level hooks.
Watch timezone and currency assumptions. Order timestamps and expiry windows are commonly hardcoded to a locale; if you run cross-border, verify both explicitly rather than discovering it in a refund dispute.
How can I help you explore Laravel packages today?