Files
water-back/modules/Payment/Models/Payment.php
2023-01-12 14:47:38 +08:00

257 lines
6.7 KiB
PHP

<?php
namespace Modules\Payment\Models;
use App\Models\Model;
use App\Traits\OrderByIdDesc;
use Carbon\Carbon;
use Exception;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Modules\Payment\Events\Paid;
use Modules\Payment\Facades\Pay;
use Modules\User\Models\User;
use Modules\User\Traits\BelongsToUser;
class Payment extends Model
{
use BelongsToUser,
OrderByIdDesc;
protected $table = 'payments';
protected $dates = [
'paid_at',
];
const STATUS_NOPAY = 'nopay';
const STATUS_SUCCESS = 'success';
const STATUS_FAIL = 'fail';
const STATUS_REFUND = 'refund';
const STATUS_CLOSED = 'closed';
const STATUS_REVOKED = 'revoked';
const STATUS_ERROR = 'error';
const STATUS_FINISHED = 'finished';
const STATUS_MAP = [
self::STATUS_NOPAY => '未支付',
self::STATUS_SUCCESS => '支付成功',
self::STATUS_FAIL => '支付失败',
self::STATUS_REFUND => '转入退款',
self::STATUS_CLOSED => '支付关闭',
self::STATUS_REVOKED => '支付撤销',
self::STATUS_ERROR => '支付错误',
self::STATUS_FINISHED => '支付完结',
];
const STATUS_LABEL_MAP = [
self::STATUS_NOPAY => 'default',
self::STATUS_SUCCESS => 'success',
self::STATUS_FAIL => 'warning',
self::STATUS_REFUND => 'info',
self::STATUS_CLOSED => 'primary',
self::STATUS_REVOKED => 'primary',
self::STATUS_ERROR => 'danger',
self::STATUS_FINISHED => 'success',
];
/**
* 支付方式
*/
const DRIVER_ALIPAY = 'alipay';
const DRIVER_WECHAT = 'wechat';
const DRIVER_SCORE = 'score';
const DRIVER_MAP = [
self::DRIVER_ALIPAY => '支付宝',
self::DRIVER_WECHAT => '微信支付',
self::DRIVER_SCORE => '水滴支付',
];
const DRIVER_LABEL_MAP = [
self::DRIVER_ALIPAY => 'info',
self::DRIVER_WECHAT => 'success',
];
protected static function boot()
{
parent::boot();
self::creating(function ($model) {
$time = explode(' ', microtime());
$counter = $model->whereDate('created_at', Carbon::today())->count() + 1;
$len = Setting::orderByDesc('in_use')->value('trade_id_counter_length');
$len = $len < 6 ? 6 : $len;
$len = $len > 16 ? 16 : $len;
$model->trade_id = date('YmdHis').
sprintf('%06d', $time[0] * 1e6).
sprintf('%0'.$len.'d', $counter);
$model->state = self::STATUS_NOPAY;
});
}
/**
* Notes: 支付渠道
*
* @Author: 玄尘
* @Date : 2021/5/18 11:14
* @return string
*/
public function getDriverTextAttribute(): string
{
return self::DRIVER_MAP[$this->driver];
}
/**
* Notes: 支付状态
*
* @Author: 玄尘
* @Date : 2021/5/18 11:17
* @return string
*/
public function getStateTextAttribute(): string
{
return self::STATUS_MAP[$this->state];
}
/**
* Notes : 要支付的模型
*
* @Date : 2021/4/21 1:59 下午
* @Author : < Jason.C >
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function order(): MorphTo
{
return $this->morphTo();
}
/**
* Notes : 结果通知
*
* @Date : 2021/4/23 11:49 上午
* @Author : < Jason.C >
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function notifies(): HasMany
{
return $this->hasMany(PaymentNotify::class);
}
/**
* Notes : 退款单
*
* @Date : 2021/6/1 11:13 上午
* @Author : < Jason.C >
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function refunds(): HasMany
{
return $this->hasMany(Refund::class);
}
/**
* Notes : 退款状态
*
* @Date : 2021/6/1 11:40 上午
* @Author : < Jason.C >
* @return string
*/
public function getRefundStatusTextAttribute(): string
{
if ($this->refunds->count()) {
return ($this->refunds->sum('total') == $this->total) ? '全额退款' : '部分退款';
} else {
return '';
}
}
/**
* Notes : 直接通过 order 来设置关联的支付订单
*
* @Date : 2021/4/21 12:43 下午
* @Author : < Jason.C >
* @param \App\Models\Model $order
*/
public function setOrderAttribute(Model $order)
{
$this->attributes['order_type'] = get_class($order);
$this->attributes['order_id'] = $order->getKey();
}
/**
* Notes : 通过模型来设置所属用户
*
* @Date : 2021/4/21 1:48 下午
* @Author : < Jason.C >
* @param \Modules\User\Models\User $user
*/
public function setUserAttribute(User $user)
{
$this->attributes['user_id'] = $user->getKey();
}
/**
* Notes : 支付成功,调用的方法
*
* @Date : 2021/4/20 5:42 下午
* @Author : < Jason.C >
*/
public function paid(): void
{
$this->state = self::STATUS_SUCCESS;
$this->paid_at = now();
$this->save();
event(new Paid($this));
}
/**
* Notes : 根据支付订单,获取支付渠道需要的接口数据
*
* @Date : 2021/4/21 4:24 下午
* @Author : < Jason.C >
* @param string $title 订单标题
* @param array $extends 扩展数据, 微信公众号 ['openid' => OPENID]
* @return mixed
* @throws \Exception
*/
public function getPaymentParams(string $title, array $extends = [])
{
$order['out_trade_no'] = $this->trade_id;
$driver = $this->driver;
$gateway = $this->gateway;
if ($driver === self::DRIVER_WECHAT) {
$order['out_trade_no'] = $this->trade_id;
if (config('payment.version', 2) == 2) {
$order['body'] = $title;
$order['total_fee'] = $this->total * 100;
} else {
$order['description'] = $title;
$order['amount']['total'] = $this->total * 100;
}
} elseif ($driver === self::DRIVER_ALIPAY) {
$order['total_amount'] = $this->total;
$order['out_trade_no'] = $this->trade_id;
$order['subject'] = $title;
} else {
throw new Exception('unsupported driver');
}
if (! empty($extends)) {
$order = array_merge($order, $extends);
}
return Pay::$driver()->$gateway($order);
}
}