Gateway::getTransactionStatus()   B
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 34
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 19
nc 3
nop 3
1
<?php
2
3
namespace Omnipay\Pesapal;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Psr7\Request;
7
use Omnipay\Common\AbstractGateway;
8
use Omnipay\Pesapal\OAuth\OAuthConsumer;
9
use Omnipay\Pesapal\OAuth\OAuthException;
10
use Omnipay\Pesapal\OAuth\OAuthRequest;
11
use Omnipay\Pesapal\OAuth\OAuthSignatureMethod_Hmac_Sha1;
12
use SimpleXMLElement;
13
14
/**
15
 * @method authorize(array $options = array())
16
 * @method completeAuthorize(array $options = array())
17
 * @method capture(array $options = array())
18
 * @method purchase(array $options = array())
19
 * @method completePurchase(array $options = array())
20
 * @method refund(array $options = array())
21
 * @method void(array $options = array())
22
 * @method createCard(array $options = array())
23
 * @method updateCard(array $options = array())
24
 * @method deleteCard(array $options = array())
25
 */
26
class Gateway extends AbstractGateway
27
{
28
    const XMLNS = 'http://www.pesapal.com';
29
    const PROD_DOMAIN = 'www.pesapal.com';
30
    const DEBUG_DOMAIN = 'https://demo.pesapal.com';
31
32
    /**
33
     * @return string
34
     */
35
    public function getName()
36
    {
37
        return 'Pesapal';
38
    }
39
40
    /**
41
     * @param string $key
42
     * @param string $secret
43
     *
44
     * @return Gateway
45
     */
46
    public function setCredentials(
47
        string $key,
48
        string $secret
49
    ): self {
50
        return $this->setParameter('key', $key)
51
            ->setParameter('secret', $secret);
52
    }
53
54
    /**
55
     * @return string
56
     */
57
    public function getKey(): string
58
    {
59
        return $this->getParameter('key');
60
    }
61
62
    /**
63
     * @return string
64
     */
65
    public function getSecret(): string
66
    {
67
        return $this->getParameter('secret');
68
    }
69
70
    /**
71
     * @return Gateway
72
     */
73
    public function setDebug(): self
74
    {
75
        return $this->setParameter('debug', true);
76
    }
77
78
    /**
79
     * @return bool
80
     */
81
    public function getDebug(): bool
82
    {
83
        return $this->getParameter('debug') ?? false;
84
    }
85
86
    /**
87
     * @param string $callbackUrl
88
     *
89
     * @return Gateway
90
     */
91
    public function setCallbackUrl(string $callbackUrl): self
92
    {
93
        return $this->setParameter('callbackUrl', $callbackUrl);
94
    }
95
96
    /**
97
     * @return string
98
     */
99
    public function getCallbackUrl(): string
100
    {
101
        return $this->getParameter('callbackUrl');
102
    }
103
104
    /**
105
     * @param string      $email
106
     * @param string      $reference
107
     * @param string      $description
108
     * @param float       $amount
109
     * @param string|null $currency
110
     * @param string      $type
111
     * @param string|null $firstName
112
     * @param string|null $lastName
113
     * @param string|null $phoneNumber
114
     *
115
     * @return string
116
     */
117
    public function getIframeSrc(
118
        string $email,
119
        string $reference,
120
        string $description,
121
        float $amount,
122
        string $currency = null,
123
        string $type = 'MERCHANT',
124
        string $firstName = null,
125
        string $lastName = null,
126
        string $phoneNumber = null
127
    ): string {
128
        $xmlPayload = $this
129
            ->arrayToXml(
130
                [
131
                    'Email'       => $email,
132
                    'Reference'   => $reference,
133
                    'Description' => $description,
134
                    'Amount'      => $amount,
135
                    'Currency'    => $currency,
136
                    'Type'        => $type,
137
                    'FirstName'   => $firstName,
138
                    'LastName'    => $lastName,
139
                    'PhoneNumber' => $phoneNumber,
140
                    'xmlns'       => $this::XMLNS,
141
                ],
142
                new SimpleXMLElement('<PesapalDirectOrderInfo/>')
143
            )->asXML();
144
145
        return (string) $this->getIframeRequest($xmlPayload);
146
    }
147
148
    /**
149
     * @return OAuthConsumer
150
     */
151
    protected function getConsumer(): OAuthConsumer
152
    {
153
        return new OAuthConsumer(
154
            $this->getKey(),
155
            $this->getSecret(),
156
            $this->getCallbackUrl()
157
        );
158
    }
159
160
    /**
161
     * @param string $xmlPayload
162
     *
163
     * @return OAuthRequest
164
     */
165
    protected function getIframeRequest(
166
        string $xmlPayload
167
    ): OAuthRequest {
168
        $consumer = $this->getConsumer();
169
        //post transaction to pesapal
170
        $iframeRequest = OAuthRequest::getRequest(
171
            $consumer,
172
            $this->getApiDomain().'/API/PostPesapalDirectOrderV4'
173
        );
174
        $iframeRequest->set_parameter('oauth_callback', $this->getCallbackUrl());
175
        $iframeRequest->set_parameter('pesapal_request_data', $xmlPayload);
176
        $iframeRequest->sign_request(new OAuthSignatureMethod_Hmac_Sha1(), $consumer);
177
178
        return $iframeRequest;
179
    }
180
181
    /**
182
     * Process the pin message frmo pesapal,
183
     * this will query the pesapal api and
184
     * return a transaction status.
185
     *
186
     * @param string $type
187
     * @param string $id
188
     * @param string $reference
189
     *
190
     * @throws OAuthException
191
     *
192
     * @return string
193
     */
194
    public function getTransactionStatus(
195
        string $type,
196
        string $id,
197
        string $reference
198
    ): string {
199
        $response = null;
200
        if (
201
            $type == 'CHANGE'
202
            && !empty($id)
203
        ) {
204
            // get transaction status
205
            $statusRequest = OAuthRequest::getRequest(
206
                $this->getConsumer(),
207
                $this->getApiDomain().'/api/querypaymentstatus'
208
                );
209
            $statusRequest->set_parameter('pesapal_merchant_reference', $reference);
210
            $statusRequest->set_parameter('pesapal_transaction_tracking_id', $id);
211
            $statusRequest->sign_request(new OAuthSignatureMethod_Hmac_Sha1(), $this->getConsumer());
212
213
            $client = new Client();
214
            $response = $client
215
                ->send(
216
                    new Request(
217
                        'GET',
218
                        (string) $statusRequest
219
                    )
220
                );
221
222
            if (!$response) {
223
                throw new OAuthException($response);
224
            }
225
        }
226
227
        return $this->transformResponse($response);
228
    }
229
230
    /**
231
     * @param array            $array
232
     * @param SimpleXMLElement $xml
233
     *
234
     * @return SimpleXMLElement
235
     */
236
    private function arrayToXml(array $array, SimpleXMLElement $xml)
237
    {
238
        foreach ($array as $key => $value) {
239
            is_array($value)
240
                ? $this->arrayToXml($value, $xml->addChild($key))
241
                : $xml->addChild($key, $value);
242
        }
243
244
        return $xml;
245
    }
246
247
    /**
248
     * @return string
249
     */
250
    protected function getApiDomain(): string
251
    {
252
        return $this->getDebug()
253
            ? $this::DEBUG_DOMAIN
254
            : $this::PROD_DOMAIN;
255
    }
256
257
    /**
258
     * @param $response
259
     *
260
     * @return string
261
     */
262
    protected function transformResponse($response): string
0 ignored issues
show
Unused Code introduced by
The parameter $response is not used and could be removed. ( Ignorable by Annotation )

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

262
    protected function transformResponse(/** @scrutinizer ignore-unused */ $response): string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
263
    {
264
        return 'COMPLETED';
265
    }
266
}
267