Completed
Push — master ( 342ac0...b858f3 )
by Orkhan
02:50
created

Payment::setCardNumberAttribute()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 2
nop 1
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Orkhanahmadov\LaravelGoldenpay\Models;
4
5
use Illuminate\Database\Eloquent\Builder;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Database\Eloquent\Relations\MorphTo;
8
use Illuminate\Support\Facades\Config;
9
use Illuminate\Support\Facades\Crypt;
10
use Orkhanahmadov\Goldenpay\Response\PaymentKey;
11
12
/**
13
 * Class Payment.
14
 *
15
 * @property int $id
16
 * @property string $payable_type
17
 * @property int $payable_id
18
 * @property string $payment_key
19
 * @property int $amount
20
 * @property string $card_type
21
 * @property string $language
22
 * @property string $description
23
 * @property int $status
24
 * @property string $message
25
 * @property string $reference_number
26
 * @property string $card_number
27
 * @property \Carbon\Carbon $payment_date
28
 * @property int $checks
29
 * @property \Carbon\Carbon $created_at
30
 * @property \Carbon\Carbon $updated_at
31
 * @property-read string $payment_url
32
 * @property-read float|int $formatted_amount
33
 * @property-read bool $successful
34
 * @method static Payment first()
35
 * @method static Builder successful()
36
 * @method static Builder pending()
37
 */
38
class Payment extends Model
39
{
40
    protected $guarded = [
41
        'status',
42
    ];
43
44
    protected $dates = [
45
        'payment_date',
46
    ];
47
48
    protected $hidden = [
49
        'card_number',
50
    ];
51
52
    protected $casts = [
53
        'amount' => 'int',
54
        'status' => 'int',
55
        'checks' => 'int',
56
    ];
57
58
    public const STATUS_SUCCESSFUL = 1;
59
60
    public const MINIMUM_REQUIRED_CHECKS = 5;
61
62
    /**
63
     * Payment constructor.
64
     *
65
     * @param array $attributes
66
     */
67
    public function __construct(array $attributes = [])
68
    {
69
        parent::__construct($attributes);
70
71
        $this->setTable(Config::get('goldenpay.table_name'));
72
    }
73
74
    /**
75
     * Returns payment's related model.
76
     *
77
     * @return MorphTo
78
     */
79
    public function payable(): MorphTo
80
    {
81
        return $this->morphTo();
82
    }
83
84
    /**
85
     * "payment_url" accessor.
86
     * Used to get "Goldenpay payment page url" from Payment model instance.
87
     * Returns "null" if payment is considered successful.
88
     *
89
     * @return string|null
90
     */
91
    public function getPaymentUrlAttribute(): ?string
92
    {
93
        if ($this->successful) {
94
            return null;
95
        }
96
97
        return (new PaymentKey($this->payment_key))->paymentUrl();
98
    }
99
100
    /**
101
     * "successful" accessor.
102
     * Used on Payment model instances to get if payment considered successful.
103
     *
104
     * @return bool
105
     */
106
    public function getSuccessfulAttribute(): bool
107
    {
108
        return $this->status === self::STATUS_SUCCESSFUL;
109
    }
110
111
    /**
112
     * "formatted_amount" accessor.
113
     * Because all amount related values stored as integer,
114
     * this accessor to return values as decimal.
115
     *
116
     * @return float|int
117
     */
118
    public function getFormattedAmountAttribute()
119
    {
120
        return $this->amount / 100;
121
    }
122
123
    /**
124
     * Mutator for encrypting "card_number" data.
125
     *
126
     * @param string|null $value
127
     */
128
    public function setCardNumberAttribute(?string $value): void
129
    {
130
        if (Config::get('goldenpay.encrypt_card_numbers') && $value) {
131
            $this->attributes['card_number'] = Crypt::encrypt($value);
132
        } else {
133
            $this->attributes['card_number'] = $value;
134
        }
135
    }
136
137
    /**
138
     * "successful()" scope to filter only successful payments.
139
     * Successful payments are payments with "status" field value equal to STATUS_SUCCESSFUL constant value.
140
     *
141
     * @param Builder $builder
142
     * @return Builder
143
     */
144
    public function scopeSuccessful(Builder $builder): Builder
145
    {
146
        return $builder->whereStatus(self::STATUS_SUCCESSFUL);
147
    }
148
149
    /**
150
     * "pending()" scope to filter only pending payments.
151
     * Pending payments are:
152
     * "status" field anything other than STATUS_SUCCESSFUL constant value,
153
     * PLUS
154
     * "checks" field less than MINIMUM_REQUIRED_CHECKS constant value OR "created_at" timestamp less than 30 minutes.
155
     *
156
     * @param Builder $builder
157
     *
158
     * @return Builder
159
     */
160
    public function scopePending(Builder $builder): Builder
161
    {
162
        return $builder
163
            ->where(function (Builder $query) {
164
                $query->whereNull('status')
165
                    ->orWhere('status', '<>', self::STATUS_SUCCESSFUL);
166
            })
167
            ->where(function (Builder $query) {
168
                $query->where('checks', '<', self::MINIMUM_REQUIRED_CHECKS)
169
                    ->orWhere('created_at', '>=', now()->subMinutes(30));
170
            });
171
    }
172
}
173