Sunt nou în Drupal și trebuie să fac un gateway de plată în afara site-ului (cu Drupal Commerce 2). Totul funcționează, dar uneori nu.
Serverul furnizorului de plăți la distanță trimite cereri de notificare către server, despre starea plății, așa că le am pe ambele onReturn
și onNotify
în clasa PaymentGateway.
De cand onReturn
nu se garantează că va fi apelat (clientul ar putea închide browserul etc., iar furnizorul nu îl trimite neapărat înapoi în cazul meu), dar onNotify
este garantat să fie apelat, creez și salvez Plată
obiect în onNotify
, nu în onReturn
, când plata este finalizată. (Acesta este și ceea ce sugerează documentația să faceți: https://docs.drupalcommerce.org/commerce2/developer-guide/payments/create-payment-gateway/off-site-gateways/handling-ipn)
Deci codul meu arată cam așa. (Este un pseudo-cod foarte simplificat; verificările de validare nu sunt incluse.)
clasa RedirectCheckout extinde OffsitePaymentGatewayBase implementează SuportsNotificationsInterface {
funcție publică onReturn() {
$is_order_accepted = /* Verificați dacă furnizorul de plăți la distanță a acceptat comanda */
dacă (!$este_comanda_acceptată) {
aruncați o nouă excepție NeedsRedirectException()
}
// Dacă totul este bine, nu faceți nimic.
}
funcția publică onNotify() {
/** @var OrderInterface $comanda */
$comanda = /* Încarcă comanda despre care este notificarea */
$is_order_accepted = /* Verificați dacă furnizorul de plăți la distanță a acceptat comanda */
dacă ($is_order_accepted) {
$plata = $payment_storage->create();
$plata->salvare();
$comanda->setData('transaction_id', $transactionId);
$comanda->salvare(); // Aceasta este ceea ce uneori este suprascris de onReturn(), cred.
}
}
}
Observați că trebuie să salvez câteva date despre comandă, atunci când o comandă este acceptată (care nu este disponibilă la crearea comenzii, doar când o plată a reușit).
Documentația Drupal Commerce spune că „nu trebuie (și nu ar trebui)” să atingeți comanda, dar trebuie să salvez câteva date suplimentare despre comanda pe care alte părți din sistem se așteaptă să fie acolo.
Acest lucru funcționează adesea. Cu toate acestea, cei doi onReturn
și onNotify
solicitările de la serverul de la distanță ajung uneori aproape în același timp, ceea ce cred că duce la o condiție de cursă.
Din păcate, chiar dacă nu fac nimic la comanda în onReturn
, Comerțul pare să salveze în continuare comanda. Cred că acest lucru poate suprascrie uneori datele salvate în comanda de onNotify
. De exemplu:
onReturn
începe să ruleze și încarcă comanda (Acest lucru este făcut de biblioteca comercială în sine, așa că nu pot face nimic în acest sens.)
- Sosește cererea de notificare, deci
onNotify
începe să ruleze, încarcă și salvează comanda și revine
- După aceasta,
onReturn
metoda revine, redă controlul către Commerce, care salvează din nou comanda; deoarece a încărcat obiectul de comandă înainte onNotify
l-a salvat, suprascrie orice onNotify
scris cu date vechi
(Poate că ordinea inversă poate fi, de asemenea, problematică, unde onNotify
poate suprascrie orice date salvate în comandă de Drupal Commerce în culise, dacă există, în timpul onReturn
cerere.)
Există o modalitate bună de a gestiona acest lucru, de exemplu, să rezolvăm condițiile de cursă pentru a putea salva datele comenzii onNotify
?
Folosesc Drupal 8.6.