Completed
Pull Request — master (#923)
by Jeroen De
61:01
created

createFailureResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\Frontend\DonationContext\UseCases\SofortPaymentNotification;
6
7
use DateTime;
8
use RuntimeException;
9
use WMDE\Fundraising\Frontend\DonationContext\Authorization\DonationAuthorizer;
10
use WMDE\Fundraising\Frontend\DonationContext\Domain\Model\Donation;
11
use WMDE\Fundraising\Frontend\DonationContext\Domain\Repositories\DonationRepository;
12
use WMDE\Fundraising\Frontend\DonationContext\Domain\Repositories\GetDonationException;
13
use WMDE\Fundraising\Frontend\DonationContext\Domain\Repositories\StoreDonationException;
14
use WMDE\Fundraising\Frontend\DonationContext\Infrastructure\DonationConfirmationMailer;
15
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\SofortPayment;
16
use WMDE\Fundraising\Frontend\PaymentContext\ResponseModel\SofortNotificationResponse;
17
use WMDE\Fundraising\Frontend\PaymentContext\RequestModel\SofortNotificationRequest;
18
19
class SofortPaymentNotificationUseCase {
20
21
	private $repository;
22
	private $authorizationService;
23
	private $mailer;
24
25
	public function __construct( DonationRepository $repository, DonationAuthorizer $authorizationService,
26
								 DonationConfirmationMailer $mailer ) {
27
		$this->repository = $repository;
28
		$this->authorizationService = $authorizationService;
29
		$this->mailer = $mailer;
30
	}
31
32
	public function handleNotification( SofortNotificationRequest $request ): SofortNotificationResponse {
33
		try {
34
			$donation = $this->repository->getDonationById( $request->getDonationId() );
35
		} catch ( GetDonationException $ex ) {
36
			return $this->createFailureResponse( $ex );
37
		}
38
39
		if ( $donation === null ) {
40
			return $this->createFailureResponse( new RuntimeException( 'Donation not found' ) );
41
		}
42
43
		return $this->handleRequestForDonation( $request, $donation );
44
	}
45
46
	private function handleRequestForDonation( SofortNotificationRequest $request, Donation $donation ): SofortNotificationResponse {
47
		$paymentMethod = $donation->getPayment()->getPaymentMethod();
48
49
		if ( !( $paymentMethod instanceof SofortPayment ) ) {
50
			return $this->createUnhandledResponse( 'Trying to handle notification for non-sofort donation' );
51
		}
52
53
		if ( !$this->authorizationService->systemCanModifyDonation( $donation->getId() ) ) {
54
			return $this->createUnhandledResponse( 'Wrong access code for donation' );
55
		}
56
57
		if ( $paymentMethod->isConfirmedPayment() ) {
58
			return $this->createUnhandledResponse( 'Duplicate notification' );
59
		}
60
61
		$paymentMethod->setConfirmedAt( $request->getTime() );
62
63
		try {
64
			$this->repository->storeDonation( $donation );
65
		}
66
		catch ( StoreDonationException $ex ) {
67
			return $this->createFailureResponse( $ex );
68
		}
69
70
		$this->sendConfirmationEmailFor( $donation );
71
72
		return SofortNotificationResponse::newSuccessResponse();
73
	}
74
75
	private function createUnhandledResponse( string $reason ): SofortNotificationResponse {
76
		return SofortNotificationResponse::newUnhandledResponse( [
77
			'message' => $reason
78
		] );
79
	}
80
81
	private function sendConfirmationEmailFor( Donation $donation ): void {
82
		if ( $donation->getDonor() !== null ) {
83
			try {
84
				$this->mailer->sendConfirmationMailFor( $donation );
85
			} catch ( RuntimeException $ex ) {
86
				// no need to re-throw or return false, this is not a fatal error, only a minor inconvenience
87
			}
88
		}
89
	}
90
91
	private function createFailureResponse( RuntimeException $ex ): SofortNotificationResponse {
92
		return SofortNotificationResponse::newFailureResponse( [
93
			'message' => $ex->getMessage(),
94
			'stackTrace' => $ex->getTraceAsString()
95
		] );
96
	}
97
98
}
99