From c14901de4adbf7fb488a641361f57c8115ccc484 Mon Sep 17 00:00:00 2001 From: ctexthuang Date: Mon, 24 Feb 2025 15:30:58 +0800 Subject: [PATCH] feat : refund --- app/Amqp/Consumer/RefundOrderConsumer.php | 21 +++-- app/Constants/Common/RefundCode.php | 6 ++ app/Model/RefundOrder.php | 3 +- app/Service/Amqp/Refund/RefundService.php | 78 +++++++++++++++---- app/Service/Api/Order/RefundOrderService.php | 3 +- app/Service/ServiceTrait/Api/OrderTrait.php | 14 ++++ .../Common/OrderChangeStatusTrait.php | 4 +- 7 files changed, 105 insertions(+), 24 deletions(-) diff --git a/app/Amqp/Consumer/RefundOrderConsumer.php b/app/Amqp/Consumer/RefundOrderConsumer.php index 6802cc8..3058cf2 100644 --- a/app/Amqp/Consumer/RefundOrderConsumer.php +++ b/app/Amqp/Consumer/RefundOrderConsumer.php @@ -15,6 +15,8 @@ use Hyperf\Amqp\Annotation\Consumer; use Hyperf\Amqp\Message\ConsumerMessage; use Hyperf\Di\Annotation\Inject; use PhpAmqpLib\Message\AMQPMessage; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; #[Consumer(exchange: 'RefundOrder', routingKey: 'RefundOrder', queue: 'RefundOrder.direct', name: "RefundOrderConsumer", nums: 1)] class RefundOrderConsumer extends ConsumerMessage @@ -40,22 +42,29 @@ class RefundOrderConsumer extends ConsumerMessage protected Order $orderModel; + /** + * @param $data + * @param AMQPMessage $message + * @return Result + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ public function consumeMessage($data, AMQPMessage $message): Result { - if (!$data['order_id'] || !$data['type'] || !$data['amount']) { + if (!$data['order_id'] || !$data['type'] || !$data['amount'] || !$data['reason']) { $this->log->error('CancelOrderConsumer:error:NoData:'.json_encode($data)); return Result::ACK; } - $orderId = (int)$data['order_id']; - $orderType = (int)$data['type']; - $amount = $data['amount']; - - try { $service = new RefundService(); + $service->orderId = (int)$data['order_id']; + $service->type = (int)$data['type']; + $service->refundAmount = $data['amount']; + $service->reason = $data['reason']; + $service->handle(); } catch (Exception $e) { $this->log->error('RefundOrderConsumer:error:'.$e->getMessage().':data:'.json_encode($data)); diff --git a/app/Constants/Common/RefundCode.php b/app/Constants/Common/RefundCode.php index 2aa5b3a..f6d262d 100644 --- a/app/Constants/Common/RefundCode.php +++ b/app/Constants/Common/RefundCode.php @@ -24,4 +24,10 @@ class RefundCode * @Message("退款失败") */ CONST INT REFUND_FAIL = 99; + + /** + * @var string 订单类型前缀 + */ + const string ORDER_TYPE_GOOD_PREFIX = 'RG'; + const string ORDER_TYPE_BALANCE_PREFIX = 'RB'; } \ No newline at end of file diff --git a/app/Model/RefundOrder.php b/app/Model/RefundOrder.php index 7ceb29f..ecc64c3 100644 --- a/app/Model/RefundOrder.php +++ b/app/Model/RefundOrder.php @@ -23,7 +23,8 @@ use Hyperf\DbConnection\Model\Model; * @property string $alipay_transaction_id * @property string $wx_transaction_id * @property string $notify_json - * @property string $remark + * @property string $remark + * @property string $reason * @property string $create_time * @property string $update_time */ diff --git a/app/Service/Amqp/Refund/RefundService.php b/app/Service/Amqp/Refund/RefundService.php index a50affc..4cf9b0e 100644 --- a/app/Service/Amqp/Refund/RefundService.php +++ b/app/Service/Amqp/Refund/RefundService.php @@ -10,11 +10,16 @@ use App\Model\Order; use App\Model\PayOrder; use App\Model\RefundOrder; use App\Service\Common\Pay\Wx\WxJsRechargeOrderService; +use App\Service\ServiceTrait\Api\OrderTrait; use Exception; use Hyperf\Di\Annotation\Inject; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; class RefundService { + use OrderTrait; + /** * @var int */ @@ -23,7 +28,12 @@ class RefundService /** * @var int */ - protected int $type; + public int $type; + + /** + * @var string + */ + public string $reason; /** * @var PayOrder @@ -76,7 +86,10 @@ class RefundService protected float $isRefundMoney; /** - * + * @return void + * @throws Exception + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function handle(): void { @@ -93,6 +106,8 @@ class RefundService $this->checkRefundAmount(); + $this->insertRefundOrder(); + $this->refund(); } catch (Exception $e) { $this->log->error('RefundOrderConsumer:RefundService:error:'.$e->getMessage()); @@ -103,6 +118,27 @@ class RefundService $this->updateRefund($errMsg); } + /** + * @return void + * @throws Exception + */ + private function insertRefundOrder(): void + { + $this->refundInfo = new RefundOrder(); + + $this->refundInfo->user_id = $this->orderInfo->user_id; + $this->refundInfo->order_type = $this->type; + $this->refundInfo->order_id = $this->orderId; + $this->refundInfo->pay_id = $this->payInfo->id; + $this->refundInfo->refund_status = RefundCode::WAIT_REFUND; + $this->refundInfo->refund_money = $this->refundAmount; + $this->refundInfo->refund_type = $this->payInfo->recharge_type; + $this->refundInfo->refund_order_sno = $this->generateRefundOrderNo($this->type, $this->orderInfo->user_id); + $this->refundInfo->reason = $this->reason; + + if (!$this->refundInfo->save()) throw new Exception('退款订单创建失败'); + } + /** * @return void * @throws Exception @@ -111,15 +147,17 @@ class RefundService { $this->payInfo = $this->payOrderModel->getInfoByOrderIdAndType($this->orderId, $this->type); - $this->refundInfo = $this->refundOrderModel->getInfoByOrderIdAndTypeWaitRefund($this->orderId,$this->type); +// $this->refundInfo = $this->refundOrderModel->getInfoByOrderIdAndTypeWaitRefund($this->orderId,$this->type); - if (!$this->payInfo || !$this->refundInfo) throw new Exception('订单信息不存在'); + if (!$this->payInfo) throw new Exception('订单信息不存在'); + + if ($this->payInfo->status != PayCode::FINISH_PAY) throw new Exception('订单支付状态不是成功'); } /** * @return void */ - protected function getOrderInfo() + protected function getOrderInfo(): void { $this->orderInfo = match ($this->type) { OrderCode::ORDER_TYPE_GOOD => $this->orderModel->getInfoById($this->orderId), @@ -131,7 +169,7 @@ class RefundService * @return void * @throws Exception */ - protected function checkOrder() + protected function checkOrder(): void { if (empty($orderInfo)) throw new Exception('订单信息不存在:'.json_encode(['order_id' => $this->orderId,'order_type' => $this->type])); @@ -149,10 +187,10 @@ class RefundService $this->isRefundMoney = $this->refundOrderModel->getSuccessMoneyByOrderId($this->orderId,$this->type); } - protected function getUser() - { - //todo 获取用户信息 - } +// protected function getUser() +// { +// //todo 获取用户信息 +// } /** * @return void @@ -167,9 +205,11 @@ class RefundService } /** + * @param null $errMsg * @return void + * @throws Exception */ - protected function updateRefund($errMsg = null) + protected function updateRefund($errMsg = null): void { $status = RefundCode::REFUND_FAIL; @@ -178,12 +218,17 @@ class RefundService $errMsg = '等待支付工具退款'; } - $this->refundOrderModel->where('id',$this->refundInfo->id)->update([ - 'refund_status' => $status, - 'remark' => $errMsg - ]); + $this->refundInfo->refund_status = $status; + $this->refundInfo->remark = $errMsg; + + if (!$this->refundInfo->save()) throw new Exception('退款订单更新失败'); } + /** + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ protected function refund(): void { $rechargeService = match ($this->refundInfo->refund_type) @@ -203,6 +248,9 @@ class RefundService ); } + /** + * @return null + */ protected function setAliPayRefund() { return null; diff --git a/app/Service/Api/Order/RefundOrderService.php b/app/Service/Api/Order/RefundOrderService.php index c10de0f..b8f4c36 100644 --- a/app/Service/Api/Order/RefundOrderService.php +++ b/app/Service/Api/Order/RefundOrderService.php @@ -36,6 +36,7 @@ class RefundOrderService extends BaseService */ public function handle(): array { + //todo 考虑是否枷锁 $orderId = (int)$this->request->input('order_id'); $type = (int)$this->request->input('type'); @@ -44,7 +45,7 @@ class RefundOrderService extends BaseService if ($orderInfo->status != OrderCode::PAYED) throw new ErrException('该订单状态已变更,请勿重复操作,刷新后无法退款请联系客服'); //立即取消 - $this->joinRefundQueue($orderId, $type); + $this->joinRefundQueue($orderId, $type, $orderInfo->amount, '用户主动取消订单'); return $this->return->success(); } diff --git a/app/Service/ServiceTrait/Api/OrderTrait.php b/app/Service/ServiceTrait/Api/OrderTrait.php index 2e2698b..707f21b 100644 --- a/app/Service/ServiceTrait/Api/OrderTrait.php +++ b/app/Service/ServiceTrait/Api/OrderTrait.php @@ -18,6 +18,7 @@ use App\Constants\ApiCode; use App\Constants\Common\GoodCode; use App\Constants\Common\OrderCode; use App\Constants\Common\PayCode; +use App\Constants\Common\RefundCode; use App\Constants\ConfigCode; use App\Exception\ErrException; use App\Model\Order; @@ -57,6 +58,19 @@ trait OrderTrait }; } + /** + * @param int $type + * @param int $userId + * @return string + */ + protected function generateRefundOrderNo(int $type,int $userId): string + { + return match ($type) { + OrderCode::ORDER_TYPE_GOOD => RefundCode::ORDER_TYPE_GOOD_PREFIX . '_' .date("YmdHis") . $userId . mt_rand(10000000, 99999999), + OrderCode::ORDER_TYPE_BALANCE => RefundCode::ORDER_TYPE_BALANCE_PREFIX. '_' .date("YmdHis"). $userId. mt_rand(10000000, 99999999), + }; + } + /** * 生成购物车数据 * @param array $data diff --git a/app/Service/ServiceTrait/Common/OrderChangeStatusTrait.php b/app/Service/ServiceTrait/Common/OrderChangeStatusTrait.php index 50b59f5..6688f44 100644 --- a/app/Service/ServiceTrait/Common/OrderChangeStatusTrait.php +++ b/app/Service/ServiceTrait/Common/OrderChangeStatusTrait.php @@ -46,16 +46,18 @@ trait OrderChangeStatusTrait * @param int $orderId * @param int $type * @param float|int $amount amount = 0 全部 amount > 0 部分 + * @param string $reason * @return void * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ - protected function joinRefundQueue(int $orderId, int $type, float|int $amount = 0): void + protected function joinRefundQueue(int $orderId, int $type, float|int $amount = 0, string $reason = '系统自动'): void { $message = new RefundOrderProducer([ 'order_id' => $orderId, 'type' => $type, 'amount' => $amount, + 'reason' => $reason ]); $producer = ApplicationContext::getContainer()->get(Producer::class); $producer->produce($message);