GivePayGatewayClient   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 312
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 133
dl 0
loc 312
ccs 0
cts 131
cp 0
rs 10
c 0
b 0
f 0
wmc 20

9 Methods

Rating   Name   Duplication   Size   Complexity  
A chargeAmount() 0 12 3
A __construct() 0 18 2
A getAccessToken() 0 32 2
A makeSaleRequest() 0 38 2
A voidTransaction() 0 12 3
A getTokenizationApiKey() 0 2 1
A makeVoidRequest() 0 40 2
A storeCard() 0 12 3
A makeStoreCardRequest() 0 36 2
1
<?php
2
3
namespace GivePay\Gateway;
4
5
use cURL\Request;
6
use Exception;
7
use GivePay\Gateway\Transactions\Card;
8
use GivePay\Gateway\Transactions\TerminalType;
9
use GivePay\Gateway\Transactions\TokenRequest;
10
use GivePay\Gateway\Transactions\V0id;
11
use Psr\Log\LoggerInterface;
12
use Psr\Log\NullLogger;
13
14
final class GivePayGatewayClient
15
{
16
17
    public $token_endpoint;
18
19
    public $gateway_url;
20
21
    private $client_secret;
22
23
    private $client_id;
24
25
    private $logger;
26
27
    /**
28
     * FRP_Gateway constructor.
29
     *
30
     * @param string $client_id
31
     * @param string $client_secret
32
     * @param string $token_endpoint
33
     * @param string $gateway_url
34
     * @param LoggerInterface $logger
35
     */
36
    public function __construct(
37
        $client_id,
38
        $client_secret,
39
        $token_endpoint = 'https://portal.flatratepay.com/connect/token',
40
        $gateway_url = 'https://gateway.givepaycommerce.com/',
41
        $logger = null
42
    )
43
    {
44
        $this->token_endpoint = $token_endpoint;
45
        $this->gateway_url = $gateway_url;
46
47
        $this->client_secret = $client_secret;
48
        $this->client_id = $client_id;
49
50
        if ($logger == null) {
51
            $this->logger = new NullLogger();
52
        } else {
53
            $this->logger = $logger;
54
        }
55
    }
56
57
    /**
58
     * @param string $merchant_id The merchant ID for the website
59
     * @param string $terminal_id The terminal ID for the website
60
     * @param Transactions\Sale $sale The transaction information
61
     *
62
     * @throws Exception
63
     * @return TransactionResult
64
     */
65
    public function chargeAmount($merchant_id, $terminal_id, $sale)
66
    {
67
        if (null == $sale) {
68
            throw new \Exception('$sale is null');
69
        }
70
71
        $access_token = $this->getAccessToken($this->client_id, $this->client_secret, $this->token_endpoint);
72
        if (null == $access_token) {
73
            throw new \Exception('Could not authorize with gateway.');
74
        }
75
76
        return $this->makeSaleRequest($access_token, $merchant_id, $terminal_id, $sale);
77
    }
78
79
    /**
80
     * Gets an API key, which can only be used for tokenization. Safe for use on client-side scripts.
81
     *
82
     * @return string the API key
83
     */
84
    public function getTokenizationApiKey() {
85
        return $this->getAccessToken($this->client_id, $this->client_secret, $this->token_endpoint, 'tokenize:transactions');
86
    }
87
88
    /**
89
     * Gets an access token from the auth server
90
     *
91
     * @param string $client_id the client ID
92
     * @param string $client_secret the client secret
93
     * @param string $token_url the token endpoint
94
     * @param string $scopes the scopes for the access token request
95
     *
96
     * @return string
97
     */
98
    private function getAccessToken($client_id, $client_secret, $token_url, $scopes = 'authorize:transactions capture:transactions sale:transactions refund:transactions void:transactions tokenize:transactions')
99
    {
100
        $token_data = array(
101
            'client_id' => $client_id,
102
            'grant_type' => 'client_credentials',
103
            'client_secret' => $client_secret,
104
            'scope' => $scopes,
105
        );
106
107
        $request = new Request($token_url);
108
        $request->getOptions()
109
            ->set(CURLOPT_RETURNTRANSFER, true)
110
            ->set(CURLOPT_POST, true)
111
            ->set(CURLOPT_POSTFIELDS, $token_data)
112
            ->set(CURLOPT_HTTPHEADER, array(
113
                'Content-Type' => 'application/x-www-form-urlencoded',
114
                'Accept: application/json'
115
            ));
116
        $response = $request->send();
117
118
        if ($response->hasError()) {
119
            $this->logger->debug('Token response status code was ' . $response->getError()->getCode());
120
            $this->logger->debug("Token request ended in failure: " . var_export($response, true));
121
            $this->logger->error("Gateway authorization failed. Check credentials.");
122
123
            return null;
124
        }
125
126
        $this->logger->debug("Token request was a success: " . $response->getContent());
127
        $token = json_decode($response->getContent());
128
129
        return $token->access_token;
130
    }
131
132
    /**
133
     * @param string $access_token
134
     * @param string $merchant_id
135
     * @param string $terminal_id
136
     * @param Transactions\Sale $sale
137
     *
138
     * @return TransactionResult
139
     */
140
    private function makeSaleRequest($access_token, $merchant_id, $terminal_id, $sale)
141
    {
142
        $sale_request = $sale->serialize($merchant_id, $terminal_id);
143
        $body = json_encode($sale_request);
144
145
        $this->logger->info("Starting transaction for $" . $sale->getTotal());
146
147
        $request = new Request($this->gateway_url . 'api/v1/transactions/sale');
148
        $request->getOptions()
149
            ->set(CURLOPT_RETURNTRANSFER, true)
150
            ->set(CURLOPT_POST, true)
151
            ->set(CURLOPT_POSTFIELDS, $body)
152
            ->set(CURLOPT_HTTPHEADER, array(
153
                'Content-Type: application/json',
154
                'Content-Length: ' . strlen($body),
155
                'Accept: application/json',
156
                'Authorization: Bearer ' . $access_token
157
            ));
158
        $response = $request->send();
159
160
        $this->logger->debug("Transaction completed");
161
162
        $sale_response = json_decode($response->getContent());
163
164
        if ($sale_response->success) {
165
            $transaction_id = $sale_response->result->transaction_id;
166
167
            $this->logger->info('Payment completed. Transaction ID: ' . $transaction_id);
168
169
            return new TransactionResult(true, $transaction_id);
170
        } else {
171
            $error_message = $sale_response->error->message;
172
            $code = $sale_response->error->code;
173
174
            $this->logger->debug("Sale response: " . var_export($sale_response, true));
175
            $this->logger->error("Payment failed.");
176
177
            return new TransactionResult(false, null, $error_message, $code);
178
        }
179
    }
180
181
    /**
182
     * @param string $transaction_id
183
     * @param string $merchant_id
184
     * @param string $terminal_id
185
     *
186
     * @throws Exception
187
     * @return TransactionResult
188
     */
189
    public function voidTransaction($transaction_id, $merchant_id, $terminal_id)
190
    {
191
        if (null == $transaction_id) {
192
            throw new Exception('Transaction ID is null');
193
        }
194
195
        $access_token = $this->getAccessToken($this->client_id, $this->client_secret, $this->token_endpoint);
196
        if (null == $access_token) {
197
            throw new Exception('Could not authorize with gateway.');
198
        }
199
200
        return $this->makeVoidRequest($access_token, $transaction_id, $merchant_id, $terminal_id);
201
    }
202
203
    /**
204
     * Makes a VOID request
205
     *
206
     * @param string $access_token
207
     * @param string $transaction_id
208
     * @param string $merchant_id
209
     * @param string $terminal_id
210
     *
211
     * @return TransactionResult
212
     */
213
    private function makeVoidRequest($access_token, $transaction_id, $merchant_id, $terminal_id)
214
    {
215
        $void = new V0id(TerminalType::$ECommerce, $transaction_id);
216
        $void_request = $void->serialize($merchant_id, $terminal_id);
217
218
        $body = json_encode($void_request);
219
220
        $this->logger->info("Starting void transaction for transaction# " . $transaction_id);
221
222
        $request = new Request($this->gateway_url . 'api/v1/transactions/void');
223
        $request->getOptions()
224
            ->set(CURLOPT_RETURNTRANSFER, true)
225
            ->set(CURLOPT_POST, true)
226
            ->set(CURLOPT_POSTFIELDS, $body)
227
            ->set(CURLOPT_HTTPHEADER, array(
228
                'Content-Type: application/json',
229
                'Content-Length: ' . strlen($body),
230
                'Accept: application/json',
231
                'Authorization: Bearer ' . $access_token
232
            ));
233
        $response = $request->send();
234
235
        $this->logger->debug("Transaction completed");
236
237
        $void_response = json_decode($response->getContent());
238
239
        if ($void_response->success) {
240
            $transaction_id = $void_response->result->transaction_id;
241
242
            $this->logger->info('Void completed. Transaction ID: ' . $transaction_id);
243
244
            return new TransactionResult(true, $transaction_id);
245
        } else {
246
            $error_message = $void_response->error->message;
247
            $code = $void_response->error->code;
248
249
            $this->logger->debug("Void response: " . var_export($void_response, true));
250
            $this->logger->error("Void failed.");
251
252
            return new TransactionResult(false, null, $error_message, $code);
253
        }
254
    }
255
256
    /**
257
     * Stores the card and gets a token from the gateway
258
     *
259
     * @param string $merchant_id
260
     * @param string $terminal_id
261
     * @param Card $card
262
     *
263
     * @return string
264
     * @throws Exception
265
     */
266
    public function storeCard($merchant_id, $terminal_id, $card)
267
    {
268
        if (null == $card) {
269
            throw new Exception('Card is null');
270
        }
271
272
        $access_token = $this->getAccessToken($this->client_id, $this->client_secret, $this->token_endpoint);
273
        if (null == $access_token) {
274
            throw new Exception('Could not store card with gateway.');
275
        }
276
277
        return $this->makeStoreCardRequest($access_token, $merchant_id, $terminal_id, $card);
278
    }
279
280
    /**
281
     * stores a card in the gateway
282
     *
283
     * @param string $access_token
284
     * @param string $terminal_id
285
     * @param string $merchant_id
286
     * @param mixed $card
287
     *
288
     * @return string
289
     */
290
    private function makeStoreCardRequest($access_token, $merchant_id, $terminal_id, $card)
291
    {
292
        $token_request = new TokenRequest($card, TerminalType::$ECommerce);
293
        $token_request_string = $token_request->serialize($merchant_id, $terminal_id);
294
        $body = json_encode($token_request_string);
295
296
        $this->logger->info("Starting request for tokenization");
297
298
        $request = new Request($this->gateway_url . 'api/v1/transactions/tokenize');
299
        $request->getOptions()
300
            ->set(CURLOPT_RETURNTRANSFER, true)
301
            ->set(CURLOPT_POST, true)
302
            ->set(CURLOPT_POSTFIELDS, $body)
303
            ->set(CURLOPT_HTTPHEADER, array(
304
                'Content-Type: application/json',
305
                'Content-Length: ' . strlen($body),
306
                'Accept: application/json',
307
                'Authorization: Bearer ' . $access_token
308
            ));
309
        $response = $request->send();
310
311
        $this->logger->debug("Transaction completed");
312
313
        $token_response = json_decode($response->getContent());
314
315
        if ($token_response->success) {
316
            $transaction_id = $token_response->result->transaction_id;
317
318
            $this->logger->info('Tokenization completed. Transaction ID: ' . $transaction_id);
319
320
            return $token_response->result->token;
321
        } else {
322
            $this->logger->debug("Tokenization response: " . var_export($token_response, true));
323
            $this->logger->error("Tokenization failed.");
324
325
            return '';
326
        }
327
    }
328
}