Completed
Push — master ( 7c22a2...e5b0e2 )
by Joachim
03:42
created

PaymentController::refundAction()   B

Complexity

Conditions 5
Paths 10

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 8.439
c 0
b 0
f 0
cc 5
eloc 14
nc 10
nop 2
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)
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...
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();
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
        $eventRepository->saveEvent(new PaymentCreated($paymentEntity));
112
113
        $terminalEntity = $terminalRepository->findTerminalBySlug($terminal, true);
114
        if (!$terminalEntity) {
115
            throw TerminalNotFoundException::create($translator->trans('payment.exception.terminal_not_found', ['%terminal%' => $terminal], 'LoevgaardDandomainAltapayBundle'), $request, $paymentEntity);
116
        }
117
118
        if (!$checksumHelper->checksumMatches()) {
119
            throw ChecksumMismatchException::create($translator->trans('payment.exception.checksum_mismatch', [], 'LoevgaardDandomainAltapayBundle'), $request, $paymentEntity);
120
        }
121
122
        $paymentRequestPayloadGenerator = new PaymentRequestPayloadGenerator($this->container, $paymentEntity, $terminalEntity, $paymentEntity, $checksumHelper);
123
        $paymentRequestPayload = $paymentRequestPayloadGenerator->generate();
124
125
        $altapay = $this->container->get('loevgaard_dandomain_altapay.altapay_client');
126
        $response = $altapay->createPaymentRequest($paymentRequestPayload);
127
128
        if (!$response->isSuccessful()) {
129
            throw AltapayPaymentRequestException::create($translator->trans('payment.exception.altapay_payment_request', ['%gateway_message%' => $response->getErrorMessage()], 'LoevgaardDandomainAltapayBundle'), $request, $paymentEntity);
130
        }
131
132
        return $this->redirect($response->getUrl());
133
    }
134
135
    /**
136
     * @Method("GET")
137
     * @Route("/{paymentId}/capture", name="loevgaard_dandomain_altapay_payment_capture")
138
     *
139
     * @param int     $paymentId
140
     * @param Request $request
141
     *
142
     * @return RedirectResponse
143
     */
144
    public function captureAction(int $paymentId, Request $request)
145
    {
146
        $payment = $this->getPaymentFromId($paymentId);
147
148
        if ($payment) {
149
            $paymentHandler = $this->getPaymentHandler();
150
            $res = $paymentHandler->capture($payment, $request->query->get('amount'));
151
152
            if ($res->isSuccessful()) {
153
                $this->addFlash('success', 'The payment for order '.$payment->getOrderId().' was captured.'); // @todo fix translation
154
            } else {
155
                $this->addFlash('danger', 'An error occurred during capture of the payment: '.$res->getErrorMessage()); // @todo fix translation
156
            }
157
        }
158
159
        $redirect = $request->headers->get('referer') ? $request->headers->get('referer') : $this->generateUrl('loevgaard_dandomain_altapay_payment_index');
160
161
        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 159 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...
162
    }
163
164
    /**
165
     * @Method({"POST", "GET"})
166
     * @Route("/{paymentId}/refund", name="loevgaard_dandomain_altapay_payment_refund")
167
     *
168
     * @param int     $paymentId
169
     * @param Request $request
170
     *
171
     * @return RedirectResponse
172
     */
173
    public function refundAction(int $paymentId, Request $request)
174
    {
175
        $payment = $this->getPaymentFromId($paymentId);
176
177
        if ($payment) {
178
            $paymentHandler = $this->getPaymentHandler();
179
180
            // @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
181
            $amount = $request->query->get('amount');
182
            if($amount) {
183
                $amount = new Money($amount, new Currency($payment->getMerchantCurrencyAlpha()));
184
            }
185
186
            $res = $paymentHandler->refund($payment, null, $amount);
187
188
            if ($res->isSuccessful()) {
189
                $this->addFlash('success', 'The payment for order '.$payment->getOrderId().' was refunded.'); // @todo fix translation
190
            } else {
191
                $this->addFlash('danger', 'An error occurred during refund of the payment: '.$res->getErrorMessage()); // @todo fix translation
192
            }
193
        }
194
195
        $redirect = $request->headers->get('referer') ?: $this->generateUrl('loevgaard_dandomain_altapay_payment_index');
196
197
        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 195 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...
198
    }
199
200
    /**
201
     * @Method("GET")
202
     * @Route("/{paymentId}/redirectToAltapay", name="loevgaard_dandomain_altapay_redirect_to_altapay_payment")
203
     *
204
     * @param int $paymentId
205
     *
206
     * @return RedirectResponse
207
     */
208
    public function redirectToAltapayPaymentAction(int $paymentId)
209
    {
210
        $payment = $this->getPaymentFromId($paymentId);
211
212
        $url = $this->getParameter('loevgaard_dandomain_altapay.altapay_url').'/merchant/transactions/paymentDetails/'.$payment->getAltapayId();
213
214
        return $this->redirect($url);
215
    }
216
217
    /**
218
     * @param int $paymentId
219
     *
220
     * @return Payment
221
     */
222 View Code Duplication
    private function getPaymentFromId(int $paymentId): Payment
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...
223
    {
224
        $paymentRepository = $this->get('loevgaard_dandomain_altapay.payment_repository');
225
226
        /** @var Payment $payment */
227
        $payment = $paymentRepository->find($paymentId);
228
229
        if (!$payment) {
230
            throw $this->createNotFoundException('Payment with id `'.$paymentId.'` not found');
231
        }
232
233
        return $payment;
234
    }
235
236
    /**
237
     * @return PaymentHandler
238
     */
239
    private function getPaymentHandler(): PaymentHandler
240
    {
241
        return $this->get('loevgaard_dandomain_altapay.payment_handler');
242
    }
243
}
244