Files
water_new/modules/Mall/Models/Traits/RefundActions.php
2023-03-08 09:16:04 +08:00

319 lines
8.0 KiB
PHP

<?php
namespace Modules\Mall\Models\Traits;
use Encore\Admin\Facades\Admin;
use Exception;
use Illuminate\Support\Facades\DB;
use Modules\Mall\Events\RefundAgreed;
use Modules\Mall\Events\RefundCompleted;
use Modules\Mall\Events\RefundRefused;
use Modules\Payment\Models\Payment;
trait RefundActions
{
public $operator;
/**
* Notes: 设置操作人
*
* @Author: 玄尘
* @Date : 2021/5/17 16:12
* @param $operator
* @return $this
*/
public function setOperator($operator)
{
$this->operator = $operator;
return $this;
}
/**
* Notes: 设置备注
*
* @Author: 玄尘
* @Date : 2021/5/17 16:12
* @param $remark
* @return $this
*/
public function setRemark($remark)
{
$this->remark = $remark;
return $this;
}
/**
* Notes: 同意退款
*
* @Author: 玄尘
* @Date : 2021/5/17 11:59
* @param $remark
* @return bool
* @throws \Exception
*/
public function agree($remark = null): bool
{
if (! $this->can('agree')) {
throw new Exception("退款单状态不可以同意退款");
}
DB::transaction(function () use ($remark) {
$this->actual_total = $this->refund_total;
$this->save();
$this->apply('agree');
$this->setOrderApply($this->order, 'agree');
if ($this->order->express) {
$this->express()->create();
}
$this->setLogs($remark);
//订单已经进入发货流程,需要客户退货
if ($this->order->express && $this->order->express->deliver_at) {
$this->apply('deliver');
$this->setOrderApply($this->order, 'user_deliver');
} else {
//未发货设置为退款中
$this->apply('process');
$this->setOrderApply($this->order, 'process');
}
event(new RefundAgreed($this));
});
return true;
}
/**
* Notes: 拒绝退款
*
* @Author: 玄尘
* @Date : 2021/5/17 12:01
* @param string|null $remark
* @return bool
* @throws \Exception
*/
public function refuse(string $remark = null): bool
{
if (! $this->can('refuse')) {
throw new Exception("退款单状态不可以拒绝退款");
}
DB::transaction(function () use ($remark) {
$this->apply('refuse');
$this->setOrderApply($this->order, 'refuse');
$this->setLogs($remark);
event(new RefundRefused($this));
});
return true;
}
/**
* Notes: 退货退款中
*
* @Author: 玄尘
* @Date : 2021/5/17 14:29
* @param $company
* @param string $number
* @return bool
* @throws \Exception
*/
public function deliver($company, string $number): bool
{
if ($this->can('delivered')) {
DB::transaction(function () use ($company, $number) {
$this->express()->update([
'company' => $company,
'number' => $number,
'deliver_at' => now(),
]);
// 修改状态机
$this->apply('delivered');
$this->setOrderApply($this->order, 'user_deliverd');
$this->setLogs('客户退货');
});
return true;
} else {
throw new Exception('订单状态不可发货');
}
}
/**
* Notes: 确认收货
*
* @Author: 玄尘
* @Date : 2021/5/17 14:30
* @return bool
* @throws \Exception
*/
public function receive(): bool
{
if (! $this->can('sign')) {
throw new Exception('退款单状态不可以确认收货');
}
$this->express->receive_at = now();
$this->express->save();
$this->apply('sign');
//设置为退款中
$this->apply('process');
$this->setOrderApply($this->order, 'process');
$this->setLogs('店家签收');
return true;
}
/**
* Notes: 标记退款完成
*
* @Author: 玄尘
* @Date : 2021/5/17 14:32
* @return bool
* @throws \Exception
*/
public function complete(): bool
{
if (! $this->can('completed')) {
throw new Exception("订单状态不对,不可设置完成");
}
DB::transaction(function () {
$this->apply('completed');
//设置时间
$this->refunded_at = now();
$this->save();
$this->setLogs('订单标记完成');
event(new RefundCompleted($this));
});
return true;
}
/**
* Notes: 退款
*
* @Author: 玄尘
* @Date : 2021/5/17 14:52
* @throws \Exception
*/
public function returns(): bool
{
try {
$payment = $this->order->payment;
if (! $payment) {
throw new Exception("退款失败,未找到支付信息");
}
//微信支付
if ($payment->driver == Payment::DRIVER_WECHAT) {
$order = [
'out_trade_no' => $payment->trade_id,
'out_refund_no' => $this->refund_no,
'total_fee' => $payment->total * 100,
'refund_fee' => $this->actual_total * 100,
];
$result = app('pay.wechat')->refund($order);
if ($result->result_code != 'SUCCESS') {
throw new Exception("退款失败,".$result->return_msg);
}
$this->setLogs('退款完成');
return true;
} elseif ($payment->driver == Payment::DRIVER_ALIPAY) {//支付宝支付
$order = [
'out_trade_no' => $this->order->order_no,
'refund_amount' => $this->actual_total,
];
$result = app('pay.alipay')->refund($order);
if ($result->code != '10000') {
throw new Exception("退款失败,".$result->msg);
}
return true;
} elseif ($payment->driver == Payment::DRIVER_SCORE) {//水滴支付
$this->user->account->rule('score_buy_refund', $this->actual_total, false, [
'order_no' => $this->order->order_no,
'refund_no' => $this->refund_no,
]);
return true;
} else {
throw new Exception("退款失败,未找到支付路径");
}
} catch (Exception $exception) {
throw new Exception($exception->getMessage());
}
}
/**
* Notes: 记录日志
*
* @Author: 玄尘
* @Date : 2021/5/17 16:03
* @param null $remark
* @param null $title
* @param null $pictures
*/
public function setLogs($remark = null, $title = null, $pictures = null)
{
if (empty($this->operator)) {
$this->operator = $this->user;
}
if (empty($this->operator)) {
$this->operator = Admin::user();
}
$refund = $this->refresh();
$logs = [
'userable_type' => get_class($this->operator),
'userable_id' => $this->operator->id,
'remark' => $remark,
'title' => $title,
'pictures' => $pictures,
'state' => $refund->state,
];
$refund->logs()->create($logs);
}
/**
* Notes: 修改订单状态机
*
* @Author: 玄尘
* @Date : 2021/6/17 9:22
*/
public function setOrderApply($order, $status)
{
//如果都已经退款/货
if ($order->refund_items_count == $order->items()->count()) {
$order->apply($status);
}
}
}