Completed
Push — master ( ec46b9...8e1cce )
by Raza
01:47
created

PayPalRequest::setApiCredentials()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
rs 9.4285
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
3
namespace Srmklive\PayPal\Traits;
4
5
use GuzzleHttp\Client as HttpClient;
6
use GuzzleHttp\Exception\BadResponseException as HttpBadResponseException;
7
use GuzzleHttp\Exception\ClientException as HttpClientException;
8
use GuzzleHttp\Exception\ServerException as HttpServerException;
9
use Illuminate\Support\Collection;
10
11
trait PayPalRequest
12
{
13
    /**
14
     * Http Client class object.
15
     *
16
     * @var HttpClient
17
     */
18
    private $client;
19
20
    /**
21
     * Http Client configuration.
22
     *
23
     * @var array
24
     */
25
    private $httpClientConfig;
26
27
    /**
28
     * PayPal API Certificate data for authentication.
29
     *
30
     * @var string
31
     */
32
    private $certificate;
33
34
    /**
35
     * PayPal API mode to be used.
36
     *
37
     * @var string
38
     */
39
    public $mode;
40
41
    /**
42
     * Request data to be sent to PayPal.
43
     *
44
     * @var \Illuminate\Support\Collection
45
     */
46
    protected $post;
47
48
    /**
49
     * PayPal API configuration.
50
     *
51
     * @var array
52
     */
53
    private $config;
54
55
    /**
56
     * Default currency for PayPal.
57
     *
58
     * @var string
59
     */
60
    private $currency;
61
62
    /**
63
     * Additional options for PayPal API request.
64
     *
65
     * @var array
66
     */
67
    private $options;
68
69
    /**
70
     * Default payment action for PayPal.
71
     *
72
     * @var string
73
     */
74
    private $paymentAction;
75
76
    /**
77
     * Default locale for PayPal.
78
     *
79
     * @var string
80
     */
81
    private $locale;
82
83
    /**
84
     * PayPal API Endpoint.
85
     *
86
     * @var string
87
     */
88
    private $apiUrl;
89
90
    /**
91
     * IPN notification url for PayPal.
92
     *
93
     * @var string
94
     */
95
    private $notifyUrl;
96
97
    /**
98
     * Http Client request body parameter name.
99
     *
100
     * @var string
101
     */
102
    private $httpBodyParam;
103
104
    /**
105
     * Validate SSL details when creating HTTP client.
106
     *
107
     * @var bool
108
     */
109
    private $validateSSL;
110
111
    /**
112
     * Function To Set PayPal API Configuration.
113
     *
114
     * @param array $config
115
     *
116
     * @throws \Exception
117
     */
118
    private function setConfig(array $config = [])
119
    {
120
        // Set Api Credentials
121
        if (function_exists('config')) {
122
            $this->setApiCredentials(
123
                config('paypal')
124
            );
125
        } elseif (!empty($config)) {
126
            $this->setApiCredentials($config);
127
        }
128
129
        $this->setRequestData();
130
    }
131
132
    /**
133
     * Set default values for configuration.
134
     *
135
     * @return void
136
     */
137
    private function setDefaultValues()
138
    {
139
        // Set default payment action.
140
        if (empty($this->paymentAction)) {
141
            $this->paymentAction = 'Sale';
142
        }
143
144
        // Set default locale.
145
        if (empty($this->locale)) {
146
            $this->locale = 'en_US';
147
        }
148
149
        // Set default value for SSL validation.
150
        if (empty($this->validateSSL)) {
151
            $this->validateSSL = false;
152
        }
153
    }
154
155
    /**
156
     * Function to initialize Http Client.
157
     *
158
     * @return void
159
     */
160
    protected function setClient()
161
    {
162
        $this->client = new HttpClient([
163
            'curl' => $this->httpClientConfig,
164
        ]);
165
    }
166
167
    /**
168
     * Function to set Http Client configuration.
169
     *
170
     * @return void
171
     */
172
    protected function setHttpClientConfiguration()
173
    {
174
        $this->httpClientConfig = [
175
            CURLOPT_SSLVERSION     => CURL_SSLVERSION_TLSv1_2,
176
            CURLOPT_SSL_VERIFYPEER => $this->validateSSL,
177
        ];
178
179
        if (!empty($this->certificate)) {
180
            $this->httpClientConfig[CURLOPT_SSLCERT] = $this->certificate;
181
        }
182
183
        // Initialize Http Client
184
        $this->setClient();
185
186
        // Set default values.
187
        $this->setDefaultValues();
188
189
        // Set PayPal API Endpoint.
190
        $this->apiUrl = $this->config['api_url'];
191
192
        // Set PayPal IPN Notification URL
193
        $this->notifyUrl = $this->config['notify_url'];
194
    }
195
196
    /**
197
     * Set PayPal API Credentials.
198
     *
199
     * @param array $credentials
200
     *
201
     * @throws \Exception
202
     *
203
     * @return void
204
     */
205
    public function setApiCredentials($credentials)
206
    {
207
        // Setting Default PayPal Mode If not set
208
        $this->setApiEnvironment($credentials);
209
210
        // Set API configuration for the PayPal provider
211
        $this->setApiProviderConfiguration($credentials);
212
213
        // Set default currency.
214
        $this->setCurrency($credentials['currency']);
215
216
        // Set Http Client configuration.
217
        $this->setHttpClientConfiguration();
218
    }
219
220
    /**
221
     * Set API environment to be used by PayPal.
222
     *
223
     * @param array $credentials
224
     *
225
     * @return void
226
     */
227
    private function setApiEnvironment($credentials)
228
    {
229
        if (empty($credentials['mode']) || !in_array($credentials['mode'], ['sandbox', 'live'])) {
230
            $this->mode = 'live';
231
        } else {
232
            $this->mode = $credentials['mode'];
233
        }
234
    }
235
236
    /**
237
     * Set configuration details for the provider.
238
     *
239
     * @param array $credentials
240
     *
241
     * @throws \Exception
242
     *
243
     * @return void
244
     */
245
    private function setApiProviderConfiguration($credentials)
246
    {
247
        // Setting PayPal API Credentials
248
        collect($credentials[$this->mode])->map(function ($value, $key) {
249
            $this->config[$key] = $value;
250
        });
251
252
        // Setup PayPal API Signature value to use.
253
        $this->config['signature'] = empty($this->config['certificate']) ?
254
            $this->config['secret'] : $this->config['certificate'];
255
256
        $this->paymentAction = $credentials['payment_action'];
257
258
        $this->locale = $credentials['locale'];
259
260
        $this->certificate = $this->config['certificate'];
261
262
        $this->validateSSL = $credentials['validate_ssl'];
263
264
        $this->setApiProvider($credentials);
265
    }
266
267
    /**
268
     * Determines which API provider should be used.
269
     *
270
     * @param array $credentials
271
     *
272
     * @throws \Exception
273
     */
274
    private function setApiProvider($credentials)
275
    {
276
        if ($this instanceof \Srmklive\PayPal\Services\AdaptivePayments) {
277
            $this->setAdaptivePaymentsOptions();
278
        } elseif ($this instanceof \Srmklive\PayPal\Services\ExpressCheckout) {
279
            $this->setExpressCheckoutOptions($credentials);
280
        } else {
281
            throw new \Exception('Invalid api credentials provided for PayPal!. Please provide the right api credentials.');
282
        }
283
    }
284
285
    /**
286
     * Setup request data to be sent to PayPal.
287
     *
288
     * @param array $data
289
     *
290
     * @return \Illuminate\Support\Collection
291
     */
292
    protected function setRequestData(array $data = [])
293
    {
294
        if (($this->post instanceof Collection) && (!$this->post->isEmpty())) {
295
            unset($this->post);
296
        }
297
298
        $this->post = new Collection($data);
299
300
        return $this->post;
301
    }
302
303
    /**
304
     * Set other/override PayPal API parameters.
305
     *
306
     * @param array $options
307
     *
308
     * @return $this
309
     */
310
    public function addOptions(array $options)
311
    {
312
        $this->options = $options;
313
314
        return $this;
315
    }
316
317
    /**
318
     * Function to set currency.
319
     *
320
     * @param string $currency
321
     *
322
     * @throws \Exception
323
     *
324
     * @return $this
325
     */
326
    public function setCurrency($currency = 'USD')
327
    {
328
        $allowedCurrencies = ['AUD', 'BRL', 'CAD', 'CZK', 'DKK', 'EUR', 'HKD', 'HUF', 'ILS', 'JPY', 'MYR', 'MXN', 'NOK', 'NZD', 'PHP', 'PLN', 'GBP', 'SGD', 'SEK', 'CHF', 'TWD', 'THB', 'USD', 'RUB'];
329
330
        // Check if provided currency is valid.
331
        if (!in_array($currency, $allowedCurrencies)) {
332
            throw new \Exception('Currency is not supported by PayPal.');
333
        }
334
335
        $this->currency = $currency;
336
337
        return $this;
338
    }
339
340
    /**
341
     * Retrieve PayPal IPN Response.
342
     *
343
     * @param array $post
344
     *
345
     * @return array
346
     */
347
    public function verifyIPN($post)
348
    {
349
        $this->setRequestData($post);
350
351
        $this->apiUrl = $this->config['gateway_url'].'/cgi-bin/webscr';
352
353
        return $this->doPayPalRequest('verifyipn');
354
    }
355
356
    /**
357
     * Create request payload to be sent to PayPal.
358
     *
359
     * @param string $method
360
     */
361
    private function createRequestPayload($method)
362
    {
363
        $config = array_merge([
364
            'USER'      => $this->config['username'],
365
            'PWD'       => $this->config['password'],
366
            'SIGNATURE' => $this->config['signature'],
367
            'VERSION'   => 123,
368
            'METHOD'    => $method,
369
        ], $this->options);
370
371
        $this->post = $this->post->merge($config);
372
        if ($method === 'verifyipn') {
373
            $this->post->forget('METHOD');
374
        }
375
    }
376
377
    /**
378
     * Perform PayPal API request & return response.
379
     *
380
     * @throws \Exception
381
     *
382
     * @return \Psr\Http\Message\StreamInterface
383
     */
384
    private function makeHttpRequest()
385
    {
386
        try {
387
            return $this->client->post($this->apiUrl, [
388
                $this->httpBodyParam => $this->post->toArray(),
389
            ])->getBody();
390
        } catch (HttpClientException $e) {
391
            throw new \Exception($e->getRequest().' '.$e->getResponse());
392
        } catch (HttpServerException $e) {
393
            throw new \Exception($e->getRequest().' '.$e->getResponse());
394
        } catch (HttpBadResponseException $e) {
395
            throw new \Exception($e->getRequest().' '.$e->getResponse());
396
        }
397
    }
398
399
    /**
400
     * Function To Perform PayPal API Request.
401
     *
402
     * @param string $method
403
     *
404
     * @throws \Exception
405
     *
406
     * @return array|\Psr\Http\Message\StreamInterface
407
     */
408
    private function doPayPalRequest($method)
409
    {
410
        // Setup PayPal API Request Payload
411
        $this->createRequestPayload($method);
412
413
        try {
414
            // Perform PayPal HTTP API request.
415
            $response = $this->makeHttpRequest();
416
417
            return $this->retrieveData($method, $response);
418
        } catch (\Exception $e) {
419
            $message = collect($e->getTrace())->implode('\n');
420
        }
421
422
        return [
423
            'type'    => 'error',
424
            'message' => $message,
425
        ];
426
    }
427
428
    /**
429
     * Parse PayPal NVP Response.
430
     *
431
     * @param string                                  $method
432
     * @param array|\Psr\Http\Message\StreamInterface $response
433
     *
434
     * @return array
435
     */
436
    private function retrieveData($method, $response)
437
    {
438
        if ($method === 'verifyipn') {
439
            return $response;
440
        }
441
442
        parse_str($response, $output);
443
444
        return $output;
445
    }
446
}
447