Test Failed
Push — query-string ( b67b86...c17fc7 )
by
unknown
02:07 queued 33s
created

getTransactionStatusFromPostBack()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 14
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 24
ccs 0
cts 14
cp 0
crap 30
rs 9.4888
1
<?php
2
3
namespace Omnipay\IcepayPayments\Message;
4
5
use Omnipay\Common\Message\ResponseInterface;
6
use Omnipay\IcepayPayments\Exception\PostBackException;
7
use Symfony\Component\HttpFoundation\Request;
8
9
/**
10
 * The request for getting the transaction status at Icepay.
11
 */
12
class TransactionStatusRequest extends AbstractRequest
13
{
14
    /**
15
     * {@inheritdoc}
16
     */
17 1
    public function getData(): array
18
    {
19 1
        $data = parent::getData();
20
21 1
        $data['ContractProfileId'] = $this->getContractProfileId();
22
23 1
        return $data;
24
    }
25
26
    /**
27
     * {@inheritdoc}
28
     */
29
    public function sendData($data): ResponseInterface
30
    {
31
        try {
32
            $transactionStatusResponse = $this->getTransactionStatusFromPostBack();
33
        } catch (PostBackException $exception) {
34
            // Optional parameter to throw the error instead of fallback.
35
            if (isset($data['throwOnPostBackError'])) {
36
                throw $exception;
37
            }
38
            $transactionStatusResponse = false;
39
        }
40
41
        if ($transactionStatusResponse !== false) {
42
            return $transactionStatusResponse;
43
        }
44
45
        $this->sendRequest(
46
            Request::METHOD_POST,
47
            sprintf(
48
                '/transaction/%s',
49
                $this->getTransactionReference()
50
            ),
51
            $data
52
        );
53
54
        return new TransactionStatusResponse(
55
            $this,
56
            $this->getResponseBody(),
57
            $this->getResponse()->getStatusCode()
0 ignored issues
show
Bug introduced by
The method getStatusCode() does not exist on Omnipay\Common\Message\ResponseInterface. ( Ignorable by Annotation )

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

57
            $this->getResponse()->/** @scrutinizer ignore-call */ getStatusCode()

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
58
        );
59
    }
60
61
    /**
62
     * Use the data sent by Icepay in the post back to check the status.
63
     * This is necessary because Icepay has a delay in their backend if you request the status immediately after the signal.
64
     *
65
     * @see http://docs2.icepay.com/payment-process/handling-the-postback/postback-sample/
66
     *
67
     * @return TransactionStatusResponse|bool False when the data is is not sent or not correct.
68
     *
69
     * @throws PostBackException
70
     */
71
    private function getTransactionStatusFromPostBack(): ?TransactionStatusResponse
72
    {
73
        $request = Request::createFromGlobals();
74
75
        if (stripos($request->getContentType(), 'json') === false) {
76
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the type-hinted return Omnipay\IcepayPayments\M...tionStatusResponse|null.
Loading history...
77
        }
78
79
        try {
80
            $contentAsArray = json_decode($request->getContent(), true);
81
        } catch(\LogicException $exception) {
82
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the type-hinted return Omnipay\IcepayPayments\M...tionStatusResponse|null.
Loading history...
83
        }
84
85
        if (is_array($contentAsArray) === false || isset($contentAsArray['StatusCode']) === false) {
86
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the type-hinted return Omnipay\IcepayPayments\M...tionStatusResponse|null.
Loading history...
87
        }
88
89
        $this->validateSecurityHashMatch($request, $contentAsArray);
90
91
        return new TransactionStatusResponse(
92
            $this,
93
            $contentAsArray,
94
            200
95
        );
96
    }
97
98
    /**
99
     * Get the security hash from the request and match it against a generated hash from the sent values.
100
     * Will throw an exception if it does not match.
101
     * Needs the POSTed Json as a php array.
102
     *
103
     * @param Request         $request
104
     * @param $contentAsArray
105
     *
106
     * @throws PostBackException
107
     */
108
    private function validateSecurityHashMatch(Request $request, $contentAsArray): void
109
    {
110
        $generatedSecurityHash = $this->getSecurityHash(
111
            Request::METHOD_POST,
112
            $request->getPathInfo(),
113
            $contentAsArray
114
        );
115
116
        $sentSecurityHash = $request->headers->get('checksum');
117
118
        if ($generatedSecurityHash !== $sentSecurityHash) {
119
            throw new PostBackException(
120
                sprintf(
121
                    'Sent security hash %s did not match generated hash %s',
122
                    $sentSecurityHash,
123
                    $generatedSecurityHash
124
                )
125
            );
126
        }
127
    }
128
}
129