Completed
Push — master ( ca9755...1beb5a )
by Joachim
03:30
created

redirectToAltapayPaymentAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 2
1
<?php
2
3
namespace Loevgaard\DandomainAltapayBundle\Controller;
4
5
use Loevgaard\AltaPay\Payload\CaptureReservation as CaptureReservationPayload;
6
use Loevgaard\AltaPay\Payload\OrderLine as OrderLinePayload;
7
use Loevgaard\AltaPay\Payload\PaymentRequest as PaymentRequestPayload;
8
use Loevgaard\AltaPay\Payload\PaymentRequest\Config as ConfigPayload;
9
use Loevgaard\AltaPay\Payload\PaymentRequest\CustomerInfo as CustomerInfoPayload;
10
use Loevgaard\AltaPay\Payload\RefundCapturedReservation as RefundCapturedReservationPayload;
11
use Loevgaard\Dandomain\Pay\Handler;
12
use Loevgaard\DandomainAltapayBundle\Annotation\LogHttpTransaction;
13
use Loevgaard\DandomainAltapayBundle\Entity\Payment;
14
use Loevgaard\DandomainAltapayBundle\Exception\AltapayPaymentRequestException;
15
use Loevgaard\DandomainAltapayBundle\Exception\ChecksumMismatchException;
16
use Loevgaard\DandomainAltapayBundle\Exception\PaymentException;
17
use Loevgaard\DandomainAltapayBundle\Exception\TerminalNotFoundException;
18
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
19
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
20
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
21
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
22
use Symfony\Component\HttpFoundation\RedirectResponse;
23
use Symfony\Component\HttpFoundation\Request;
24
use Symfony\Component\HttpFoundation\Response;
25
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
26
27
/**
28
 * @Route("/payment")
29
 */
30
class PaymentController extends Controller
31
{
32
    /**
33
     * @Method("GET")
34
     * @Route("", name="loevgaard_dandomain_altapay_payment_index")
35
     *
36
     * @param Request $request
37
     *
38
     * @return Response
39
     */
40
    public function indexAction(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...
41
    {
42
        $paymentManager = $this->container->get('loevgaard_dandomain_altapay.payment_manager');
43
44
        /** @var Payment[] $payments */
45
        $payments = $paymentManager->getRepository()->findAll();
46
47
        return $this->render('@LoevgaardDandomainAltapay/payment/index.html.twig', [
48
            'payments' => $payments,
49
        ]);
50
    }
51
52
    /**
53
     * @Method("GET")
54
     * @Route("/{paymentId}/show", name="loevgaard_dandomain_altapay_payment_show")
55
     *
56
     * @param int     $paymentId
57
     * @param Request $request
58
     *
59
     * @return Response
60
     */
61
    public function showAction(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...
62
    {
63
        $payment = $this->getPaymentFromId($paymentId);
64
        if(!$payment) {
65
            throw $this->createNotFoundException('Payment with id `'.$paymentId.'` not found');
66
        }
67
68
        return $this->render('@LoevgaardDandomainAltapay/payment/show.html.twig', [
69
            'payment' => $payment,
70
        ]);
71
    }
72
73
    /**
74
     * Payment flow
75
     * 1. The Dandomain payment API POSTs to this page with the terminal slug in the URL
76
     * 2. After validating all input, we create a payment request to the Altapay API
77
     * 3. Finally we redirect the user to the URL given by the Altapay API.
78
     *
79
     * @Method("POST")
80
     * @Route("/{terminal}", name="loevgaard_dandomain_altapay_payment_new")
81
     *
82
     * @LogHttpTransaction()
83
     *
84
     * @param $terminal
85
     * @param Request $request
86
     *
87
     * @return RedirectResponse
88
     *
89
     * @throws PaymentException
90
     */
91
    public function newAction($terminal, Request $request)
92
    {
93
        $terminalManager = $this->container->get('loevgaard_dandomain_altapay.terminal_manager');
94
        $paymentManager = $this->container->get('loevgaard_dandomain_altapay.payment_manager');
95
96
        // convert symfony request to PSR7 request
97
        $psr7Factory = new DiactorosFactory();
98
        $psrRequest = $psr7Factory->createRequest($request);
99
100
        $handler = new Handler(
101
            $psrRequest,
102
            $this->container->getParameter('loevgaard_dandomain_altapay.shared_key_1'),
103
            $this->container->getParameter('loevgaard_dandomain_altapay.shared_key_2')
104
        );
105
106
        $dandomainPaymentRequest = $handler->getPaymentRequest();
107
108
        $paymentEntity = $paymentManager->createPaymentFromDandomainPaymentRequest($dandomainPaymentRequest);
109
        $paymentManager->update($paymentEntity);
110
111
        $terminalEntity = $terminalManager->findTerminalBySlug($terminal, true);
112
        if (!$terminalEntity) {
113
            // @todo fix translation
114
            throw TerminalNotFoundException::create('Terminal `'.$terminal.'` does not exist', $request, $paymentEntity);
115
        }
116
117
        if (!$handler->checksumMatches()) {
118
            // @todo fix translation
119
            throw ChecksumMismatchException::create('Checksum mismatch. Try again', $request, $paymentEntity);
120
        }
121
122
        $paymentRequestPayload = new PaymentRequestPayload(
123
            $terminalEntity->getTitle(),
124
            $dandomainPaymentRequest->getOrderId(),
125
            $dandomainPaymentRequest->getTotalAmount(),
126
            $dandomainPaymentRequest->getCurrencySymbol()
127
        );
128
129
        foreach ($dandomainPaymentRequest->getPaymentLines() as $paymentLine) {
130
            $orderLinePayload = new OrderLinePayload(
131
                $paymentLine->getName(),
132
                $paymentLine->getProductNumber(),
133
                $paymentLine->getQuantity(),
134
                $paymentLine->getPrice()
135
            );
136
            $orderLinePayload->setTaxPercent($paymentLine->getVat());
137
138
            $paymentRequestPayload->addOrderLine($orderLinePayload);
139
        }
140
141
        $customerInfoPayload = new CustomerInfoPayload();
142
        $customerNames = explode(' ', $dandomainPaymentRequest->getCustomerName(), 2);
143
        $shippingNames = explode(' ', $dandomainPaymentRequest->getDeliveryName(), 2);
144
        $customerInfoPayload
145
            ->setBillingFirstName($customerNames[0] ?? '')
146
            ->setBillingLastName($customerNames[1] ?? '')
147
            ->setBillingAddress(
148
                $dandomainPaymentRequest->getCustomerAddress().
149
                ($dandomainPaymentRequest->getCustomerAddress2() ? "\r\n".$dandomainPaymentRequest->getCustomerAddress2() : '')
150
            )
151
            ->setBillingPostal($dandomainPaymentRequest->getCustomerZipCode())
152
            ->setBillingCity($dandomainPaymentRequest->getCustomerCity())
153
            ->setBillingCountry($dandomainPaymentRequest->getCustomerCountry())
154
            ->setShippingFirstName($shippingNames[0] ?? '')
155
            ->setShippingLastName($shippingNames[1] ?? '')
156
            ->setShippingAddress(
157
                $dandomainPaymentRequest->getDeliveryAddress().
158
                ($dandomainPaymentRequest->getDeliveryAddress2() ? "\r\n".$dandomainPaymentRequest->getDeliveryAddress2() : '')
159
            )
160
            ->setShippingPostal($dandomainPaymentRequest->getDeliveryZipCode())
161
            ->setShippingCity($dandomainPaymentRequest->getDeliveryCity())
162
            ->setShippingCountry($dandomainPaymentRequest->getDeliveryCountry())
163
        ;
164
        $paymentRequestPayload->setCustomerInfo($customerInfoPayload);
165
166
        $configPayload = new ConfigPayload();
167
        $configPayload
168
            ->setCallbackForm($this->generateUrl('loevgaard_dandomain_altapay_callback_form', [], UrlGeneratorInterface::ABSOLUTE_URL))
169
            ->setCallbackOk($this->generateUrl('loevgaard_dandomain_altapay_callback_ok', [], UrlGeneratorInterface::ABSOLUTE_URL))
170
            ->setCallbackFail($this->generateUrl('loevgaard_dandomain_altapay_callback_fail', [], UrlGeneratorInterface::ABSOLUTE_URL))
171
            ->setCallbackRedirect($this->generateUrl('loevgaard_dandomain_altapay_callback_redirect', [], UrlGeneratorInterface::ABSOLUTE_URL))
172
            ->setCallbackOpen($this->generateUrl('loevgaard_dandomain_altapay_callback_open', [], UrlGeneratorInterface::ABSOLUTE_URL))
173
            ->setCallbackNotification($this->generateUrl('loevgaard_dandomain_altapay_callback_notification', [], UrlGeneratorInterface::ABSOLUTE_URL))
174
        ;
175
        $paymentRequestPayload->setConfig($configPayload);
176
177
        $paymentRequestPayload
178
            ->setCookiePart($this->getParameter('loevgaard_dandomain_altapay.cookie_payment_id'), $paymentEntity->getId())
179
            ->setCookiePart($this->getParameter('loevgaard_dandomain_altapay.cookie_checksum_complete'), $handler->getChecksum2())
180
        ;
181
182
        $altapay = $this->container->get('loevgaard_dandomain_altapay.altapay_client');
183
        $response = $altapay->createPaymentRequest($paymentRequestPayload);
184
185
        if (!$response->isSuccessful()) {
186
            // @todo fix translation
187
            throw AltapayPaymentRequestException::create('An error occured during payment request. Try again. Message from gateway: '.$response->getErrorMessage(), $request, $paymentEntity);
188
        }
189
190
        return new RedirectResponse($response->getUrl());
191
    }
192
193
    /**
194
     * @Method("GET")
195
     * @Route("/{paymentId}/capture", name="loevgaard_dandomain_altapay_payment_capture")
196
     *
197
     * @param int     $paymentId
198
     * @param Request $request
199
     *
200
     * @return RedirectResponse
201
     */
202 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...
203
    {
204
        $payment = $this->getPaymentFromId($paymentId);
205
206
        if ($payment) {
207
            $altapayClient = $this->get('loevgaard_dandomain_altapay.altapay_client');
208
209
            $payload = new CaptureReservationPayload($payment->getAltapayId());
210
            $res = $altapayClient->captureReservation($payload);
211
212
            if ($res->isSuccessful()) {
213
                $this->addFlash('success', 'The payment for order '.$payment->getOrderId().' was captured.'); // @todo fix translation
214
            } else {
215
                $this->addFlash('danger', 'An error occurred during capture of the payment: '.$res->getErrorMessage()); // @todo fix translation
216
            }
217
        }
218
219
        $redirect = $request->headers->get('referer') ? $request->headers->get('referer') : $this->generateUrl('loevgaard_dandomain_altapay_payment_index');
220
221
        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 219 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...
222
    }
223
224
    /**
225
     * @Method({"POST", "GET"})
226
     * @Route("/{paymentId}/refund", name="loevgaard_dandomain_altapay_payment_refund")
227
     *
228
     * @param int     $paymentId
229
     * @param Request $request
230
     *
231
     * @return RedirectResponse
232
     */
233 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...
234
    {
235
        $payment = $this->getPaymentFromId($paymentId);
236
237
        if ($payment) {
238
            $altapayClient = $this->get('loevgaard_dandomain_altapay.altapay_client');
239
240
            $payload = new RefundCapturedReservationPayload($payment->getAltapayId());
241
            $res = $altapayClient->refundCapturedReservation($payload);
242
243
            if ($res->isSuccessful()) {
244
                $this->addFlash('success', 'The payment for order '.$payment->getOrderId().' was refunded.'); // @todo fix translation
245
            } else {
246
                $this->addFlash('danger', 'An error occurred during refund of the payment: '.$res->getErrorMessage()); // @todo fix translation
247
            }
248
        }
249
250
        $redirect = $request->headers->get('referer') ? : $this->generateUrl('loevgaard_dandomain_altapay_payment_index');
251
252
        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 250 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...
253
    }
254
255
    /**
256
     * @Method("GET")
257
     * @Route("/{paymentId}/redirectToAltapay", name="loevgaard_dandomain_altapay_redirect_to_altapay_payment")
258
     *
259
     * @param int     $paymentId
260
     * @param Request $request
261
     *
262
     * @return RedirectResponse
263
     */
264
    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...
265
    {
266
        $payment = $this->getPaymentFromId($paymentId);
267
268
        // @todo the host should be fetched from parameters.yml
269
        $url = 'https://testgateway.altapaysecure.com/merchant/transactions/paymentDetails/'.$payment->getAltapayId();
270
271
        return $this->redirect($url);
272
    }
273
274
    /**
275
     * @param int $paymentId
276
     *
277
     * @return Payment
278
     */
279
    private function getPaymentFromId(int $paymentId): Payment
280
    {
281
        $paymentManager = $this->get('loevgaard_dandomain_altapay.payment_manager');
282
283
        /** @var Payment $payment */
284
        $payment = $paymentManager->getRepository()->find($paymentId);
285
286
        if(!$payment) {
287
            throw $this->createNotFoundException('Payment with id `'.$paymentId.'` not found');
288
        }
289
290
        return $payment;
291
    }
292
}
293