208 lines
6.8 KiB
PHP
208 lines
6.8 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Enums\DealerDeliveryBillStatus;
|
|
use App\Enums\DealerOrderStatus;
|
|
use App\Exceptions\BizException;
|
|
use App\Exceptions\InvalidPaySerialNumberException;
|
|
use App\Models\DealerDeliveryBill;
|
|
use App\Models\DealerOrder;
|
|
use App\Models\DealerUserProduct;
|
|
use App\Models\DealerUserProductLog;
|
|
use App\Models\DistributionPreIncomeJob;
|
|
use App\Models\Order;
|
|
use App\Models\PayLog;
|
|
use App\Services\Dealer\OrderService;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class PayService
|
|
{
|
|
/**
|
|
* 根据支付流水号处理支付成功业务
|
|
*
|
|
* @param string $sn
|
|
* @param array $params
|
|
* @return \App\Models\PayLog
|
|
*
|
|
* @throws \App\Exceptions\BizException
|
|
* @throws \App\Exceptions\InvalidPaySerialNumberException
|
|
*/
|
|
public function handleSuccessByPaySerialNumber(string $paySerialNumber, array $params = []): PayLog
|
|
{
|
|
$payLog = PayLog::where('pay_sn', $paySerialNumber)->lockForUpdate()->first();
|
|
|
|
if ($payLog === null) {
|
|
throw new InvalidPaySerialNumberException();
|
|
}
|
|
|
|
return $this->handleSuccess($payLog, $params);
|
|
}
|
|
|
|
/**
|
|
* 处理支付成功业务
|
|
*
|
|
* @param \App\Models\PayLog $payLog
|
|
* @param array $params
|
|
* @return \App\Models\PayLog
|
|
*
|
|
* @throws \App\Exceptions\BizException
|
|
* @throws \App\Exceptions\InvalidPaySerialNumberException
|
|
*/
|
|
public function handleSuccess(PayLog $payLog, array $params = []): PayLog
|
|
{
|
|
if (! $payLog->isPending()) {
|
|
throw new InvalidPaySerialNumberException();
|
|
}
|
|
|
|
$payLog->update([
|
|
'pay_at' => $params['pay_at'] ?? now(),
|
|
'out_trade_no' => $params['out_trade_no'] ?? null,
|
|
'status' => PayLog::STATUS_SUCCESS,
|
|
]);
|
|
|
|
$payable = $payLog->payable;
|
|
|
|
if ($payable instanceof Order) {
|
|
if ($payable->isPaid()) {
|
|
throw new BizException('订单已支付');
|
|
}
|
|
|
|
if ($payable->isCompleted()) {
|
|
throw new BizException('订单已完成');
|
|
}
|
|
|
|
$payable->update([
|
|
'pay_sn' => $payLog->pay_sn,
|
|
'pay_way' => $payLog->pay_way,
|
|
'pay_at' => $payLog->pay_at,
|
|
'out_trade_no' => $payLog->out_trade_no,
|
|
'status' => Order::STATUS_PAID,
|
|
]);
|
|
|
|
// 增加用户预成长值
|
|
$payable->userInfo->incrPreGrowthValue($payable->sales_value, false);
|
|
|
|
DistributionPreIncomeJob::create([
|
|
'jobable_id' => $payable->id,
|
|
'jobable_type' => $payable->getMorphClass(),
|
|
'remarks' => '支付订单',
|
|
]);
|
|
} elseif ($payable instanceof DealerOrder) {
|
|
if (! $payable->isPendinged()) {
|
|
throw new BizException('订单不是待打款');
|
|
}
|
|
|
|
$payable->pay_sn = $payLog->pay_sn;
|
|
$payable->pay_time = $payLog->pay_at;
|
|
$payable->out_trade_no = $payLog->out_trade_no;
|
|
$payable->pay_way = $payLog->pay_way;
|
|
|
|
if ($payLog->isOffline()) {
|
|
$payable->pay_image = $params['pay_image'] ?? null;
|
|
$payable->pay_info = $params['pay_info'] ?? null;
|
|
$payable->status = DealerOrderStatus::Confirming;
|
|
} else {
|
|
$payable->paied_time = $payLog->pay_at;
|
|
$payable->status = DealerOrderStatus::Paid;
|
|
//签约单,云库存直接发货
|
|
if ($payable->consignor === null) {
|
|
(new OrderService())->orderInDepositstock($payable);
|
|
}
|
|
}
|
|
|
|
$payable->save();
|
|
} elseif ($payable instanceof DealerDeliveryBill) {
|
|
if (! $payable->isPending()) {
|
|
throw new BizException('提货单状态不是待打款');
|
|
}
|
|
|
|
$payable->pay_sn = $payLog->pay_sn;
|
|
$payable->pay_at = $payLog->pay_at;
|
|
$payable->out_trade_no = $payLog->out_trade_no;
|
|
$payable->pay_way = $payLog->pay_way;
|
|
$payable->status = DealerDeliveryBillStatus::Paid;
|
|
$payable->save();
|
|
|
|
// 将云仓库存变更为本地库存
|
|
$dealerProductLogs = [];
|
|
|
|
foreach ($payable->deliveryProducts as $deliveryProduct) {
|
|
DealerUserProduct::where([
|
|
'user_id' => $payable->user_id,
|
|
'product_id' => $deliveryProduct->product_id,
|
|
])->update([
|
|
'stock' => DB::raw("stock + {$deliveryProduct->qty}"),
|
|
]);
|
|
|
|
$dealerProductLogs[] = [
|
|
'user_id' => $payable->user_id,
|
|
'product_id' => $deliveryProduct->product_id,
|
|
'type' => DealerUserProductLog::TYPE_TRANSFER_IN,
|
|
'qty' => $deliveryProduct->qty,
|
|
'remark' => "云库存转本地库存,提货单【{$payable->sn}】",
|
|
'is_deposit' => false,
|
|
'created_at' => $payable->updated_at,
|
|
'updated_at' => $payable->updated_at,
|
|
];
|
|
}
|
|
|
|
DealerUserProductLog::insert($dealerProductLogs);
|
|
|
|
//如果云仓库提货单存在关联订单,则该订单直接处理云仓部分的发货
|
|
if ($payable->order_id) {
|
|
$dealerOrder = DealerOrder::find($payable->order_id);
|
|
(new OrderService())->shippingOrder($dealerOrder, 'deposit_qty');
|
|
}
|
|
}
|
|
|
|
return $payLog;
|
|
}
|
|
|
|
/**
|
|
* 根据支付流水号处理支付失败业务
|
|
*
|
|
* @param string $sn
|
|
* @param array $params
|
|
* @return \App\Models\PayLog
|
|
*
|
|
* @throws \App\Exceptions\BizException
|
|
* @throws \App\Exceptions\InvalidPaySerialNumberException
|
|
*/
|
|
public function handleFailedByPaySerialNumber(string $paySerialNumber, array $params = []): PayLog
|
|
{
|
|
$payLog = PayLog::where('pay_sn', $paySerialNumber)->lockForUpdate()->first();
|
|
|
|
if ($payLog === null) {
|
|
throw new InvalidPaySerialNumberException();
|
|
}
|
|
|
|
return $this->handleFailed($payLog, $params);
|
|
}
|
|
|
|
/**
|
|
* 处理支付失败业务
|
|
*
|
|
* @param \App\Models\PayLog $payLog
|
|
* @param array $params
|
|
* @return \App\Models\PayLog
|
|
*
|
|
* @throws \App\Exceptions\BizException
|
|
* @throws \App\Exceptions\InvalidPaySerialNumberException
|
|
*/
|
|
public function handleFailed(PayLog $payLog, array $params = []): PayLog
|
|
{
|
|
if (! $payLog->isPending()) {
|
|
throw new InvalidPaySerialNumberException();
|
|
}
|
|
|
|
$payLog->update([
|
|
'out_trade_no' => $params['out_trade_no'] ?? null,
|
|
'status' => PayLog::STATUS_FAILED,
|
|
'failed_reason' => $params['failed_reason'] ?? null,
|
|
]);
|
|
|
|
return $payLog;
|
|
}
|
|
}
|