2017-01-30 20:40:43 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Models;
|
2016-05-11 00:46:32 +02:00
|
|
|
|
|
|
|
use Cache;
|
|
|
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
2017-01-30 20:40:43 +01:00
|
|
|
* Class PaymentMethod.
|
2016-07-03 18:11:58 +02:00
|
|
|
*/
|
2016-05-11 00:46:32 +02:00
|
|
|
class PaymentMethod extends EntityModel
|
|
|
|
{
|
|
|
|
use SoftDeletes;
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @var bool
|
|
|
|
*/
|
2016-05-11 00:46:32 +02:00
|
|
|
public $timestamps = true;
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @var array
|
|
|
|
*/
|
2016-06-20 16:14:43 +02:00
|
|
|
protected $dates = ['deleted_at'];
|
2017-08-31 14:55:15 +02:00
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @var array
|
|
|
|
*/
|
2016-06-20 16:14:43 +02:00
|
|
|
protected $hidden = ['id'];
|
2016-05-11 00:46:32 +02:00
|
|
|
|
2017-08-31 14:55:15 +02:00
|
|
|
/**
|
|
|
|
* @var array
|
|
|
|
*/
|
|
|
|
protected $fillable = [
|
|
|
|
'contact_id',
|
|
|
|
'payment_type_id',
|
|
|
|
'source_reference',
|
|
|
|
'last4',
|
|
|
|
'expiration',
|
|
|
|
'email',
|
|
|
|
'currency_id',
|
|
|
|
];
|
|
|
|
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
|
|
*/
|
2016-05-11 00:46:32 +02:00
|
|
|
public function account()
|
|
|
|
{
|
|
|
|
return $this->belongsTo('App\Models\Account');
|
|
|
|
}
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
|
|
*/
|
2016-05-11 00:46:32 +02:00
|
|
|
public function contact()
|
|
|
|
{
|
|
|
|
return $this->belongsTo('App\Models\Contact');
|
|
|
|
}
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
|
|
*/
|
2016-05-11 00:46:32 +02:00
|
|
|
public function account_gateway_token()
|
|
|
|
{
|
|
|
|
return $this->belongsTo('App\Models\AccountGatewayToken');
|
|
|
|
}
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
|
|
*/
|
2016-05-11 00:46:32 +02:00
|
|
|
public function payment_type()
|
|
|
|
{
|
|
|
|
return $this->belongsTo('App\Models\PaymentType');
|
|
|
|
}
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
|
|
|
*/
|
2016-05-11 00:46:32 +02:00
|
|
|
public function currency()
|
|
|
|
{
|
|
|
|
return $this->belongsTo('App\Models\Currency');
|
|
|
|
}
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
|
|
*/
|
2016-05-11 00:46:32 +02:00
|
|
|
public function payments()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Payments');
|
|
|
|
}
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @return mixed|null|\stdClass|string
|
|
|
|
*/
|
2016-05-15 22:27:56 +02:00
|
|
|
public function getBankDataAttribute()
|
2016-05-11 00:46:32 +02:00
|
|
|
{
|
2017-01-30 20:40:43 +01:00
|
|
|
if (! $this->routing_number) {
|
2016-05-11 00:46:32 +02:00
|
|
|
return null;
|
|
|
|
}
|
2017-01-30 20:40:43 +01:00
|
|
|
|
2016-05-11 00:46:32 +02:00
|
|
|
return static::lookupBankData($this->routing_number);
|
|
|
|
}
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @param $bank_name
|
2017-01-30 20:40:43 +01:00
|
|
|
*
|
2016-07-03 18:11:58 +02:00
|
|
|
* @return null
|
|
|
|
*/
|
2016-05-24 20:16:42 +02:00
|
|
|
public function getBankNameAttribute($bank_name)
|
|
|
|
{
|
|
|
|
if ($bank_name) {
|
|
|
|
return $bank_name;
|
|
|
|
}
|
|
|
|
$bankData = $this->bank_data;
|
|
|
|
|
2017-01-30 20:40:43 +01:00
|
|
|
return $bankData ? $bankData->name : null;
|
2016-05-24 20:16:42 +02:00
|
|
|
}
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @param $value
|
2017-01-30 20:40:43 +01:00
|
|
|
*
|
2016-07-03 18:11:58 +02:00
|
|
|
* @return null|string
|
|
|
|
*/
|
2016-05-11 01:17:55 +02:00
|
|
|
public function getLast4Attribute($value)
|
|
|
|
{
|
|
|
|
return $value ? str_pad($value, 4, '0', STR_PAD_LEFT) : null;
|
|
|
|
}
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @param $query
|
|
|
|
* @param $clientId
|
2017-01-30 20:40:43 +01:00
|
|
|
*
|
2016-07-03 18:11:58 +02:00
|
|
|
* @return mixed
|
|
|
|
*/
|
2016-06-20 16:14:43 +02:00
|
|
|
public function scopeClientId($query, $clientId)
|
2016-05-11 00:46:32 +02:00
|
|
|
{
|
2017-01-30 17:05:31 +01:00
|
|
|
$query->whereHas('contact', function ($query) use ($clientId) {
|
2016-07-15 10:23:19 +02:00
|
|
|
$query->whereClientId($clientId);
|
|
|
|
});
|
2016-06-20 16:14:43 +02:00
|
|
|
}
|
2016-05-11 00:46:32 +02:00
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @param $query
|
|
|
|
* @param $isBank
|
|
|
|
*/
|
2016-06-20 16:14:43 +02:00
|
|
|
public function scopeIsBankAccount($query, $isBank)
|
|
|
|
{
|
|
|
|
if ($isBank) {
|
|
|
|
$query->where('payment_type_id', '=', PAYMENT_TYPE_ACH);
|
|
|
|
} else {
|
|
|
|
$query->where('payment_type_id', '!=', PAYMENT_TYPE_ACH);
|
2016-05-11 00:46:32 +02:00
|
|
|
}
|
2016-06-20 16:14:43 +02:00
|
|
|
}
|
2016-05-11 00:46:32 +02:00
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @return \Illuminate\Contracts\Routing\UrlGenerator|string
|
|
|
|
*/
|
2016-06-20 16:14:43 +02:00
|
|
|
public function imageUrl()
|
|
|
|
{
|
|
|
|
return url(sprintf('/images/credit_cards/%s.png', str_replace(' ', '', strtolower($this->payment_type->name))));
|
2016-05-11 00:46:32 +02:00
|
|
|
}
|
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @param $routingNumber
|
2017-01-30 20:40:43 +01:00
|
|
|
*
|
2016-07-03 18:11:58 +02:00
|
|
|
* @return mixed|null|\stdClass|string
|
|
|
|
*/
|
2017-01-30 17:05:31 +01:00
|
|
|
public static function lookupBankData($routingNumber)
|
|
|
|
{
|
2016-05-11 00:46:32 +02:00
|
|
|
$cached = Cache::get('bankData:'.$routingNumber);
|
|
|
|
|
|
|
|
if ($cached != null) {
|
|
|
|
return $cached == false ? null : $cached;
|
|
|
|
}
|
|
|
|
|
|
|
|
$dataPath = base_path('vendor/gatepay/FedACHdir/FedACHdir.txt');
|
|
|
|
|
2017-01-30 20:40:43 +01:00
|
|
|
if (! file_exists($dataPath) || ! $size = filesize($dataPath)) {
|
2016-05-11 00:46:32 +02:00
|
|
|
return 'Invalid data file';
|
|
|
|
}
|
|
|
|
|
|
|
|
$lineSize = 157;
|
2017-01-30 20:40:43 +01:00
|
|
|
$numLines = $size / $lineSize;
|
2016-05-11 00:46:32 +02:00
|
|
|
|
|
|
|
if ($numLines % 1 != 0) {
|
|
|
|
// The number of lines should be an integer
|
|
|
|
return 'Invalid data file';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Format: http://www.sco.ca.gov/Files-21C/Bank_Master_Interface_Information_Package.pdf
|
|
|
|
$file = fopen($dataPath, 'r');
|
|
|
|
|
|
|
|
// Binary search
|
|
|
|
$low = 0;
|
|
|
|
$high = $numLines - 1;
|
|
|
|
while ($low <= $high) {
|
|
|
|
$mid = floor(($low + $high) / 2);
|
|
|
|
|
|
|
|
fseek($file, $mid * $lineSize);
|
|
|
|
$thisNumber = fread($file, 9);
|
|
|
|
|
|
|
|
if ($thisNumber > $routingNumber) {
|
|
|
|
$high = $mid - 1;
|
2017-01-30 17:05:31 +01:00
|
|
|
} elseif ($thisNumber < $routingNumber) {
|
2016-05-11 00:46:32 +02:00
|
|
|
$low = $mid + 1;
|
|
|
|
} else {
|
|
|
|
$data = new \stdClass();
|
|
|
|
$data->routing_number = $thisNumber;
|
|
|
|
|
|
|
|
fseek($file, 26, SEEK_CUR);
|
|
|
|
|
|
|
|
$data->name = trim(fread($file, 36));
|
|
|
|
$data->address = trim(fread($file, 36));
|
|
|
|
$data->city = trim(fread($file, 20));
|
|
|
|
$data->state = fread($file, 2);
|
|
|
|
$data->zip = fread($file, 5).'-'.fread($file, 4);
|
|
|
|
$data->phone = fread($file, 10);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-30 20:40:43 +01:00
|
|
|
if (! empty($data)) {
|
2016-05-11 00:46:32 +02:00
|
|
|
Cache::put('bankData:'.$routingNumber, $data, 5);
|
2017-01-30 20:40:43 +01:00
|
|
|
|
2016-05-11 00:46:32 +02:00
|
|
|
return $data;
|
|
|
|
} else {
|
|
|
|
Cache::put('bankData:'.$routingNumber, false, 5);
|
2017-01-30 20:40:43 +01:00
|
|
|
|
2016-05-11 00:46:32 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2016-05-24 20:16:42 +02:00
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @return bool
|
|
|
|
*/
|
2016-06-23 19:17:02 +02:00
|
|
|
public function requiresDelayedAutoBill()
|
|
|
|
{
|
2016-05-26 21:22:09 +02:00
|
|
|
return $this->payment_type_id == PAYMENT_TYPE_ACH;
|
2016-05-24 20:16:42 +02:00
|
|
|
}
|
2016-06-23 19:17:02 +02:00
|
|
|
|
2016-07-03 18:11:58 +02:00
|
|
|
/**
|
|
|
|
* @return mixed
|
|
|
|
*/
|
2016-06-23 19:17:02 +02:00
|
|
|
public function gatewayType()
|
|
|
|
{
|
|
|
|
if ($this->payment_type_id == PAYMENT_TYPE_ACH) {
|
|
|
|
return GATEWAY_TYPE_BANK_TRANSFER;
|
|
|
|
} elseif ($this->payment_type_id == PAYMENT_TYPE_PAYPAL) {
|
|
|
|
return GATEWAY_TYPE_PAYPAL;
|
|
|
|
} else {
|
|
|
|
return GATEWAY_TYPE_TOKEN;
|
|
|
|
}
|
|
|
|
}
|
2016-05-11 00:46:32 +02:00
|
|
|
}
|
|
|
|
|
2017-01-30 17:05:31 +01:00
|
|
|
PaymentMethod::deleting(function ($paymentMethod) {
|
2016-05-11 00:46:32 +02:00
|
|
|
$accountGatewayToken = $paymentMethod->account_gateway_token;
|
|
|
|
if ($accountGatewayToken->default_payment_method_id == $paymentMethod->id) {
|
2017-01-30 17:05:31 +01:00
|
|
|
$newDefault = $accountGatewayToken->payment_methods->first(function ($i, $paymentMethdod) use ($accountGatewayToken) {
|
2016-05-11 00:46:32 +02:00
|
|
|
return $paymentMethdod->id != $accountGatewayToken->default_payment_method_id;
|
|
|
|
});
|
|
|
|
$accountGatewayToken->default_payment_method_id = $newDefault ? $newDefault->id : null;
|
|
|
|
$accountGatewayToken->save();
|
|
|
|
}
|
2016-06-20 16:14:43 +02:00
|
|
|
});
|