Braintree::getClientToken()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
/**
4
 * @author Anton Tuyakhov <[email protected]>
5
 */
6
7
namespace tuyakhov\braintree;
8
9
use Braintree\Address;
10
use Braintree\ClientToken;
11
use Braintree\Configuration;
12
use Braintree\CreditCard;
13
use Braintree\Customer;
14
use Braintree\MerchantAccount;
15
use Braintree\PaymentMethod;
16
use Braintree\Plan;
17
use Braintree\ResourceCollection;
18
use Braintree\Result\Error;
19
use Braintree\Result\Successful;
20
use Braintree\Subscription;
21
use Braintree\Transaction;
22
use Braintree\WebhookNotification;
23
use yii\base\Component;
24
use yii\base\InvalidConfigException;
25
use yii\helpers\ArrayHelper;
26
27
/**
28
 * Class Braintree.
29
 * @package tuyakhov\braintree
30
 *
31
 * @property UrlManager $urlManager provides methods for creating of URLs to Braintree; this property is read-only
32
 */
33
class Braintree extends Component
34
{
35
    public $environment = 'sandbox';
36
    public $merchantId;
37
    public $publicKey;
38
    public $privateKey;
39
40
    protected $clientToken;
41
    protected $options;
42
43
    /**
44
     * @var UrlManager
45
     */
46
    protected $urlManager;
47
48
    /**
49
     * @var Plan[] cached plans from Braintree
50
     */
51
    protected $plans;
52
53
    /**
54
     * Sets up Braintree configuration from config file.
55
     * @throws InvalidConfigException
56
     */
57 9
    public function init()
58
    {
59 9
        foreach (['merchantId', 'publicKey', 'privateKey', 'environment'] as $attribute) {
60 9
            if ($this->$attribute === null) {
61
                throw new InvalidConfigException(
62
                    strtr(
63
                        '"{class}::{attribute}" cannot be empty.',
64
                        [
65
                            '{class}' => static::class,
66
                            '{attribute}' => '$' . $attribute,
67
                        ]
68
                    )
69
                );
70
            }
71 9
            Configuration::$attribute($this->$attribute);
72
        }
73
74 9
        parent::init();
75 9
    }
76
77
    /**
78
     * Returns the URL manager object.
79
     * @return UrlManager
80
     */
81 1
    public function getUrlManager(): UrlManager
82
    {
83 1
        if (!isset($this->urlManager)) {
84 1
            $this->urlManager = new UrlManager();
85
        }
86
87 1
        return $this->urlManager;
88
    }
89
90
    public function getClientToken($params = []): string
91
    {
92
        if (!isset($this->clientToken)) {
93
            $this->clientToken = ClientToken::generate($params);
94
        }
95
96
        return $this->clientToken;
97
    }
98
99
    /**
100
     * Braintree sale function.
101
     * @param bool $submitForSettlement
102
     * @param bool $storeInVaultOnSuccess
103
     * @return array
104
     */
105 3
    public function sale(bool $submitForSettlement = true, bool $storeInVaultOnSuccess = true): array
106
    {
107 3
        $this->options['options']['submitForSettlement'] = $submitForSettlement;
108 3
        $this->options['options']['storeInVaultOnSuccess'] = $storeInVaultOnSuccess;
109 3
        $result = Transaction::sale($this->options);
110
111 3
        return ['status' => $result->success, 'result' => $result];
112
    }
113
114
    public function saleWithServiceFee($merchantAccountId, $amount, $paymentMethodNonce, $serviceFeeAmount): array
115
    {
116
        $result = Transaction::sale(
117
            [
118
                'merchantAccountId' => $merchantAccountId,
119
                'amount' => $amount,
120
                'paymentMethodNonce' => $paymentMethodNonce,
121
                'serviceFeeAmount' => $serviceFeeAmount,
122
            ]
123
        );
124
125
        return ['status' => $result->success, 'result' => $result];
126
    }
127
128
    public function saleWithPaymentNonce($amount, $paymentMethodNonce): array
129
    {
130
        $result = Transaction::sale(
131
            [
132
                'amount' => $amount,
133
                'paymentMethodNonce' => $paymentMethodNonce,
134
                'options' => [
135
                    'submitForSettlement' => true,
136
                    'storeInVaultOnSuccess' => true,
137
                ],
138
            ]
139
        );
140
141
        return ['status' => $result->success, 'result' => $result];
142
    }
143
144
    public function savePaymentMethod(): array
145
    {
146
        $result = PaymentMethod::create($this->options['paymentMethod']);
147
148
        return ['status' => $result->success, 'result' => $result];
149
    }
150
151
    public function updatePaymentMethod(): array
152
    {
153
        $result = PaymentMethod::update($this->options['paymentMethodToken'], $this->options['paymentMethod']);
154
155
        return ['status' => $result->success, 'result' => $result];
156
    }
157
158
    public function deletePaymentMethod(): array
159
    {
160
        $result = PaymentMethod::delete($this->options['paymentMethodToken']);
161
162
        return ['status' => $result->success, 'result' => $result];
163
    }
164
165
    /**
166
     * This method saves the customer to the Braintree and returns the resulting array.
167
     * @return array
168
     */
169 1
    public function saveCustomer(): array
170
    {
171 1
        if (isset($this->options['customerId'])) {
172
            $this->options['customer']['id'] = $this->options['customerId'];
173
        }
174 1
        $result = Customer::create($this->options['customer']);
175
176 1
        return ['status' => $result->success, 'result' => $result];
177
    }
178
179
    /**
180
     * This method saves the credit card to the Braintree and returns the resulting array.
181
     * @return array
182
     */
183 1
    public function saveCreditCard(): array
184
    {
185 1
        $sendArray = $this->options['creditCard'];
186 1
        if (isset($this->options['billing'])) {
187
            $sendArray['billingAddress'] = $this->options['billing'];
188
        }
189 1
        if (isset($this->options['customerId'])) {
190 1
            $sendArray['customerId'] = $this->options['customerId'];
191
        }
192 1
        $result = CreditCard::create($sendArray);
193
194 1
        return ['status' => $result->success, 'result' => $result];
195
    }
196
197
    public function saveAddress(): array
198
    {
199
        $sendArray = $this->options['billing'];
200
        if (isset($this->options['customerId'])) {
201
            $sendArray['customerId'] = $this->options['customerId'];
202
        }
203
        $result = Address::create($sendArray);
204
205
        return ['status' => $result->success, 'result' => $result];
206
    }
207
208
    /**
209
     * Constructs the array of credit card data for payment.
210
     * @param array $values credit card data, an array with structure:
211
     * [
212
     *     'number' => int (required) credit card number
213
     *     'cvv' => int (optional) credit card security code
214
     *     'expirationMonth' => int (optional) format: MM
215
     *         (use 'expirationMonth' and 'expirationYear' or 'expirationDate', not all at once)
216
     *     'expirationYear' => int (optional) format: YYYY
217
     *         (use 'expirationMonth' and 'expirationYear' or 'expirationDate', not all at once)
218
     *     'expirationDate' => string (optional) format: MM/YYYY
219
     *         (use 'expirationMonth' and 'expirationYear' or 'expirationDate', not all at once)
220
     *     'cardholderName' => string (optional) the cardholder name associated with the credit card
221
     * ]
222
     */
223 3
    public function setCreditCard(array $values)
224
    {
225 3
        $creditCard = ['number' => $values['number']];
226 3
        $optionalParamNames = ['cvv', 'expirationMonth', 'expirationYear', 'expirationDate', 'cardholderName'];
227 3
        foreach ($optionalParamNames as $optionalParamName) {
228 3
            $optionalValue = ArrayHelper::getValue($values, $optionalParamName);
229 3
            if (isset($optionalValue)) {
230 3
                $creditCard[$optionalParamName] = $optionalValue;
231
            }
232
        }
233 3
        $this->options['creditCard'] = $creditCard;
234 3
    }
235
236
    /**
237
     * @param array $values
238
     * @return $this
239
     */
240 5
    public function setOptions(array $values): Braintree
241
    {
242 5
        if (!empty($values)) {
243 5
            foreach ($values as $key => $value) {
244 5
                if ($key === 'amount') {
245 3
                    $this->setAmount($values['amount']);
246 5
                } elseif ($key === 'creditCard') {
247 3
                    $this->setCreditCard($values['creditCard']);
248
                } else {
249 3
                    $this->options[$key] = $value;
250
                }
251
            }
252
        }
253
254 5
        return $this;
255
    }
256
257
    /**
258
     * Set the amount to charge.
259
     * @param float $amount no currency sign needed
260
     */
261 3
    public function setAmount(float $amount)
262
    {
263 3
        $this->options['amount'] = round($amount, 2);
264 3
    }
265
266
    /**
267
     * @param bool $allowCaching whether to allow caching the result of retrieving of data from Braintree;
268
     * when this parameter is true (default), if data was retrieved before,
269
     * result will be directly returned when calling this method;
270
     * if this parameter is false, this method will always perform request to Braintree to obtain the up-to-date data;
271
     * note that this caching is effective only within the same HTTP request
272
     * @return Plan[]
273
     */
274 1
    public function getAllPlans(bool $allowCaching = true): array
275
    {
276 1
        if (!$allowCaching || !isset($this->plans)) {
277 1
            $this->plans = Plan::all();
278
        }
279
280 1
        return $this->plans;
281
    }
282
283
    /**
284
     * @param bool $allowCaching whether to allow caching the result of retrieving of data from Braintree;
285
     * when this parameter is true (default), if data was retrieved before,
286
     * result will be directly returned when calling this method;
287
     * if this parameter is false, this method will always perform request to Braintree to obtain the up-to-date data;
288
     * note that this caching is effective only within the same HTTP request
289
     * @return array
290
     */
291
    public function getPlanIds(bool $allowCaching = true): array
292
    {
293
        $plans = $this->getAllPlans($allowCaching);
294
        $planIds = [];
295
        foreach ($plans as $plan) {
296
            $planIds[] = $plan->id;
297
        }
298
299
        return $planIds;
300
    }
301
302
    /**
303
     * @param string $planId
304
     * @param bool $allowCaching whether to allow caching the result of retrieving of data from Braintree;
305
     * when this parameter is true (default), if data was retrieved before,
306
     * result will be directly returned when calling this method;
307
     * if this parameter is false, this method will always perform request to Braintree to obtain the up-to-date data;
308
     * note that this caching is effective only within the same HTTP request
309
     * @return null|Plan
310
     */
311
    public function getPlanById(string $planId, bool $allowCaching = true): ?Plan
312
    {
313
        $plans = $this->getAllPlans($allowCaching);
314
        foreach ($plans as $plan) {
315
            if ($plan->id === $planId) {
316
                return $plan;
317
            }
318
        }
319
320
        return null;
321
    }
322
323
    /**
324
     * Finds transaction by id.
325
     * @param string $id
326
     * @return Transaction
327
     */
328
    public function findTransaction(string $id): Transaction
329
    {
330
        return Transaction::find($id);
331
    }
332
333
    public function searchTransaction($params = []): ResourceCollection
334
    {
335
        return Transaction::search($params);
336
    }
337
338
    /**
339
     * @param string $merchantId
340
     * @return MerchantAccount
341
     */
342 1
    public function findMerchant(string $merchantId): MerchantAccount
343
    {
344 1
        return MerchantAccount::find($merchantId);
345
    }
346
347
    /**
348
     * @param string $customerId
349
     * @return Customer
350
     */
351
    public function findCustomer(string $customerId): Customer
352
    {
353
        return Customer::find($customerId);
354
    }
355
356
    public function findSubscription(string $subscriptionId): Subscription
357
    {
358
        return Subscription::find($subscriptionId);
359
    }
360
361 1
    public function searchSubscription($params = []): ResourceCollection
362
    {
363 1
        return Subscription::search($params);
364
    }
365
366
    /**
367
     * Create subscription.
368
     * @param array $params
369
     * @return Error|Successful
370
     */
371
    public function createSubscription(array $params)
372
    {
373
        return Subscription::create($params);
374
    }
375
376
    /**
377
     * Update subscription.
378
     * @param string $subscriptionId
379
     * @param array $params
380
     * @return Error|Successful
381
     */
382
    public function updateSubscription(string $subscriptionId, array $params)
383
    {
384
        return Subscription::update($subscriptionId, $params);
385
    }
386
387
    /**
388
     * Cancel subscription.
389
     * @param string $subscriptionId
390
     * @return Error|Successful
391
     */
392
    public function cancelSubscription(string $subscriptionId)
393
    {
394
        return Subscription::cancel($subscriptionId);
395
    }
396
397
    public function retryChargeSubscription(string $subscriptionId, $amount)
398
    {
399
        $retryResult = Subscription::retryCharge($subscriptionId, $amount);
400
401
        if ($retryResult->success) {
402
            $result = Transaction::submitForSettlement($retryResult->transaction->id);
403
404
            return $result;
405
        }
406
407
        return $retryResult;
408
    }
409
410
    public function parseWebhookNotification(string $signature, $payload): WebhookNotification
411
    {
412
        return WebhookNotification::parse($signature, $payload);
413
    }
414
}
415