createApp(); $server = $app->getServer(); // 获取解密消息 $message = $server->getDecryptedMessage(); if (empty($message)) { return $this->response->withStatus(500)->withBody(new SwooleStream(strval(json_encode(['code' => 'ERROR', 'message' => "问诊微信支付回调数据为空"], JSON_UNESCAPED_UNICODE)))); } Log::getInstance("CallBack-wxPayInquirySuccess")->info(json_encode($message->toArray(), JSON_UNESCAPED_UNICODE)); if (empty($message['out_trade_no'])) { Log::getInstance("CallBack-wxPayInquirySuccess")->error("问诊微信支付回调数据处理失败,缺少外部订单号"); return $server->serve(); } } catch (\Exception $e) { // 验证失败 Log::getInstance("CallBack-wxPayInquirySuccess")->error($e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Db::beginTransaction(); try { // 查询订单 $params = array(); $params['inquiry_no'] = $message['out_trade_no']; $order_inquiry = OrderInquiry::getOne($params); if (empty($order_inquiry)) { Db::rollBack(); Log::getInstance("CallBack-wxPayInquirySuccess")->error("无订单数据"); return $server->serve(); } // 获取病例数据 $params = array(); $params['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; $order_inquiry_case = OrderInquiryCase::getOne($params); if (empty($order_inquiry_case)){ Db::rollBack(); Log::getInstance("CallBack-wxPayInquirySuccess")->error("患者病例错误"); return $server->serve(); } // 验证订单状态 if ($order_inquiry['inquiry_status'] != 1) { // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) Db::rollBack(); Log::getInstance("CallBack-wxPayInquirySuccess")->error("订单状态当前为" . $order_inquiry['inquiry_status']); return $server->serve(); } // 支付状态无需验证,如第一次支付失败,会修改支付状态,再次支付时,会出现验证不通过的情况 // 处理支付状态 if ($message['trade_state'] == "SUCCESS") { // 支付成功 $pay_status = 2; $pay_time = date('Y-m-d H:i:s', strtotime($message['success_time']));// 支付时间 if ($order_inquiry['inquiry_type'] == 1 || $order_inquiry['inquiry_type'] == 3) { // 专家-公益 $inquiry_status = 3;// 3:待接诊 } elseif ($order_inquiry['inquiry_type'] == 2 || $order_inquiry['inquiry_type'] == 4) { // 快速-购药 $inquiry_status = 2;// 2:待分配 } } elseif ($message['trade_state'] == "CLOSED") { // 已关闭 $pay_status = 6; } elseif ($message['trade_state'] == "REVOKED") { // 已撤销(付款码支付) $pay_status = 7; } elseif ($message['trade_state'] == "USERPAYING") { // 用户支付中(付款码支付) $pay_status = 3; } elseif ($message['trade_state'] == "PAYERROR") { // 支付失败(其他原因,如银行返回失败) $pay_status = 4; }else{ Db::rollBack(); return $server->serve(); } // 修改问诊订单表 $data = array(); if (isset($inquiry_status)){ $data['inquiry_status'] = $inquiry_status; } $data['inquiry_pay_status'] = $pay_status; if (isset($pay_time)){ $data['pay_time'] = $pay_time; } $data['escrow_trade_no'] = $message['transaction_id']; $data['updated_at'] = date('Y-m-d H:i:s', time()); $params = array(); $params['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; OrderInquiry::edit($params, $data); // 修改订单表 $data = array(); $data['pay_status'] = $pay_status; if (isset($pay_time)){ $data['pay_time'] = $pay_time; } $data['escrow_trade_no'] = $message['transaction_id']; $data['updated_at'] = date('Y-m-d H:i:s', time()); $params = array(); $params['order_no'] = $order_inquiry['inquiry_no']; Order::edit($params,$data); Db::commit(); } catch (\Exception $e) { // 验证失败 Db::rollBack(); Log::getInstance("CallBack-wxPayInquirySuccess")->error($e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Log::getInstance("CallBack-wxPayInquirySuccess")->info("成功"); Log::getInstance("CallBack-wxPayInquirySuccess")->info("分配医生/发送问诊消息"); try { if ($message['trade_state'] == "SUCCESS") { if ($order_inquiry['inquiry_type'] == 2 || $order_inquiry['inquiry_type'] == 4) { Log::getInstance()->info("加入分配医生队列"); // 快速-购药 // 加入分配医生队列 $data = array(); $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; $message = new AssignDoctorDelayDirectProducer($data); $message->setDelayMs(1000 * 5); $producer = $this->container->get(Producer::class); $res = $producer->produce($message); if (!$res) { Log::getInstance("CallBack-wxPayInquirySuccess")->error("加入分配医生队列失败"); return $server->serve(); } Log::getInstance("CallBack-wxPayInquirySuccess")->info("加入分配医生队列成功"); } elseif ($order_inquiry['inquiry_type'] == 1 || $order_inquiry['inquiry_type'] == 3) { // 专家-公益,发送im消息 Log::getInstance("CallBack-wxPayInquirySuccess")->info("开始发送im消息"); // 获取订单医生数据 $params = array(); $params['doctor_id'] = $order_inquiry['doctor_id']; $user_doctor = UserDoctor::getOne($params); if (empty($user_doctor)) { Log::getInstance("CallBack-wxPayInquirySuccess")->error("医生数据错误"); return $server->serve(); } // 发送im消息 $imService = new ImService(); // 等待医生接诊 $imService->waitDoctorInquiry($order_inquiry, $user_doctor['user_id'], $order_inquiry['user_id']); // 发送站内、订阅失败发送短信消息-医生有新问诊 $MessagePush = new MessagePush($user_doctor['user_id'], $order_inquiry['order_inquiry_id']); $MessagePush->doctorHaveNewInquiry(); // 加入xx时间未接诊通知队列 $data = array(); $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; $time = 1000 * 60 * 60 * 2; $message = new DoctorNotYetInquiryDelayDirectProducer($data); $message->setDelayMs($time); $producer = $this->container->get(Producer::class); $producer->produce($message); Log::getInstance("CallBack-wxPayInquirySuccess")->info("发送im消息成功"); } } } catch (\Exception $e) { // 验证失败 Log::getInstance("CallBack-wxPayInquirySuccess")->error("问诊微信支付回调数据处理成功,分配医生/发送问诊消息失败:" . $e->getMessage()); return $server->serve(); } Log::getInstance("CallBack-wxPayInquirySuccess")->info("问诊微信支付回调处理成功"); return $server->serve(); } /** * 微信问诊退款回调 * @return ResponseInterface * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface * @throws \Throwable */ public function wxPayInquiryRefundCallBack(): ResponseInterface { try { // 处理支付结果事件 $WechatPay = new WechatPay(1, 1); $app = $WechatPay->createApp(); $server = $app->getServer(); // 获取解密消息 $message = $server->getDecryptedMessage(); if (empty($message)) { return $this->response->withStatus(500)->withBody(new SwooleStream(strval(json_encode(['code' => 'ERROR', 'message' => "回调数据为空"], JSON_UNESCAPED_UNICODE)))); } Log::getInstance("CallBack-wxPayInquiryRefund")->info(json_encode($message->toArray(), JSON_UNESCAPED_UNICODE)); if (empty($message['out_trade_no'])) { Log::getInstance("CallBack-wxPayInquiryRefund")->error("微信退款回调数据错误"); return $server->serve(); } } catch (\Exception $e) { // 验证失败 Log::getInstance("CallBack-wxPayInquiryRefund")->error($e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Db::beginTransaction(); try { // 验证订单数据 $params = array(); $params['inquiry_no'] = $message['out_trade_no']; $order_inquiry = OrderInquiry::getOne($params); if (empty($order_inquiry)) { Db::rollBack(); Log::getInstance("CallBack-wxPayInquiryRefund")->error("非法订单"); return $server->serve(); } // 验证订单状态 if ($order_inquiry['inquiry_status'] == 1) { // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) Db::rollBack(); Log::getInstance("CallBack-wxPayInquiryRefund")->error("订单状态错误:当前为" . $order_inquiry['inquiry_status']); return $server->serve(); } // 验证订单退款状态 if ($order_inquiry['inquiry_refund_status'] == 3) { // 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) Db::rollBack(); Log::getInstance("CallBack-wxPayInquiryRefund")->error("订单退款状态错误:当前为" . $order_inquiry['inquiry_refund_status']); return $server->serve(); } // 验证订单支付状态 if (in_array($order_inquiry['inquiry_pay_status'], [1, 3, 4, 5, 6, 7])) { // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) Db::rollBack(); Log::getInstance("CallBack-wxPayInquiryRefund")->error("订单支付状态错误:当前为" . $order_inquiry['inquiry_pay_status']); return $server->serve(); } // 处理退款回调结果 $OrderService = new OrderService(); $OrderService->orderRefundResult($order_inquiry['inquiry_no'],$message['refund_status'],$message['success_time']); Db::commit(); } catch (\Exception $e) { // 验证失败 Db::rollBack(); Log::getInstance("CallBack-wxPayInquiryRefund")->error("微信支付回调数据验证失败:" . $e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Log::getInstance("CallBack-wxPayInquiryRefund")->info("微信退款回调处理成功,推送消息"); // 发送推送消息 if ($message['refund_status'] == "SUCCESS") { try { // 发送站内、订阅、短信消息-问诊服务退款成功 $MessagePush = new MessagePush($order_inquiry['user_id'], $order_inquiry['order_inquiry_id']); // 取消订单原因(1:医生未接诊 2:主动取消 3:无可分配医生 4:客服取消 5:支付超时) $MessagePush->refundInquirySuccess($order_inquiry['cancel_reason']); } catch (\Exception $e) { // 验证失败 Log::getInstance("CallBack-wxPayInquiryRefund")->error("微信退款回调处理成功,推送消息失败:" . $e->getMessage()); return $server->serve(); } } return $server->serve(); } /** * 患者端药品微信支付回调 * @return ResponseInterface * @throws \Throwable */ public function wxPayProductSuccessCallBack(): ResponseInterface { try { // 处理支付结果事件 $WechatPay = new WechatPay(1, 2); $app = $WechatPay->createApp(); $server = $app->getServer(); // 获取解密消息 $message = $server->getDecryptedMessage(); if (empty($message)) { return $this->response->withStatus(500)->withBody(new SwooleStream(strval(json_encode(['code' => 'ERROR', 'message' => "药品微信支付回调数据为空"], JSON_UNESCAPED_UNICODE)))); } Log::getInstance("CallBack-wxPayProductSuccess")->info(json_encode($message->toArray(), JSON_UNESCAPED_UNICODE)); if (empty($message['out_trade_no'])) { Log::getInstance("CallBack-wxPayProductSuccess")->error("缺少外部订单号"); return $server->serve(); } } catch (\Exception $e) { // 验证失败 Log::getInstance("CallBack-wxPayProductSuccess")->error($e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Log::getInstance("CallBack-wxPayProductSuccess")->info("药品微信支付回调数据验证成功,执行数据库操作"); Db::beginTransaction(); try { // 查询药品订单 $params = array(); $params['order_product_no'] = $message['out_trade_no']; $order_product = OrderProduct::getOne($params); if (empty($order_product)) { Db::rollBack(); Log::getInstance("CallBack-wxPayProductSuccess")->error("无订单数据"); return $server->serve(); } // 验证订单状态 if ($order_product['order_product_status'] != 1) { Db::rollBack(); // 订单状态(1:待支付 2:待发货 3:已发货 4:已签收 5:已取消) Log::getInstance("CallBack-wxPayProductSuccess")->error("药品微信支付回调数据处理失败,订单状态当前为" . $order_product['order_product_status']); return $server->serve(); } // 支付状态无需验证,如第一次支付失败,会修改支付状态,再次支付时,会出现验证不通过的情况 // 处理支付状态 if ($message['trade_state'] == "SUCCESS") { // 支付成功 $order_product_status = 2; $pay_status = 2;// 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) $pay_time = date('Y-m-d H:i:s', strtotime($message['success_time']));// 支付时间 } elseif ($message['trade_state'] == "CLOSED") { // 已关闭 $pay_status = 6; } elseif ($message['trade_state'] == "REVOKED") { // 已撤销(付款码支付) $pay_status = 7; } elseif ($message['trade_state'] == "USERPAYING") { // 用户支付中(付款码支付) $pay_status = 3; } elseif ($message['trade_state'] == "PAYERROR") { // 支付失败(其他原因,如银行返回失败) $pay_status = 4; } else { Db::rollBack(); return $server->serve(); } // 修改药品订单表 $data = array(); if (isset($order_product_status)){ $data['order_product_status'] = $order_product_status; } if (isset($pay_time)){ $data['pay_time'] = $pay_time; } $data['pay_status'] = $pay_status; $data['escrow_trade_no'] = $message['transaction_id']; $data['updated_at'] = date('Y-m-d H:i:s', time()); $params = array(); $params['order_product_id'] = $order_product['order_product_id']; OrderProduct::edit($params, $data); // 修改订单表 $data = array(); $data['pay_status'] = $pay_status; if (isset($pay_time)){ $data['pay_time'] = $pay_time; } $data['escrow_trade_no'] = $message['transaction_id']; $data['updated_at'] = date('Y-m-d H:i:s', time()); $params = array(); $params['order_no'] = $order_product['order_product_no']; Order::edit($params,$data); // 获取订单商品订单列表 $params = array(); $params['order_product_id'] = $order_product['order_product_id']; $order_product_item = OrderProductItem::getList($params); if (empty($order_product_item)) { Db::rollBack(); Log::getInstance("CallBack-wxPayProductSuccess")->error("未查询到对应订单商品订单列表"); return $server->serve(); } Db::commit(); } catch (\Exception $e) { Db::rollBack(); Log::getInstance("CallBack-wxPayProductSuccess")->error("药品微信支付回调数据处理失败:" . $e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Log::getInstance("CallBack-wxPayProductSuccess")->error("药品微信支付回调数据处理成功"); try { // 再次发放优惠卷数据 if ($order_product['coupon_amount_total'] > 0){ // 获取药品订单优惠卷数据 $params = array(); $params['order_product_id'] = $order_product['order_product_id']; $order_product_coupons = OrderProductCoupon::getList($params); if (!empty($order_product_coupons)){ foreach ($order_product_coupons as $order_product_coupon){ // 获取用户优惠卷数据 $params = array(); $params['user_coupon_id'] = $order_product_coupon['user_coupon_id']; $user_coupon = UserCoupon::getOne($params); if (!empty($user_coupon)){ // 获取优惠卷数据 $params = array(); $params['coupon_id'] = $user_coupon['coupon_id']; $coupon = Coupon::getOne($params); if (!empty($coupon)){ if ($coupon['reissue_interval_days'] > 0){ $data = array(); $data['coupon_id'] = $coupon['coupon_id']; $data['user_id'] = $user_coupon['user_id']; $time = $coupon['reissue_interval_days'] * 24 * 60 * 60 * 1000; $message = new GrantUserCouponDelayDirectProducer($data); $message->setDelayMs($time); $producer = $this->container->get(Producer::class); $res = $producer->produce($message); if (!$res) { Log::getInstance("CallBack-wxPayProductSuccess")->error("再次发放优惠卷失败"); } Log::getInstance("CallBack-wxPayProductSuccess")->info("再次发放优惠卷成功"); } } } } } } }catch (\Throwable $e){ Log::getInstance("CallBack-wxPayProductSuccess")->error("药品微信支付回调数据处理失败:" . $e->getMessage()); } return $server->serve(); } /** * 微信药品退款回调 * @return ResponseInterface * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface * @throws \Throwable */ public function wxPayProductRefundCallBack(): ResponseInterface { try { // 处理支付结果事件 $WechatPay = new WechatPay(1, 2); $app = $WechatPay->createApp(); $server = $app->getServer(); // 获取解密消息 $message = $server->getDecryptedMessage(); if (empty($message)) { Db::rollBack(); return $this->response->withStatus(500)->withBody(new SwooleStream(strval(json_encode(['code' => 'ERROR', 'message' => "回调数据为空"], JSON_UNESCAPED_UNICODE)))); } Log::getInstance("CallBack-wxPayProductRefund")->info(json_encode($message->toArray(), JSON_UNESCAPED_UNICODE)); if (empty($message['out_trade_no'])) { Log::getInstance("CallBack-wxPayProductRefund")->error("缺少外部订单号"); return $server->serve(); } } catch (\Exception $e) { // 验证失败 Log::getInstance("CallBack-wxPayProductRefund")->error($e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Db::beginTransaction(); try { // 查询药品订单 $params = array(); $params['order_product_no'] = $message['out_trade_no']; $order_product = OrderProduct::getOne($params); if (empty($order_product)) { Db::rollBack(); Log::getInstance("CallBack-wxPayProductRefund")->error("无订单数据"); return $server->serve(); } // 查询患者数据 $params = array(); $params['patient_id'] = $order_product["patient_id"]; $user_patient = UserPatient::getOne($params); if (empty($user_patient)) { Db::rollBack(); Log::getInstance("CallBack-wxPayProductRefund")->info("无患者数据"); return $server->serve(); } // 验证订单状态 if ($order_product['order_product_status'] == 1) { // 订单状态(1:待支付 2:待发货 3:已发货 4:已签收 5:已取消) Db::rollBack(); Log::getInstance("CallBack-wxPayProductRefund")->error("药品微信退款回调数据处理失败,订单状态错误:当前为" . $order_product['order_product_status']); return $server->serve(); } // 验证订单退款状态 if ($order_product['refund_status'] == 3) { // 商品订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭) Db::rollBack(); Log::getInstance("CallBack-wxPayProductRefund")->error("药品微信退款回调数据处理失败,订单退款状态为" . $order_product['refund_status']); return $server->serve(); } // 验证订单支付状态 if (in_array($order_product['pay_status'], [1, 3, 4, 5, 6, 7])) { // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) Db::rollBack(); Log::getInstance("CallBack-wxPayProductRefund")->error("订单未支付"); return $server->serve(); } // 处理退款回调结果 $OrderService = new OrderService(); $OrderService->orderRefundResult($order_product['order_product_no'],$message['refund_status'],$message['success_time']); Db::commit(); } catch (\Exception $e) { // 验证失败 Db::rollBack(); Log::getInstance("CallBack-wxPayProductRefund")->error("药品微信退款回调数据处理失败:" . $e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Log::getInstance("CallBack-wxPayProductRefund")->info("药品微信退款回调数据处理成功"); // 发送推送消息 try { // 获取患者数据 $params = array(); $params['patient_id'] = $order_product['patient_id']; $user_patient = UserPatient::getOne($params); if (!empty($user_patient)) { // 发送站内、订阅、短信消息-药品订单退款成功 $MessagePush = new MessagePush($user_patient['user_id']); $MessagePush->refundProductSuccess($order_product['order_product_id']); } } catch (\Exception $e) { // 验证失败 Log::getInstance("CallBack-wxPayProductRefund")->error("微信退款回调处理成功,推送消息失败:" . $e->getMessage()); return $server->serve(); } return $server->serve(); } /** * 微信支付返回错误响应 * @param string $message * @return ResponseInterface */ protected function wxPayErrorReturn(string $message): ResponseInterface { return $this->response ->withStatus(500) ->withBody( new SwooleStream( strval( json_encode(['code' => 'ERROR', 'message' => $message], JSON_UNESCAPED_UNICODE) ) ) ); } /** * im回调 * @return ResponseInterface */ public function imCallBack(): ResponseInterface { $request_params = $this->request->all(); try { Log::getInstance("CallBackController-imCallBack")->info(json_encode($request_params, JSON_UNESCAPED_UNICODE)); if (empty($request_params['RequestTime']) || empty($request_params['Sign'])) { return $this->ImErrorReturn("缺少时间时间戳/签名字段"); } // 鉴定回调签名 $imService = new ImService(); $result = $imService->validateSign($request_params['RequestTime'], $request_params['Sign']); if (!$result) { return $this->ImErrorReturn("回调签名不匹配"); } if (empty($request_params['CallbackCommand'])){ return $this->ImErrorReturn("回调事件为空"); } $userService = new UserService(); if ($request_params['CallbackCommand'] == "State.StateChange"){ // 用户状态变更 $result = $userService->userImLoginStatus($request_params); if ($result['code'] == 0){ return $this->ImErrorReturn($result['message']); } }elseif ($request_params['CallbackCommand'] == "C2C.CallbackAfterSendMsg"){ // 用户im消息发送后回调 $result = $userService->userImAfterSendMsg($request_params); if ($result['code'] == 0){ return $this->ImErrorReturn($result['message']); } }else{ return $this->ImErrorReturn("非法事件"); } } catch (\Exception $e) { // 验证失败 return $this->ImErrorReturn($e->getMessage()); } Log::getInstance()->info("Im回调数据处理成功"); return $this->ImSuccessReturn(); } /** * im返回错误响应 * @param string $message * @return ResponseInterface */ protected function ImErrorReturn(string $message): ResponseInterface { Log::getInstance("CallBackController-imCallBack")->error($message); return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'ActionStatus' => 'FAIL', 'ErrorCode' => 1, 'ErrorInfo' => $message, ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * im返回正确响应 * @return ResponseInterface */ protected function ImSuccessReturn(): ResponseInterface { return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'ActionStatus' => 'OK', 'ErrorCode' => 0, 'ErrorInfo' => "", ], JSON_UNESCAPED_UNICODE) ) ) ); } // 处方平台物流回调 public function platformLogisticsCallBack(): ResponseInterface { $request_params = $this->request->all(); try { Log::getInstance()->info("处方平台物流回调数据:" . json_encode($request_params, JSON_UNESCAPED_UNICODE)); if (!isset($request_params['sign'])) { Log::getInstance()->error("处方平台物流回调数据处理失败:缺少签名结果"); return $this->platformLogisticsErrorReturn("缺少签名结果"); } if (!isset($request_params['nonce'])) { Log::getInstance()->error("处方平台物流回调数据处理失败:缺少随机数"); return $this->platformLogisticsErrorReturn("缺少随机数"); } if (!isset($request_params['timestamp'])) { Log::getInstance()->error("处方平台物流回调数据处理失败:缺少签名时间戳"); return $this->platformLogisticsErrorReturn("缺少签名时间戳"); } if (!isset($request_params['paramJsonStr'])) { Log::getInstance()->error("处方平台物流回调数据处理失败:缺少数据体"); return $this->platformLogisticsErrorReturn("缺少数据体"); } // 验证签名 $sign_params = array(); $sign_params['clientId'] = config('prescription_platform.client_id'); $sign_params['paramJsonStr'] = $request_params['paramJsonStr']; $sign_params['timestamp'] = $request_params['timestamp']; $sign_params['nonce'] = $request_params['nonce']; $sign_params['clientSecret'] = config('prescription_platform.client_secret'); $sign = md5(http_build_query($sign_params, '', '&')); if ($sign != $request_params['sign']) { Log::getInstance()->error("处方平台物流回调数据处理失败:签名错误"); Log::getInstance()->error("系统签名:" . $sign); Log::getInstance()->error("处方平台签名:" . $sign); Log::getInstance()->error("处方平台签名:" . $request_params['sign']); return $this->platformLogisticsErrorReturn("签名错误"); } $param_json_str = json_decode($request_params['paramJsonStr'], true); if (empty($param_json_str)) { // 数据体为空,直接返回成功,不进行验证签名 Log::getInstance()->info("处方平台物流回调数据处理成功:数据体解析为空"); return $this->platformLogisticsSuccessReturn(); } } catch (\Exception $e) { // 验证失败 Log::getInstance()->error("处方平台物流回调数据处理失败:" . $e->getMessage()); return $this->platformLogisticsErrorReturn($e->getMessage()); } Log::getInstance()->info("处方平台物流回调数据处理成功"); return $this->platformLogisticsSuccessReturn(); } /** * 处方平台物流返回错误响应 * @param string $message * @return ResponseInterface */ protected function platformLogisticsErrorReturn(string $message): ResponseInterface { return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'resultCode' => '0', 'resultDesc' => $message, ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * 处方平台物流返回正确响应 * @return ResponseInterface */ protected function platformLogisticsSuccessReturn(): ResponseInterface { return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'resultCode' => "1000", 'resultDesc' => "成功", ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * 快递100订阅回调 * @return ResponseInterface * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface */ public function LogisticsCallBack(): ResponseInterface { $request_params = $this->request->all(); try { Log::getInstance()->info("快递100订阅回调数据:" . json_encode($request_params, JSON_UNESCAPED_UNICODE)); // 检测回调数据 if (!isset($request_params['sign']) || !isset($request_params['param'])) { return $this->LogisticsFailReturn("缺少推送参数:sign/param"); } // 检测签名 $sign = strtoupper(md5( $request_params['param'] . config('kuaidi100.salt') )); if ($sign != $request_params['sign']){ return $this->LogisticsFailReturn("签名验证错误"); } // 转换编码 $request_params['param'] = json_decode($request_params['param'],true); if (empty($request_params['param'])){ return $this->LogisticsFailReturn("转换json失败"); } // 检测消息体 if (!isset($request_params['param']['lastResult'])){ return $this->LogisticsFailReturn("缺少推送参数:lastResult"); } // 检测订单号 if (!isset($request_params['param']['lastResult']['nu'])){ return $this->LogisticsFailReturn("缺少推送参数:nu"); } // 检测快递公司编码 if (!isset($request_params['param']['lastResult']['com'])){ return $this->LogisticsFailReturn("缺少推送参数:com"); } // 检测内容 if (!isset($request_params['param']['lastResult']['data'])){ return $this->LogisticsFailReturn("缺少推送参数:data"); } // 检测状态 if (!isset($request_params['param']['lastResult']['state'])){ return $this->LogisticsFailReturn("缺少推送参数:state"); } // 运单签收状态(0在途 1揽收 2疑难 3签收 4退签 5派件 8清关 14拒签) $logistics_status = [0,1,2,3,4,5,8,14]; if (!in_array($request_params['param']['lastResult']['state'],$logistics_status)){ return $this->LogisticsSuccessReturn("非可执行状态"); } Db::beginTransaction(); try { // 获取药品订单数据 $params = array(); $params['logistics_no'] = $request_params['param']['lastResult']['nu']; $params['logistics_company_code'] = $request_params['param']['lastResult']['com']; $order_product = OrderProduct::getOne($params); if (empty($order_product)){ Db::rollBack(); return $this->LogisticsFailReturn("药品订单数据错误"); } // 检测药品订单数据 if (in_array($order_product['order_product_status'],[1,4,5])){ // 订单状态(1:待支付 2:待发货 3:已发货 4:已签收 5:已取消) Db::rollBack(); return $this->LogisticsSuccessReturn("无需处理"); } // 获取快递公司数据 $params = array(); $params['company_code'] = $request_params['param']['lastResult']['com']; $params['company_type'] = 1; $basic_logistics_company = BasicLogisticsCompany::getOne($params); if (empty($basic_logistics_company)){ Db::rollBack(); return $this->LogisticsFailReturn("快递公司编码错误"); } // 获取商品订单-物流数据 $params = array(); $params['logistics_no'] = $request_params['param']['lastResult']['nu']; $params['company_code'] = $request_params['param']['lastResult']['com']; $order_product_logistics = OrderProductLogistic::getOne($params); if (empty($order_product_logistics)){ // 不存在物流数据 $data = array(); $data['order_product_id'] = $order_product['order_product_id']; $data['logistics_status'] = $request_params['param']['lastResult']['state']; $data['logistics_no'] = $request_params['param']['lastResult']['nu']; $data['company_name'] = $basic_logistics_company['company_name']; $data['company_code'] = $request_params['param']['lastResult']['com']; $data['logistics_content'] = json_encode($request_params['param']['lastResult']['data'],JSON_UNESCAPED_UNICODE); $order_product_logistics = OrderProductLogistic::addOrderProductLogistic($data); if (empty($order_product_logistics)){ Db::rollBack(); return $this->LogisticsFailReturn("添加物流数据错误"); } }else{ $params = array(); $params['logistics_id'] = $order_product_logistics['logistics_id']; $data = array(); if ($order_product_logistics['logistics_status'] != $request_params['param']['lastResult']['state']){ $data['logistics_status'] = $request_params['param']['lastResult']['state']; } $data['logistics_content'] = json_encode($request_params['param']['lastResult']['data'],JSON_UNESCAPED_UNICODE); OrderProductLogistic::edit($params,$data); } // 运单签收状态(0在途 1揽收 2疑难 3签收 4退签 5派件 8清关 14拒签) if ($request_params['param']['lastResult']['state'] == 3){ // 修改药品订单数据为已签收 $params = array(); $params['order_product_id'] = $order_product['order_product_id']; $data = array(); $data['order_product_status'] = 4; OrderProduct::edit($params,$data); // 新增药品用药记录 } Db::commit(); } catch (\Exception $e) { Db::rollBack(); return $this->LogisticsFailReturn($e->getMessage()); } // 推送消息 try { // 获取患者数据 $params = array(); $params['patient_id'] = $order_product['patient_id']; $user_patient = UserPatient::getOne($params); if (empty($user_patient)){ return $this->LogisticsSuccessReturn("推送消息错误:用户数据错误"); } // 检测是否推送过 $redis = $this->container->get(Redis::class); $redis_key = "logistics_" . $request_params['param']['lastResult']['nu'] . $request_params['param']['lastResult']['state']; $redis_value = $redis->get($redis_key); if (empty($redis_value)){ // 未推送过 $status = ""; if ($request_params['param']['lastResult']['state'] == 1){ // 1揽收 $status = "已揽收"; }elseif ($request_params['param']['lastResult']['state'] == 0){ // 0在途 $status = "已发货"; }elseif ($request_params['param']['lastResult']['state'] == 3){ // 3签收 $status = "已签收"; } if (!empty($status)){ // 患者-物流信息-站内 $MessagePush = new MessagePush($user_patient['user_id']); $MessagePush->logistics($status,$order_product['order_product_id']); $redis->set($redis_key, 1, 60 * 10); } } }catch (\Exception $e){ return $this->LogisticsSuccessReturn("推送消息错误:" . $e->getMessage()); } return $this->LogisticsSuccessReturn(); } catch (\Exception $e) { return $this->LogisticsFailReturn("异常:" . $e->getMessage()); } } /** * 快递100订阅回调失败 * @param string $message * @return ResponseInterface */ protected function LogisticsFailReturn(string $message): ResponseInterface { return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'result' => false, 'returnCode' => "500", 'message' => $message, ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * 快递100订阅回调成功 * @param string $message * @return ResponseInterface */ protected function LogisticsSuccessReturn(string $message = ""): ResponseInterface { return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'result' => true, 'returnCode' => "200", 'message' => $message, ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * 患者端检测支付回调 * @return ResponseInterface * @throws \Throwable */ public function wxPayDetectionSuccessCallBack(): ResponseInterface { try { // 处理支付结果事件 $WechatPay = new WechatPay(1, 3); $app = $WechatPay->createApp(); $server = $app->getServer(); // 获取解密消息 $message = $server->getDecryptedMessage(); if (empty($message)) { return $this->response->withStatus(500)->withBody(new SwooleStream(strval(json_encode(['code' => 'ERROR', 'message' => "问诊微信支付回调数据为空"], JSON_UNESCAPED_UNICODE)))); } Log::getInstance("CallBack-xPayDetectionSuccess")->info(json_encode($message->toArray(), JSON_UNESCAPED_UNICODE)); if (empty($message['out_trade_no'])) { Log::getInstance("CallBack-xPayDetectionSuccess")->error("缺少外部订单号"); return $server->serve(); } }catch (\Throwable $e){ // 验证失败 Log::getInstance("CallBack-xPayDetectionSuccess")->error($e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Db::beginTransaction(); try { // 查询订单 $params = array(); $params['detection_no'] = $message['out_trade_no']; $order_detection = OrderDetection::getOne($params); if (empty($order_detection)) { Db::rollBack(); Log::getInstance("CallBack-xPayDetectionSuccess")->info("无订单数据"); return $server->serve(); } // 验证订单状态 if ($order_detection['detection_status'] != 1) { // 检测订单状态(1:待支付 2:待绑定 3:检测中 4:检测完成 5:已取消) Db::rollBack(); Log::getInstance("CallBack-xPayDetectionSuccess")->error("检测微信支付回调数据处理失败,订单状态当前为" . $order_detection['detection_status']); return $server->serve(); } // 支付状态无需验证,如第一次支付失败,会修改支付状态,再次支付时,会出现验证不通过的情况 // 处理支付状态 if ($message['trade_state'] == "SUCCESS") { // 支付成功 $pay_status = 2; $pay_time = date('Y-m-d H:i:s', strtotime($message['success_time']));// 支付时间 $detection_status = 2;// 2:待绑定 if (empty($message['amount'])){ Db::rollBack(); Log::getInstance("CallBack-xPayDetectionSuccess")->error("无支付金额"); return $this->wxPayErrorReturn("无支付金额"); } } elseif ($message['trade_state'] == "CLOSED") { // 已关闭 $pay_status = 6; } elseif ($message['trade_state'] == "REVOKED") { // 已撤销(付款码支付) $pay_status = 7; } elseif ($message['trade_state'] == "USERPAYING") { // 用户支付中(付款码支付) $pay_status = 3; } elseif ($message['trade_state'] == "PAYERROR") { // 支付失败(其他原因,如银行返回失败) $pay_status = 4; } else { Db::rollBack(); return $server->serve(); } $data = array(); $data['detection_pay_status'] = $pay_status; if (isset($detection_status)){ $data['detection_status'] = $detection_status; } if (isset($pay_time)){ $data['pay_time'] = $pay_time; } $data['escrow_trade_no'] = $message['transaction_id']; $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); // 修改订单表 $data = array(); $data['pay_status'] = $pay_status; if (isset($pay_time)){ $data['pay_time'] = $pay_time; } $data['escrow_trade_no'] = $message['transaction_id']; $data['updated_at'] = date('Y-m-d H:i:s', time()); $params = array(); $params['order_no'] = $order_detection['detection_no']; Order::edit($params,$data); Db::commit(); } catch (\Exception $e) { // 验证失败 Db::rollBack(); Log::getInstance("CallBack-xPayDetectionSuccess")->error("问诊微信支付回调数据处理失败:" . $e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Log::getInstance("CallBack-xPayDetectionSuccess")->info("检测微信支付回调处理成功"); return $server->serve(); } /** * 微信检测退款回调 * @return ResponseInterface * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface * @throws \Throwable */ public function wxPayDetectionRefundCallBack(): ResponseInterface { try { // 处理支付结果事件 $WechatPay = new WechatPay(1, 1); $app = $WechatPay->createApp(); $server = $app->getServer(); // 获取解密消息 $message = $server->getDecryptedMessage(); if (empty($message)) { Db::rollBack(); return $this->response->withStatus(500)->withBody(new SwooleStream(strval(json_encode(['code' => 'ERROR', 'message' => "回调数据为空"], JSON_UNESCAPED_UNICODE)))); } Log::getInstance("CallBack-wxPayDetectionRefund")->info(json_encode($message->toArray(), JSON_UNESCAPED_UNICODE)); if (empty($message['out_trade_no'])) { Log::getInstance("CallBack-wxPayDetectionRefund")->error("缺少外部订单号"); return $server->serve(); } } catch (\Exception $e) { // 验证失败 Log::getInstance("CallBack-wxPayDetectionRefund")->error($e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Db::beginTransaction(); try { // 验证订单数据 $params = array(); $params['detection_no'] = $message['out_trade_no']; $order_detection = OrderDetection::getOne($params); if (empty($order_detection)) { Db::rollBack(); Log::getInstance("CallBack-wxPayDetectionRefund")->error("非法订单"); return $server->serve(); } // 验证订单状态 if ($order_detection['detection_status'] == 1) { // 检测订单状态(1:待支付 2:待绑定 3:检测中 4:检测完成 5:已取消) Db::rollBack(); Log::getInstance("CallBack-wxPayDetectionRefund")->error("订单状态错误:当前为" . $order_detection['detection_status']); return $server->serve(); } // 验证订单退款状态 if ($order_detection['detection_refund_status'] == 3) { // 检测订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常) Db::rollBack(); Log::getInstance("CallBack-wxPayDetectionRefund")->error("订单退款状态错误:当前为" . $order_detection['detection_refund_status']); return $server->serve(); } // 验证订单支付状态 if (in_array($order_detection['detection_pay_status'], [1, 3, 4, 5, 6, 7])) { // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) Db::rollBack(); Log::getInstance("CallBack-wxPayDetectionRefund")->error("订单支付状态错误:当前为" . $order_detection['detection_pay_status']); return $server->serve(); } // 处理退款回调结果 $OrderService = new OrderService(); $OrderService->orderRefundResult($order_detection['detection_no'],$message['refund_status'],$message['success_time']); Db::commit(); } catch (\Exception $e) { // 验证失败 Db::rollBack(); Log::getInstance("CallBack-wxPayDetectionRefund")->error("微信支付回调数据验证失败:" . $e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Log::getInstance("CallBack-wxPayDetectionRefund")->info("微信退款回调处理成功"); return $server->serve(); } /** * 检测所结果回调 * @return ResponseInterface */ public function DetectionResultCallBack(): ResponseInterface { $request_params = $this->request->all(); $auth = $this->request->header("Authorization"); if (empty($auth)){ return $this->detectionResultFailReturn("非法请求"); } Log::getInstance("CallBackController-DetectionResultCallBack")->info("处理检测所结果"); try { // 检测参数 if (!isset($request_params['appId'])){ return $this->detectionResultFailReturn("缺少appId参数"); } if (!isset($request_params['orderCode'])){ return $this->detectionResultFailReturn("缺少orderCode参数"); } if (!isset($request_params['detectBarcode'])){ return $this->detectionResultFailReturn("缺少detectBarcode参数"); } if (!isset($request_params['pdfReport'])){ return $this->detectionResultFailReturn("缺少pdfReport参数"); } // 检测签名 $params = array(); $params['app_id'] = $request_params['appId']; $basic_detection_organ = BasicDetectionOrgan::getOne($params); if (empty($basic_detection_organ)){ return $this->detectionResultFailReturn("非法appId"); } $time = date('Ymd'); $sign = md5($basic_detection_organ['app_id'] . $basic_detection_organ['app_secret'] . $time); dump($sign); if ($auth != $sign){ return $this->detectionResultFailReturn("签名错误"); } // 检测pdf文件 $pdfData = base64_decode($request_params['pdfReport']); if (!$pdfData){ return $this->detectionResultFailReturn("文件错误"); } // 获取检测订单数据 $params = array(); $params['detection_no'] = $request_params['orderCode']; $order_detection = OrderDetection::getOne($params); if (empty($order_detection)){ return $this->detectionResultFailReturn("非法订单"); } // 检测订单状态 if ($order_detection['detection_status'] != 3){ return $this->detectionResultFailReturn("订单状态错误,无法处理"); } if (!empty($order_detection['detection_result_pdf'])){ return $this->detectionResultSuccessReturn(); } if ($order_detection['detection_bar_code'] != $request_params['detectBarcode']){ return $this->detectionResultFailReturn("检测条码无法对应"); } // 上传处方图片至oss $oss = new Oss(); $detection_result_pdf_name = "applet/patient/detection/pdf/" . $order_detection['order_detection_id'] . '.' . 'pdf'; $detection_result_pdf = $oss->putObject($detection_result_pdf_name, $pdfData); $detection_result_pdf = '/' . $detection_result_pdf; // 回填检测结果字段 $order_detection['detection_result_pdf'] = $detection_result_pdf; // 获取医生数据 $params = array(); $params['doctor_id'] = $order_detection['doctor_id']; $user_doctor = UserDoctor::getOne($params); if (empty($user_doctor)){ return $this->detectionResultFailReturn("医生数据错误"); } // 获取检测病例数据 $params = array(); $params['order_detection_id'] = $order_detection['order_detection_id']; $order_detection_case = OrderDetectionCase::getOne($params); if (empty($order_detection_case)){ return $this->detectionResultFailReturn("订单数据错误"); } // 获取检测项目数据 $params = array(); $params['detection_project_id'] = $order_detection['detection_project_id']; $detection_project = DetectionProject::getOne($params); if (empty($detection_project)){ return $this->detectionResultFailReturn("订单数据错误"); } // 发送im消息 $imService = new ImService(); // 检测当前医生是否和患者存在未完成问诊订单 $InquiryService = new InquiryService(); $order_inquiry = $InquiryService->checkPatientDoctorProgressInquiry($order_detection['patient_id'],$order_detection['doctor_id']); if(!empty($order_inquiry)){ // 存在问诊订单 $time_diff = $InquiryService->getInquiryFinishTimeDiff($order_inquiry); if ($time_diff == 0){ $time_diff = 60; } dump($time_diff); // 计算时间并重新加入队列 $queue_data = array(); $queue_data['detection_no'] = $order_detection['detection_no']; $message = new DetectionCompleteDelayDirectProducer($queue_data); $message->setDelayMs(1000 * $time_diff); $producer = $this->container->get(Producer::class); $res = $producer->produce($message); if (!$res) { return $this->detectionResultFailReturn("加入队列失败"); } // 修改检测订单 $data = array(); $data['detection_status'] = 4; $data['detection_result_pdf'] = $detection_result_pdf; $data['detection_result_date'] = date('Y-m-d H:i:s',time()); $params = array(); $params['order_detection_id'] = $order_detection['order_detection_id']; OrderDetection::editOrderDetection($params,$data); // 发送IM消息-检测报告结果 $data = [ "order_inquiry_id" => $order_inquiry['order_inquiry_id'], "inquiry_type" => $order_inquiry['inquiry_type'], "detection_no" => $order_detection['detection_no'], "patient_name" => $order_inquiry['patient_name'], "patient_sex" => $order_inquiry['patient_sex'], "patient_age" => $order_inquiry['patient_age'], "detection_project_name" => $detection_project['detection_project_name'], "disease_class_names" => $order_detection_case['detection_disease_class_names'], "detection_result_pdf" => $order_detection['detection_result_pdf'], "patient_user_id" => $order_detection['user_id'], "doctor_user_id" => $user_doctor['user_id'], ]; $imService->detectionTestReport($data); // 发送IM消息-检测报告结果-文字 $data = [ "order_inquiry_id" => $order_inquiry['order_inquiry_id'], "inquiry_type" => $order_inquiry['inquiry_type'], "detection_no" => $order_detection['detection_no'], "doctor_name" => $user_doctor['user_name'], "patient_name" => $order_inquiry['patient_name'], "patient_sex" => $order_inquiry['patient_sex'], "patient_age" => $order_inquiry['patient_age'], "detection_project_name" => $detection_project['detection_project_name'], "patient_user_id" => $order_detection['user_id'], "doctor_user_id" => $user_doctor['user_id'], ]; $imService->detectionTestReportStr($data); return $this->detectionResultSuccessReturn(); }else{ // 检测家庭成员是否存在 $params = array(); $params['family_id'] = $order_detection['family_id']; $params['patient_id'] = $order_detection['patient_id']; $patient_family = PatientFamily::getOne($params); if (empty($patient_family)) { return $this->detectionResultFailReturn("患者信息错误"); } Db::beginTransaction(); try { $generator = $this->container->get(IdGeneratorInterface::class); // 创建问诊订单 $data = array(); $data['user_id'] = $order_detection['user_id']; $data['patient_id'] = $order_detection['patient_id']; $data['doctor_id'] = $order_detection['doctor_id']; $data['family_id'] = $order_detection['family_id']; $data['inquiry_type'] = 5; // 订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药 5:检测) $data['inquiry_mode'] = 1; // 订单问诊方式(1:图文 2:视频 3:语音 4:电话 5:会员) $data['inquiry_status'] = 4; // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) $data['inquiry_pay_channel'] = 3; // 支付渠道(1:小程序支付 2:微信扫码支付 3:模拟支付) $data['inquiry_pay_status'] = 2; // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) $data['inquiry_no'] = $generator->generate();// 订单编号 $data['escrow_trade_no'] = "GD" . $generator->generate(); // 第三方支付流水号 $data['amount_total'] = 0;// 订单金额 $data['coupon_amount_total'] = 0;// 优惠卷总金额 $data['payment_amount_total'] = 0;// 实际付款金额 $data['pay_time'] = date('Y-m-d H:i:s', time());// 支付时间 $data['reception_time'] = date('Y-m-d H:i:s', time());// 接诊时间 $data['patient_name'] = $patient_family['card_name'];// 患者姓名-就诊人 $data['patient_name_mask'] = $patient_family['card_name_mask'];// 患者姓名-就诊人(掩码) $data['patient_sex'] = $patient_family['sex'];// 患者性别-就诊人(0:未知 1:男 2:女) $data['patient_age'] = $patient_family['age'];// 患者年龄-就诊人 $order_inquiry = OrderInquiry::addOrderInquiry($data); if (empty($order_inquiry)) { Db::rollBack(); return $this->detectionResultFailReturn("问诊订单创建失败"); } // 增加患者问诊病例 $data = array(); $data['user_id'] = $order_detection['user_id']; $data['patient_id'] = $order_detection['patient_id']; $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];// 订单-问诊id $data['family_id'] = $patient_family['family_id']; // 家庭成员id $data['relation'] = $patient_family['relation']; // 与患者关系(1:本人 2:父母 3:爱人 4:子女 5:亲戚 6:其他 ) $data['name'] = $patient_family['card_name']; // 患者名称 $data['sex'] = $patient_family['sex'] ?? 0; // 患者性别(0:未知 1:男 2:女) $data['age'] = $patient_family['age'] ?? null; // 患者年龄 $data['height'] = $patient_family['height'] ?: null; // 身高(cm) $data['weight'] = $patient_family['weight'] ?: null;; // 体重(kg) $data['nation_id'] = $order_detection_case['nation_id'] ?: $patient_family['nation_id'] ?: null;; // 民族 $data['nation_name'] = $order_detection_case['nation_name'] ?: $patient_family['nation_name'] ?: null;; // 民族名称 $order_inquiry_case = OrderInquiryCase::addOrderInquiryCase($data); if (empty($order_inquiry_case)) { Db::rollBack(); return $this->detectionResultFailReturn("问诊订单病例创建失败"); } // 修改检测订单 $data = array(); $data['detection_status'] = 4; $data['detection_result_pdf'] = $detection_result_pdf; $data['detection_result_date'] = date('Y-m-d H:i:s',time()); $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];// 订单-问诊id $params = array(); $params['order_detection_id'] = $order_detection['order_detection_id']; OrderDetection::editOrderDetection($params,$data); // 添加自动完成队列 $time = 1000 * 60 * 60 * 24 * 3; $data = array(); $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; $message = new AutoCompleteInquiryDelayDirectProducer($data); $message->setDelayMs($time); $producer = $this->container->get(Producer::class); $res = $producer->produce($message); if (!$res) { Db::rollBack(); return $this->detectionResultFailReturn("添加自动完成队列失败"); } $imService->patientCase( $order_inquiry, $user_doctor['user_id'], $order_inquiry_case['disease_desc'] ); // 发送IM消息-检测报告结果 $data = [ "order_inquiry_id" => $order_inquiry['order_inquiry_id'], "inquiry_type" => $order_inquiry['inquiry_type'], "detection_no" => $order_detection['detection_no'], "patient_name" => $order_detection['patient_name'], "patient_sex" => $order_detection['patient_sex'], "patient_age" => $order_detection['patient_age'], "detection_project_name" => $detection_project['detection_project_name'], "disease_class_names" => $order_detection_case['detection_disease_class_names'], "detection_result_pdf" => $order_detection['detection_result_pdf'], "patient_user_id" => $order_detection['user_id'], "doctor_user_id" => $user_doctor['user_id'], ]; $imService->detectionTestReport($data); // 发送IM消息-检测报告结果-文字 $data = [ "order_inquiry_id" => $order_inquiry['order_inquiry_id'], "inquiry_type" => $order_inquiry['inquiry_type'], "detection_no" => $order_detection['detection_no'], "doctor_name" => $user_doctor['user_name'], "patient_name" => $order_detection['patient_name'], "patient_sex" => $order_detection['patient_sex'], "patient_age" => $order_detection['patient_age'], "detection_project_name" => $detection_project['detection_project_name'], "patient_user_id" => $order_detection['user_id'], "doctor_user_id" => $user_doctor['user_id'], ]; $imService->detectionTestReportStr($data); Db::commit(); } catch (\Throwable $e) { Db::rollBack(); return $this->detectionResultFailReturn($e->getMessage()); } } try { // 患者-新报告生成通知 $MessagePush = new MessagePush($order_detection['user_id']); $MessagePush->patientDetectionResultNotice($order_detection['order_detection_id']); // 医生-通知医生患者检测报告已生成 $MessagePush = new MessagePush($user_doctor['user_id']); $MessagePush->doctorDetectionResultNotice($order_detection['order_detection_id']); }catch (\Throwable $e){ Log::getInstance("detectionResult")->error($e->getMessage()); } return $this->detectionResultSuccessReturn(); } catch (\Throwable $e) { return $this->detectionResultFailReturn("异常:" . $e->getMessage()); } } /** * 检测所结果回调失败 * @param string $message * @return ResponseInterface */ protected function detectionResultFailReturn(string $message): ResponseInterface { return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'code' => 0, 'msg' => $message, ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * 检测所结果回调成功 * @param string $message * @return ResponseInterface */ protected function detectionResultSuccessReturn(string $message = ""): ResponseInterface { return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'code' => 1, 'msg' => $message, ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * 音视频回调-房间与媒体 * @return ResponseInterface */ public function videoTrtcCallBack(): ResponseInterface { $request_params = $this->request->getBody()->getContents(); $SdkAppId = $this->request->header("SdkAppId"); $Sign = $this->request->header("Sign"); $Sign = stripslashes($Sign); try { Log::getInstance("CallBackController-videoTrtcCallBack")->info(json_encode($request_params, JSON_UNESCAPED_UNICODE)); if (empty($SdkAppId)) { return $this->videoTrtcErrorReturn("缺少SdkAppId字段"); } if (empty($Sign)) { return $this->videoTrtcErrorReturn("缺少签名字段"); } // 鉴定回调签名 $VideoSafe = new VideoSafe(); $result = $VideoSafe->validateSign($request_params,$Sign); if (!$result) { return $this->videoTrtcErrorReturn("回调签名不匹配"); } $request_params = json_decode($request_params,true); // 验证参数 if (!isset($request_params['EventGroupId'])){ return $this->videoTrtcErrorReturn("缺少回调事件组"); } if (empty($request_params['EventGroupId'])){ return $this->videoTrtcErrorReturn("回调事件组为空"); } if (!isset($request_params['EventType'])){ return $this->videoTrtcErrorReturn("回调事件类型"); } if (empty($request_params['EventType'])){ return $this->videoTrtcErrorReturn("回调事件类型为空"); } if (!isset($request_params['EventInfo'])){ return $this->videoTrtcErrorReturn("缺少回调事件信息"); } if (empty($request_params['EventInfo'])){ return $this->videoTrtcErrorReturn("回调事件信息为空"); } if (!isset($request_params['EventInfo']['RoomId'])){ return $this->videoTrtcErrorReturn("缺少房间id"); } if (empty($request_params['EventInfo']['RoomId'])){ return $this->videoTrtcErrorReturn("房间id为空"); } if (!isset($request_params['EventInfo']['EventMsTs'])){ return $this->videoTrtcErrorReturn("缺少时间戳"); } if (empty($request_params['EventInfo']['EventMsTs'])){ return $this->videoTrtcErrorReturn("时间戳为空"); } // 排除数据 if ($request_params['EventGroupId'] != 1 && $request_params['EventGroupId'] != 2){ return $this->videoTrtcErrorReturn("回调地址推送错误"); } if (!in_array($request_params['EventType'],[102,103,201,203])){ return $this->videoTrtcSuccessReturn(); } } catch (\Throwable $e) { // 验证失败 return $this->videoTrtcErrorReturn($e->getMessage()); } // 处理业务逻辑 try { // 获取视频预约记录 $params = array(); $params['room_id'] = $request_params['EventInfo']['RoomId']; $order_inquiry_video_reservation = OrderInquiryVideoReservation::getLastOne($params); if (empty($order_inquiry_video_reservation)){ return $this->videoTrtcErrorReturn("未查询到该房间号,此条数据不接收"); } // 获取视频记录 $params = array(); $params['room_id'] = $request_params['EventInfo']['RoomId']; $params['order_inquiry_id'] = $order_inquiry_video_reservation['order_inquiry_id']; $order_inquiry_video_record = OrderInquiryVideoRecord::getLastOne($params); if (empty($order_inquiry_video_record)){ return $this->videoTrtcErrorReturn("缺少视频开启记录"); } // 检测缓存-只允许同时处理同一房间的一个请求,防止数据库冲突 $redis = $this->container->get(Redis::class); $redis_key = "videoTrtcCallBack_" . $request_params['EventInfo']['RoomId']; $redis_value = $redis->get($redis_key); // 加入缓存 $redis->set($redis_key, $request_params['EventType'], 20); if (!empty($redis_value)){ if ($redis_value == $request_params['EventType']){ // 存在正在执行的相同事件,此次事件不处理 return $this->videoTrtcSuccessReturn(); } // 解散房间 if ($redis_value == 102){ // 正在处理结束通话事件,此次事件不处理 return $this->videoTrtcSuccessReturn(); } // 视频推流 if ($redis_value == 201){ if ($request_params['EventType'] == 103){ // 正在处理视频推流事件,进入房间事件不处理 return $this->videoTrtcSuccessReturn(); } if ($request_params['EventType'] == 203){ // 正在处理视频推流事件,音频推流事件不处理 return $this->videoTrtcSuccessReturn(); } } // 音频推流 if ($redis_value == 203){ if ($request_params['EventType'] == 103){ // 正在处理视频推流事件,进入房间事件不处理 return $this->videoTrtcSuccessReturn(); } if ($request_params['EventType'] == 201){ // 正在处理视频推流事件,视频推流事件不处理 return $this->videoTrtcSuccessReturn(); } } } // 处理业务逻辑 switch ($request_params['EventType']) { case '103': // 进入房间 if (empty($request_params['EventInfo']['UserId'])){ return $this->videoTrtcErrorReturn("缺少用户id"); } // 获取用户数据 $params = array(); $params['user_id'] = $request_params['EventInfo']['UserId']; $user = User::getOne($params); if (empty($user)){ return $this->videoTrtcErrorReturn("非法用户"); } if ($user['user_type'] != 1){ return $this->videoTrtcSuccessReturn(); } // 检测视频状态 if ($order_inquiry_video_record['video_status'] == 3 || $order_inquiry_video_record['video_status'] == 4){ // 已开始/结束通话,进入房间动作不做处理 return $this->videoTrtcSuccessReturn(); } // 修改视频状态 $params = array(); $params['records_id'] = $order_inquiry_video_record['records_id']; $data = array(); $data['video_status'] = 2; $res = OrderInquiryVideoRecord::edit($params,$data); if (!$res){ return $this->videoTrtcErrorReturn("修改视频状态失败"); } break; case '102': // 解散房间 // 检测视频状态 if ($order_inquiry_video_record['video_status'] == 4){ // 已结束通话,解散房间动作不做处理 return $this->videoTrtcSuccessReturn(); } // 修改视频状态 $params = array(); $params['records_id'] = $order_inquiry_video_record['records_id']; $data = array(); $data['video_status'] = 4; $data['stop_video_time'] = date('Y-m-d H:i:s',$request_params['EventInfo']['EventMsTs']); $res = OrderInquiryVideoRecord::edit($params,$data); if (!$res){ return $this->videoTrtcErrorReturn("修改视频状态失败"); } break; case '201': // 视频推流 // 检测视频状态 if ($order_inquiry_video_record['video_status'] == 4){ // 已结束通话,视频推流动作不做处理 return $this->videoTrtcSuccessReturn(); } if ($order_inquiry_video_record['video_status'] == 3){ // 已开始通话,视频推流动作不做处理 return $this->videoTrtcSuccessReturn(); } // 修改视频状态 $params = array(); $params['records_id'] = $order_inquiry_video_record['records_id']; $data = array(); $data['video_status'] = 3; $data['stop_video_time'] = date('Y-m-d H:i:s',$request_params['EventInfo']['EventMsTs']); $res = OrderInquiryVideoRecord::edit($params,$data); if (!$res){ return $this->videoTrtcErrorReturn("修改视频状态失败"); } break; case '203': // 音频推流 // 检测视频状态 if ($order_inquiry_video_record['video_status'] == 4){ // 已结束通话,音频推流动作不做处理 return $this->videoTrtcSuccessReturn(); } if ($order_inquiry_video_record['video_status'] == 3){ // 已开始通话,音频推流动作不做处理 return $this->videoTrtcSuccessReturn(); } // 修改视频状态 $params = array(); $params['records_id'] = $order_inquiry_video_record['records_id']; $data = array(); $data['video_status'] = 3; $data['stop_video_time'] = date('Y-m-d H:i:s',$request_params['EventInfo']['EventMsTs']); $res = OrderInquiryVideoRecord::edit($params,$data); if (!$res){ return $this->videoTrtcErrorReturn("修改视频状态失败"); } break; default: return $this->videoTrtcErrorReturn("未知事件"); } // 删除缓存 $redis->del($redis_key); }catch (\Throwable $e){ return $this->videoTrtcErrorReturn($e->getMessage()); } Log::getInstance("CallBackController-videoTrtcCallBack")->info("音视频回调-房间与媒体处理成功"); return $this->videoTrtcSuccessReturn(); } /** * 音视频返回错误响应 * @param string $message * @return ResponseInterface */ protected function videoTrtcErrorReturn(string $message): ResponseInterface { Log::getInstance("CallBackController-videoTrtcCallBack")->error($message); return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'code' => 0, 'ErrorInfo' => $message, ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * 音视频返回正确响应 * @return ResponseInterface */ protected function videoTrtcSuccessReturn(): ResponseInterface { return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'code' => 0, 'ErrorInfo' => "", ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * 音视频回调-云端录制 * @return ResponseInterface */ public function videoRecordingCallBack(): ResponseInterface { $request_params = $this->request->getBody()->getContents(); $SdkAppId = $this->request->header("SdkAppId"); $Sign = $this->request->header("Sign"); $Sign = stripslashes($Sign); try { Log::getInstance("CallBackController-videoRecordingCallBack")->info(json_encode($request_params, JSON_UNESCAPED_UNICODE)); if (empty($SdkAppId)) { return $this->videoRecordingErrorReturn("缺少SdkAppId字段"); } if (empty($Sign)) { return $this->videoRecordingErrorReturn("缺少签名字段"); } // 鉴定回调签名 $VideoSafe = new VideoSafe(); $result = $VideoSafe->validateSign($request_params,$Sign); if (!$result) { return $this->videoRecordingErrorReturn("回调签名不匹配"); } $request_params = json_decode($request_params,true); // 验证参数 if (!isset($request_params['EventGroupId'])){ return $this->videoRecordingErrorReturn("缺少回调事件组"); } if (empty($request_params['EventGroupId'])){ return $this->videoRecordingErrorReturn("回调事件组为空"); } if (!isset($request_params['EventType'])){ return $this->videoRecordingErrorReturn("缺少回调事件类型"); } if (empty($request_params['EventType'])){ return $this->videoRecordingErrorReturn("回调事件类型为空"); } if (!isset($request_params['EventInfo'])){ return $this->videoRecordingErrorReturn("缺少回调事件信息"); } if (empty($request_params['EventInfo'])){ return $this->videoRecordingErrorReturn("回调事件信息为空"); } if (!isset($request_params['EventInfo']['RoomId'])){ return $this->videoRecordingErrorReturn("缺少房间id"); } if (empty($request_params['EventInfo']['RoomId'])){ return $this->videoRecordingErrorReturn("房间id为空"); } // 排除数据 if ($request_params['EventGroupId'] != 3){ return $this->videoRecordingErrorReturn("回调地址推送错误"); } if (!in_array($request_params['EventType'],[311])){ return $this->videoRecordingSuccessReturn(); } if (!isset($request_params['EventInfo']['Payload'])){ return $this->videoRecordingErrorReturn("缺少有效载荷"); } if (empty($request_params['EventInfo']['Payload'])){ return $this->videoRecordingErrorReturn("有效载荷为空"); } if (!isset($request_params['EventInfo']['Payload']['Status'])){ return $this->videoRecordingErrorReturn("缺少录制状态"); } } catch (\Throwable $e) { // 验证失败 return $this->videoRecordingErrorReturn($e->getMessage()); } // 处理业务逻辑 Db::beginTransaction(); try { // 获取视频预约记录 $params = array(); $params['room_id'] = $request_params['EventInfo']['RoomId']; $order_inquiry_video_reservation = OrderInquiryVideoReservation::getLastOne($params); if (empty($order_inquiry_video_reservation)){ Db::rollBack(); return $this->videoRecordingErrorReturn("未查询到该房间号,此条数据不接收"); } // 获取视频记录 $params = array(); $params['room_id'] = $request_params['EventInfo']['RoomId']; $params['order_inquiry_id'] = $order_inquiry_video_reservation['order_inquiry_id']; $order_inquiry_video_record = OrderInquiryVideoRecord::getLastOne($params); if (empty($order_inquiry_video_record)){ Db::rollBack(); return $this->videoRecordingErrorReturn("缺少视频开启记录"); } if (!empty($order_inquiry_video_record['doctor_vod_path']) && !empty($order_inquiry_video_record['patient_vod_path'])){ // 已存在点播路径,此次请求无需处理 Db::rollBack(); return $this->videoRecordingSuccessReturn(); } // 检测缓存-只允许同时处理同一房间的一个请求,防止数据库冲突 $redis = $this->container->get(Redis::class); $redis_key = "videoRecordingCallBack_" . $request_params['EventInfo']['RoomId'] . $order_inquiry_video_reservation['patient_user_id']; $redis_value = $redis->get($redis_key); // 加入缓存 $redis->set($redis_key, $request_params['EventType'], 20); if (!empty($redis_value)){ // 事件正在处理,重复请求不处理 Db::rollBack(); return $this->videoRecordingSuccessReturn(); } // 处理业务逻辑 if (!isset($request_params['EventInfo']['Payload']['TencentVod'])){ Db::rollBack(); return $this->videoRecordingErrorReturn("缺少关键参数"); } if (empty($request_params['EventInfo']['Payload']['TencentVod'])){ Db::rollBack(); return $this->videoRecordingErrorReturn("缺少关键参数"); } if (!isset($request_params['EventInfo']['Payload']['TencentVod']['UserId'])){ Db::rollBack(); return $this->videoRecordingErrorReturn("缺少用户id参数"); } if (empty($request_params['EventInfo']['Payload']['TencentVod']['UserId'])){ Db::rollBack(); return $this->videoRecordingErrorReturn("缺少用户id参数"); } // 获取用户数据 $params = array(); $params['user_id'] = $request_params['EventInfo']['Payload']['TencentVod']['UserId']; $user = User::getOne($params); if (empty($user)){ Db::rollBack(); return $this->videoRecordingErrorReturn("非法用户"); } if ($request_params['EventInfo']['Payload']['Status'] == 0){ if (!isset($request_params['EventInfo']['Payload']['TencentVod']['VideoUrl'])){ Db::rollBack(); return $this->videoRecordingErrorReturn("缺少播放地址参数"); } if (empty($request_params['EventInfo']['Payload']['TencentVod']['VideoUrl'])){ Db::rollBack(); return $this->videoRecordingErrorReturn("缺少播放地址参数"); } // 修改视频状态 $params = array(); $params['records_id'] = $order_inquiry_video_record['records_id']; if ($user['user_type'] == 1){ $data = array(); $data['vod_path_patient'] = $request_params['EventInfo']['Payload']['TencentVod']['VideoUrl']; $data['vod_status_patient'] = 1; $res = OrderInquiryVideoRecord::edit($params,$data); if (!$res){ Db::rollBack(); return $this->videoRecordingErrorReturn("播放地址存储失败"); } }elseif($user['user_type'] == 2){ $data = array(); $data['vod_path_doctor'] = $request_params['EventInfo']['Payload']['TencentVod']['VideoUrl']; $data['vod_status_doctor'] = 1; $res = OrderInquiryVideoRecord::edit($params,$data); if (!$res){ Db::rollBack(); return $this->videoRecordingErrorReturn("播放地址存储失败"); } }else{ Db::rollBack(); return $this->videoRecordingErrorReturn("非法用户类型"); } }else{ // 录制上传失败 if (!isset($request_params['EventInfo']['Payload']['Errmsg'])){ Db::rollBack(); return $this->videoRecordingErrorReturn("录制上传失败但缺少错误描述"); } if (empty($request_params['EventInfo']['Payload']['Errmsg'])){ Db::rollBack(); return $this->videoRecordingErrorReturn("录制上传失败但错误描述为空"); } // 修改视频状态 $params = array(); $params['records_id'] = $order_inquiry_video_record['records_id']; $data = array(); if ($user['user_type'] == 1){ $data['vod_status_patient'] = 2; $data['vod_err_patient'] = $request_params['EventInfo']['Payload']['Errmsg']; }elseif($user['user_type'] == 2){ $data['vod_status_doctor'] = 2; $data['vod_err_doctor'] = $request_params['EventInfo']['Payload']['Errmsg']; }else{ Db::rollBack(); return $this->videoRecordingErrorReturn("非法用户类型"); } $res = OrderInquiryVideoRecord::edit($params,$data); if (!$res){ Db::rollBack(); return $this->videoRecordingErrorReturn("修改视频状态失败"); } } Db::commit(); // 删除缓存 $redis->del($redis_key); }catch (\Throwable $e){ Db::rollBack(); return $this->videoRecordingErrorReturn($e->getMessage()); } Log::getInstance("CallBackController-videoRecordingCallBack")->info("音视频回调-云端录制处理成功"); return $this->videoTrtcSuccessReturn(); } /** * 音视频回调-云端录制-返回错误响应 * @param string $message * @return ResponseInterface */ protected function videoRecordingErrorReturn(string $message): ResponseInterface { Log::getInstance("CallBackController-videoRecordingCallBack")->error($message); return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'code' => 0, 'ErrorInfo' => $message, ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * 音视频回调-云端录制-返回正确响应 * @return ResponseInterface */ protected function videoRecordingSuccessReturn(): ResponseInterface { return $this->response ->withStatus(200) ->withBody( new SwooleStream( strval( json_encode([ 'code' => 0, 'ErrorInfo' => "", ], JSON_UNESCAPED_UNICODE) ) ) ); } /** * 微信服务包退款回调 * @return ResponseInterface * @throws ContainerExceptionInterface * @throws NotFoundExceptionInterface * @throws \Throwable */ public function wxPayServiceRefundCallBack(): ResponseInterface { try { // 处理支付结果事件 $WechatPay = new WechatPay(1, 4); $app = $WechatPay->createApp(); $server = $app->getServer(); // 获取解密消息 $message = $server->getDecryptedMessage(); if (empty($message)) { Db::rollBack(); return $this->response->withStatus(500)->withBody(new SwooleStream(strval(json_encode(['code' => 'ERROR', 'message' => "回调数据为空"], JSON_UNESCAPED_UNICODE)))); } Log::getInstance("CallBack-wxPayServiceRefund")->info(json_encode($message->toArray(), JSON_UNESCAPED_UNICODE)); if (empty($message['out_trade_no'])) { Log::getInstance("CallBack-wxPayServiceRefund")->error("缺少外部订单号"); return $server->serve(); } } catch (\Exception $e) { // 验证失败 Log::getInstance("CallBack-wxPayServiceRefund")->error($e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Db::beginTransaction(); try { // 验证订单数据 $params = array(); $params['order_service_no'] = $message['out_trade_no']; $order_service_package = OrderServicePackage::getOne($params); if (empty($order_service_package)) { Db::rollBack(); Log::getInstance("CallBack-wxPayServiceRefund")->error("非法订单"); return $server->serve(); } // 验证订单状态 if ($order_service_package['order_service_status'] == 1) { // 订单状态(1:待支付 2:未开始 3:服务中 4:服务完成 5:服务取消) Db::rollBack(); Log::getInstance("CallBack-wxPayServiceRefund")->error("订单状态错误:当前为" . $order_service_package['order_service_status']); return $server->serve(); } // 验证订单退款状态 if ($order_service_package['refund_status'] == 3) { // 检测订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常) Db::rollBack(); Log::getInstance("CallBack-wxPayServiceRefund")->error("订单退款状态错误:当前为" . $order_service_package['refund_status']); return $server->serve(); } // 验证订单支付状态 if (in_array($order_service_package['pay_status'], [1, 3, 4, 5, 6, 7])) { // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) Db::rollBack(); Log::getInstance("CallBack-wxPayServiceRefund")->error("订单支付状态错误:当前为" . $order_service_package['pay_status']); return $server->serve(); } // 处理退款回调结果 $OrderService = new OrderService(); $OrderService->orderRefundResult($order_service_package['order_service_no'],$message['refund_status'],$message['success_time']); Db::commit(); } catch (\Exception $e) { // 验证失败 Db::rollBack(); Log::getInstance("CallBack-wxPayServiceRefund")->error("微信支付回调数据验证失败:" . $e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Log::getInstance("CallBack-wxPayServiceRefund")->info("微信退款回调处理成功"); return $server->serve(); } /** * 患者端服务包支付回调 * @return ResponseInterface * @throws \Throwable */ public function wxPayServiceSuccessCallBack(): ResponseInterface { try { // 处理支付结果事件 $WechatPay = new WechatPay(1, 4); $app = $WechatPay->createApp(); $server = $app->getServer(); // 获取解密消息 $message = $server->getDecryptedMessage(); if (empty($message)) { return $this->response->withStatus(500)->withBody(new SwooleStream(strval(json_encode(['code' => 'ERROR', 'message' => "问诊微信支付回调数据为空"], JSON_UNESCAPED_UNICODE)))); } Log::getInstance("CallBack-wxPayServiceSuccess")->info(json_encode($message->toArray(), JSON_UNESCAPED_UNICODE)); if (empty($message['out_trade_no'])) { Log::getInstance("CallBack-wxPayServiceSuccess")->error("缺少外部订单号"); return $server->serve(); } }catch (\Throwable $e){ // 验证失败 Log::getInstance("CallBack-wxPayServiceSuccess")->error($e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Db::beginTransaction(); try { // 查询订单 $params = array(); $params['order_service_no'] = $message['out_trade_no']; $order_service_package = OrderServicePackage::getOne($params); if (empty($order_service_package)) { Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("无订单数据"); return $server->serve(); } // 验证订单状态 if ($order_service_package['order_service_status'] != 1) { // 检测订单状态(1:待支付 2:待绑定 3:检测中 4:检测完成 5:已取消) Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("检测微信支付回调数据处理失败,订单状态当前为" . $order_service_package['order_service_status']); return $server->serve(); } // 处理问诊类型 if ($order_service_package['order_service_type'] == 1) { $inquiry_mode = 8; } else { $inquiry_mode = 9; } // 支付状态无需验证,如第一次支付失败,会修改支付状态,再次支付时,会出现验证不通过的情况 // 处理支付状态 if ($message['trade_state'] == "SUCCESS") { // 支付成功 $pay_status = 2; $pay_time = date('Y-m-d H:i:s', strtotime($message['success_time']));// 支付时间 $order_service_status = 2;// 2:未开始 if (empty($message['amount'])){ Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("无支付金额"); return $this->wxPayErrorReturn("无支付金额"); } } elseif ($message['trade_state'] == "CLOSED") { // 已关闭 $pay_status = 6; } elseif ($message['trade_state'] == "REVOKED") { // 已撤销(付款码支付) $pay_status = 7; } elseif ($message['trade_state'] == "USERPAYING") { // 用户支付中(付款码支付) $pay_status = 3; } elseif ($message['trade_state'] == "PAYERROR") { // 支付失败(其他原因,如银行返回失败) $pay_status = 4; } else { Db::rollBack(); return $server->serve(); } $data = array(); $data['pay_status'] = $pay_status; if (isset($order_service_status)){ $data['order_service_status'] = $order_service_status; } if (isset($pay_time)){ $data['pay_time'] = $pay_time; } $data['escrow_trade_no'] = $message['transaction_id']; $data['updated_at'] = date('Y-m-d H:i:s', time()); $params = array(); $params['order_service_id'] = $order_service_package['order_service_id']; OrderServicePackage::edit($params, $data); // 修改订单表 $data = array(); $data['pay_status'] = $pay_status; if (isset($pay_time)){ $data['pay_time'] = $pay_time; } $data['escrow_trade_no'] = $message['transaction_id']; $data['updated_at'] = date('Y-m-d H:i:s', time()); $params = array(); $params['order_no'] = $order_service_package['order_service_no']; Order::edit($params,$data); // 获取检测病例数据 $params = array(); $params['order_service_id'] = $order_service_package['order_service_id']; $order_service_package_case = OrderServicePackageCase::getOne($params); if (empty($order_service_package_case)) { Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("问诊病例数据错误"); return $server->serve(); } $order_service_package_case = $order_service_package_case->toArray(); // 获取患者家庭成员信息表-健康情况 $params = array(); $params['family_id'] = $order_service_package['family_id']; $patient_family_health = PatientFamilyHealth::getOne($params); // 获取患者家庭成员信息表-个人情况 $params = array(); $params['family_id'] = $order_service_package['family_id']; $patient_family_personal = PatientFamilyPersonal::getOne($params); // 获取家庭成员是否存在 $params = array(); $params['family_id'] = $order_service_package['family_id']; $params['patient_id'] = $order_service_package['patient_id']; $patient_family = PatientFamily::getOne($params); if (empty($patient_family)) { Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("家庭成员数据错误"); return $server->serve(); } // 沟通次数,沟通时长 $params = array(); $params['inquiry_type'] = 1; $params['inquiry_mode'] = $inquiry_mode; $system_inquiry_config = SystemInquiryConfig::getOne($params); if (empty($system_inquiry_config)) { Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("系统问诊配置错误"); return $server->serve(); } $generator = $this->container->get(IdGeneratorInterface::class); // 生成订单表 $data = array(); $data['user_id'] = $order_service_package['user_id']; $data['patient_id'] = $order_service_package['patient_id']; $data['doctor_id'] = $order_service_package['doctor_id']; if ($order_service_package['order_service_type'] == 1){ $data['order_type'] = 5; // 订单类型(1:问诊订单 2:药品订单 3:检测订单 4:随访包订单 5:健康包订单) }else{ $data['order_type'] = 4; // 订单类型(1:问诊订单 2:药品订单 3:检测订单 4:随访包订单 5:健康包订单) } $data['inquiry_pay_channel'] = 3; // 支付渠道(1:小程序支付 2:微信扫码支付) $data['pay_status'] = 2; // 1:待支付 $data['order_no'] = "I" . $generator->generate(); // 订单编号 $data['amount_total'] = 0; // 订单金额 $data['coupon_amount_total'] = 0; // 优惠卷总金额 $data['payment_amount_total'] = 0; // 实际付款金额 $order = Order::addOrder($data); if (empty($order)) { Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("订单创建失败"); return $server->serve(); } // 创建问诊订单 $data = array(); $data['user_id'] = $order_service_package['user_id']; $data['patient_id'] = $order_service_package['patient_id']; $data['doctor_id'] = $order_service_package['doctor_id']; $data['family_id'] = $order_service_package['family_id']; $data['inquiry_type'] = 1; // 订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药 5:检测) $data['inquiry_mode'] = $inquiry_mode; // 接诊方式(1:图文 2:视频 3:语音 4:电话 5:会员 6:疑难会诊 7:附赠 8:健康包 9:随访包) $data['inquiry_status'] = 3; // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消) $data['inquiry_pay_channel'] = 3; // 支付渠道(1:小程序支付 2:微信扫码支付 3:模拟支付) $data['inquiry_pay_status'] = 2; // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) $data['inquiry_no'] = $order['order_no'];// 订单编号 $data['escrow_trade_no'] = "GD" . $generator->generate(); // 第三方支付流水号 $data['amount_total'] = 0;// 订单金额 $data['coupon_amount_total'] = 0;// 优惠卷总金额 $data['payment_amount_total'] = 0;// 实际付款金额 $data['times_number'] = $system_inquiry_config['times_number'];// 沟通次数(0为不限制次数) $data['duration'] = $system_inquiry_config['duration'];// 沟通时长(分钟,0为不限制时长) $data['pay_time'] = date('Y-m-d H:i:s', time());// 支付时间 $data['patient_name'] = $patient_family['card_name'];// 患者姓名-就诊人 $data['patient_name_mask'] = $patient_family['card_name_mask'];// 患者姓名-就诊人(掩码) $data['patient_sex'] = $patient_family['sex'];// 患者性别-就诊人(0:未知 1:男 2:女) $data['patient_age'] = $patient_family['age'];// 患者年龄-就诊人 $order_inquiry = OrderInquiry::addOrderInquiry($data); if (empty($order_inquiry)) { Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("订单创建失败"); return $server->serve(); } // 增加患者问诊病例 $data = array(); $data['user_id'] = $order_service_package['user_id']; $data['patient_id'] = $order_service_package['patient_id']; $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];// 订单-问诊id $data['family_id'] = $patient_family['family_id']; // 家庭成员id $data['relation'] = $patient_family['relation']; // 与患者关系(1:本人 2:父母 3:爱人 4:子女 5:亲戚 6:其他 ) $data['name'] = $patient_family['card_name']; // 患者名称 $data['sex'] = $patient_family['sex']; // 患者性别(0:未知 1:男 2:女) $data['disease_class_id'] = $order_service_package_case['disease_class_id']; // 疾病分类id-系统 $data['disease_class_name'] = $order_service_package_case['disease_class_name']; // 疾病名称-系统 $data['diagnosis_date'] = $order_service_package_case['diagnosis_date']; // 确诊日期 $data['disease_desc'] = $order_service_package_case['disease_desc']; // 病情描述(主诉) $data['diagnose_images'] = $order_service_package_case['diagnose_images'] ?? ""; // 复诊凭证(多个使用逗号分隔) if ($patient_family['age'] != null) { $data['age'] = getIdCardAge($patient_family['id_number']);// 患者年龄 } // 身高(cm) if ($patient_family['height'] != null) { $data['height'] = $patient_family['height']; } // 体重(kg) if ($patient_family['weight'] != null) { $data['weight'] = $patient_family['weight']; } // 职业id-职业名称 if ($patient_family['job_id'] != null) { $data['job_id'] = $patient_family['job_id']; if ($patient_family['job_name'] != null) { $data['job_name'] = $patient_family['job_name']; } } // 民族id-民族名称 if ($patient_family['nation_id'] != null) { $data['nation_id'] = $patient_family['nation_id']; if ($patient_family['nation_name'] != null) { $data['nation_name'] = $patient_family['nation_name']; } } // 婚姻状况 if ($patient_family['marital_status'] != null) { $data['marital_status'] = $patient_family['marital_status']; } // 家庭成员-健康情况 if (!empty($patient_family_health)) { if ($patient_family_health['diagnosis_hospital'] != null) { $data['diagnosis_hospital'] = $patient_family_health['diagnosis_hospital']; // 确诊医院 } if ($patient_family_health['is_take_medicine'] != null) { $data['is_take_medicine'] = $patient_family_health['is_take_medicine']; // 正在服药 if ($patient_family_health['drugs_name'] != null) { $data['drugs_name'] = $patient_family_health['drugs_name']; // 正在服药名称 } } } // 家庭成员-个人情况 if (!empty($patient_family_personal)) { if ($patient_family_personal['drink_wine_status'] != null) { $data['drink_wine_status'] = $patient_family_personal['drink_wine_status']; // 饮酒状态 } if ($patient_family_personal['smoke_status'] != null) { $data['smoke_status'] = $patient_family_personal['smoke_status']; // 吸烟状态 } if ($patient_family_personal['chemical_compound_status'] != null) { $data['chemical_compound_status'] = $patient_family_personal['chemical_compound_status']; // 化合物状态 if ($patient_family_personal['chemical_compound_describe'] != null) { $data['chemical_compound_describe'] = $patient_family_personal['chemical_compound_describe']; // 化合物描述 } } if ($patient_family_personal['is_operation'] != null) { $data['is_operation'] = $patient_family_personal['is_operation']; // 是否存在手术 if ($patient_family_personal['operation'] != null) { $data['operation'] = $patient_family_personal['operation']; // 手术描述 } } } // 过敏史 if (array_key_exists("is_allergy_history", $order_service_package_case)) { if ($order_service_package_case['is_allergy_history'] !== null) { $data['is_allergy_history'] = $order_service_package_case['is_allergy_history']; // 是否存在过敏史(0:否 1:是) if ($order_service_package_case['allergy_history'] != "") { $data['allergy_history'] = $order_service_package_case['allergy_history']; // 过敏史描述 } } } // 家族病史 if (array_key_exists("is_family_history", $order_service_package_case)) { if ($order_service_package_case['is_family_history'] !== null) { $data['is_family_history'] = $order_service_package_case['is_family_history']; // 是否存在家族病史(0:否 1:是) if ($order_service_package_case['family_history'] != "") { $data['family_history'] = $order_service_package_case['family_history']; // 家族病史描述 } } } // 是否备孕、妊娠、哺乳期(0:否 1:是) if (array_key_exists("is_pregnant", $order_service_package_case)) { if ($order_service_package_case['is_pregnant'] !== null) { $data['is_pregnant'] = $order_service_package_case['is_pregnant']; // 是否备孕、妊娠、哺乳期(0:否 1:是) } } $order_inquiry_case = OrderInquiryCase::addOrderInquiryCase($data); if (empty($order_inquiry_case)) { Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("订单创建失败"); return $server->serve(); } // 加入未接诊取消订单延迟队列 $time = 60 * 60 * 24; if (\Hyperf\Config\config('app_env') == "dev"){ $time = 60 * 10; } $data = array(); $data['order_inquiry_id'] = $order_inquiry['order_inquiry_id']; $data['order_no'] = $order_inquiry['inquiry_no']; $message = new CancelUnInquiryOrdersDelayDirectProducer($data); $message->setDelayMs(1000 * $time); $producer = $this->container->get(Producer::class); $res = $producer->produce($message); if (!$res) { Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("订单创建失败"); return $server->serve(); } Db::commit(); } catch (\Exception $e) { // 验证失败 Db::rollBack(); Log::getInstance("CallBack-wxPayServiceSuccess")->error("问诊微信支付回调数据处理失败:" . $e->getMessage()); return $this->wxPayErrorReturn($e->getMessage()); } Log::getInstance("CallBack-wxPayServiceSuccess")->info("检测微信支付回调处理成功"); return $server->serve(); } }