From a2821171efa497603662b740a9fd93548dbc2dbb Mon Sep 17 00:00:00 2001 From: wucongxing <815046773@qq.com> Date: Fri, 4 Aug 2023 13:52:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=96=E6=B6=88=E6=A3=80=E6=B5=8B=E8=AE=A2?= =?UTF-8?q?=E5=8D=95,=E5=8F=96=E6=B6=88=E8=AE=A2=E5=8D=95=E8=AE=A2?= =?UTF-8?q?=E9=98=85=E6=B6=88=E6=81=AF=E6=8E=A8=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Controller/PatientOrderController.php | 13 +++ app/Services/DetectionService.php | 113 +++++++++++++++++++++- app/Services/MessagePush.php | 60 ++++++++++++ app/Services/PatientOrderService.php | 90 +++++++++++++++++ config/routes.php | 6 +- 5 files changed, 280 insertions(+), 2 deletions(-) diff --git a/app/Controller/PatientOrderController.php b/app/Controller/PatientOrderController.php index c446f31..d4c2817 100644 --- a/app/Controller/PatientOrderController.php +++ b/app/Controller/PatientOrderController.php @@ -274,4 +274,17 @@ class PatientOrderController extends AbstractController $data = $PatientOrderService->deletePatientDetectionOrder(); return $this->response->json($data); } + + /** + * 取消检测订单 + * @return ResponseInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function putCancelPatientDetectionOrder(): ResponseInterface + { + $PatientOrderService = new PatientOrderService(); + $data = $PatientOrderService->putCancelPatientDetectionOrder(); + return $this->response->json($data); + } } \ No newline at end of file diff --git a/app/Services/DetectionService.php b/app/Services/DetectionService.php index 378cdfe..1b761cb 100644 --- a/app/Services/DetectionService.php +++ b/app/Services/DetectionService.php @@ -4,6 +4,7 @@ namespace App\Services; use App\Amqp\Producer\CancelUnpayOrdersDelayDirectProducer; use App\Constants\HttpEnumCode; +use App\Exception\BusinessException; use App\Model\Area; use App\Model\BasicCompany; use App\Model\BasicNation; @@ -12,10 +13,12 @@ use App\Model\DetectionProjectPurpose; use App\Model\DiseaseClassDetection; use App\Model\OrderDetection; use App\Model\OrderDetectionCase; +use App\Model\OrderDetectionRefund; use App\Model\PatientFamily; use App\Model\UserDoctor; use App\Model\UserLocation; use App\Utils\Log; +use Extend\Wechat\WechatPay; use Hyperf\Amqp\Producer; use Hyperf\DbConnection\Db; use Hyperf\Snowflake\IdGeneratorInterface; @@ -242,7 +245,7 @@ class DetectionService extends BaseService $doctor['hospital_name'] = $value['Hospital']['hospital_name']; } -// unset($value['Hospital']); + unset($value['Hospital']); $value['avatar'] = addAliyunOssWebsite($value['avatar']); } @@ -547,4 +550,112 @@ class DetectionService extends BaseService return $result; } + + /** + * 检测订单退款接口 + */ + public function detectionRefund(string $order_detection_id, string $refund_reason) + { + // 获取订单数据 + $params = array(); + $params['order_detection_id'] = $order_detection_id; + $order_detection = OrderDetection::getOne($params); + if (empty($order_detection)) { + throw new BusinessException("订单数据为空"); + } + + // 检测问诊订单状态 + if (!in_array($order_detection['detection_status'], [2, 5])) { + // 检测订单状态(1:待支付 2:待绑定 3:检测中 4:检测完成 5:已取消) + throw new BusinessException("订单状态错误"); + } + + // 检测订单退款状态 + if (in_array($order_detection['detection_refund_status'], [2, 3, 5,6])) { + // 检测订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常) + throw new BusinessException("订单退款状态错误"); + } + + // 检测支付状态 + if ($order_detection['detection_pay_status'] != 2) { + // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) + throw new BusinessException("订单支付状态错误"); + } + + // 系统退款编号 + $generator = $this->container->get(IdGeneratorInterface::class); + $detection_refund_no = $generator->generate(); + + // 检测订单金额 + if ($order_detection['payment_amount_total'] > 0){ + // 发起退款 + $WechatPay = new WechatPay(1, 1); + + $options = array(); + $options['transaction_id'] = $order_detection['escrow_trade_no']; + $options['out_refund_no'] = (string)$detection_refund_no; + $options['reason'] = $refund_reason; + $options['amount'] = [ + 'refund' => (int)round($order_detection['payment_amount_total'] * 100), + 'total' => (int)round($order_detection['payment_amount_total'] * 100), + 'currency' => "CNY", + ]; + + $result = $WechatPay->refund($options); + + // 处理订单退款状态 + // 检测订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) + $success_time = ""; + if ($result['status'] == "SUCCESS") { + // 退款成功 + $detection_refund_status = 3; + $success_time = $result['success_time']; + } elseif ($result['status'] == "CLOSED") { + // 退款关闭 + $detection_refund_status = 5; + } elseif ($result['status'] == "PROCESSING") { + // 退款处理中 + $detection_refund_status = 2; + } elseif ($result['status'] == "ABNORMAL") { + // 退款异常,此情况不处理,进行短信通知 + throw new BusinessException("订单退款状态异常"); + } else { + throw new BusinessException("订单退款状态错误"); + } + + $refund_id = $result['refund_id']; + }else{ + $detection_refund_status = 3; + $success_time = date('Y-m-d H:i:s',time()); + $refund_id = $generator->generate(); + } + + // 新增退款表 + $data = array(); + $data['patient_id'] = $order_detection['patient_id']; + $data['order_detection_id'] = $order_detection['order_detection_id']; + $data['detection_no'] = $order_detection['detection_no']; + $data['detection_refund_no'] = $detection_refund_no; + $data['refund_id'] = $refund_id; + $data['detection_refund_status'] = $detection_refund_status; + $data['refund_total'] = $order_detection['payment_amount_total']; + $data['refund_reason'] = $refund_reason; + + if ($detection_refund_status == 3 && !empty($success_time)) { + $data['success_time'] = date("Y-m-d H:i:s", strtotime($success_time)); // 退款成功时间 + } + + $order_detection_refund = OrderDetectionRefund::add($data); + if (empty($order_detection_refund)) { + throw new BusinessException("添加退款表失败"); + } + + // 修改问诊订单表状态 + $data = array(); + $data['detection_refund_status'] = $detection_refund_status; + + $params = array(); + $params['order_detection_id'] = $order_detection['order_detection_id']; + OrderDetection::editOrderDetection($params, $data); + } } \ No newline at end of file diff --git a/app/Services/MessagePush.php b/app/Services/MessagePush.php index a7c8267..2b97394 100644 --- a/app/Services/MessagePush.php +++ b/app/Services/MessagePush.php @@ -7,7 +7,9 @@ use App\Amqp\Producer\SendStationMessageProducer; use App\Amqp\Producer\SendSubMessageProducer; use App\Constants\HttpEnumCode; use App\Exception\BusinessException; +use App\Model\DetectionProject; use App\Model\DoctorWithdrawal; +use App\Model\OrderDetection; use App\Model\OrderInquiry; use App\Model\OrderInquiryCase; use App\Model\OrderInquiryCoupon; @@ -2074,6 +2076,7 @@ class MessagePush extends BaseService $user_doctor = UserDoctor::getOne($params); if (empty($user_doctor)) { Log::getInstance("MessagePush")->error("错误:医生数据为空"); + return; } // 获取问诊订单关联病例 @@ -2108,6 +2111,7 @@ class MessagePush extends BaseService $result = $producer->produce($message); if (!$result) { Log::getInstance("MessagePush")->error("错误:加入推送队列失败" . json_encode($data, JSON_UNESCAPED_UNICODE)); + return; } // 问诊内容-病情主诉 @@ -2226,4 +2230,60 @@ class MessagePush extends BaseService Log::getInstance("MessagePush")->error("错误:加入推送队列失败" . $e->getMessage()); } } + + /** + * 患者-订单取消成功通知 + * 订阅 + * @param string $order_detection_id + * @return void + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function patientCancelOrderSuccess(string $order_detection_id): void + { + try { + // 获取检测订单 + $params = array(); + $params['order_detection_id'] = $order_detection_id; + $order_detection = OrderDetection::getOne($params); + if (empty($order_detection)) { + Log::getInstance("MessagePush")->error("错误:加入推送队列失败,无检测订单数据"); + return; + } + + // 获取检测项目 + $params = array(); + $params['detection_project_id'] = $order_detection['detection_project_id']; + $detection_project = DetectionProject::getOne($params); + if (empty($detection_project)){ + Log::getInstance("MessagePush")->error("错误:加入推送队列失败,检测项目错误"); + return; + } + + $sub_data = array(); + $sub_data['push_user_id'] = $this->user['user_id']; + $sub_data['wx_template_id'] = "5aJSrO8SU5rxqdB99zzl4rMVgcOTjt5mQh56cpZI1Hg";//咨询提醒 + $sub_data['params']['page'] = "/pages/checkOrderDetail/checkOrderDetail?order_detection_id="; + $sub_data['params']['data'] = [ + "thing1" => $order_detection['patient_name'],// 就诊人 + "thing7" => (string)$detection_project['detection_project_name'],// 服务项目 + "time6" => date('Y年m月d日 H:i'),// 取消时间 + "amount8" => $order_detection['payment_amount_total'],// 退款金额 + "thing5" => "订单取消成功,支付金额将立即原路退回。",// 温馨提示 + ]; + + $data = array(); + $data['sub_data'] = $sub_data; + $data['sms_data'] = []; + + $message = new SendSubMessageProducer($data); + $producer = ApplicationContext::getContainer()->get(Producer::class); + $result = $producer->produce($message); + if (!$result) { + Log::getInstance("MessagePush")->error("错误:加入推送队列失败" . json_encode($data, JSON_UNESCAPED_UNICODE)); + } + } catch (\Exception $e) { + Log::getInstance("MessagePush")->error("错误:加入推送队列失败" . $e->getMessage()); + } + } } \ No newline at end of file diff --git a/app/Services/PatientOrderService.php b/app/Services/PatientOrderService.php index 761bed5..5ceb793 100644 --- a/app/Services/PatientOrderService.php +++ b/app/Services/PatientOrderService.php @@ -1780,6 +1780,96 @@ class PatientOrderService extends BaseService return success(); } + /** + * 取消检测订单 + * @return array + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function putCancelPatientDetectionOrder(): array + { + $user_info = $this->request->getAttribute("userInfo") ?? []; + + $order_detection_id = $this->request->route('order_detection_id'); + + // 获取订单数据 + $params = array(); + $params['patient_id'] = $user_info['client_user_id']; + $params['order_detection_id'] = $order_detection_id; + $params['is_delete'] = 0; + $order_detection = OrderDetection::getOne($params); + if (empty($order_detection)) { + return fail(); + } + + $redis = $this->container->get(Redis::class); + $redis_key = "order_detection_lock_" . $order_detection_id; + $redis_lock = $redis->setnx($redis_key, 1); + // 设置过期时间 + $redis->expire($redis_key, 3); + if (!$redis_lock) { + // 设置失败,表示已经设置该值 + return fail(HttpEnumCode::HTTP_SUCCESS, "请您稍后重试"); + } + + // 检测订单状态 + if (!in_array($order_detection['detection_status'], [2])) { + // 检测订单状态(1:待支付 2:待绑定 3:检测中 4:检测完成 5:已取消) + return fail(HttpEnumCode::HTTP_ERROR, "订单无法取消"); + } + + if ($order_detection['detection_refund_status'] == 1) { + // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) + return fail(HttpEnumCode::HTTP_ERROR, "订单申请退款中,请您稍后取消"); + } + + if ($order_detection['detection_refund_status'] == 2) { + // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) + return fail(HttpEnumCode::HTTP_ERROR, "订单正在退款中,请您稍后取消"); + } + + Db::beginTransaction(); + try { + // 退款成功 + // 修改问诊订单为取消 + $data = array(); + $data['detection_status'] = 5; + $data['cancel_time'] = date("Y-m-d H:i:s", time()); + $data['cancel_reason'] = 2; // 取消订单原因(1:主动取消 2:客服取消 3:支付超时) + $data['updated_at'] = date("Y-m-d H:i:s", time()); + + $params = array(); + $params['order_detection_id'] = $order_detection['order_detection_id']; + OrderDetection::editOrderDetection($params, $data); + + // 检测支付状态,判断是否需要退款处理 + if ($order_detection['detection_pay_status'] == 2 && $order_detection['detection_refund_status'] != 3) { + // 需退款 + $detectionService = new DetectionService(); + $detectionService->detectionRefund($order_detection['order_detection_id'], "取消检测"); + } + + // 删除锁 + $redis->del($redis_key); + + Db::commit(); + } catch (\Exception $e) { + Db::rollBack(); + return fail(HttpEnumCode::HTTP_ERROR, $e->getMessage()); + } + + try { + if (!empty($order_inquiry['doctor_id'])) { + // 推送患者-订单取消成功通知 + $MessagePush = new MessagePush($order_detection['user_id'], $order_inquiry['order_inquiry_id']); + $MessagePush->patientCancelOrderSuccess($order_detection['order_detection_id']); + } + } catch (\Exception $e) { + return success(); + } + + return success(); + } /** * 获取患者未完成订单 diff --git a/config/routes.php b/config/routes.php index fc5717b..c2fd465 100644 --- a/config/routes.php +++ b/config/routes.php @@ -269,7 +269,11 @@ Router::addGroup('/patient', function () { // 检测 Router::addGroup('/detection', function () { // 创建检测订单 - Router::post('', [DetectionController::class, 'addDetectionOrder']); + Router::post('', [DetectionController::class, 'addDetectionOrder'], + [ + 'middleware' => [LockRequestMiddleware::class] // 锁定重复请求 + ] + ); // 获取检测机构合作医生列表 Router::get('/doctor', [DetectionController::class, 'getDetectionDoctorList']);