NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Purchases for Laravel

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=purchases

So 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;         // ?Carbon

Spracovanie 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 jehandle()
nový — vložilo ho toto doručenieudalosť spracuje a záznam označí ako spracovaný
spracovaný, alebo ho hostiteľ soft-delete zmazalvráti tento záznam; nič neuloží ani nespustí
nespracovaný, s nárokom mladším ako claim_timeout sekúndvyhodí 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 date

Prejavte 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 kryptomien

Odoslaní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.