Completed
Push — master ( 5f4236...e5600d )
by Raza
06:25
created

PayPalRequest::setHttpClientConfiguration()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 11
rs 9.4285
cc 2
eloc 6
nc 2
nop 0
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
     * Function to initialize Http Client.
134
     *
135
     * @return void
136
     */
137
    protected function setClient()
138
    {
139
        $this->client = new HttpClient([
140
            'curl' => $this->httpClientConfig,
141
        ]);
142
    }
143
144
    /**
145
     * Function to set Http Client configuration.
146
     *
147
     * @return void
148
     */
149
    protected function setHttpClientConfiguration()
150
    {
151
        $this->httpClientConfig = [
152
            CURLOPT_SSLVERSION     => CURL_SSLVERSION_TLSv1_2,
153
            CURLOPT_SSL_VERIFYPEER => $this->validateSSL,
154
        ];
155
156
        if (!empty($this->certificate)) {
157
            $this->httpClientConfig[CURLOPT_SSLCERT] = $this->certificate;
158
        }
159
    }
160
161
    /**
162
     * Set PayPal API Credentials.
163
     *
164
     * @param array $credentials
165
     *
166
     * @throws \Exception
167
     *
168
     * @return void
169
     */
170
    public function setApiCredentials($credentials)
171
    {
172
        // Setting Default PayPal Mode If not set
173
        $this->setApiEnvironment($credentials);
174
175
        // Set API configuration for the PayPal provider
176
        $this->setApiProviderConfiguration($credentials);
177
178
        // Set default currency.
179
        $this->setCurrency($credentials['currency']);
180
181
        // Set Http Client configuration.
182
        $this->setHttpClientConfiguration();
183
184
        // Initialize Http Client
185
        $this->setClient();
186
187
        // Set default payment action.
188
        $this->paymentAction = !empty($this->config['payment_action']) ? $this->config['payment_action'] : 'Sale';
189
190
        // Set default locale.
191
        $this->locale = !empty($this->config['locale']) ? $this->config['locale'] : 'en_US';
192
193
        // Set PayPal API Endpoint.
194
        $this->apiUrl = $this->config['api_url'];
195
196
        // Set PayPal IPN Notification URL
197
        $this->notifyUrl = $this->config['notify_url'];
198
    }
199
200
    /**
201
     * Set API environment to be used by PayPal.
202
     *
203
     * @param array $credentials
204
     *
205
     * @return void
206
     */
207
    private function setApiEnvironment($credentials)
208
    {
209
        if (empty($credentials['mode']) || !in_array($credentials['mode'], ['sandbox', 'live'])) {
210
            $this->mode = 'live';
211
        } else {
212
            $this->mode = $credentials['mode'];
213
        }
214
    }
215
216
    /**
217
     * Set configuration details for the provider.
218
     *
219
     * @param array $credentials
220
     *
221
     * @throws \Exception
222
     *
223
     * @return void
224
     */
225
    private function setApiProviderConfiguration($credentials)
226
    {
227
        // Setting PayPal API Credentials
228
        collect($credentials[$this->mode])->map(function ($value, $key) {
229
            $this->config[$key] = $value;
230
        });
231
232
        // Setup PayPal API Signature value to use.
233
        $this->config['signature'] = empty($this->config['certificate']) ?
234
            $this->config['secret'] : file_get_contents($this->config['certificate']);
235
236
        $this->certificate = file_get_contents($this->config['certificate']);
237
238
        $this->validateSSL = !empty($credentials['validate_ssl']) ? $credentials['validate_ssl'] : false;
239
240
        if ($this instanceof \Srmklive\PayPal\Services\AdaptivePayments) {
241
            $this->setAdaptivePaymentsOptions();
242
        } elseif ($this instanceof \Srmklive\PayPal\Services\ExpressCheckout) {
243
            $this->setExpressCheckoutOptions($credentials);
244
        } else {
245
            throw new \Exception('Invalid api credentials provided for PayPal!. Please provide the right api credentials.');
246
        }
247
    }
248
249
    /**
250
     * Setup request data to be sent to PayPal.
251
     *
252
     * @param array $data
253
     *
254
     * @return \Illuminate\Support\Collection
255
     */
256
    protected function setRequestData(array $data = [])
257
    {
258
        if (($this->post instanceof Collection) && (!$this->post->isEmpty())) {
259
            unset($this->post);
260
        }
261
262
        $this->post = new Collection($data);
263
264
        return $this->post;
265
    }
266
267
    /**
268
     * Set other/override PayPal API parameters.
269
     *
270
     * @param array $options
271
     *
272
     * @return $this
273
     */
274
    public function addOptions(array $options)
275
    {
276
        $this->options = $options;
277
278
        return $this;
279
    }
280
281
    /**
282
     * Function to set currency.
283
     *
284
     * @param string $currency
285
     *
286
     * @throws \Exception
287
     *
288
     * @return $this
289
     */
290
    public function setCurrency($currency = 'USD')
291
    {
292
        $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'];
293
294
        // Check if provided currency is valid.
295
        if (!in_array($currency, $allowedCurrencies)) {
296
            throw new \Exception('Currency is not supported by PayPal.');
297
        }
298
299
        $this->currency = $currency;
300
301
        return $this;
302
    }
303
304
    /**
305
     * Retrieve PayPal IPN Response.
306
     *
307
     * @param array $post
308
     *
309
     * @return array
310
     */
311
    public function verifyIPN($post)
312
    {
313
        $this->setRequestData($post);
314
315
        $this->apiUrl = $this->config['gateway_url'].'/cgi-bin/webscr';
316
317
        return $this->doPayPalRequest('verifyipn');
318
    }
319
320
    /**
321
     * Create request payload to be sent to PayPal.
322
     *
323
     * @param string $method
324
     */
325
    private function createRequestPayload($method)
326
    {
327
        $config = array_merge([
328
            'USER'      => $this->config['username'],
329
            'PWD'       => $this->config['password'],
330
            'SIGNATURE' => $this->config['signature'],
331
            'VERSION'   => 123,
332
            'METHOD'    => $method,
333
        ], $this->options);
334
335
        $this->post = $this->post->merge($config);
336
        if ($method === 'verifyipn') {
337
            $this->post->forget('METHOD');
338
        }
339
    }
340
341
    /**
342
     * Perform PayPal API request & return response.
343
     *
344
     * @throws \Exception
345
     *
346
     * @return \Psr\Http\Message\StreamInterface
347
     */
348
    private function makeHttpRequest()
349
    {
350
        try {
351
            return $this->client->post($this->apiUrl, [
352
                $this->httpBodyParam => $this->post->toArray(),
353
            ])->getBody();
354
        } catch (HttpClientException $e) {
355
            throw new \Exception($e->getRequest().' '.$e->getResponse());
356
        } catch (HttpServerException $e) {
357
            throw new \Exception($e->getRequest().' '.$e->getResponse());
358
        } catch (HttpBadResponseException $e) {
359
            throw new \Exception($e->getRequest().' '.$e->getResponse());
360
        }
361
    }
362
363
    /**
364
     * Function To Perform PayPal API Request.
365
     *
366
     * @param string $method
367
     *
368
     * @throws \Exception
369
     *
370
     * @return array|\Psr\Http\Message\StreamInterface
371
     */
372
    private function doPayPalRequest($method)
373
    {
374
        // Setup PayPal API Request Payload
375
        $this->createRequestPayload($method);
376
377
        try {
378
            // Perform PayPal HTTP API request.
379
            $response = $this->makeHttpRequest();
380
381
            return $this->retrieveData($method, $response);
382
        } catch (\Exception $e) {
383
            $message = collect($e->getTrace())->implode('\n');
384
        }
385
386
        return [
387
            'type'    => 'error',
388
            'message' => $message,
389
        ];
390
    }
391
392
    /**
393
     * Parse PayPal NVP Response.
394
     *
395
     * @param string                                  $method
396
     * @param array|\Psr\Http\Message\StreamInterface $response
397
     *
398
     * @return array
399
     */
400
    private function retrieveData($method, $response)
401
    {
402
        if ($method === 'verifyipn') {
403
            return $response;
404
        }
405
406
        parse_str($response, $output);
407
408
        return $output;
409
    }
410
}
411