Completed
Push — master ( 04583c...efa664 )
by Joachim
18:49
created

PaymentController::showAction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 11
rs 9.4285
cc 2
eloc 6
nc 2
nop 1
1
<?php
2
3
namespace Loevgaard\DandomainAltapayBundle\Controller;
4
5
use Loevgaard\Dandomain\Pay\Helper\ChecksumHelper;
6
use Loevgaard\Dandomain\Pay\Model\Payment as DandomainPayment;
7
use Loevgaard\DandomainAltapayBundle\Annotation\LogHttpTransaction;
8
use Loevgaard\DandomainAltapayBundle\Entity\Payment;
9
use Loevgaard\DandomainAltapayBundle\Exception\AltapayPaymentRequestException;
10
use Loevgaard\DandomainAltapayBundle\Exception\ChecksumMismatchException;
11
use Loevgaard\DandomainAltapayBundle\Exception\PaymentException;
12
use Loevgaard\DandomainAltapayBundle\Exception\TerminalNotFoundException;
13
use Loevgaard\DandomainAltapayBundle\Handler\PaymentHandler;
14
use Loevgaard\DandomainAltapayBundle\PayloadGenerator\PaymentRequestPayloadGenerator;
15
use Loevgaard\DandomainAltapayBundle\PsrHttpMessage\DiactorosTrait;
16
use Loevgaard\DandomainAltapayBundle\Translation\TranslatorTrait;
17
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
18
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
19
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
20
use Symfony\Component\HttpFoundation\RedirectResponse;
21
use Symfony\Component\HttpFoundation\Request;
22
use Symfony\Component\HttpFoundation\Response;
23
24
/**
25
 * @Route("/payment")
26
 */
27
class PaymentController extends Controller
28
{
29
    use TranslatorTrait;
30
    use DiactorosTrait;
31
32
    /**
33
     * @Method("GET")
34
     * @Route("", name="loevgaard_dandomain_altapay_payment_index")
35
     *
36
     * @return Response
37
     */
38
    public function indexAction()
39
    {
40
        $paymentManager = $this->container->get('loevgaard_dandomain_altapay.payment_manager');
41
42
        /** @var Payment[] $payments */
43
        $payments = $paymentManager->getRepository()->findAll();
44
45
        return $this->render('@LoevgaardDandomainAltapay/payment/index.html.twig', [
46
            'payments' => $payments,
47
        ]);
48
    }
49
50
    /**
51
     * @Method("GET")
52
     * @Route("/{paymentId}/show", name="loevgaard_dandomain_altapay_payment_show")
53
     *
54
     * @param int $paymentId
55
     *
56
     * @return Response
57
     */
58
    public function showAction(int $paymentId)
59
    {
60
        $payment = $this->getPaymentFromId($paymentId);
61
        if (!$payment) {
62
            throw $this->createNotFoundException('Payment with id `'.$paymentId.'` not found');
63
        }
64
65
        return $this->render('@LoevgaardDandomainAltapay/payment/show.html.twig', [
66
            'payment' => $payment,
67
        ]);
68
    }
69
70
    /**
71
     * Payment flow
72
     * 1. The Dandomain payment API POSTs to this page with the terminal slug in the URL
73
     * 2. After validating all input, we create a payment request to the Altapay API
74
     * 3. Finally we redirect the user to the URL given by the Altapay API.
75
     *
76
     * @Method("POST")
77
     * @Route("/{terminal}", name="loevgaard_dandomain_altapay_payment_new")
78
     *
79
     * @LogHttpTransaction()
80
     *
81
     * @param string  $terminal
82
     * @param Request $request
83
     *
84
     * @return RedirectResponse
85
     *
86
     * @throws PaymentException
87
     */
88
    public function newAction(string $terminal, Request $request)
89
    {
90
        $terminalManager = $this->container->get('loevgaard_dandomain_altapay.terminal_manager');
91
        $paymentManager = $this->container->get('loevgaard_dandomain_altapay.payment_manager');
92
        $translator = $this->getTranslator();
93
94
        $psrRequest = $this->createPsrRequest($request);
95
        $dandomainPayment = DandomainPayment::createFromRequest($psrRequest);
96
97
        $checksumHelper = new ChecksumHelper(
98
            $dandomainPayment,
99
            $this->container->getParameter('loevgaard_dandomain_altapay.shared_key_1'),
100
            $this->container->getParameter('loevgaard_dandomain_altapay.shared_key_2')
101
        );
102
103
        $paymentEntity = $paymentManager->createPaymentFromDandomainPaymentRequest($dandomainPayment);
104
        $paymentManager->update($paymentEntity);
105
106
        $terminalEntity = $terminalManager->findTerminalBySlug($terminal, true);
107
        if (!$terminalEntity) {
108
            throw TerminalNotFoundException::create($translator->trans('payment.exception.terminal_not_found', ['%terminal%' => $terminal], 'LoevgaardDandomainAltapayBundle'), $request, $paymentEntity);
109
        }
110
111
        if (!$checksumHelper->checksumMatches()) {
112
            throw ChecksumMismatchException::create($translator->trans('payment.exception.checksum_mismatch', [], 'LoevgaardDandomainAltapayBundle'), $request, $paymentEntity);
113
        }
114
115
        $paymentRequestPayloadGenerator = new PaymentRequestPayloadGenerator($this->container, $dandomainPayment, $terminalEntity, $paymentEntity, $checksumHelper);
116
        $paymentRequestPayload = $paymentRequestPayloadGenerator->generate();
117
118
        $altapay = $this->container->get('loevgaard_dandomain_altapay.altapay_client');
119
        $response = $altapay->createPaymentRequest($paymentRequestPayload);
120
121
        if (!$response->isSuccessful()) {
122
            throw AltapayPaymentRequestException::create($translator->trans('payment.exception.altapay_payment_request', ['%gateway_message%' => $response->getErrorMessage()], 'LoevgaardDandomainAltapayBundle'), $request, $paymentEntity);
123
        }
124
125
        return $this->redirect($response->getUrl());
126
    }
127
128
    /**
129
     * @Method("GET")
130
     * @Route("/{paymentId}/capture", name="loevgaard_dandomain_altapay_payment_capture")
131
     *
132
     * @param int     $paymentId
133
     * @param Request $request
134
     *
135
     * @return RedirectResponse
136
     */
137 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...
138
    {
139
        $payment = $this->getPaymentFromId($paymentId);
140
141
        if ($payment) {
142
            $paymentHandler = $this->getPaymentHandler();
143
            $res = $paymentHandler->capture($payment, $request->query->get('amount'));
144
145
            if ($res->isSuccessful()) {
146
                $this->addFlash('success', 'The payment for order '.$payment->getOrderId().' was captured.'); // @todo fix translation
147
            } else {
148
                $this->addFlash('danger', 'An error occurred during capture of the payment: '.$res->getErrorMessage()); // @todo fix translation
149
            }
150
        }
151
152
        $redirect = $request->headers->get('referer') ? $request->headers->get('referer') : $this->generateUrl('loevgaard_dandomain_altapay_payment_index');
153
154
        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 152 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...
155
    }
156
157
    /**
158
     * @Method({"POST", "GET"})
159
     * @Route("/{paymentId}/refund", name="loevgaard_dandomain_altapay_payment_refund")
160
     *
161
     * @param int     $paymentId
162
     * @param Request $request
163
     *
164
     * @return RedirectResponse
165
     */
166 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...
167
    {
168
        $payment = $this->getPaymentFromId($paymentId);
169
170
        if ($payment) {
171
            $paymentHandler = $this->getPaymentHandler();
172
            $res = $paymentHandler->refund($payment, null, $request->query->get('amount'));
173
174
            if ($res->isSuccessful()) {
175
                $this->addFlash('success', 'The payment for order '.$payment->getOrderId().' was refunded.'); // @todo fix translation
176
            } else {
177
                $this->addFlash('danger', 'An error occurred during refund of the payment: '.$res->getErrorMessage()); // @todo fix translation
178
            }
179
        }
180
181
        $redirect = $request->headers->get('referer') ?: $this->generateUrl('loevgaard_dandomain_altapay_payment_index');
182
183
        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 181 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...
184
    }
185
186
    /**
187
     * @Method("GET")
188
     * @Route("/{paymentId}/redirectToAltapay", name="loevgaard_dandomain_altapay_redirect_to_altapay_payment")
189
     *
190
     * @param int $paymentId
191
     *
192
     * @return RedirectResponse
193
     */
194
    public function redirectToAltapayPaymentAction(int $paymentId)
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