Fronta, auditný log a replay
Spracovanie na pozadí
Nastavte PURCHASES_QUEUE_ENABLED=true, ak chcete overovať synchrónne, no ukladať cez frontu. Webhook aj tak odpovie 204 okamžite; úloha ProcessProviderNotification uloží výsledok na nakonfigurovanom spojení a fronte a označí auditný záznam ako spracovaný. Predvolená je synchrónna cesta:
PURCHASES_QUEUE_ENABLED=true
PURCHASES_QUEUE_CONNECTION=redis
PURCHASES_QUEUE_NAME=purchasesSo zapnutou frontou vracia handle() PurchaseNotification, ktorý opisuje, čo sa zaradilo do fronty — alebo neuložený zástupný objekt, ak je auditný log vypnutý.
Auditný log
Pri PURCHASES_AUDIT_ENABLED=true (predvolene) sa každá overená notifikácia uloží do purchase_notifications — poskytovateľ, typ, príznak overeného podpisu, snapshot normalizovaného výsledku a pôvodného payloadu a processed_at — ešte predtým, než sa premietne do stavu modelov. Rovnako aj každý výsledok odovzdaný do Purchases::sync(), so signature_verified false a pôvodom host, pretože ho balík nikdy neoveroval (vyhľadáte ho cez where('payload->origin', 'host')):
use RoundlyConsulting\Purchases\Models\PurchaseNotification;
PurchaseNotification::forProvider('apple')->pending()->get(); // recorded, not yet processed
$notification->provider; // 'apple'
$notification->type; // 'subscription', 'purchase', 'refund' …
$notification->signature_verified; // bool — false for a sync() row
$notification->origin(); // NotificationOrigin::Provider, or ::Host for a sync() row
$notification->payload; // Collection — the stored snapshot
$notification->processed_at; // ?CarbonSpracovanie každej udalosti len raz
Obchody doručujú aspoň raz. Ukladanie je idempotentné a udalosti životného cyklu sa spúšťajú len pri skutočnej zmene, no opakované doručenie aj tak zapíše druhý auditný záznam a signál sa spustí znova. purchases.audit.deduplicate uloží id udalosti každého výsledku do jeho auditného záznamu pod unikátnym indexom pre poskytovateľa, takže z dvoch súbežných doručení ho uloží presne jedno:
PURCHASES_AUDIT_DEDUPLICATE=true # needs PURCHASES_AUDIT_ENABLED=true and the event_id migration
PURCHASES_AUDIT_CLAIM_TIMEOUT=300 # seconds before a redelivery may take over a stuck claim| Auditný záznam udalosti je | handle() |
|---|---|
| nový — vložilo ho toto doručenie | udalosť spracuje a záznam označí ako spracovaný |
| spracovaný, alebo ho hostiteľ soft-delete zmazal | vráti tento záznam; nič neuloží ani nespustí |
| nespracovaný, s nárokom mladším ako claim_timeout sekúnd | vyhodí EventInProgressException — webhook routa odpovie 409, takže obchod doručenie neskôr zopakuje |
| nespracovaný, nárok uvoľnený (doručenie vyhodilo výnimku) alebo vypršaný (doručenie zaniklo) | udalosť prevezme — jednou podmienenou aktualizáciou, takže vyhrá jedno doručenie — a spracuje ju |
- Pri zapnutej fronte si záznam nárokuje prvé doručenie a odošle job; opakované doručenie dostáva 409, kým job udalosť nespracuje, a potom sa preskočí.
- Predvolene vypnuté: vyžaduje migráciu, ktorá pridáva event_id a claimed_at (pozrite Inštalácia), a auditný log — zapnuté pri vypnutom audit.enabled vyhodí InvalidConfigurationException. Ďalšia hlavná verzia ho má zapnúť predvolene.
- Deduplikuje len handle(). sync() ani replay() nikdy a handle() v Purchases::fake() auditný log vynecháva.
- Stripe niekedy pošle k jednej zmene dve rôzne udalosti; majú rôzne id a spracujú sa obe — ukladanie zostáva idempotentné.
- PurchaseNotification::eventId() vráti id udalosti — stĺpec event_id, ak ho deduplikácia uložila, inak hodnotu zo snapshotu.
Replay
purchases:replay vyberie uložené notifikácie a každú znova spracuje cez Purchases::replay() — vrátane udalostí —, takže sa zotavíte z chyby v nadväzujúcom kroku bez čakania, kým obchod niečo pošle znova. Notifikáciu, ktorú spracovať nesmie alebo nemôže (notifikácia poskytovateľa s neovereným podpisom alebo snapshot, ktorý sa už nedá obnoviť), vypíše ako preskočenú a pokračuje ďalej; záznamy z sync() sa spracujú:
php artisan purchases:replay # every stored notification
php artisan purchases:replay 42 # a single notification by id
php artisan purchases:replay --provider=stripe # one provider
php artisan purchases:replay --since=2026-01-01 # recorded on or after a datePrejavte lásku k open source
Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.
Ďalšie spôsoby podpory vrátane kryptomienOdoslaním daru súhlasíte s našimi podmienkami prijímania darov.
Chcete to zabudovať do svojho produktu?
Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.