183 lines
6.1 KiB
PHP
183 lines
6.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Enums\OfflineOrderStatus;
|
|
use App\Enums\SocialiteType;
|
|
use App\Exceptions\BizException;
|
|
use App\Exceptions\InvalidPaySerialNumberException;
|
|
use App\Jobs\UploadShippingInfoJob;
|
|
use App\Models\PayLog;
|
|
use App\Models\{OfflineOrder, Order, OrderPre, SocialiteUser};
|
|
|
|
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;
|
|
$userId = null;
|
|
|
|
if ($payable instanceof Order) {
|
|
if ($payable->isPaid()) {
|
|
throw new BizException('订单已支付');
|
|
}
|
|
|
|
if ($payable->isCompleted()) {
|
|
throw new BizException('订单已完成');
|
|
}
|
|
$userId = $payable->user_id;
|
|
|
|
$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,
|
|
]);
|
|
} elseif ($payable instanceof OfflineOrder) {
|
|
if ($payable->isPaid()) {
|
|
throw new BizException('订单已支付');
|
|
} elseif ($payable->isRevoked()) {
|
|
throw new BizException('订单取消');
|
|
}
|
|
$userId = $payable->user_id;
|
|
|
|
OfflineOrderService::make()->paySuccess($payable, [
|
|
'payment_sn' => $payLog->pay_sn,
|
|
'payment_method' => $payLog->pay_way,
|
|
'payment_time' => $payLog->pay_at,
|
|
'out_trade_no' => $payLog->out_trade_no,
|
|
'status' => OfflineOrderStatus::Paid,
|
|
]);
|
|
} elseif ($payable instanceof \App\Models\UserVip) {
|
|
$userId = $payable->user_id;
|
|
(new \App\Services\VipService())->success($payable, ['pay_at' => $payLog->pay_at]);
|
|
}
|
|
|
|
// TODO 延迟1分钟执行, 不然会出现错误信息: (10060001)支付单不存在
|
|
// TODO 订单支付成功, 调用发货信息API
|
|
// try {
|
|
// if (!$userId) {
|
|
// throw new BizException("未找到userId");
|
|
// }
|
|
// $socialite = SocialiteUser::where('user_id', $userId)->where('socialite_type', SocialiteType::WechatMiniProgram)->first();
|
|
// if (!$socialite) {
|
|
// throw new BizException("未找到 SocialiteUser 记录, userId: " . $userId);
|
|
// }
|
|
// $openid = $socialite->socialite_id;
|
|
// if (!$openid) {
|
|
// throw new BizException("未找到 openid, userId: " . $userId);
|
|
// }
|
|
// $data = [
|
|
// "order_key" => [
|
|
// // "mchid" => config("wechat.payment.sub.mch_id"),
|
|
// // "out_trade_no" => $payLog->pay_sn,
|
|
// "order_number_type" => 2,
|
|
// "transaction_id" => $payLog->out_trade_no,
|
|
// ],
|
|
// "logistics_type" => 4,
|
|
// "delivery_mode" => 1,
|
|
// "shipping_list" => [
|
|
// ["item_desc" => "定制服务"]
|
|
// ],
|
|
// "upload_time" => $payLog->pay_at->format('Y-m-d\TH:i:s.vP'),
|
|
// "payer" => [
|
|
// "openid" => $openid
|
|
// ]
|
|
// ];
|
|
// WxMpService::make()->uploadShippingInfo($data);
|
|
// } catch (\Exception $e) {
|
|
// logger()->error("微信小程序-发货信息录入, " . $e->getMessage(), ['pay_log_id' => $payLog->id]);
|
|
// }
|
|
|
|
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;
|
|
}
|
|
}
|