Completed
Push — master ( 92e87d...c7ea00 )
by Raza
03:11
created

PayPalRequest::searchTransactions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
rs 9.4285
c 2
b 0
f 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
     * PayPal API mode to be used.
22
     *
23
     * @var string
24
     */
25
    public $mode;
26
27
    /**
28
     * Request data to be sent to PayPal.
29
     *
30
     * @var \Illuminate\Support\Collection
31
     */
32
    protected $post;
33
34
    /**
35
     * PayPal API configuration.
36
     *
37
     * @var array
38
     */
39
    private $config;
40
41
    /**
42
     * Default currency for PayPal.
43
     *
44
     * @var string
45
     */
46
    private $currency;
47
48
    /**
49
     * Additional options for PayPal API request.
50
     *
51
     * @var array
52
     */
53
    private $options;
54
55
    /**
56
     * Default payment action for PayPal.
57
     *
58
     * @var string
59
     */
60
    private $paymentAction;
61
62
    /**
63
     * Default locale for PayPal.
64
     *
65
     * @var string
66
     */
67
    private $locale;
68
69
    /**
70
     * PayPal API Endpoint.
71
     *
72
     * @var string
73
     */
74
    private $apiUrl;
75
76
    /**
77
     * IPN notification url for PayPal.
78
     *
79
     * @var string
80
     */
81
    private $notifyUrl;
82
83
    /**
84
     * Http Client request body parameter name.
85
     *
86
     * @var string
87
     */
88
    private $httpBodyParam;
89
90
    /**
91
     * Function To Set PayPal API Configuration.
92
     *
93
     * @param array $config
94
     *
95
     * @return void
96
     */
97
    private function setConfig(array $config = [])
98
    {
99
        // Setting Http Client
100
        $this->client = $this->setClient();
101
102
        // Set Api Credentials
103
        if (function_exists('config')) {
104
            $this->setApiCredentials(
105
                config('paypal')
106
            );
107
        } elseif (!empty($config)) {
108
            $this->setApiCredentials($config);
109
        }
110
111
        $this->setRequestData();
112
    }
113
114
    /**
115
     * Function to initialize Http Client.
116
     *
117
     * @return HttpClient
118
     */
119
    protected function setClient()
120
    {
121
        return new HttpClient([
122
            'curl' => [
123
                CURLOPT_SSLVERSION     => CURL_SSLVERSION_TLSv1_2,
124
                CURLOPT_SSL_VERIFYPEER => false,
125
            ],
126
        ]);
127
    }
128
129
    /**
130
     * Set PayPal API Credentials.
131
     *
132
     * @param array $credentials
133
     *
134
     * @throws \Exception
135
     *
136
     * @return void
137
     */
138
    public function setApiCredentials($credentials)
139
    {
140
        // Setting Default PayPal Mode If not set
141
        $this->setApiEnvironment($credentials);
142
143
        // Set API configuration for the PayPal provider
144
        $this->setApiProviderConfiguration($credentials);
145
146
        // Set default currency.
147
        $this->setCurrency($credentials['currency']);
148
149
        // Set default payment action.
150
        $this->paymentAction = !empty($this->config['payment_action']) ? $this->config['payment_action'] : 'Sale';
151
152
        // Set default locale.
153
        $this->locale = !empty($this->config['locale']) ? $this->config['locale'] : 'en_US';
154
155
        // Set PayPal API Endpoint.
156
        $this->apiUrl = $this->config['api_url'];
157
158
        // Set PayPal IPN Notification URL
159
        $this->notifyUrl = $credentials['notify_url'];
160
    }
161
162
    /**
163
     * Set API environment to be used by PayPal.
164
     *
165
     * @param array $credentials
166
     *
167
     * @return void
168
     */
169
    private function setApiEnvironment($credentials)
170
    {
171
        if (empty($credentials['mode']) || !in_array($credentials['mode'], ['sandbox', 'live'])) {
172
            $this->mode = 'live';
173
        } else {
174
            $this->mode = $credentials['mode'];
175
        }
176
    }
177
178
    /**
179
     * Set configuration details for the provider.
180
     *
181
     * @param array $credentials
182
     *
183
     * @throws \Exception
184
     *
185
     * @return void
186
     */
187
    private function setApiProviderConfiguration($credentials)
188
    {
189
        // Setting PayPal API Credentials
190
        collect($credentials[$this->mode])->map(function ($value, $key) {
191
            $this->config[$key] = $value;
192
        });
193
194
        // Setup PayPal API Signature value to use.
195
        $this->config['signature'] = empty($this->config['certificate']) ?
196
            $this->config['secret'] : file_get_contents($this->config['certificate']);
197
198
        if ($this instanceof \Srmklive\PayPal\Services\AdaptivePayments) {
199
            $this->setAdaptivePaymentsOptions();
200
        } elseif ($this instanceof \Srmklive\PayPal\Services\ExpressCheckout) {
201
            $this->setExpressCheckoutOptions($credentials);
202
        } else {
203
            throw new \Exception('Invalid api credentials provided for PayPal!. Please provide the right api credentials.');
204
        }
205
    }
206
207
    /**
208
     * Setup request data to be sent to PayPal.
209
     *
210
     * @param array $data
211
     *
212
     * @return \Illuminate\Support\Collection
213
     */
214
    protected function setRequestData(array $data = [])
215
    {
216
        if (($this->post instanceof Collection) && (!$this->post->isEmpty())) {
217
            unset($this->post);
218
        }
219
220
        $this->post = new Collection($data);
221
222
        return $this->post;
223
    }
224
225
    /**
226
     * Set other/override PayPal API parameters.
227
     *
228
     * @param array $options
229
     *
230
     * @return $this
231
     */
232
    public function addOptions(array $options)
233
    {
234
        $this->options = $options;
235
236
        return $this;
237
    }
238
239
    /**
240
     * Function to set currency.
241
     *
242
     * @param string $currency
243
     *
244
     * @throws \Exception
245
     *
246
     * @return $this
247
     */
248
    public function setCurrency($currency = 'USD')
249
    {
250
        $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'];
251
252
        // Check if provided currency is valid.
253
        if (!in_array($currency, $allowedCurrencies)) {
254
            throw new \Exception('Currency is not supported by PayPal.');
255
        }
256
257
        $this->currency = $currency;
258
259
        return $this;
260
    }
261
262
    /**
263
     * Retrieve PayPal IPN Response.
264
     *
265
     * @param array $post
266
     *
267
     * @return array
268
     */
269
    public function verifyIPN($post)
270
    {
271
        $this->setRequestData($post);
272
273
        $this->apiUrl = $this->config['gateway_url'].'/cgi-bin/webscr';
274
275
        return $this->doPayPalRequest('verifyipn');
276
    }
277
278
    /**
279
     * Create request payload to be sent to PayPal.
280
     *
281
     * @param string $method
282
     */
283
    private function createRequestPayload($method)
284
    {
285
        $config = array_merge([
286
            'USER'      => $this->config['username'],
287
            'PWD'       => $this->config['password'],
288
            'SIGNATURE' => $this->config['signature'],
289
            'VERSION'   => 123,
290
            'METHOD'    => $method,
291
        ], $this->options);
292
293
        $this->post = $this->post->merge($config);
294
        if ($method === 'verifyipn') {
295
            $this->post->forget('METHOD');
296
        }
297
    }
298
299
    /**
300
     * Perform PayPal API request & return response.
301
     *
302
     * @throws \Exception
303
     *
304
     * @return \Psr\Http\Message\StreamInterface
305
     */
306
    private function makeHttpRequest()
307
    {
308
        try {
309
            return $this->client->post($this->apiUrl, [
310
                $this->httpBodyParam => $this->post->toArray(),
311
            ])->getBody();
312
        } catch (HttpClientException $e) {
313
            throw new \Exception($e->getRequest().' '.$e->getResponse());
314
        } catch (HttpServerException $e) {
315
            throw new \Exception($e->getRequest().' '.$e->getResponse());
316
        } catch (HttpBadResponseException $e) {
317
            throw new \Exception($e->getRequest().' '.$e->getResponse());
318
        }
319
    }
320
321
    /**
322
     * Function To Perform PayPal API Request.
323
     *
324
     * @param string $method
325
     *
326
     * @throws \Exception
327
     *
328
     * @return array|\Psr\Http\Message\StreamInterface
329
     */
330
    private function doPayPalRequest($method)
331
    {
332
        // Setup PayPal API Request Payload
333
        $this->createRequestPayload($method);
334
335
        try {
336
            // Perform PayPal HTTP API request.
337
            $response = $this->makeHttpRequest();
338
339
            return $this->retrieveData($method, $response);
340
        } catch (\Exception $e) {
341
            $message = collect($e->getTrace())->implode('\n');
342
        }
343
344
        return [
345
            'type'      => 'error',
346
            'message'   => $message,
347
        ];
348
    }
349
350
    /**
351
     * Parse PayPal NVP Response.
352
     *
353
     * @param string                                  $method
354
     * @param array|\Psr\Http\Message\StreamInterface $response
355
     *
356
     * @return array
357
     */
358
    private function retrieveData($method, $response)
359
    {
360
        if ($method === 'verifyipn') {
361
            return $response;
362
        }
363
364
        parse_str($response, $output);
365
366
        return $output;
367
    }
368
}
369