Completed
Push — master ( 61d469...6253bf )
by Orkhan
03:16
created

Payment::getCardNumberDecryptedAttribute()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 3
nc 2
nop 0
dl 0
loc 7
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|null $payment_url
32
 * @property-read float|int $formatted_amount
33
 * @property-read string|null $card_number_decrypted
34
 * @property-read bool $successful
35
 * @method static Payment first()
36
 * @method static Builder successful()
37
 * @method static Builder pending()
38
 */
39
class Payment extends Model
40
{
41
    protected $guarded = [
42
        'status',
43
    ];
44
45
    protected $dates = [
46
        'payment_date',
47
    ];
48
49
    protected $hidden = [
50
        'card_number',
51
    ];
52
53
    protected $casts = [
54
        'amount' => 'int',
55
        'status' => 'int',
56
        'checks' => 'int',
57
    ];
58
59
    public const STATUS_SUCCESSFUL = 1;
60
61
    public const MINIMUM_REQUIRED_CHECKS = 5;
62
63
    /**
64
     * Payment constructor.
65
     *
66
     * @param array $attributes
67
     */
68
    public function __construct(array $attributes = [])
69
    {
70
        parent::__construct($attributes);
71
72
        $this->setTable(Config::get('goldenpay.table_name'));
73
    }
74
75
    /**
76
     * Returns payment's related model.
77
     *
78
     * @return MorphTo
79
     */
80
    public function payable(): MorphTo
81
    {
82
        return $this->morphTo();
83
    }
84
85
    /**
86
     * "payment_url" accessor.
87
     * Used to get "Goldenpay payment page url" from Payment model instance.
88
     * Returns "null" if payment is considered successful.
89
     *
90
     * @return string|null
91
     */
92
    public function getPaymentUrlAttribute(): ?string
93
    {
94
        if ($this->successful) {
95
            return null;
96
        }
97
98
        return (new PaymentKey($this->payment_key))->paymentUrl();
99
    }
100
101
    /**
102
     * "successful" accessor.
103
     * Used on Payment model instances to get if payment considered successful.
104
     *
105
     * @return bool
106
     */
107
    public function getSuccessfulAttribute(): bool
108
    {
109
        return $this->status === self::STATUS_SUCCESSFUL;
110
    }
111
112
    /**
113
     * "formatted_amount" accessor.
114
     * Because all amount related values stored as integer,
115
     * this accessor is used to return values as decimal.
116
     *
117
     * @return float|int
118
     */
119
    public function getFormattedAmountAttribute()
120
    {
121
        return $this->amount / 100;
122
    }
123
124
    /**
125
     * "card_number_decrypted" accessor.
126
     * Returns decrypted value for "card_number".
127
     * Returns null if "encrypt_card_numbers" setting turned off or "card_number" is not available.
128
     *
129
     * @return string|null
130
     */
131
    public function getCardNumberDecryptedAttribute(): ?string
132
    {
133
        if (Config::get('goldenpay.encrypt_card_numbers') && $this->card_number) {
134
            return Crypt::decrypt($this->card_number);
135
        }
136
137
        return null;
138
    }
139
140
    /**
141
     * Mutator for encrypting "card_number" data.
142
     *
143
     * @param string|null $value
144
     */
145
    public function setCardNumberAttribute(?string $value): void
146
    {
147
        if (Config::get('goldenpay.encrypt_card_numbers') && $value) {
148
            $this->attributes['card_number'] = Crypt::encrypt($value);
149
        } else {
150
            $this->attributes['card_number'] = $value;
151
        }
152
    }
153
154
    /**
155
     * "successful()" scope to filter only successful payments.
156
     * Successful payments are payments with "status" field value equal to STATUS_SUCCESSFUL constant value.
157
     *
158
     * @param Builder $builder
159
     * @return Builder
160
     */
161
    public function scopeSuccessful(Builder $builder): Builder
162
    {
163
        return $builder->where('status', self::STATUS_SUCCESSFUL);
164
    }
165
166
    /**
167
     * "pending()" scope to filter only pending payments.
168
     * Pending payments are:
169
     * "status" field anything other than STATUS_SUCCESSFUL constant value,
170
     * PLUS
171
     * "checks" field less than MINIMUM_REQUIRED_CHECKS constant value OR "created_at" timestamp less than 30 minutes.
172
     *
173
     * @param Builder $builder
174
     *
175
     * @return Builder
176
     */
177
    public function scopePending(Builder $builder): Builder
178
    {
179
        return $builder
180
            ->where(function (Builder $query) {
181
                $query->whereNull('status')
182
                    ->orWhere('status', '<>', self::STATUS_SUCCESSFUL);
183
            })
184
            ->where(function (Builder $query) {
185
                $query->where('checks', '<', self::MINIMUM_REQUIRED_CHECKS)
186
                    ->orWhere('created_at', '>=', now()->subMinutes(30));
187
            });
188
    }
189
}
190