Callbacky z klienta
Metóda callback() každého poskytovateľa overí vstup, ktorý vaša aplikácia dostala od klienta — účtenku Apple, purchaseToken z Google (pri jednorazovom produkte aj productId) alebo session_id či payment_intent zo Stripe. Nie je autentifikovaná, preto ju volajte z vlastnej routy; webhook routa prijíma len podpísané udalosti obchodov. Chyby sú dvojakého druhu: VerificationException znamená chybný vstup od klienta, takže odpovedzte klientovi; RequestException alebo ConnectionException z HTTP klienta znamená, že obchod alebo vaše prístupové údaje neodpovedali, takže to skúste znova alebo nechajte požiadavku skončiť chybou 500:
use RoundlyConsulting\Purchases\Exceptions\VerificationException;
use RoundlyConsulting\Purchases\Facades\Purchases;
try {
$verified = Purchases::provider('stripe')->callback($request);
} catch (VerificationException $e) {
abort(422, $e->getMessage()); // the client's id: answer it
}
// RequestException / ConnectionException: Stripe or the secret key, not the id. Let it 500.Čo jednotlivé callbacky prijímajú
- Stripe — prednosť má session_id (Checkout Session), inak payment_intent. Identifikátor, ktorý je prítomný, no nie je reťazcom (session_id[]=x, číslo, boolean), sa odmietne — „Malformed Stripe session id.“ / „Malformed Stripe payment intent id.“ — bez ohľadu na druhý identifikátor, takže chybné session_id sa nikdy nepreskočí v prospech payment_intent poslaného vedľa neho. Chýbajúci, null alebo prázdny identifikátor sa považuje za neposlaný; ak nepríde ani jeden, vyhodí sa „No Stripe session or payment intent id provided.“
- Google — callback() a callbackResult() vyžadujú purchaseToken ako neprázdny reťazec („Missing or malformed Google purchase token.“). productId, ktoré je prítomné, no nie je reťazcom, sa odmietne („Malformed Google product id.“) namiesto toho, aby sa čítalo ako „bez produktu“ — to by jednorazový nákup overilo ako predplatné; chýbajúce, null alebo prázdne productId znamená predplatné. Obe idú cez product() / subscription(), takže podtrieda, ktorá ich prepíše, vidí každý callback.
- Apple — surové telo požiadavky ide do verifyReceipt ako účtenka; pri produkčnej konfigurácii sa odpoveď 21007 (sandboxová účtenka z App Review alebo TestFlightu) overí znova voči sandboxu. Neplatný status vyhodí VerificationException, ktorá ho uvádza, napríklad [21003].
Identifikátory v ceste API
Každý identifikátor, ktorý poskytovateľ vkladá do cesty API obchodu, je percentuálne zakódovaný (rawurlencode), takže session_id klienta v tvare cs_1?expand[]=customer nepridá query string k požiadavke odoslanej s vaším tajným kľúčom, # cestu neskráti a ../ ju neposunie na iný endpoint. Prázdny identifikátor, . alebo .. sa odmietne ešte pred volaním obchodu — žiadne kódovanie ho neudrží ako jeden segment cesty — so správou „Malformed Stripe id.“, „Malformed Google id.“ alebo „Malformed Apple transaction id.“ Platný identifikátor, napríklad cs_test_a1B2, sa pošle bez zmeny:
session_id=cs_1?expand[]=customer
→ GET /v1/checkout/sessions/cs_1%3Fexpand%5B%5D%3Dcustomer
transaction id ../../v1/notifications/test
→ GET /inApps/v1/transactions/..%2F..%2Fv1%2Fnotifications%2Ftest
purchaseToken ..
→ VerificationException: Malformed Google id. (Google is never called)Platí to pre paymentIntent(), subscription(), session() a invoice() v Stripe; pre product(), subscription(), acknowledgeSubscription() a čítanie predplatného pri RTDN v Google, ako aj pre nakonfigurované package_name . alebo ..; a pre AppStoreServerApi::transaction().
Čo vyhadzuje callback()
| Výnimka | Kedy |
|---|---|
VerificationException | Vstup od klienta je chybný: chybný alebo chýbajúci identifikátor (pozrite vyššie) alebo taký, na ktorý obchod odpovie 4xx — 400, 404, pri tokene Google, ktorý už neplatí, 410: „Stripe rejected the session id.“ / „Stripe rejected the payment intent id.“, „Google rejected the purchase token.“ / „Google rejected the purchase token or product id.“, „Apple rejected the receipt.“ Jej getPrevious() je RequestException obchodu. Ďalej neplatná alebo chybná účtenka Apple, nákup Google, ktorý nie je v stave zakúpený, expirované predplatné a chýbajúci tajný kľúč Stripe či package_name alebo servisný účet Google. |
RequestException | Obchod odpovedal 401 / 403 (odmietol vaše prístupové údaje), 429 (limit požiadaviek) alebo 5xx. Pri Google aj 4xx s dôvodom applicationNotFound (nesprávne package_name), odmietnutie servisného účtu na OAuth endpointe tokenov (napríklad invalid_grant) a odmietnuté potvrdenie po úspešnom vyhľadaní. Opravte konfiguráciu, skúste to znova alebo nechajte odpovedať 500. |
ConnectionException | Obchod nebol dostupný. Skúste to znova alebo nechajte odpovedať 500. |
Pri Google rozhoduje dôvod chyby, nie status: 404 rovnako často znamená neznámy token ako neznámu aplikáciu. Ako chyba vašej konfigurácie sa číta len applicationNotFound — package_name, ktoré Google nepozná, alebo aplikácia, ktorá ešte nemá nič nahraté v žiadnej stope (track); akýkoľvek iný dôvod a 4xx bez chybovej obálky Google zostanú „Google rejected the purchase token.“ Aj purchaseTokenDoesNotMatchPackageName (400) je odmietnutie: klient poslal token inej aplikácie.
Priame vyhľadanie
Pri priamom volaní paymentIntent(), subscription(), session() a invoice() v Stripe, product() a subscription() v Google a AppStoreServerApi::transaction() sa chybný identifikátor odmietne rovnako, no každá chybová odpoveď obchodu — vrátane 404 pre neznámy identifikátor — zostane ako RequestException z HTTP klienta. Len callback() (a callbackResult() v Google) premení 4xx týkajúcu sa vstupu na VerificationException.
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 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.