Completed
Push — master ( 76090d...0eaa28 )
by Joachim
03:51
created

Controller/PaymentController.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Loevgaard\DandomainAltapayBundle\Controller;
4
5
use Loevgaard\Dandomain\Pay\Helper\ChecksumHelper;
6
use Loevgaard\DandomainAltapayBundle\Annotation\LogHttpTransaction;
7
use Loevgaard\DandomainAltapayBundle\Entity\Payment;
8
use Loevgaard\DandomainAltapayBundle\Event\PaymentCreated;
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 Money\Currency;
18
use Money\Money;
19
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
20
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
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
26
/**
27
 * @Route("/payment")
28
 */
29
class PaymentController extends Controller
30
{
31
    use TranslatorTrait;
32
    use DiactorosTrait;
33
34
    /**
35
     * @Method("GET")
36
     * @Route("", name="loevgaard_dandomain_altapay_payment_index")
37
     *
38
     * @param Request $request
39
     *
40
     * @return Response
41
     */
42 View Code Duplication
    public function indexAction(Request $request)
43
    {
44
        $paymentRepository = $this->container->get('loevgaard_dandomain_altapay.payment_repository');
45
46
        /** @var Payment[] $payments */
47
        $payments = $paymentRepository->findAllWithPaging($request->query->getInt('page', 1));
48
49
        return $this->render('@LoevgaardDandomainAltapay/payment/index.html.twig', [
50
            'payments' => $payments,
51
        ]);
52
    }
53
54
    /**
55
     * @Method("GET")
56
     * @Route("/{paymentId}/show", name="loevgaard_dandomain_altapay_payment_show")
57
     *
58
     * @param int $paymentId
59
     *
60
     * @return Response
61
     */
62
    public function showAction(int $paymentId)
63
    {
64
        $payment = $this->getPaymentFromId($paymentId);
65
        if (!$payment) {
66
            throw $this->createNotFoundException('Payment with id `'.$paymentId.'` not found');
67
        }
68
69
        return $this->render('@LoevgaardDandomainAltapay/payment/show.html.twig', [
70
            'payment' => $payment,
71
        ]);
72
    }
73
74
    /**
75
     * Payment flow
76
     * 1. The Dandomain payment API POSTs to this page with the terminal slug in the URL
77
     * 2. After validating all input, we create a payment request to the Altapay API
78
     * 3. Finally we redirect the user to the URL given by the Altapay API.
79
     *
80
     * @Method("POST")
81
     * @Route("/{terminal}", name="loevgaard_dandomain_altapay_payment_new")
82
     *
83
     * @LogHttpTransaction()
84
     *
85
     * @param string  $terminal
86
     * @param Request $request
87
     *
88
     * @return RedirectResponse
89
     *
90
     * @throws PaymentException
91
     */
92
    public function newAction(string $terminal, Request $request)
93
    {
94
        $terminalRepository = $this->container->get('loevgaard_dandomain_altapay.terminal_repository');
95
        $paymentRepository = $this->container->get('loevgaard_dandomain_altapay.payment_repository');
96
        $eventRepository = $this->container->get('loevgaard_dandomain_altapay.event_repository');
97
        $translator = $this->getTranslator($this->container);
98
99
        $psrRequest = $this->createPsrRequest($request);
100
        /** @var Payment $paymentEntity */
101
        $paymentEntity = Payment::createFromRequest($psrRequest);
102
103
        $checksumHelper = new ChecksumHelper(
104
            $paymentEntity,
105
            $this->container->getParameter('loevgaard_dandomain_altapay.shared_key_1'),
106
            $this->container->getParameter('loevgaard_dandomain_altapay.shared_key_2')
107
        );
108
109
        $paymentRepository->save($paymentEntity);
110
111
        $event = $eventRepository->createFromDomainEvent(new PaymentCreated($paymentEntity));
112
        $eventRepository->save($event);
113
114
        $terminalEntity = $terminalRepository->findTerminalBySlug($terminal, true);
115
        if (!$terminalEntity) {
116
            throw TerminalNotFoundException::create($translator->trans('payment.exception.terminal_not_found', ['%terminal%' => $terminal], 'LoevgaardDandomainAltapayBundle'), $request, $paymentEntity);
117
        }
118
119
        if (!$checksumHelper->checksumMatches()) {
120
            throw ChecksumMismatchException::create($translator->trans('payment.exception.checksum_mismatch', [], 'LoevgaardDandomainAltapayBundle'), $request, $paymentEntity);
121
        }
122
123
        $paymentRequestPayloadGenerator = new PaymentRequestPayloadGenerator($this->container->get('router'), $paymentEntity, $terminalEntity, $paymentEntity, $checksumHelper, $this->container->getParameter('loevgaard_dandomain_altapay.cookie_payment_id'), $this->container->getParameter('loevgaard_dandomain_altapay.cookie_checksum_complete'));
124
        $paymentRequestPayload = $paymentRequestPayloadGenerator->generate();
125
126
        $altapay = $this->container->get('loevgaard_dandomain_altapay.altapay_client');
127
        $response = $altapay->createPaymentRequest($paymentRequestPayload);
128
129
        if (!$response->isSuccessful()) {
130
            throw AltapayPaymentRequestException::create($translator->trans('payment.exception.altapay_payment_request', ['%gateway_message%' => $response->getErrorMessage()], 'LoevgaardDandomainAltapayBundle'), $request, $paymentEntity);
131
        }
132
133
        return $this->redirect($response->getUrl());
134
    }
135
136
    /**
137
     * @Method("GET")
138
     * @Route("/{paymentId}/capture", name="loevgaard_dandomain_altapay_payment_capture")
139
     *
140
     * @param int     $paymentId
141
     * @param Request $request
142
     *
143
     * @return RedirectResponse
144
     */
145
    public function captureAction(int $paymentId, Request $request)
146
    {
147
        $payment = $this->getPaymentFromId($paymentId);
148
149
        if ($payment) {
150
            $paymentHandler = $this->getPaymentHandler();
151
            $res = $paymentHandler->capture($payment, $request->query->get('amount'));
152
153
            if ($res->isSuccessful()) {
154
                $this->addFlash('success', 'The payment for order '.$payment->getOrderId().' was captured.'); // @todo fix translation
155
            } else {
156
                $this->addFlash('danger', 'An error occurred during capture of the payment: '.$res->getErrorMessage()); // @todo fix translation
157
            }
158
        }
159
160
        $redirect = $request->headers->get('referer') ? $request->headers->get('referer') : $this->generateUrl('loevgaard_dandomain_altapay_payment_index');
161
162
        return $this->redirect($redirect);
163
    }
164
165
    /**
166
     * @Method({"POST", "GET"})
167
     * @Route("/{paymentId}/refund", name="loevgaard_dandomain_altapay_payment_refund")
168
     *
169
     * @param int     $paymentId
170
     * @param Request $request
171
     *
172
     * @return RedirectResponse
173
     */
174
    public function refundAction(int $paymentId, Request $request)
175
    {
176
        $payment = $this->getPaymentFromId($paymentId);
177
178
        if ($payment) {
179
            $paymentHandler = $this->getPaymentHandler();
180
181
            // @todo this is ugly. Should be put somewhere else, maybe on the Payment entity. Maybe the createMoney*() methods on the payment entity should be public so it's easy to create Money objects based on the Payments currency
182
            $amount = (float)$request->query->get('amount');
183
            if ($amount) {
184
                $amount = new Money($amount * 100, new Currency($payment->getMerchantCurrencyAlpha()));
185
            }
186
187
            $res = $paymentHandler->refund($payment, null, $amount);
0 ignored issues
show
It seems like $amount defined by (double) $request->query->get('amount') on line 182 can also be of type double; however, Loevgaard\DandomainAltap...aymentHandler::refund() does only seem to accept null|object<Money\Money>, 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...
188
189
            if ($res->isSuccessful()) {
190
                $this->addFlash('success', 'The payment for order '.$payment->getOrderId().' was refunded.'); // @todo fix translation
191
            } else {
192
                $this->addFlash('danger', 'An error occurred during refund of the payment: '.$res->getErrorMessage()); // @todo fix translation
193
            }
194
        }
195
196
        $redirect = $request->headers->get('referer') ?: $this->generateUrl('loevgaard_dandomain_altapay_payment_index');
197
198
        return $this->redirect($redirect);
199
    }
200
201
    /**
202
     * @Method("GET")
203
     * @Route("/{paymentId}/redirectToAltapay", name="loevgaard_dandomain_altapay_redirect_to_altapay_payment")
204
     *
205
     * @param int $paymentId
206
     *
207
     * @return RedirectResponse
208
     */
209
    public function redirectToAltapayPaymentAction(int $paymentId)
210
    {
211
        $payment = $this->getPaymentFromId($paymentId);
212
213
        $url = $this->getParameter('loevgaard_dandomain_altapay.altapay_url').'/merchant/transactions/paymentDetails/'.$payment->getAltapayId();
214
215
        return $this->redirect($url);
216
    }
217
218
    /**
219
     * @param int $paymentId
220
     *
221
     * @return Payment
222
     */
223 View Code Duplication
    private function getPaymentFromId(int $paymentId): Payment
224
    {
225
        $paymentRepository = $this->get('loevgaard_dandomain_altapay.payment_repository');
226
227
        /** @var Payment $payment */
228
        $payment = $paymentRepository->find($paymentId);
229
230
        if (!$payment) {
231
            throw $this->createNotFoundException('Payment with id `'.$paymentId.'` not found');
232
        }
233
234
        return $payment;
235
    }
236
237
    /**
238
     * @return PaymentHandler
239
     */
240
    private function getPaymentHandler(): PaymentHandler
241
    {
242
        return $this->get('loevgaard_dandomain_altapay.payment_handler');
243
    }
244
}
245