feat : refund
This commit is contained in:
@@ -9,6 +9,7 @@ use App\Lib\Log;
|
|||||||
use App\Model\Order;
|
use App\Model\Order;
|
||||||
use App\Service\Amqp\Refund\GoodOrderAllRefundService;
|
use App\Service\Amqp\Refund\GoodOrderAllRefundService;
|
||||||
use App\Service\Amqp\Refund\RefundFactory;
|
use App\Service\Amqp\Refund\RefundFactory;
|
||||||
|
use App\Service\Amqp\Refund\RefundService;
|
||||||
use App\Service\ServiceTrait\Api\OrderTrait;
|
use App\Service\ServiceTrait\Api\OrderTrait;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Hyperf\Amqp\Message\Type;
|
use Hyperf\Amqp\Message\Type;
|
||||||
@@ -41,11 +42,6 @@ class RefundOrderConsumer extends ConsumerMessage
|
|||||||
#[Inject]
|
#[Inject]
|
||||||
protected Order $orderModel;
|
protected Order $orderModel;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var RefundFactory
|
|
||||||
*/
|
|
||||||
#[Inject]
|
|
||||||
protected RefundFactory $refundFactory;
|
|
||||||
|
|
||||||
public function consumeMessage($data, AMQPMessage $message): Result
|
public function consumeMessage($data, AMQPMessage $message): Result
|
||||||
{
|
{
|
||||||
@@ -58,45 +54,10 @@ class RefundOrderConsumer extends ConsumerMessage
|
|||||||
$orderType = (int)$data['type'];
|
$orderType = (int)$data['type'];
|
||||||
$amount = $data['amount'];
|
$amount = $data['amount'];
|
||||||
|
|
||||||
$orderInfo = match ($orderType) {
|
|
||||||
OrderCode::ORDER_TYPE_GOOD => $this->orderModel->getInfoById($orderId),
|
|
||||||
default => null,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (empty($orderInfo)) {
|
|
||||||
$this->log->debug('RefundOrderConsumer:error:NoOrderData:'.json_encode($data));
|
|
||||||
return Result::ACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!in_array($orderInfo->status,OrderCode::CAN_REFUND_STATUS)) {
|
|
||||||
$this->log->debug('CancelOrderConsumer:error:orderStatusError:'.json_encode($orderInfo->toArray()));
|
|
||||||
return Result::ACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
//余额订单必须退款全部金额
|
|
||||||
if ($orderType == OrderCode::ORDER_TYPE_BALANCE && $amount != 0) {
|
|
||||||
$this->log->debug('CancelOrderConsumer:error:orderStatusError:'.json_encode($orderInfo->toArray()));
|
|
||||||
return Result::ACK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$service = null;
|
$service = new RefundService();
|
||||||
|
|
||||||
switch ($orderType) {
|
|
||||||
case OrderCode::ORDER_TYPE_GOOD:
|
|
||||||
if ($amount == 0) {
|
|
||||||
$service = $this->refundFactory->newGoodOrderRefundAll();
|
|
||||||
} else {
|
|
||||||
$service = $this->refundFactory->newGoodOrderRefundPart();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OrderCode::ORDER_TYPE_BALANCE:
|
|
||||||
$service = $this->refundFactory->newBalanceOrderRefund();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Exception('service not found or orderType error');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
|||||||
27
app/Constants/Common/RefundCode.php
Normal file
27
app/Constants/Common/RefundCode.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Constants\Common;
|
||||||
|
|
||||||
|
class RefundCode
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 退款状态 1=待退款 2=待支付工具退款 3=退款成功 99=退款失败
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Message("等待退款")
|
||||||
|
*/
|
||||||
|
CONST INT WAIT_REFUND = 1;
|
||||||
|
/**
|
||||||
|
* @Message("等待支付工具退款")
|
||||||
|
*/
|
||||||
|
CONST INT WAIT_BY_PAY_TOOL = 2;
|
||||||
|
/**
|
||||||
|
* @Message("退款成功")
|
||||||
|
*/
|
||||||
|
CONST INT REFUND_SUCCESS = 3;
|
||||||
|
/**
|
||||||
|
* @Message("退款失败")
|
||||||
|
*/
|
||||||
|
CONST INT REFUND_FAIL = 99;
|
||||||
|
}
|
||||||
@@ -5,11 +5,14 @@ declare(strict_types=1);
|
|||||||
namespace App\Controller\Common;
|
namespace App\Controller\Common;
|
||||||
|
|
||||||
use App\Service\Common\OssCallbackService;
|
use App\Service\Common\OssCallbackService;
|
||||||
|
use App\Service\Common\Pay\Wx\WxJsRechargeOrderService;
|
||||||
use Hyperf\HttpServer\Annotation\Controller;
|
use Hyperf\HttpServer\Annotation\Controller;
|
||||||
use Hyperf\HttpServer\Annotation\RequestMapping;
|
use Hyperf\HttpServer\Annotation\RequestMapping;
|
||||||
use Psr\Container\ContainerExceptionInterface;
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
use Psr\Container\NotFoundExceptionInterface;
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use RedisException;
|
use RedisException;
|
||||||
|
use Yansongda\Artful\Exception\InvalidParamsException;
|
||||||
|
|
||||||
#[Controller]
|
#[Controller]
|
||||||
class ThirdCallbackController
|
class ThirdCallbackController
|
||||||
@@ -22,8 +25,34 @@ class ThirdCallbackController
|
|||||||
* @throws RedisException
|
* @throws RedisException
|
||||||
*/
|
*/
|
||||||
#[RequestMapping(path: "/common/oss/ossCallBack", methods: "post")]
|
#[RequestMapping(path: "/common/oss/ossCallBack", methods: "post")]
|
||||||
public function callback()
|
public function ossCallback()
|
||||||
{
|
{
|
||||||
return (new OssCallbackService)->process();
|
return (new OssCallbackService)->process();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信js通道支付回调
|
||||||
|
* @return ResponseInterface
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws InvalidParamsException
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
#[RequestMapping(path: "/common/wxPay/order/js/callBack", methods: "post")]
|
||||||
|
public function wxJsPayCallBack(): ResponseInterface
|
||||||
|
{
|
||||||
|
return (new WxJsRechargeOrderService)->callBackHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信js通道退款回调
|
||||||
|
* @return ResponseInterface
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws InvalidParamsException
|
||||||
|
*/
|
||||||
|
#[RequestMapping(path: "/common/wxPay/order/js/refund/callBack", methods: "post")]
|
||||||
|
public function wxJsRefundCallBack(): ResponseInterface
|
||||||
|
{
|
||||||
|
return (new WxJsRechargeOrderService)->refundCallBackHandle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
98
app/Model/RefundOrder.php
Normal file
98
app/Model/RefundOrder.php
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Model;
|
||||||
|
|
||||||
|
use App\Constants\Common\RefundCode;
|
||||||
|
use Hyperf\Database\Concerns\BuildsQueries;
|
||||||
|
use Hyperf\Database\Model\Builder;
|
||||||
|
use Hyperf\DbConnection\Model\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property int $user_id
|
||||||
|
* @property int $order_type
|
||||||
|
* @property int $order_id
|
||||||
|
* @property int $pay_id
|
||||||
|
* @property int $refund_status
|
||||||
|
* @property string $refund_money
|
||||||
|
* @property string $refund_time
|
||||||
|
* @property int $refund_type
|
||||||
|
* @property string $refund_order_sno
|
||||||
|
* @property string $alipay_transaction_id
|
||||||
|
* @property string $wx_transaction_id
|
||||||
|
* @property string $notify_json
|
||||||
|
* @property string $remark
|
||||||
|
* @property string $create_time
|
||||||
|
* @property string $update_time
|
||||||
|
*/
|
||||||
|
class RefundOrder extends Model
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The table associated with the model.
|
||||||
|
*/
|
||||||
|
protected ?string $table = 'refund_order';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that are mass assignable.
|
||||||
|
*/
|
||||||
|
protected array $fillable = [];
|
||||||
|
|
||||||
|
protected array $guarded = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be cast to native types.
|
||||||
|
*/
|
||||||
|
protected array $casts = ['id' => 'integer', 'user_id' => 'integer', 'order_type' => 'integer', 'order_id' => 'integer', 'pay_id' => 'integer', 'refund_status' => 'integer', 'refund_type' => 'integer'];
|
||||||
|
|
||||||
|
const string CREATED_AT = 'create_time';
|
||||||
|
const string UPDATED_AT = 'update_time';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $orderId
|
||||||
|
* @param int $type
|
||||||
|
* @return int|mixed|string
|
||||||
|
*/
|
||||||
|
public function getAllMoneyByOrderId(int $orderId, int $type): mixed
|
||||||
|
{
|
||||||
|
return $this
|
||||||
|
->where('order_id', $orderId)
|
||||||
|
->where('order_type', $type)
|
||||||
|
->whereIn('refund_status',[
|
||||||
|
RefundCode::WAIT_REFUND,
|
||||||
|
RefundCode::REFUND_SUCCESS
|
||||||
|
])->sum('refund_amount') ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSuccessMoneyByOrderId(int $orderId, int $type): mixed
|
||||||
|
{
|
||||||
|
return $this
|
||||||
|
->where('order_id', $orderId)
|
||||||
|
->where('order_type', $type)
|
||||||
|
->whereIn('refund_status',[
|
||||||
|
RefundCode::WAIT_REFUND,
|
||||||
|
RefundCode::REFUND_SUCCESS
|
||||||
|
])->sum('refund_amount') ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
* @param int $type
|
||||||
|
* @return \Hyperf\Database\Model\Model|null
|
||||||
|
*/
|
||||||
|
public function getInfoByOrderIdAndTypeWaitRefund(int $id,int $type): \Hyperf\Database\Model\Model|null
|
||||||
|
{
|
||||||
|
return $this->where('order_id',$id)->where('order_type',$type)->where('refund_status',RefundCode::WAIT_REFUND)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $orderSno
|
||||||
|
* @param int $type
|
||||||
|
* @return \Hyperf\Database\Model\Model|null
|
||||||
|
*/
|
||||||
|
public function getInfoByOrderSnoAndType(string $orderSno, int $type): \Hyperf\Database\Model\Model|null
|
||||||
|
{
|
||||||
|
return $this->where('order_sno',$orderSno)->where('order_type',$type)->first();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* This service file is part of item.
|
|
||||||
*
|
|
||||||
* @author ctexthuang
|
|
||||||
* @contact ctexthuang@qq.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Service\Amqp\Refund;
|
|
||||||
|
|
||||||
class BalanceOrderRefundService
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public int $orderId;
|
|
||||||
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* This service file is part of item.
|
|
||||||
*
|
|
||||||
* @author ctexthuang
|
|
||||||
* @contact ctexthuang@qq.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Service\Amqp\Refund;
|
|
||||||
|
|
||||||
use App\Constants\Common\OrderCode;
|
|
||||||
use App\Model\Order;
|
|
||||||
use App\Model\PayOrder;
|
|
||||||
use Exception;
|
|
||||||
use Hyperf\Di\Annotation\Inject;
|
|
||||||
|
|
||||||
class GoodOrderAllRefundService extends RefundBaseService
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->type = OrderCode::ORDER_TYPE_GOOD;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
$this->getOrderInfo();
|
|
||||||
|
|
||||||
$this->getPayOrder();
|
|
||||||
|
|
||||||
$this->getRefundAmount();
|
|
||||||
|
|
||||||
if ($this->refundAmount <= 0) throw new Exception('退款金额不能小于等于0');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* This service file is part of item.
|
|
||||||
*
|
|
||||||
* @author ctexthuang
|
|
||||||
* @contact ctexthuang@qq.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace App\Service\Amqp\Refund;
|
|
||||||
|
|
||||||
use App\Model\Order;
|
|
||||||
use Hyperf\Di\Annotation\Inject;
|
|
||||||
|
|
||||||
class GoodOrderPartRefundService
|
|
||||||
{
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
//todo Write logic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Service\Amqp\Refund;
|
|
||||||
|
|
||||||
use App\Constants\Common\OrderCode;
|
|
||||||
use App\Model\Order;
|
|
||||||
use App\Model\PayOrder;
|
|
||||||
use Exception;
|
|
||||||
use Hyperf\Di\Annotation\Inject;
|
|
||||||
|
|
||||||
class RefundBaseService
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
public int $orderId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
protected int $type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var PayOrder
|
|
||||||
*/
|
|
||||||
#[Inject]
|
|
||||||
protected PayOrder $payOrderModel;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Order
|
|
||||||
*/
|
|
||||||
#[Inject]
|
|
||||||
protected Order $orderModel;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var mixed
|
|
||||||
*/
|
|
||||||
protected mixed $payInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var mixed
|
|
||||||
*/
|
|
||||||
protected mixed $orderInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var float
|
|
||||||
*/
|
|
||||||
protected float $refundAmount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function getPayOrder()
|
|
||||||
{
|
|
||||||
$this->payInfo = $this->payOrderModel->getInfoByOrderIdAndType($this->orderId, $this->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function getOrderInfo()
|
|
||||||
{
|
|
||||||
$this->orderInfo = match ($this->type) {
|
|
||||||
OrderCode::ORDER_TYPE_GOOD => $this->orderModel->getInfoById($this->orderId),
|
|
||||||
default => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getAllRefundByOrderId()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return void
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
protected function checkInfo()
|
|
||||||
{
|
|
||||||
if (!$this->payInfo || !$this->orderInfo) {
|
|
||||||
throw new Exception('订单信息不存在');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getUser()
|
|
||||||
{
|
|
||||||
//todo 获取用户信息
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function getRefundAmount(): void
|
|
||||||
{
|
|
||||||
//todo 等于支付金额 减去 已退款金额
|
|
||||||
$this->refundAmount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function insertRefund()
|
|
||||||
{
|
|
||||||
//todo 写入退款记录
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function updateOrderInfo()
|
|
||||||
{
|
|
||||||
//todo 更新订单信息
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function refund()
|
|
||||||
{
|
|
||||||
//todo 退款 参考调起支付
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Service\Amqp\Refund;
|
|
||||||
|
|
||||||
class RefundFactory
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @return GoodOrderAllRefundService
|
|
||||||
*/
|
|
||||||
public function newGoodOrderRefundAll(): GoodOrderAllRefundService
|
|
||||||
{
|
|
||||||
return new GoodOrderAllRefundService();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return GoodOrderPartRefundService
|
|
||||||
*/
|
|
||||||
public function newGoodOrderRefundPart(): GoodOrderPartRefundService
|
|
||||||
{
|
|
||||||
return new GoodOrderPartRefundService();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return BalanceOrderRefundService
|
|
||||||
*/
|
|
||||||
public function newBalanceOrderRefund(): BalanceOrderRefundService
|
|
||||||
{
|
|
||||||
return new BalanceOrderRefundService();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
218
app/Service/Amqp/Refund/RefundService.php
Normal file
218
app/Service/Amqp/Refund/RefundService.php
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service\Amqp\Refund;
|
||||||
|
|
||||||
|
use App\Constants\Common\OrderCode;
|
||||||
|
use App\Constants\Common\PayCode;
|
||||||
|
use App\Constants\Common\RefundCode;
|
||||||
|
use App\Lib\Log;
|
||||||
|
use App\Model\Order;
|
||||||
|
use App\Model\PayOrder;
|
||||||
|
use App\Model\RefundOrder;
|
||||||
|
use App\Service\Common\Pay\Wx\WxJsRechargeOrderService;
|
||||||
|
use Exception;
|
||||||
|
use Hyperf\Di\Annotation\Inject;
|
||||||
|
|
||||||
|
class RefundService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
public int $orderId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected int $type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PayOrder
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected PayOrder $payOrderModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Order
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected Order $orderModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var RefundOrder
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected RefundOrder $refundOrderModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Log
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected Log $log;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
protected mixed $payInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
protected mixed $orderInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
protected mixed $refundInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var float
|
||||||
|
*/
|
||||||
|
public float $refundAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var float
|
||||||
|
*/
|
||||||
|
protected float $isRefundMoney;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
$errMsg = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->getOrderInfo();
|
||||||
|
|
||||||
|
$this->checkOrder();
|
||||||
|
|
||||||
|
$this->getPayAndRefundOrder();
|
||||||
|
|
||||||
|
$this->getAllRefundMoneyByOrderId();
|
||||||
|
|
||||||
|
$this->checkRefundAmount();
|
||||||
|
|
||||||
|
$this->refund();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->log->error('RefundOrderConsumer:RefundService:error:'.$e->getMessage());
|
||||||
|
$errArr = explode(":", $e->getMessage());
|
||||||
|
$errMsg = $errArr[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->updateRefund($errMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function getPayAndRefundOrder(): void
|
||||||
|
{
|
||||||
|
$this->payInfo = $this->payOrderModel->getInfoByOrderIdAndType($this->orderId, $this->type);
|
||||||
|
|
||||||
|
$this->refundInfo = $this->refundOrderModel->getInfoByOrderIdAndTypeWaitRefund($this->orderId,$this->type);
|
||||||
|
|
||||||
|
if (!$this->payInfo || !$this->refundInfo) throw new Exception('订单信息不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function getOrderInfo()
|
||||||
|
{
|
||||||
|
$this->orderInfo = match ($this->type) {
|
||||||
|
OrderCode::ORDER_TYPE_GOOD => $this->orderModel->getInfoById($this->orderId),
|
||||||
|
default => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function checkOrder()
|
||||||
|
{
|
||||||
|
if (empty($orderInfo)) throw new Exception('订单信息不存在:'.json_encode(['order_id' => $this->orderId,'order_type' => $this->type]));
|
||||||
|
|
||||||
|
if (!in_array($orderInfo->status,OrderCode::CAN_REFUND_STATUS)) throw new Exception('订单状态不能退款:'.json_encode($this->orderInfo->toArray()));
|
||||||
|
|
||||||
|
//余额订单必须退款全部金额
|
||||||
|
if ($this->type == OrderCode::ORDER_TYPE_BALANCE && $this->refundAmount != $this->orderInfo->actual_price) throw new Exception('余额订单必须退款全部金额:'.json_encode($this->orderInfo->toArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function getAllRefundMoneyByOrderId(): void
|
||||||
|
{
|
||||||
|
$this->isRefundMoney = $this->refundOrderModel->getSuccessMoneyByOrderId($this->orderId,$this->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getUser()
|
||||||
|
{
|
||||||
|
//todo 获取用户信息
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected function checkRefundAmount(): void
|
||||||
|
{
|
||||||
|
// 等于支付金额 减去 已退款金额 减去 本次退款金额 小于 0 就是错误的 大于等于 0 就是正确的
|
||||||
|
if ($this->orderInfo->actual_price - $this->isRefundMoney - $this->refundAmount < 0) throw new Exception('退款金额不能大于订单金额');
|
||||||
|
|
||||||
|
$this->refundAmount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function updateRefund($errMsg = null)
|
||||||
|
{
|
||||||
|
$status = RefundCode::REFUND_FAIL;
|
||||||
|
|
||||||
|
if (empty($errMsg)) {
|
||||||
|
$status = RefundCode::WAIT_BY_PAY_TOOL;
|
||||||
|
$errMsg = '等待支付工具退款';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->refundOrderModel->where('id',$this->refundInfo->id)->update([
|
||||||
|
'refund_status' => $status,
|
||||||
|
'remark' => $errMsg
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function refund()
|
||||||
|
{
|
||||||
|
$rechargeService = match ($this->refundInfo->refund_type)
|
||||||
|
{
|
||||||
|
PayCode::ALIPAY => $this->setAliPayRefund(),
|
||||||
|
PayCode::WECHAT_PAY => $this->setWechatPayRefund(),
|
||||||
|
};
|
||||||
|
|
||||||
|
$rechargeService->setConfig();
|
||||||
|
$rechargeService->setNotify();
|
||||||
|
|
||||||
|
$payData = $rechargeService->pay(
|
||||||
|
(float)$this->orderInfo->actual_price,
|
||||||
|
$this->request->input('body','订单支付'),
|
||||||
|
$this->orderInfo->order_no,
|
||||||
|
$this->userId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function setAliPayRefund()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return WxJsRechargeOrderService
|
||||||
|
*/
|
||||||
|
protected function setWechatPayRefund(): WxJsRechargeOrderService
|
||||||
|
{
|
||||||
|
return new WxJsRechargeOrderService();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,11 +66,21 @@ abstract class WxJsRechargeBaseService implements ThirdPayInterface
|
|||||||
*/
|
*/
|
||||||
abstract public function callBackHandle();
|
abstract public function callBackHandle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退款回调
|
||||||
|
*/
|
||||||
|
abstract public function refundCallbackHandle();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置回调地址
|
* 设置回调地址
|
||||||
*/
|
*/
|
||||||
abstract public function setNotify();
|
abstract public function setNotify();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置退款回调地址
|
||||||
|
*/
|
||||||
|
abstract public function setRefundNotify();
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * 设置商户号id
|
// * 设置商户号id
|
||||||
// */
|
// */
|
||||||
@@ -90,16 +100,16 @@ abstract class WxJsRechargeBaseService implements ThirdPayInterface
|
|||||||
try {
|
try {
|
||||||
$this->callbackData = $this->ysdPay->wechat($this->config)->callback($this->request)->toArray()['resource']['ciphertext'];
|
$this->callbackData = $this->ysdPay->wechat($this->config)->callback($this->request)->toArray()['resource']['ciphertext'];
|
||||||
}catch (Exception $e) {
|
}catch (Exception $e) {
|
||||||
$this->log->debug(__CLASS__.'微信支付回调解密失败'.json_encode($e->getMessage()));
|
$this->log->debug(__CLASS__.'wxPay回调解密失败'.json_encode($e->getMessage()));
|
||||||
throw new ErrException('微信支付回调解密失败');
|
throw new ErrException('wxPay回调解密失败');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($this->callbackData)) {
|
if (!empty($this->callbackData)) {
|
||||||
$this->log->debug(__CLASS__.'获取回调失败'.json_encode($this->request));
|
$this->log->debug(__CLASS__.'wxPay获取回调失败'.json_encode($this->request));
|
||||||
throw new ErrException('获取回调失败');
|
throw new ErrException('wxPay获取回调失败');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->log->info(__CLASS__.'微信支付完成回调'.json_encode($this->callbackData));
|
$this->log->info(__CLASS__.'wxPay完成回调'.json_encode($this->callbackData));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -156,4 +166,39 @@ abstract class WxJsRechargeBaseService implements ThirdPayInterface
|
|||||||
throw new ErrException($e->getMessage());
|
throw new ErrException($e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param float $refundAmount
|
||||||
|
* @param float $totalAmount
|
||||||
|
* @param string $outTradeNo
|
||||||
|
* @param string $outRefundNo
|
||||||
|
* @return Collection|Rocket
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
public function refund(float $refundAmount,float $totalAmount, string $outTradeNo, string $outRefundNo): Collection|Rocket
|
||||||
|
{
|
||||||
|
if (empty($this->config)) throw new ErrException('调起支付失败-微信支付配置项不存在');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$order = [
|
||||||
|
'out_trade_no' => $outTradeNo,
|
||||||
|
'out_refund_no' => $outRefundNo,
|
||||||
|
'amount' => [
|
||||||
|
'refund' => (int)bcmul((string)$refundAmount, "100"),
|
||||||
|
'total' => (int)bcmul((string)$totalAmount, "100"),
|
||||||
|
'currency' => 'CNY',
|
||||||
|
],
|
||||||
|
'_action' => 'mini', // jsapi 退款,默认
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = $this->ysdPay->wechat($this->config)->refund($order);
|
||||||
|
|
||||||
|
$this->log->callbackLog(__CLASS__.'微信退款调起数据|回调地址:'. json_encode($this->config['wechat']['default']).'|回调数据:'.json_encode($result).'|请求数据:'.json_encode($order));
|
||||||
|
return $result;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->log->error(__CLASS__.'微信退款调起失败。reason:'.$e->getMessage());
|
||||||
|
throw new ErrException($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ use App\Service\ServiceTrait\Api\CheckOrderCallBackTrait;
|
|||||||
use App\Service\ServiceTrait\Api\GoodOrderTrait;
|
use App\Service\ServiceTrait\Api\GoodOrderTrait;
|
||||||
use App\Service\ServiceTrait\Api\OrderTrait;
|
use App\Service\ServiceTrait\Api\OrderTrait;
|
||||||
use App\Service\ServiceTrait\Api\PayFinishTrait;
|
use App\Service\ServiceTrait\Api\PayFinishTrait;
|
||||||
|
use App\Service\ServiceTrait\Api\RefundOrderTrait;
|
||||||
use Hyperf\DbConnection\Db;
|
use Hyperf\DbConnection\Db;
|
||||||
use Psr\Container\ContainerExceptionInterface;
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
use Psr\Container\NotFoundExceptionInterface;
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
@@ -19,7 +20,9 @@ class WxJsRechargeOrderService extends WxJsRechargeBaseService
|
|||||||
{
|
{
|
||||||
use CheckOrderCallBackTrait,
|
use CheckOrderCallBackTrait,
|
||||||
GoodOrderTrait,
|
GoodOrderTrait,
|
||||||
PayFinishTrait;
|
PayFinishTrait,
|
||||||
|
RefundOrderTrait,
|
||||||
|
OrderTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -47,15 +50,20 @@ class WxJsRechargeOrderService extends WxJsRechargeBaseService
|
|||||||
*/
|
*/
|
||||||
protected mixed $payInfo;
|
protected mixed $payInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
protected mixed $refundInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ResponseInterface
|
* @return ResponseInterface
|
||||||
* @throws ContainerExceptionInterface
|
* @throws ContainerExceptionInterface
|
||||||
* @throws NotFoundExceptionInterface
|
* @throws NotFoundExceptionInterface
|
||||||
* @throws InvalidParamsException
|
* @throws InvalidParamsException
|
||||||
*/
|
*/
|
||||||
public function callBackHandle()
|
public function callBackHandle(): ResponseInterface
|
||||||
{
|
{
|
||||||
$this-> getWechatData();
|
$this->getWechatData();
|
||||||
|
|
||||||
$this->checkWxCallBackOrder();
|
$this->checkWxCallBackOrder();
|
||||||
|
|
||||||
@@ -79,6 +87,31 @@ class WxJsRechargeOrderService extends WxJsRechargeBaseService
|
|||||||
return $this->returnSuccess();
|
return $this->returnSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ResponseInterface
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws InvalidParamsException
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
public function refundCallBackHandle(): ResponseInterface
|
||||||
|
{
|
||||||
|
$this->getWechatData();
|
||||||
|
|
||||||
|
$this->checkWxRefundCallBackOrder();
|
||||||
|
|
||||||
|
$this->checkRefundOrder();
|
||||||
|
|
||||||
|
Db::transaction(function (){
|
||||||
|
$this->manageRefundOrder();
|
||||||
|
|
||||||
|
$this->manageOrderByRefund();
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->sendStockMq($this->orderInfo->id,$this->orderInfo->status);
|
||||||
|
|
||||||
|
return $this->returnSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
@@ -87,4 +120,13 @@ class WxJsRechargeOrderService extends WxJsRechargeBaseService
|
|||||||
//返回的回调地址
|
//返回的回调地址
|
||||||
$this->config['wechat']['default']['notify_url'] = config('system.api_url').'/common/wxPay/order/js/callBack';
|
$this->config['wechat']['default']['notify_url'] = config('system.api_url').'/common/wxPay/order/js/callBack';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setRefundNotify(): void
|
||||||
|
{
|
||||||
|
//返回的退款回调地址
|
||||||
|
$this->config['wechat']['default']['notify_url'] = config('system.api_url').'/common/wxPay/order/js/refund/callBack';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,9 @@ use App\Exception\ErrException;
|
|||||||
|
|
||||||
trait CheckOrderCallBackTrait
|
trait CheckOrderCallBackTrait
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function checkWxCallBackOrder(): void
|
public function checkWxCallBackOrder(): void
|
||||||
{
|
{
|
||||||
if (
|
if (
|
||||||
@@ -24,4 +27,23 @@ trait CheckOrderCallBackTrait
|
|||||||
|
|
||||||
$this->orderNo = $this->callbackData['out_trade_no'];
|
$this->orderNo = $this->callbackData['out_trade_no'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function checkWxRefundCallBackOrder(): void
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
!isset($this->callbackData['return_code']) ||
|
||||||
|
$this->callbackData['return_code']!= 'SUCCESS' ||
|
||||||
|
!isset($this->callbackData['out_trade_no']) ||
|
||||||
|
empty($this->callbackData['out_trade_no']) ||
|
||||||
|
!isset($this->callbackData['mch_id']) ||
|
||||||
|
empty($this->callbackData['mch_id'])
|
||||||
|
) {
|
||||||
|
throw new ErrException('此订单回调异常');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->orderNo = $this->callbackData['out_trade_no'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,11 @@ namespace App\Service\ServiceTrait\Api;
|
|||||||
|
|
||||||
use App\Constants\Common\OrderCode;
|
use App\Constants\Common\OrderCode;
|
||||||
use App\Constants\Common\PayCode;
|
use App\Constants\Common\PayCode;
|
||||||
|
use App\Constants\Common\RefundCode;
|
||||||
use App\Exception\ErrException;
|
use App\Exception\ErrException;
|
||||||
use App\Model\Order;
|
use App\Model\Order;
|
||||||
use App\Model\PayOrder;
|
use App\Model\PayOrder;
|
||||||
|
use App\Model\RefundOrder;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Hyperf\Di\Annotation\Inject;
|
use Hyperf\Di\Annotation\Inject;
|
||||||
use Psr\Container\ContainerExceptionInterface;
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
@@ -27,6 +29,12 @@ trait GoodOrderTrait
|
|||||||
#[Inject]
|
#[Inject]
|
||||||
protected PayOrder $payOrderModel;
|
protected PayOrder $payOrderModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var RefundOrder
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected RefundOrder $refundOrderModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
* @throws ContainerExceptionInterface
|
* @throws ContainerExceptionInterface
|
||||||
@@ -53,6 +61,8 @@ trait GoodOrderTrait
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
* @throws ContainerExceptionInterface
|
* @throws ContainerExceptionInterface
|
||||||
|
|||||||
89
app/Service/ServiceTrait/Api/RefundOrderTrait.php
Normal file
89
app/Service/ServiceTrait/Api/RefundOrderTrait.php
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service\ServiceTrait\Api;
|
||||||
|
|
||||||
|
use App\Constants\Common\OrderCode;
|
||||||
|
use App\Constants\Common\PayCode;
|
||||||
|
use App\Constants\Common\RefundCode;
|
||||||
|
use App\Exception\ErrException;
|
||||||
|
use Exception;
|
||||||
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
|
|
||||||
|
trait RefundOrderTrait
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
protected function checkRefundOrder(): void
|
||||||
|
{
|
||||||
|
$this->refundInfo = $this->refundOrderModel->getInfoByOrderSnoAndType($this->orderNo,self::OrderType);
|
||||||
|
$this->orderInfo = $this->orderModel->getInfoById($this->refundInfo->order_id);
|
||||||
|
$this->payInfo = $this->payOrderModel->getInfoByOrderIdAndType($this->orderInfo->id,self::OrderType);
|
||||||
|
|
||||||
|
if (empty($this->orderInfo) || empty($this->payInfo) || empty($this->refundInfo)) {
|
||||||
|
$this->log->debug(__CLASS__.':订单不存在,订单号:'.$this->orderNo);
|
||||||
|
throw new ErrException('订单不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->refundInfo->refund_status != RefundCode::WAIT_BY_PAY_TOOL) {
|
||||||
|
$this->log->debug(__CLASS__.':订单已退款成功,订单信息:'.json_encode($this->refundInfo->toArray()));
|
||||||
|
throw new ErrException('订单已退款成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->refundInfo->refund_type != PayCode::WECHAT_PAY) {
|
||||||
|
$this->log->debug(__CLASS__.':订单退款渠道错误,订单信息:'.json_encode($this->refundInfo->toArray()));
|
||||||
|
throw new ErrException('订单退款渠道错误');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
protected function manageRefundOrder(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->refundInfo->refund_status = RefundCode::REFUND_SUCCESS;
|
||||||
|
$this->refundInfo->refund_time = date('Y-m-d H:i:s');
|
||||||
|
$this->refundInfo->wx_transaction_id = $this->callbackData['transaction_id'];
|
||||||
|
$this->refundInfo->notify_json = json_encode($this->callbackData);
|
||||||
|
|
||||||
|
if (!$this->refundInfo->save()) throw new Exception('更新退款订单失败');
|
||||||
|
|
||||||
|
}catch (Exception $e) {
|
||||||
|
$this->log->error(__CLASS__.':Function:manageGoodOrder:'.$e->getMessage().':orderId:'.$this->orderInfo->id);
|
||||||
|
throw new ErrException($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
protected function manageOrderByRefund(): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$isRefundMoney = $this->refundOrderModel->getSuccessMoneyByOrderId($this->refundInfo->order_id,$this->refundInfo->order_type);
|
||||||
|
|
||||||
|
if ($isRefundMoney <= 0) throw new Exception('订单退款金额错误');
|
||||||
|
|
||||||
|
if ($isRefundMoney == $this->orderInfo->actual_price) {
|
||||||
|
$this->orderInfo->status = OrderCode::FINISH_REFUND;
|
||||||
|
$this->orderInfo->is_refund_all = 1;//todo 感觉可以删除这个值
|
||||||
|
} else {
|
||||||
|
$this->orderInfo->status = OrderCode::UNCOMPLETED_REFUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->orderInfo->save()) throw new Exception('更新退款订单失败');
|
||||||
|
|
||||||
|
}catch (Exception $e) {
|
||||||
|
$this->log->error(__CLASS__.':Function:manageGoodOrder:'.$e->getMessage().':orderId:'.$this->orderInfo->id);
|
||||||
|
throw new ErrException($e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user