Completed
Push — master ( c55f61...fd7370 )
by Joachim
16:23
created

PaymentController   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 204
Duplicated Lines 18.63 %

Coupling/Cohesion

Components 1
Dependencies 15

Importance

Changes 0
Metric Value
wmc 19
c 0
b 0
f 0
lcom 1
cbo 15
dl 38
loc 204
rs 9.1666

8 Methods

Rating   Name   Duplication   Size   Complexity  
A indexAction() 0 11 1
A showAction() 0 11 2
B newAction() 0 39 4
A captureAction() 19 19 4
A refundAction() 19 19 4
A redirectToAltapayPaymentAction() 0 8 1
A getPaymentFromId() 0 13 2
A getPaymentHandler() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Loevgaard\DandomainAltapayBundle\Controller;
4
5
use Loevgaard\Dandomain\Pay\Handler;
6
use Loevgaard\DandomainAltapayBundle\Annotation\LogHttpTransaction;
7
use Loevgaard\DandomainAltapayBundle\Entity\Payment;
8
use Loevgaard\DandomainAltapayBundle\Exception\AltapayPaymentRequestException;
9
use Loevgaard\DandomainAltapayBundle\Exception\ChecksumMismatchException;
10
use Loevgaard\DandomainAltapayBundle\Exception\PaymentException;
11
use Loevgaard\DandomainAltapayBundle\Exception\TerminalNotFoundException;
12
use Loevgaard\DandomainAltapayBundle\Handler\PaymentHandler;
13
use Loevgaard\DandomainAltapayBundle\PayloadGenerator\PaymentRequestPayloadGenerator;
14
use Loevgaard\DandomainAltapayBundle\PsrHttpMessage\DiactorosTrait;
15
use Loevgaard\DandomainAltapayBundle\Translation\TranslatorTrait;
16
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
17
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
18
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
19
use Symfony\Component\HttpFoundation\RedirectResponse;
20
use Symfony\Component\HttpFoundation\Request;
21
use Symfony\Component\HttpFoundation\Response;
22
23
/**
24
 * @Route("/payment")
25
 */
26
class PaymentController extends Controller
27
{
28
    use TranslatorTrait;
29
    use DiactorosTrait;
30
31
    /**
32
     * @Method("GET")
33
     * @Route("", name="loevgaard_dandomain_altapay_payment_index")
34
     *
35
     * @return Response
36
     */
37
    public function indexAction()
38
    {
39
        $paymentManager = $this->container->get('loevgaard_dandomain_altapay.payment_manager');
40
41
        /** @var Payment[] $payments */
42
        $payments = $paymentManager->getRepository()->findAll();
43
44
        return $this->render('@LoevgaardDandomainAltapay/payment/index.html.twig', [
45
            'payments' => $payments,
46
        ]);
47
    }
48
49
    /**
50
     * @Method("GET")
51
     * @Route("/{paymentId}/show", name="loevgaard_dandomain_altapay_payment_show")
52
     *
53
     * @param int $paymentId
54
     *
55
     * @return Response
56
     */
57
    public function showAction(int $paymentId)
58
    {
59
        $payment = $this->getPaymentFromId($paymentId);
60
        if (!$payment) {
61
            throw $this->createNotFoundException('Payment with id `'.$paymentId.'` not found');
62
        }
63
64
        return $this->render('@LoevgaardDandomainAltapay/payment/show.html.twig', [
65
            'payment' => $payment,
66
        ]);
67
    }
68
69
    /**
70
     * Payment flow
71
     * 1. The Dandomain payment API POSTs to this page with the terminal slug in the URL
72
     * 2. After validating all input, we create a payment request to the Altapay API
73
     * 3. Finally we redirect the user to the URL given by the Altapay API.
74
     *
75
     * @Method("POST")
76
     * @Route("/{terminal}", name="loevgaard_dandomain_altapay_payment_new")
77
     *
78
     * @LogHttpTransaction()
79
     *
80
     * @param string  $terminal
81
     * @param Request $request
82
     *
83
     * @return RedirectResponse
84
     *
85
     * @throws PaymentException
86
     */
87
    public function newAction(string $terminal, Request $request)
88
    {
89
        $terminalManager = $this->container->get('loevgaard_dandomain_altapay.terminal_manager');
90
        $paymentManager = $this->container->get('loevgaard_dandomain_altapay.payment_manager');
91
92
        $psrRequest = $this->createPsrRequest($request);
93
94
        $handler = new Handler(
95
            $psrRequest,
96
            $this->container->getParameter('loevgaard_dandomain_altapay.shared_key_1'),
97
            $this->container->getParameter('loevgaard_dandomain_altapay.shared_key_2')
98
        );
99
100
        $dandomainPaymentRequest = $handler->getPaymentRequest();
101
102
        $paymentEntity = $paymentManager->createPaymentFromDandomainPaymentRequest($dandomainPaymentRequest);
103
        $paymentManager->update($paymentEntity);
104
105
        $terminalEntity = $terminalManager->findTerminalBySlug($terminal, true);
106
        if (!$terminalEntity) {
107
            throw TerminalNotFoundException::create($this->trans('payment.exception.terminal_not_found', ['%terminal%' => $terminal]), $request, $paymentEntity);
108
        }
109
110
        if (!$handler->checksumMatches()) {
111
            throw ChecksumMismatchException::create($this->trans('payment.exception.checksum_mismatch'), $request, $paymentEntity);
112
        }
113
114
        $paymentRequestPayloadGenerator = new PaymentRequestPayloadGenerator($this->container, $dandomainPaymentRequest, $terminalEntity, $paymentEntity, $handler);
115
        $paymentRequestPayload = $paymentRequestPayloadGenerator->generate();
116
117
        $altapay = $this->container->get('loevgaard_dandomain_altapay.altapay_client');
118
        $response = $altapay->createPaymentRequest($paymentRequestPayload);
119
120
        if (!$response->isSuccessful()) {
121
            throw AltapayPaymentRequestException::create($this->trans('payment.exception.altapay_payment_request', ['%gateway_message%' => $response->getErrorMessage()]), $request, $paymentEntity);
122
        }
123
124
        return $this->redirect($response->getUrl());
125
    }
126
127
    /**
128
     * @Method("GET")
129
     * @Route("/{paymentId}/capture", name="loevgaard_dandomain_altapay_payment_capture")
130
     *
131
     * @param int     $paymentId
132
     * @param Request $request
133
     *
134
     * @return RedirectResponse
135
     */
136 View Code Duplication
    public function captureAction(int $paymentId, Request $request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
137
    {
138
        $payment = $this->getPaymentFromId($paymentId);
139
140
        if ($payment) {
141
            $paymentHandler = $this->getPaymentHandler();
142
            $res = $paymentHandler->capture($payment, $request->query->get('amount'));
143
144
            if ($res->isSuccessful()) {
145
                $this->addFlash('success', 'The payment for order '.$payment->getOrderId().' was captured.'); // @todo fix translation
146
            } else {
147
                $this->addFlash('danger', 'An error occurred during capture of the payment: '.$res->getErrorMessage()); // @todo fix translation
148
            }
149
        }
150
151
        $redirect = $request->headers->get('referer') ? $request->headers->get('referer') : $this->generateUrl('loevgaard_dandomain_altapay_payment_index');
152
153
        return $this->redirect($redirect);
0 ignored issues
show
Bug introduced by
It seems like $redirect defined by $request->headers->get('...altapay_payment_index') on line 151 can also be of type array; however, Symfony\Bundle\Framework...rollerTrait::redirect() does only seem to accept string, 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...
154
    }
155
156
    /**
157
     * @Method({"POST", "GET"})
158
     * @Route("/{paymentId}/refund", name="loevgaard_dandomain_altapay_payment_refund")
159
     *
160
     * @param int     $paymentId
161
     * @param Request $request
162
     *
163
     * @return RedirectResponse
164
     */
165 View Code Duplication
    public function refundAction(int $paymentId, Request $request)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
166
    {
167
        $payment = $this->getPaymentFromId($paymentId);
168
169
        if ($payment) {
170
            $paymentHandler = $this->getPaymentHandler();
171
            $res = $paymentHandler->refund($payment, null, $request->query->get('amount'));
172
173
            if ($res->isSuccessful()) {
174
                $this->addFlash('success', 'The payment for order '.$payment->getOrderId().' was refunded.'); // @todo fix translation
175
            } else {
176
                $this->addFlash('danger', 'An error occurred during refund of the payment: '.$res->getErrorMessage()); // @todo fix translation
177
            }
178
        }
179
180
        $redirect = $request->headers->get('referer') ?: $this->generateUrl('loevgaard_dandomain_altapay_payment_index');
181
182
        return $this->redirect($redirect);
0 ignored issues
show
Bug introduced by
It seems like $redirect defined by $request->headers->get('...altapay_payment_index') on line 180 can also be of type array; however, Symfony\Bundle\Framework...rollerTrait::redirect() does only seem to accept string, 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...
183
    }
184
185
    /**
186
     * @Method("GET")
187
     * @Route("/{paymentId}/redirectToAltapay", name="loevgaard_dandomain_altapay_redirect_to_altapay_payment")
188
     *
189
     * @param int     $paymentId
190
     * @param Request $request
191
     *
192
     * @return RedirectResponse
193
     */
194
    public function redirectToAltapayPaymentAction(int $paymentId, Request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
195
    {
196
        $payment = $this->getPaymentFromId($paymentId);
197
198
        $url = $this->getParameter('loevgaard_dandomain_altapay.altapay_url').'/merchant/transactions/paymentDetails/'.$payment->getAltapayId();
199
200
        return $this->redirect($url);
201
    }
202
203
    /**
204
     * @param int $paymentId
205
     *
206
     * @return Payment
207
     */
208
    private function getPaymentFromId(int $paymentId): Payment
209
    {
210
        $paymentManager = $this->get('loevgaard_dandomain_altapay.payment_manager');
211
212
        /** @var Payment $payment */
213
        $payment = $paymentManager->getRepository()->find($paymentId);
214
215
        if (!$payment) {
216
            throw $this->createNotFoundException('Payment with id `'.$paymentId.'` not found');
217
        }
218
219
        return $payment;
220
    }
221
222
    /**
223
     * @return PaymentHandler
224
     */
225
    private function getPaymentHandler(): PaymentHandler
226
    {
227
        return $this->get('loevgaard_dandomain_altapay.payment_handler');
228
    }
229
}
230