Transaction::setCard()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Greenlyst\BaseCommerce\Models;
6
7
use function ArrayHelpers\array_get;
8
use function ArrayHelpers\array_set;
9
use Carbon\Carbon;
10
use Greenlyst\BaseCommerce\ClientException;
11
use Greenlyst\BaseCommerce\Core\Helpers;
12
use Greenlyst\BaseCommerce\LogicException;
13
use Greenlyst\BaseCommerce\Traits\HasClient;
14
use Greenlyst\BaseCommerce\Traits\HasErrorMessages;
15
16
final class Transaction
17
{
18
    use HasClient, HasErrorMessages;
19
20
    private $transactionId;
21
    private $status;
22
    private $authorizationDate;
23
    private $capturedDate;
24
    private $amount;
25
    private $taxAmount;
26
    private $tipAmount;
27
    private $transactionType;
28
    private $responseCode;
29
    private $responseMessage;
30
    private $card;
31
32
    const TRANSACTION_STATUS_FAILED = 'FAILED';
33
    const TRANSACTION_STATUS_CREATED = 'CREATED';
34
    const TRANSACTION_STATUS_AUTHORIZED = 'AUTHORIZED';
35
    const TRANSACTION_STATUS_CAPTURED = 'CAPTURED';
36
    const TRANSACTION_STATUS_SETTLED = 'SETTLED';
37
    const TRANSACTION_STATUS_VOIDED = 'VOIDED';
38
    const TRANSACTION_STATUS_DECLINED = 'DECLINED';
39
    const TRANSACTION_STATUS_3D_SECURE = '3DSECURE';
40
    const TRANSACTION_STATUS_VERIFIED = 'VERIFIED';
41
42
    const TRANSACTION_TYPE_AUTHORIZE = 'AUTH';
43
    const TRANSACTION_TYPE_CAPTURE = 'CAPTURE';
44
    const TRANSACTION_TYPE_CREDIT = 'CREDIT';
45
    const TRANSACTION_TYPE_REFUND = 'REFUND';
46
    const TRANSACTION_TYPE_SALE = 'SALE';
47
    const TRANSACTION_TYPE_VOID = 'VOID';
48
49
    const URI_CARD_TRANSACTION = '/pcms/?f=API_processBankCardTransactionV4';
50
51
    /**
52
     * @return mixed
53
     */
54
    public function getTransactionId()
55
    {
56
        return $this->transactionId;
57
    }
58
59
    /**
60
     * @param mixed $transactionId
61
     */
62
    public function setTransactionId($transactionId): void
63
    {
64
        $this->transactionId = $transactionId;
65
    }
66
67
    /**
68
     * @return mixed
69
     */
70
    public function getStatus()
71
    {
72
        return $this->status;
73
    }
74
75
    /**
76
     * @param mixed $status
77
     */
78
    public function setStatus($status): void
79
    {
80
        $this->status = $status;
81
    }
82
83
    /**
84
     * @return mixed
85
     */
86
    public function getAuthorizationDate()
87
    {
88
        return $this->authorizationDate;
89
    }
90
91
    /**
92
     * @param mixed $authorizationDate
93
     */
94
    public function setAuthorizationDate($authorizationDate): void
95
    {
96
        $this->authorizationDate = $authorizationDate;
97
    }
98
99
    /**
100
     * @return mixed
101
     */
102
    public function getCapturedDate()
103
    {
104
        return $this->capturedDate;
105
    }
106
107
    /**
108
     * @param mixed $capturedDate
109
     */
110
    public function setCapturedDate($capturedDate): void
111
    {
112
        $this->capturedDate = $capturedDate;
113
    }
114
115
    /**
116
     * @return mixed
117
     */
118
    public function getAmount()
119
    {
120
        return $this->amount;
121
    }
122
123
    /**
124
     * @param mixed $amount
125
     */
126
    public function setAmount($amount): void
127
    {
128
        $this->amount = $amount;
129
    }
130
131
    /**
132
     * @return mixed
133
     */
134
    public function getTaxAmount()
135
    {
136
        return $this->taxAmount;
137
    }
138
139
    /**
140
     * @param mixed $taxAmount
141
     */
142
    public function setTaxAmount($taxAmount): void
143
    {
144
        $this->taxAmount = $taxAmount;
145
    }
146
147
    /**
148
     * @return mixed
149
     */
150
    public function getTipAmount()
151
    {
152
        return $this->tipAmount;
153
    }
154
155
    /**
156
     * @param mixed $tipAmount
157
     */
158
    public function setTipAmount($tipAmount): void
159
    {
160
        $this->tipAmount = $tipAmount;
161
    }
162
163
    /**
164
     * @return mixed
165
     */
166
    public function getTransactionType()
167
    {
168
        return $this->transactionType;
169
    }
170
171
    /**
172
     * @param mixed $transactionType
173
     */
174
    public function setTransactionType($transactionType): void
175
    {
176
        $this->transactionType = $transactionType;
177
    }
178
179
    /**
180
     * @return mixed
181
     */
182
    public function getResponseCode()
183
    {
184
        return $this->responseCode;
185
    }
186
187
    /**
188
     * @param mixed $responseCode
189
     */
190
    public function setResponseCode($responseCode): void
191
    {
192
        $this->responseCode = $responseCode;
193
    }
194
195
    /**
196
     * @return mixed
197
     */
198
    public function getResponseMessage()
199
    {
200
        return $this->responseMessage;
201
    }
202
203
    /**
204
     * @param mixed $responseMessage
205
     */
206
    public function setResponseMessage($responseMessage): void
207
    {
208
        $this->responseMessage = $responseMessage;
209
    }
210
211
    /**
212
     * @return Card
213
     */
214
    public function getCard()
215
    {
216
        return $this->card;
217
    }
218
219
    /**
220
     * @param Card $card
221
     */
222
    public function setCard($card): void
223
    {
224
        $this->card = $card;
225
    }
226
227
    public function isVaultTransaction()
228
    {
229
        if ($this->getCard() !== null) {
230
            return !empty($this->getCard()->getToken());
231
        }
232
233
        //TODO: Do the same for ACH Bank Account Token as well
234
        return false;
235
    }
236
237
    public function isCardTransaction()
238
    {
239
        return $this->getCard() !== null;
240
    }
241
242
    /**
243
     * @throws LogicException
244
     * @throws ClientException
245
     */
246
    public function authorize()
247
    {
248
        if ($this->isVaultTransaction()) {
249
            Helpers::validateArray($this->toAuthorizeTransactionArray(), ['bank_card_transaction_type', 'token', 'bank_card_transaction_amount']);
250
        } else {
251
            Helpers::validateArray($this->toAuthorizeTransactionArray(), [
252
                'bank_card_transaction_name', 'bank_card_transaction_card_number', 'bank_card_transaction_expiration_month',
253
                'bank_card_transaction_expiration_year', 'bank_card_transaction_type', 'bank_card_transaction_amount',
254
            ]);
255
        }
256
257
        return $this->processTransaction($this->toAuthorizeTransactionArray());
258
    }
259
260
    /**
261
     * @throws ClientException
262
     * @throws LogicException
263
     *
264
     * @return $this
265
     */
266
    public function capture()
267
    {
268
        Helpers::validateArray($this->toCaptureTransactionArray(), ['bank_card_transaction_id', 'bank_card_transaction_amount', 'bank_card_transaction_type']);
269
270
        return $this->processTransaction($this->toCaptureTransactionArray());
271
    }
272
273
    /**
274
     * @throws LogicException
275
     * @throws ClientException
276
     */
277
    public function createSale()
278
    {
279
        if ($this->isVaultTransaction()) {
280
            Helpers::validateArray($this->toCreateTransactionArray(), ['bank_card_transaction_type', 'token', 'bank_card_transaction_amount']);
281
        } else {
282
            Helpers::validateArray($this->toCreateTransactionArray(), [
283
                'bank_card_transaction_name', 'bank_card_transaction_card_number', 'bank_card_transaction_expiration_month',
284
                'bank_card_transaction_expiration_year', 'bank_card_transaction_type', 'bank_card_transaction_amount',
285
            ]);
286
        }
287
288
        return $this->processTransaction($this->toCreateTransactionArray());
289
    }
290
291
    /**
292
     * @throws LogicException
293
     * @throws ClientException
294
     */
295
    public function refundSale()
296
    {
297
        Helpers::validateArray($this->toRefundTransactionArray(), ['bank_card_transaction_id', 'bank_card_transaction_amount', 'bank_card_transaction_type']);
298
299
        return $this->processTransaction($this->toRefundTransactionArray());
300
    }
301
302
    /**
303
     * @param $data
304
     *
305
     * @throws ClientException
306
     *
307
     * @return $this
308
     */
309
    private function processTransaction($data)
310
    {
311
        $response = $this->client->postRequest(self::URI_CARD_TRANSACTION, json_encode($data));
312
313
        $instance = $this->fromArray($response['bank_card_transaction']);
314
315
        $instance->handleMessages($response);
316
317
        return $instance;
318
    }
319
320
    /**
321
     * @return array
322
     */
323
    private function toRefundTransactionArray(): array
324
    {
325
        return clear_array([
326
            'bank_card_transaction_id'     => $this->getTransactionId(),
327
            'bank_card_transaction_amount' => $this->getAmount(),
328
            'bank_card_transaction_type'   => self::TRANSACTION_TYPE_REFUND,
329
        ]);
330
    }
331
332
    private function toCaptureTransactionArray(): array
333
    {
334
        $data = $this->toRefundTransactionArray();
335
336
        array_set($data, 'bank_card_transaction_type', self::TRANSACTION_TYPE_CAPTURE);
337
338
        return $data;
339
    }
340
341
    /**
342
     * @throws LogicException
343
     *
344
     * @return array
345
     */
346
    private function toCreateTransactionArray(): array
347
    {
348
        if ($this->isCardTransaction()) {
349
            if ($this->isVaultTransaction()) {
350
                return clear_array([
351
                    'bank_card_transaction_type'   => self::TRANSACTION_TYPE_SALE,
352
                    'token'                        => $this->getCard()->getToken(),
353
                    'bank_card_transaction_amount' => $this->getAmount(),
354
                ]);
355
            } else {
356
                return clear_array([
357
                    'bank_card_transaction_name'             => $this->getCard()->getName(),
358
                    'bank_card_transaction_card_number'      => $this->getCard()->getCardNumber(),
359
                    'bank_card_transaction_expiration_month' => $this->getCard()->getCardExpirationMonth(),
360
                    'bank_card_transaction_expiration_year'  => $this->getCard()->getCardExpirationYear(),
361
                    'bank_card_transaction_billing_address'  => $this->getCard()->getBillingAddress() ? $this->getCard()->getBillingAddress()->toArray() : null,
362
                    'bank_card_transaction_type'             => self::TRANSACTION_TYPE_SALE,
363
                    'bank_card_transaction_amount'           => $this->getAmount(),
364
                ]);
365
            }
366
        } else {
367
            throw LogicException::pendingImplementation('ACH Bank Transaction implementation');
368
        }
369
    }
370
371
    /**
372
     * @throws LogicException
373
     *
374
     * @return array
375
     */
376
    private function toAuthorizeTransactionArray(): array
377
    {
378
        if ($this->isCardTransaction()) {
379
            $data = $this->toCreateTransactionArray();
380
381
            array_set($data, 'bank_card_transaction_type', self::TRANSACTION_TYPE_AUTHORIZE);
382
383
            return $data;
384
        } else {
385
            throw LogicException::methodCallNotSupported('ACH Processing');
386
        }
387
    }
388
389
    private function fromArray(array $data)
390
    {
391
        $instance = new static();
392
393
        $instance->setTransactionId(array_get($data, 'bank_card_transaction_id'));
394
        $instance->setStatus(array_get($data, 'bank_card_transaction_status.bank_card_transaction_status_name'));
395
        $instance->setAmount(array_get($data, 'bank_card_transaction_amount', 0));
396
        $instance->setTipAmount(array_get($data, 'bank_card_transaction_tip_amount', 0));
397
        $instance->setTaxAmount(array_get($data, 'bank_card_transaction_tax_amount', 0));
398
        $instance->setAuthorizationDate(Carbon::parse(array_get($data, 'bank_card_transaction_authorization_date'))->toDateTime());
399
        $instance->setCapturedDate(Carbon::parse(array_get($data, 'bank_card_transaction_capture_date'))->toDateTime());
400
        $instance->setTransactionType(array_get($data, 'bank_card_transaction_type.bank_card_transaction_type_name'));
401
        $instance->setResponseCode(array_get($data, 'bank_card_transaction_response_code'));
402
        $instance->setResponseMessage(array_get($data, 'bank_card_transaction_response_message'));
403
404
        return $instance;
405
    }
406
}
407