where([ 'user_id' =>\Yii::$app->user->identity->getId(), 'id' => $order_id ])->one(); if(!$prescription || $prescription->cancel_status){ throw new Exception('订单不存在'); } switch($prescription->is_pay){ case 0://未支付 $t = \Yii::$app->db->beginTransaction(); try { $prescription->cancel_status = 1; $prescription->cancel_time = time(); $prescription->cancel_remark = '主动取消订单'; $prescription->saveOrFail(); $event = new OrderEvent([ 'order' => $prescription, ]); \Yii::$app->trigger(Prescription::AUTO_EXPIRE, $event); $t->commit(); return []; } catch (\Exception $exception) { $t->rollBack(); throw $exception; } case 1://已支付 $config = \Yii::$app->params; $orderForbiddenRefundTime = isset($config['product_order']['forbidden_refund_time']) ? $config['product_order']['forbidden_refund_time'] :3600*24*7; if ($prescription->prescription_type==1 || $prescription->prescription_type==3 ){ throw new Exception('中药饮片和配方颗粒禁止退款'); } if ($prescription->prescription_type==2 &&$prescription->prescription_type==4 ){ if (time()-$prescription->pay_time>=120){ throw new Exception('西药一周之后禁止退款'); } } $t = \Yii::$app->db->beginTransaction(); try { //生成记录 $prescripOrderRefund = new PrescripOrderRefund(); $prescripOrderRefund->user_id = $prescription->user_id; $prescripOrderRefund->order_id = $prescription->id; $prescripOrderRefund->refund_no = FuncHelper::generate_order_no('RF'); $prescripOrderRefund->refund_price = $prescription->total_pay_price; $prescripOrderRefund->remark = '主动取消订单'; $prescripOrderRefund->saveOrFail(); //取消状态 $prescription->cancel_status = 1; $prescription->cancel_time = time(); $prescription->cancel_remark = '主动取消订单'; //退款状态 $prescription->refund_status = 1; $prescription->refund_time = time(); $prescription->saveOrFail(); //退款操作 $this->refundMoney($prescripOrderRefund); //可能报错 无效的订单号 $t->commit(); }catch (Exception $exception){ $t->rollBack(); throw $exception; } break; } } public function refundMoney($prescripOrderRefund) { $orderNo = $prescripOrderRefund->order->order_no; $prescription = Prescription::findOne([ 'order_no' => $orderNo, 'is_pay' => 1 ]); $paymentPrescripOrder = PaymentPrescripOrder::findOne([ 'order_no' => $orderNo, 'is_pay' => 1 ]); if (!$prescription || !$paymentPrescripOrder) { throw new Exception('无效的订单号'); } $price = $prescripOrderRefund->refund_price; if(bccomp($paymentPrescripOrder->amount,$price,2)==-1){ throw new Exception('退款金额大于可退款金额'); } $transaction = \Yii::$app->db->beginTransaction(); try { $paymentPrescripRefund = new PaymentPrescripRefund(); $paymentPrescripRefund->refund_no = $prescripOrderRefund->refund_no; $paymentPrescripRefund->amount = $price; $paymentPrescripRefund->is_pay = 0; $paymentPrescripRefund->pay_type = 0; $paymentPrescripRefund->created_at = time(); $paymentPrescripRefund->saveOrFail(); if(bccomp($price,0,2)<=0) { $paymentPrescripRefund->is_pay = 1; $paymentPrescripRefund->save(); $prescripOrderRefund->is_refund = 1; $prescripOrderRefund->refund_time = time(); $prescripOrderRefund->save(); }else{ if(\Yii::$app instanceof \yii\web\Application){ $notifyUrl = \Yii::$app->request->hostInfo."/member/v1/callback/refund-notify/"; }else{ //如果是job中调用的 $notifyUrl = \Yii::$app->getHostInfo()."/member/v1/callback/refund-notify/"; } $order_amount = bcmul($paymentPrescripOrder->amount,100,0); $refund_amount = bcmul($price,100,0); $result = WechatService::getInstance()->payment->refund->byTransactionId($paymentPrescripOrder->transaction_id, $paymentPrescripRefund->refund_no,$order_amount, $refund_amount, [ 'refund_desc' => '订单取消退款', 'notify_url' => $notifyUrl ]); if($result['return_code']!='SUCCESS' || $result['result_code']!='SUCCESS'){ $error = isset($result['err_code_des']) ? $result['err_code_des'] : $result['return_msg']; throw new Exception($error); } //其他状态变更在回调 } $transaction->commit(); return []; }catch (\Exception $exception){ $transaction->rollBack(); throw $exception; } } }