Completed
Push — master ( 5c407a...f3a94d )
by Raza
02:19
created

PayPalRequest::addOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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