Completed
Push — typo3-10-compatibility ( b4f2e1...42d8ec )
by Torben
03:17
created

PaymentController::cancelAction()   B

Complexity

Conditions 5
Paths 12

Size

Total Lines 44

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 44
rs 8.9048
c 0
b 0
f 0
cc 5
nc 12
nop 2
1
<?php
2
namespace DERHANSEN\SfEventMgt\Controller;
3
4
/*
5
 * This file is part of the Extension "sf_event_mgt" for TYPO3 CMS.
6
 *
7
 * For the full copyright and license information, please read the
8
 * LICENSE.txt file that was distributed with this source code.
9
 */
10
11
use DERHANSEN\SfEventMgt\Event\ProcessPaymentCancelEvent;
12
use DERHANSEN\SfEventMgt\Event\ProcessPaymentFailureEvent;
13
use DERHANSEN\SfEventMgt\Event\ProcessPaymentInitializeEvent;
14
use DERHANSEN\SfEventMgt\Event\ProcessPaymentNotifyEvent;
15
use DERHANSEN\SfEventMgt\Event\ProcessPaymentSuccessEvent;
16
use DERHANSEN\SfEventMgt\Payment\Exception\PaymentException;
17
use TYPO3\CMS\Core\Utility\GeneralUtility;
18
use TYPO3\CMS\Extbase\Mvc\RequestInterface;
19
use TYPO3\CMS\Extbase\Mvc\ResponseInterface;
20
use TYPO3\CMS\Extbase\Security\Exception\InvalidHashException;
21
use TYPO3\CMS\Extbase\Utility\LocalizationUtility;
22
23
/**
24
 * PaymentController
25
 *
26
 * @author Torben Hansen <[email protected]>
27
 */
28
class PaymentController extends AbstractController
29
{
30
    /**
31
     * Catches all PaymentExceptions and sets the Exception message to the response content
32
     *
33
     * @param RequestInterface $request
34
     * @param ResponseInterface $response
35
     * @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
36
     */
37
    public function processRequest(RequestInterface $request, ResponseInterface $response)
38
    {
39
        try {
40
            parent::processRequest($request, $response);
41
        } catch (\DERHANSEN\SfEventMgt\Exception $e) {
42
            $response->setContent('<div class="payment-error">' . $e->getMessage() . '</div>');
43
        } catch (\TYPO3\CMS\Extbase\Security\Exception\InvalidHashException $e) {
44
            $response->setContent('<div class="payment-error">' . $e->getMessage() . '</div>');
45
        }
46
    }
47
48
    /**
49
     * Redirect to payment provider
50
     *
51
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
52
     * @param string $hmac
53
     */
54
    public function redirectAction($registration, $hmac)
55
    {
56
        $this->validateHmacForAction($registration, $hmac, $this->actionMethodName);
57
        $this->proceedWithAction($registration, $this->actionMethodName);
58
59
        $variables = [
60
            'sfEventMgtSettings' => $this->settings,
61
            'successUrl' => $this->getPaymentUriForAction('success', $registration),
62
            'failureUrl' => $this->getPaymentUriForAction('failure', $registration),
63
            'cancelUrl' => $this->getPaymentUriForAction('cancel', $registration),
64
            'notifyUrl' => $this->getPaymentUriForAction('notify', $registration),
65
            'registration' => $registration,
66
            'html' => ''
67
        ];
68
69
        $paymentMethod = $registration->getPaymentmethod();
70
71
        /**
72
         * If true, the externally called BeforeRedirect method requested, that the registration should be updated
73
         */
74
        $updateRegistration = false;
75
76
        $processPaymentRedirectEvent = new ProcessPaymentInitializeEvent(
77
            $variables,
78
            $paymentMethod,
79
            $updateRegistration,
80
            $registration,
81
            $this
82
        );
83
        $this->eventDispatcher->dispatch($processPaymentRedirectEvent);
0 ignored issues
show
Documentation introduced by
$processPaymentRedirectEvent is of type object<DERHANSEN\SfEvent...PaymentInitializeEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
84
        $variables = $processPaymentRedirectEvent->getVariables();
85
        $updateRegistration = $processPaymentRedirectEvent->getUpdateRegistration();
86
87
        if ($updateRegistration) {
88
            $this->registrationRepository->update($registration);
89
        }
90
91
        $this->view->assign('result', $variables);
92
    }
93
94
    /**
95
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
96
     * @param string $hmac
97
     */
98
    public function successAction($registration, $hmac)
99
    {
100
        $this->validateHmacForAction($registration, $hmac, $this->actionMethodName);
101
        $this->proceedWithAction($registration, $this->actionMethodName);
102
103
        $variables = ['html' => ''];
104
105
        $paymentMethod = $registration->getPaymentmethod();
106
107
        /**
108
         * If true, the externally called ProcessSuccess method requested, that the registration should be updated
109
         */
110
        $updateRegistration = false;
111
112
        $getVariables = is_array(GeneralUtility::_GET()) ? GeneralUtility::_GET() : [];
113
        $processPaymentSuccessEvent = new ProcessPaymentSuccessEvent(
114
            $variables,
115
            $paymentMethod,
116
            $updateRegistration,
117
            $registration,
118
            $getVariables,
0 ignored issues
show
Bug introduced by
It seems like $getVariables defined by is_array(\TYPO3\CMS\Core...ility::_GET() : array() on line 112 can also be of type string; however, DERHANSEN\SfEventMgt\Eve...essEvent::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
119
            $this
120
        );
121
        $this->eventDispatcher->dispatch($processPaymentSuccessEvent);
0 ignored issues
show
Documentation introduced by
$processPaymentSuccessEvent is of type object<DERHANSEN\SfEvent...essPaymentSuccessEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
122
        $variables = $processPaymentSuccessEvent->getVariables();
123
        $updateRegistration = $processPaymentSuccessEvent->getUpdateRegistration();
124
125
        if ($updateRegistration) {
126
            $this->registrationRepository->update($registration);
127
        }
128
129
        $this->view->assign('result', $variables);
130
    }
131
132
    /**
133
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
134
     * @param string $hmac
135
     */
136
    public function failureAction($registration, $hmac)
137
    {
138
        $this->validateHmacForAction($registration, $hmac, $this->actionMethodName);
139
        $this->proceedWithAction($registration, $this->actionMethodName);
140
141
        $variables = ['html' => ''];
142
143
        $paymentMethod = $registration->getPaymentmethod();
144
145
        /**
146
         * Update- and remove flags
147
         */
148
        $updateRegistration = false;
149
        $removeRegistration = false;
150
151
        $getVariables = is_array(GeneralUtility::_GET()) ? GeneralUtility::_GET() : [];
152
        $processPaymentFailureEvent = new ProcessPaymentFailureEvent(
153
            $variables,
154
            $paymentMethod,
155
            $updateRegistration,
156
            $removeRegistration,
157
            $registration,
158
            $getVariables,
0 ignored issues
show
Bug introduced by
It seems like $getVariables defined by is_array(\TYPO3\CMS\Core...ility::_GET() : array() on line 151 can also be of type string; however, DERHANSEN\SfEventMgt\Eve...ureEvent::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
159
            $this
160
        );
161
        $this->eventDispatcher->dispatch($processPaymentFailureEvent);
0 ignored issues
show
Documentation introduced by
$processPaymentFailureEvent is of type object<DERHANSEN\SfEvent...essPaymentFailureEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
162
        $variables = $processPaymentFailureEvent->getVariables();
163
        $updateRegistration = $processPaymentFailureEvent->getUpdateRegistration();
164
        $removeRegistration = $processPaymentFailureEvent->getRemoveRegistration();
165
166
        if ($updateRegistration) {
167
            $this->registrationRepository->update($registration);
168
        }
169
170
        if ($removeRegistration) {
171
            // First cancel depending registrations
172
            if ($registration->getAmountOfRegistrations() > 1) {
173
                $this->registrationService->cancelDependingRegistrations($registration);
174
            }
175
            $this->registrationRepository->remove($registration);
176
        }
177
178
        $this->view->assign('result', $variables);
179
    }
180
181
    /**
182
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
183
     * @param string $hmac
184
     */
185
    public function cancelAction($registration, $hmac)
186
    {
187
        $this->validateHmacForAction($registration, $hmac, $this->actionMethodName);
188
        $this->proceedWithAction($registration, $this->actionMethodName);
189
190
        $variables = ['html' => ''];
191
192
        $paymentMethod = $registration->getPaymentmethod();
193
194
        /**
195
         * Update- and remove flags
196
         */
197
        $updateRegistration = false;
198
        $removeRegistration = false;
199
200
        $getVariables = is_array(GeneralUtility::_GET()) ? GeneralUtility::_GET() : [];
201
        $processPaymentCancelEvent = new ProcessPaymentCancelEvent(
202
            $variables,
203
            $paymentMethod,
204
            $updateRegistration,
205
            $removeRegistration,
206
            $registration,
207
            $getVariables,
0 ignored issues
show
Bug introduced by
It seems like $getVariables defined by is_array(\TYPO3\CMS\Core...ility::_GET() : array() on line 200 can also be of type string; however, DERHANSEN\SfEventMgt\Eve...celEvent::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
208
            $this
209
        );
210
        $this->eventDispatcher->dispatch($processPaymentCancelEvent);
0 ignored issues
show
Documentation introduced by
$processPaymentCancelEvent is of type object<DERHANSEN\SfEvent...cessPaymentCancelEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
211
        $variables = $processPaymentCancelEvent->getVariables();
212
        $updateRegistration = $processPaymentCancelEvent->getUpdateRegistration();
213
        $removeRegistration = $processPaymentCancelEvent->getRemoveRegistration();
214
215
        if ($updateRegistration) {
216
            $this->registrationRepository->update($registration);
217
        }
218
219
        if ($removeRegistration) {
220
            // First cancel depending registrations
221
            if ($registration->getAmountOfRegistrations() > 1) {
222
                $this->registrationService->cancelDependingRegistrations($registration);
223
            }
224
            $this->registrationRepository->remove($registration);
225
        }
226
227
        $this->view->assign('result', $variables);
228
    }
229
230
    /**
231
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
232
     * @param string $hmac
233
     */
234
    public function notifyAction($registration, $hmac)
235
    {
236
        $this->validateHmacForAction($registration, $hmac, $this->actionMethodName);
237
        $this->proceedWithAction($registration, $this->actionMethodName);
238
239
        $variables = ['html' => ''];
240
241
        $paymentMethod = $registration->getPaymentmethod();
242
243
        /**
244
         * Initialize update-flag
245
         *
246
         * If true, the externally called ProcessNotify method requested, that the registration should be updated
247
         */
248
        $updateRegistration = false;
249
250
        $getVariables = is_array(GeneralUtility::_GET()) ? GeneralUtility::_GET() : [];
251
        $processPaymentNotifyEvent = new ProcessPaymentNotifyEvent(
252
            $variables,
253
            $paymentMethod,
254
            $updateRegistration,
255
            $registration,
256
            $getVariables,
0 ignored issues
show
Bug introduced by
It seems like $getVariables defined by is_array(\TYPO3\CMS\Core...ility::_GET() : array() on line 250 can also be of type string; however, DERHANSEN\SfEventMgt\Eve...ifyEvent::__construct() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
257
            $this
258
        );
259
        $this->eventDispatcher->dispatch($processPaymentNotifyEvent);
0 ignored issues
show
Documentation introduced by
$processPaymentNotifyEvent is of type object<DERHANSEN\SfEvent...cessPaymentNotifyEvent>, but the function expects a object<Psr\EventDispatcher\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
260
        $variables = $processPaymentNotifyEvent->getVariables();
261
        $updateRegistration = $processPaymentNotifyEvent->getUpdateRegistration();
262
263
        if ($updateRegistration) {
264
            $this->registrationRepository->update($registration);
265
        }
266
267
        $this->view->assign('result', $variables);
268
    }
269
270
    /**
271
     * Checks if the given action can be called for the given registration / event and throws
272
     * an exception if action should not proceed
273
     *
274
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
275
     * @param string $actionName
276
     * @throws PaymentException
277
     * @return void
278
     */
279
    protected function proceedWithAction($registration, $actionName)
280
    {
281
        if ($registration->getEvent()->getEnablePayment() === false) {
282
            $message = LocalizationUtility::translate('payment.messages.paymentNotEnabled', 'sf_event_mgt');
283
            throw new PaymentException($message, 1899934881);
284
        }
285
286
        if ($this->paymentService->paymentActionEnabled($registration->getPaymentmethod(), $actionName) === false) {
287
            $message = LocalizationUtility::translate('payment.messages.actionNotEnabled', 'sf_event_mgt');
288
            throw new PaymentException($message, 1899934882);
289
        }
290
291
        if ($registration->getPaid()) {
292
            $message = LocalizationUtility::translate('payment.messages.paymentAlreadyProcessed', 'sf_event_mgt');
293
            throw new PaymentException($message, 1899934883);
294
        }
295
296
        if ($registration->getEvent()->getRestrictPaymentMethods()) {
297
            $selectedPaymentMethods = explode(',', $registration->getEvent()->getSelectedPaymentMethods());
298
            if (!in_array($registration->getPaymentmethod(), $selectedPaymentMethods)) {
299
                $message = LocalizationUtility::translate('payment.messages.paymentMethodNotAvailable', 'sf_event_mgt');
300
                throw new PaymentException($message, 1899934884);
301
            }
302
        }
303
    }
304
305
    /**
306
     * Checks the HMAC for the given action and registration
307
     *
308
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
309
     * @param string $hmac
310
     * @param string $action
311
     * @throws InvalidHashException
312
     */
313
    protected function validateHmacForAction($registration, $hmac, $action)
314
    {
315
        $result = $this->hashService->validateHmac($action . '-' . $registration->getUid(), $hmac);
316
        if (!$result) {
317
            $message = LocalizationUtility::translate('payment.messages.invalidHmac', 'sf_event_mgt');
318
            throw new InvalidHashException($message, 1899934890);
319
        }
320
    }
321
322
    /**
323
     * Returns the payment Uri for the given action and registration
324
     *
325
     * @param string $action
326
     * @param \DERHANSEN\SfEventMgt\Domain\Model\Registration $registration
327
     * @throws \TYPO3\CMS\Extbase\Security\Exception\InvalidArgumentForHashGenerationException
328
     * @return string
329
     */
330
    protected function getPaymentUriForAction($action, $registration)
331
    {
332
        $this->uriBuilder
333
            ->setCreateAbsoluteUri(true);
334
335
        return $this->uriBuilder->uriFor(
336
            $action,
337
            [
338
                'registration' => $registration,
339
                'hmac' => $this->hashService->generateHmac($action . 'Action-' . $registration->getUid())
340
            ],
341
            'Payment',
342
            'sfeventmgt',
343
            'Pipayment'
344
        );
345
    }
346
}
347