Completed
Push — master ( 262e68...84540b )
by Jeroen De
10s
created

PayPalNotificationHandler::createErrorResponse()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 15
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 12
nc 5
nop 1
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\Frontend\App\RouteHandlers;
6
7
use Symfony\Component\HttpFoundation\ParameterBag;
8
use Symfony\Component\HttpFoundation\Request;
9
use Symfony\Component\HttpFoundation\Response;
10
use WMDE\Euro\Euro;
11
use WMDE\Fundraising\Frontend\DonationContext\UseCases\HandlePayPalPaymentNotification\PayPalNotificationRequest;
12
use WMDE\Fundraising\Frontend\Factories\FunFunFactory;
13
use WMDE\Fundraising\Frontend\Infrastructure\PayPalPaymentNotificationVerifierException;
14
15
/**
16
 * @license GNU GPL v2+
17
 * @author Kai Nissen < [email protected] >
18
 */
19
class PayPalNotificationHandler {
20
21
	private $ffFactory;
22
23
	public function __construct( FunFunFactory $ffFactory ) {
24
		$this->ffFactory = $ffFactory;
25
	}
26
27
	public function handle( Request $request ): Response {
28
		$post = $request->request;
29
30
		try {
31
			$this->ffFactory->getPayPalPaymentNotificationVerifier()->verify( $post->all() );
32
		} catch ( PayPalPaymentNotificationVerifierException $e ) {
33
			// TODO: let PayPal resend IPN?
34
35
			return $this->createErrorResponse( $e );
36
		}
37
38
		// TODO: check txn_type
39
40
		$useCase = $this->ffFactory->newHandlePayPalPaymentNotificationUseCase( $this->getUpdateToken( $post ) );
41
42
		$useCase->handleNotification( $this->newUseCaseRequestFromPost( $post ) );
43
44
		return new Response( '', Response::HTTP_OK ); # PayPal expects an empty response
45
	}
46
47
	private function getUpdateToken( ParameterBag $postRequest ): string {
48
		return $this->getValueFromCustomVars( $postRequest->get( 'custom', '' ), 'utoken' );
49
	}
50
51
	private function getValueFromCustomVars( string $customVars, string $key ): string {
52
		$vars = json_decode( $customVars, true );
53
		return !empty( $vars[$key] ) ? $vars[$key] : '';
54
	}
55
56
	private function newUseCaseRequestFromPost( ParameterBag $postRequest ): PayPalNotificationRequest {
57
		return ( new PayPalNotificationRequest() )
58
			->setTransactionType( $postRequest->get( 'txn_type', '' ) )
59
			->setTransactionId( $postRequest->get( 'txn_id', '' ) )
60
			->setPayerId( $postRequest->get( 'payer_id', '' ) )
61
			->setSubscriberId( $postRequest->get( 'subscr_id', '' ) )
62
			->setPayerEmail( $postRequest->get( 'payer_email', '' ) )
63
			->setPayerStatus( $postRequest->get( 'payer_status', '' ) )
64
			->setPayerFirstName( $postRequest->get( 'first_name', '' ) )
65
			->setPayerLastName( $postRequest->get( 'last_name', '' ) )
66
			->setPayerAddressName( $postRequest->get( 'address_name', '' ) )
67
			->setPayerAddressStreet( $postRequest->get( 'address_street', '' ) )
68
			->setPayerAddressPostalCode( $postRequest->get( 'address_zip', '' ) )
69
			->setPayerAddressCity( $postRequest->get( 'address_city', '' ) )
70
			->setPayerAddressCountryCode( $postRequest->get( 'address_country_code', '' ) )
71
			->setPayerAddressStatus( $postRequest->get( 'address_status', '' ) )
72
			->setDonationId( (int)$postRequest->get( 'item_number', 0 ) )
73
			->setCurrencyCode( $postRequest->get( 'mc_currency', '' ) )
74
			->setTransactionFee( Euro::newFromString( $postRequest->get( 'mc_fee', '0' ) ) )
75
			->setAmountGross( Euro::newFromString( $postRequest->get( 'mc_gross', '0' ) ) )
76
			->setSettleAmount( Euro::newFromString( $postRequest->get( 'settle_amount', '0' ) ) )
77
			->setPaymentTimestamp( $postRequest->get( 'payment_date', '' ) )
78
			->setPaymentStatus( $postRequest->get( 'payment_status', '' ) )
79
			->setPaymentType( $postRequest->get( 'payment_type', '' ) );
80
	}
81
82
	private function createErrorResponse( PayPalPaymentNotificationVerifierException $e ): Response {
83
		switch ( $e->getCode() ) {
84
			case PayPalPaymentNotificationVerifierException::ERROR_UNSUPPORTED_STATUS;
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
85
				// Just ignore IPN notices with a status we don't handle
86
				return new Response( '', Response::HTTP_OK );
87
			case PayPalPaymentNotificationVerifierException::ERROR_WRONG_RECEIVER:
88
				return new Response( $e->getMessage(), Response::HTTP_FORBIDDEN );
89
			case PayPalPaymentNotificationVerifierException::ERROR_VERIFICATION_FAILED:
90
				return new Response( $e->getMessage(), Response::HTTP_FORBIDDEN );
91
			case PayPalPaymentNotificationVerifierException::ERROR_UNSUPPORTED_CURRENCY:
92
				return new Response( $e->getMessage(), Response::HTTP_NOT_ACCEPTABLE );
93
			default:
94
				return new Response( $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR );
95
		}
96
	}
97
98
}
99