From 798ec7ba67f1e1dd27842144230363c04f5adbb8 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Tue, 31 Oct 2023 15:48:43 +0100 Subject: [PATCH] Allow the PSP connector to fail in all cases In case the PSP connector throws we should still handle the cleanup and not just fail abort: * In case the PSP could have changed the entity we need to persist it * In case the cleanup failed we want to continue the cleanup for other PSPs * In case the ID lookup fails, we still want to ask all other connectors --- src/Service/PaymentService.php | 48 ++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/Service/PaymentService.php b/src/Service/PaymentService.php index 340f4a7..1cbfc40 100644 --- a/src/Service/PaymentService.php +++ b/src/Service/PaymentService.php @@ -425,14 +425,16 @@ public function startPayAction(StartPayAction $startPayAction): StartResponseInt $paymentPersistence->setStartedAt($now); $paymentServiceProvider = $this->paymentServiceProviderService->getByPaymentContract($paymentContract); - $startResponse = $paymentServiceProvider->start($paymentPersistence); - try { - $this->em->persist($paymentPersistence); - $this->em->flush(); - } catch (\Exception $e) { - $this->logger->error('Payment could not be updated!', ['exception' => $e]); - throw new ApiError(Response::HTTP_INTERNAL_SERVER_ERROR, 'Payment could not be updated!'); + $startResponse = $paymentServiceProvider->start($paymentPersistence); + } finally { + try { + $this->em->persist($paymentPersistence); + $this->em->flush(); + } catch (\Exception $e) { + $this->logger->error('Payment could not be updated!', ['exception' => $e]); + throw new ApiError(Response::HTTP_INTERNAL_SERVER_ERROR, 'Payment could not be updated!'); + } } return $startResponse; @@ -448,7 +450,12 @@ public function completeGetPaymentId(string $pspData): string // first map the PSP data to an existing payment entry by asking all PSP connectors foreach ($this->configurationService->getPaymentContracts() as $contract) { $pspService = $this->paymentServiceProviderService->getByPaymentContract($contract); - $paymentId = $pspService->getPaymentIdForPspData($pspData); + try { + $paymentId = $pspService->getPaymentIdForPspData($pspData); + } catch (\Exception $e) { + $this->logger->error('PSP service failed to get payment ID', ['exception' => $e]); + continue; + } if ($paymentId !== null) { return $paymentId; } @@ -470,14 +477,16 @@ public function completePayAction( $paymentContract = $this->configurationService->getPaymentContractByTypeAndPaymentMethod($type, $paymentMethod); $paymentServiceProvider = $this->paymentServiceProviderService->getByPaymentContract($paymentContract); - $completeResponse = $paymentServiceProvider->complete($paymentPersistence); - try { - $this->em->persist($paymentPersistence); - $this->em->flush(); - } catch (\Exception $e) { - $this->logger->error('Payment could not be updated!', ['exception' => $e]); - throw new ApiError(Response::HTTP_INTERNAL_SERVER_ERROR, 'Payment could not be updated!'); + $completeResponse = $paymentServiceProvider->complete($paymentPersistence); + } finally { + try { + $this->em->persist($paymentPersistence); + $this->em->flush(); + } catch (\Exception $e) { + $this->logger->error('Payment could not be updated!', ['exception' => $e]); + throw new ApiError(Response::HTTP_INTERNAL_SERVER_ERROR, 'Payment could not be updated!'); + } } $this->notifyIfCompleted($paymentPersistence); @@ -522,8 +531,15 @@ public function cleanup() $this->logger->error("Can't find payment contract for method '$paymentMethod'. Can't clean up entry: ".$paymentPersistence->getIdentifier()); continue; } + $paymentServiceProvider = $this->paymentServiceProviderService->getByPaymentContract($paymentContract); - $cleanupWorked = $paymentServiceProvider->cleanup($paymentPersistence); + try { + $cleanupWorked = $paymentServiceProvider->cleanup($paymentPersistence); + } catch (\Exception $e) { + $this->logger->error('PSP cleanup failed', ['exception' => $e]); + $cleanupWorked = false; + } + if ($cleanupWorked !== true) { $this->logger->error('Payment provider cleanup failed for '.$paymentPersistence->getIdentifier().', skipping further cleanup'); continue;