Passed
Push — master ( 673c47...b98ab3 )
by Adrien
07:19
created

DatatransAction::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
nc 1
nop 2
dl 0
loc 4
c 0
b 0
f 0
cc 1
ccs 3
cts 3
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Action;
6
7
use Application\Model\Transaction;
8
use Application\Model\TransactionLine;
9
use Application\Model\User;
10
use Cake\Chronos\Date;
11
use Doctrine\ORM\EntityManager;
12
use Psr\Http\Message\ResponseInterface;
13
use Psr\Http\Message\ServerRequestInterface;
14
use Psr\Http\Server\RequestHandlerInterface;
15
use Zend\Diactoros\Response\HtmlResponse;
16
use Zend\Expressive\Template\TemplateRendererInterface;
17
18
class DatatransAction extends AbstractAction
19
{
20
    /** @var TemplateRendererInterface */
21
    private $template;
22
23
    /**
24
     * @var EntityManager
25
     */
26
    private $entityManager;
27
28 3
    public function __construct(EntityManager $entityManager, TemplateRendererInterface $template)
29
    {
30 3
        $this->entityManager = $entityManager;
31 3
        $this->template = $template;
32 3
    }
33
34
    /**
35
     * Webhook called by datatrans when a payment was made
36
     *
37
     * See documentation: https://api-reference.datatrans.ch/#failed-unsuccessful-authorization-response
38
     *
39
     * @param ServerRequestInterface $request
40
     * @param RequestHandlerInterface $handler
41
     *
42
     * @return ResponseInterface
43
     */
44 3
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
45
    {
46 3
        $request->getMethod();
47 3
        $body = $request->getParsedBody();
48 3
        $status = $body['status'] ?? '';
49
50 3
        switch ($status) {
51 3
            case 'success':
52 1
                $this->createTransactions($body);
0 ignored issues
show
Bug introduced by
It seems like $body can also be of type null and object; however, parameter $body of Application\Action\Datat...n::createTransactions() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

52
                $this->createTransactions(/** @scrutinizer ignore-type */ $body);
Loading history...
53
                $message = [
54 1
                    'type' => $status,
55 1
                    'message' => $body['responseMessage'],
56 1
                    'detail' => $body,
57
                ];
58
59 1
                break;
60 2
            case 'error':
61
                $message = [
62 1
                    'type' => $status,
63 1
                    'message' => $body['errorMessage'],
64 1
                    'detail' => $body,
65
                ];
66
67 1
                break;
68 1
            case 'cancel':
69
                $message = [
70 1
                    'type' => 'error', // Here we cheat because the JS cannot handle 'cancel' status
71 1
                    'message' => 'Cancelled',
72 1
                    'detail' => $body,
73
                ];
74
75 1
                break;
76
            default:
77
                throw new \Exception('Unsupported status in Datatrans data: ' . $status);
78
        }
79
80
        $viewModel = [
81 3
            'message' => $message,
82
        ];
83
84 3
        return new HtmlResponse($this->template->render('app::datatrans', $viewModel));
85
    }
86
87 1
    private function createTransactions(array $body): void
88
    {
89 1
        $userId = $body['refno'];
90
91
        /** @var User $user */
92 1
        $user = $this->entityManager->getRepository(User::class)->getOneById((int) $userId);
93 1
        if (!$user) {
94
            throw new \Exception('Cannot create transactions without a user');
95
        }
96
97 1
        $account = $user->getAccount();
98 1
        if (!$account) {
99
            throw new \Exception('Cannot create transactions for a user who does not have an account');
100
        }
101
102 1
        if (!array_key_exists('amount', $body)) {
103
            // Do not support "registrations"
104
            throw new \Exception('Cannot create transactions without an amount');
105
        }
106
107 1
        $currency = $body['currency'] ?? '';
108 1
        if ($currency !== 'CHF') {
109
            throw new \Exception('Can only create transactions for CHF, but got: ' . $currency);
110
        }
111
112 1
        $now = Date::today();
113 1
        $datatransRef = $body['uppTransactionId'];
114 1
        $name = 'Datatrans: ' . $datatransRef;
115
116 1
        $transaction = new Transaction();
117 1
        $this->entityManager->persist($transaction);
118 1
        $transaction->setName($name);
119 1
        $transaction->setTransactionDate($now);
120
121 1
        $line = new TransactionLine();
122 1
        $this->entityManager->persist($line);
123 1
        $line->setName($name);
124 1
        $line->setTransactionDate($now);
125 1
        $line->setBalance((string) ($body['amount'] / 100));
126 1
        $line->setDatatransRef($datatransRef);
127 1
        $line->setTransaction($transaction);
128 1
        $line->setCredit($account);
129
130
        // This could be removed later on. For now it's mostly for debugging
131 1
        $line->setRemarks(json_encode($body, JSON_PRETTY_PRINT));
132
133 1
        $this->entityManager->flush();
134 1
    }
135
}
136