response->format = Response::FORMAT_RAW; Yii::$app->response->formatters = []; $response = WechatService::getInstance()->payment->handlePaidNotify(function ($notify, $fail) { /** * {"appid":"wx36bbb299d88c6127","bank_type":"ZJRCUB_DEBIT","cash_fee":"1","fee_type":"CNY","is_subscribe":"N","mch_id":"1496340382","nonce_str":"637ed1617f5f3","openid":"o88xX5Z-mpVWWV-yw2X6MefDIUqE","out_trade_no":"PY20221124100521434224","result_code":"SUCCESS","return_code":"SUCCESS","sign":"FAB5D4E3AD785DBF7D6FB1FE0E1A897E","time_end":"20221124100606","total_fee":"1","trade_type":"JSAPI","transaction_id":"4200001675202211242752421487"} */ //记录回调信息 $callback = new Callback(); $callback->content = json_encode($notify); $callback->type = 'order'; $callback->save(); if ($notify['return_code'] == 'SUCCESS' && $notify['result_code'] == 'SUCCESS') { $t = \Yii::$app->db->beginTransaction(); try { $out_trade_no = $notify['out_trade_no']; $paymentProductOrder = PaymentProductOrder::find()->where([ 'pay_order_no' => $out_trade_no ])->one(); if ($paymentProductOrder) { $data['order_no'] = $paymentProductOrder->order_no; $data['transaction_id'] = $notify['transaction_id']; $data['pay_order_no'] = $out_trade_no; $data['pay_type'] = 1; $productOrderPayForm = new ProductOrderSubmitForm(); $order = $productOrderPayForm->paid($data); $order_type = 1; } else { $PaymentRegister = PaymentRegister::find()->where([ 'pay_order_no' => $out_trade_no ])->one(); if (!$PaymentRegister) { throw new Exception('订单不存在'); } $data['order_no'] = $PaymentRegister->order_no; $data['transaction_id'] = $notify['transaction_id']; $data['pay_type'] = 1; $RegisterSubmitForm = new RegisterSubmitForm(); $order = $RegisterSubmitForm->paid($data); $order_type = 2; } // 增加流水记录 $fundWater = new FundWater(); $fundWater->store_id = $order->store_id; // 入账 $fundWater->type = 'enter'; // 入账 $fundWater->order_type = $order_type; $fundWater->order_id = $order->id; $fundWater->user_id = $order->user_id; $fundWater->service_user_id = $order_type == 1 ? $order->su_id : $order->service_user_id; $fundWater->order_no = $order->order_no; $fundWater->price = $order_type == 1 ? $order->total_pay_price : $order->price; $fundWater->pay_type = 1; //微信 $fundWater->saveOrFail(); //回调处理成功 $callback->status = 1; $callback->save(); $t->commit(); return true; } catch (\Exception $exception) { $t->rollBack(); $callback->message = $exception->getMessage(); $callback->save(); return $fail('通信失败,请稍后再通知我'); } } }); // $response = unserialize('O:41:"Symfony\\Component\\HttpFoundation\\Response":6:{s:7:"headers";O:50:"Symfony\\Component\\HttpFoundation\\ResponseHeaderBag":5:{s:23:"' . "\0" . '*' . "\0" . 'computedCacheControl";a:1:{s:8:"no-cache";b:1;}s:10:"' . "\0" . '*' . "\0" . 'cookies";a:0:{}s:14:"' . "\0" . '*' . "\0" . 'headerNames";a:2:{s:13:"cache-control";s:13:"Cache-Control";s:4:"date";s:4:"Date";}s:10:"' . "\0" . '*' . "\0" . 'headers";a:2:{s:13:"cache-control";a:1:{i:0;s:8:"no-cache";}s:4:"date";a:1:{i:0;s:29:"Wed, 09 Mar 2022 02:19:18 GMT";}}s:15:"' . "\0" . '*' . "\0" . 'cacheControl";a:0:{}}s:10:"' . "\0" . '*' . "\0" . 'content";s:96:"";s:10:"' . "\0" . '*' . "\0" . 'version";s:3:"1.0";s:13:"' . "\0" . '*' . "\0" . 'statusCode";i:200;s:13:"' . "\0" . '*' . "\0" . 'statusText";s:2:"OK";s:10:"' . "\0" . '*' . "\0" . 'charset";N;}'); return $response; } /** * 退款回调 */ public function actionRefundNotify() { Yii::$app->response->format = Response::FORMAT_RAW; Yii::$app->response->formatters = []; $response = WechatService::getInstance()->payment->handleRefundedNotify(function ($message, $reqInfo, $fail) { // 其中 $message['req_info'] 获取到的是加密信息 // $reqInfo 为 message['req_info'] 解密后的信息 // 你的业务逻辑... /** * {"cash_refund_fee":"1","out_refund_no":"RF20221124103051025400","out_trade_no":"PY20221124100521434224","refund_account":"REFUND_SOURCE_RECHARGE_FUNDS","refund_fee":"1","refund_id":"50300503882022112427569050043","refund_recv_accout":"\u6d59\u6c5f\u519c\u4fe1\u501f\u8bb0\u53617865","refund_request_source":"API","refund_status":"SUCCESS","settlement_refund_fee":"1","settlement_total_fee":"1","success_time":"2022-11-24 10:31:00","total_fee":"1","transaction_id":"4200001675202211242752421487"} */ //记录回调信息 $callback = new Callback(); $callback->content = json_encode($reqInfo); $callback->type = 'refund'; $callback->save(); $t = \Yii::$app->db->beginTransaction(); try { $transaction_id = $reqInfo['transaction_id']; $out_refund_no = $reqInfo['out_refund_no']; $paymentProductOrder = PaymentProductOrder::find()->where([ 'transaction_id' => $transaction_id, ])->one(); if ($paymentProductOrder) { if ($paymentProductOrder->is_pay != 1) { throw new Exception('支付订单不存在'); } $order = ProductOrder::find()->where([ 'order_no' => $paymentProductOrder->order_no, ])->with('prescription')->one(); if (!$order || $order->is_pay != 1) { throw new Exception('订单不存在'); } $order_type = 1; $refund = ProductOrderRefund::find()->where(['refund_no' => $out_refund_no])->one();//退款订单 $payment_refund = PaymentProductRefund::find()->where(['refund_no' => $out_refund_no])->one(); } else { $PaymentRegister = PaymentRegister::find()->where([ 'transaction_id' => $transaction_id ])->one(); if (!$PaymentRegister || $PaymentRegister->is_pay != 1) { throw new \yii\db\Exception('支付订单不存在'); } $order = Register::find()->where([ 'order_no' => $PaymentRegister->order_no, ])->one(); if (!$order || $order->is_pay != 1) { throw new Exception('订单不存在'); } $order_type = 2; $refund = RegisterRefund::find()->where(['refund_no' => $out_refund_no])->one();//退款订单 $payment_refund = PaymentRegisterRefund::find()->where(['refund_no' => $out_refund_no])->one(); } if (!$refund || !$payment_refund) { throw new Exception('退款订单不存在'); } if ($reqInfo['refund_status'] == 'SUCCESS') { if ($order_type == 1) { $order->refund_status = 3;//已退款 $order->status = ProductOrderEnum::REFUND;//已退款 $order->refund_time = time(); $order->save(); if ($order->is_online) { //平台订单状态同步 \Yii::$app->queue->delay(0)->push(new ProductOrderSyncPlatformJob([ 'orderId' => $order->id, 'status' => 3 ])); } } $refund->is_refund = 1; $refund->refund_time = date('Y-m-d H:i:s', strtotime($reqInfo['success_time'])); $refund->save(); $payment_refund->is_pay = 1; $payment_refund->pay_type = 1; $payment_refund->save(); } else { $refund->is_refund = -1; $refund->save(); $payment_refund->is_pay = -1; $payment_refund->save(); } // 增加流水记录 $fundWater = new FundWater();//出账 $fundWater->store_id = $order->store_id; $fundWater->order_type = $order_type; $fundWater->type = 'refund'; // 出账 $fundWater->order_id = $order->id; $fundWater->user_id = $order->user_id; $fundWater->service_user_id = $order_type == 1 ? $order->su_id : $order->service_user_id; $fundWater->refund_no = $refund->refund_no; $fundWater->price = $order_type == 1 ? $order->total_pay_price : $order->price; $fundWater->pay_type = 1; //微信 $fundWater->saveOrFail(); $callback->status = 1; $callback->save(); $t->commit(); return true; // 返回 true 告诉微信“我已处理完成” // 或返回错误原因 $fail('参数格式校验错误'); } catch (\Exception $exception) { $t->rollBack(); $callback->message = $exception->getMessage(); $callback->save(); $fail($exception->getMessage()); } }); return $response; } /** * 阿里oss直传回调 */ public function actionUploadNotify() { // 1.获取OSS的签名header和公钥url header $headers = Yii::$app->request->getHeaders(); $authorizationBase64 = ""; $pubKeyUrlBase64 = ""; if (isset($headers['authorization'])) { $authorizationBase64 = $headers['authorization']; } else { if (isset($_SERVER['HTTP_AUTHORIZATION'])) { $authorizationBase64 = $_SERVER['HTTP_AUTHORIZATION']; } } if (isset($headers['x-oss-pub-key-url'])) { $pubKeyUrlBase64 = $headers['x-oss-pub-key-url']; } else { if (isset($_SERVER['HTTP_X_OSS_PUB_KEY_URL'])) { $pubKeyUrlBase64 = $_SERVER['HTTP_X_OSS_PUB_KEY_URL']; } } if ($authorizationBase64 == '' || $pubKeyUrlBase64 == '') { throw new Exception('参数异常'); } // 2.获取OSS的签名 $authorization = base64_decode($authorizationBase64); // 4.获取回调body $body = file_get_contents('php://input'); // 5.拼接待签名字符串 $authStr = ''; $path = $_SERVER['REQUEST_URI']; $pos = strpos($path, '?'); if ($pos === false) { $authStr = urldecode($path) . "\n" . $body; } else { $authStr = urldecode(substr($path, 0, $pos)) . substr($path, $pos, strlen($path) - $pos) . "\n" . $body; } // 3.获取公钥 $pubKey = (new UploadService())->getPublicKey($pubKeyUrlBase64); if ($pubKey == "") { throw new Exception('公钥异常'); } // 6.验证签名 $ok = openssl_verify($authStr, $authorization, $pubKey, OPENSSL_ALGO_MD5); if (!$ok) { throw new Exception('签名异常'); } $data = (new UploadService())->getBody($body); return $data; } // 互医订单同步 public function actionPlatformNotify() { Yii::$app->response->format = Response::FORMAT_RAW; $content = file_get_contents('php://input'); $callback = new Callback(); $callback->content = $content; $callback->type = 'platform_notify'; $callback->save(); $t = \Yii::$app->db->beginTransaction(); try { $data = json_decode($content, true); $config = \Yii::$app->params; switch ($data['type']) { case 'order_create'://订单创建 $sign = md5($data['order']['order_no'] . $data['time'] . $config['platform']['token'] . $data['type']); if ($sign != $data['sign']) { throw new Exception('sign不匹配'); } $isExist = ProductOrder::find()->where(['sync_order_no' => $data['order']['order_no'], 'is_online' => 1])->one(); if ($isExist) { throw new Exception('产品订单已存在'); } $userPatient = UserPatient::findOne([ 'user_id' => $data['order']['user_id'], 'id_card' => $data['order']['patient']['id_card'], 'is_delete' => 0 ]); $storeUser = StoreUser::find()->where([ 'user_id' => $data['order']['user_id'], 'is_online' => 1 ])->one(); $repice = $data['order']['recipe']; $prescription_type = $data['order']['prescription_type']; $priceTotal = $data['order']['total_price']; foreach ($data['order']['goods'] as $v) { $drug = Drug::find()->alias('d')->where(['d.id' => $v['id']])->joinWith('drugStoreDrug')->one(); if (!$drug) { throw new Exception('基础药品不存在:' . $v['id']); } } $is_decoct = $data['order']['decoct']; $process_price = 0; $dosage = $data['order']['dosage']; $process_rule_id = 0; $process_rule = ''; $process_rule_note = ''; if ($prescription_type == 1 || $prescription_type == 3) { //中药 $ids = array_column($data['order']['goods'], 'id'); $medicine = ChineseMedicine::find()->select('id,drug_id,name,order,unit,number,price,drug_number,buy_price')->with(['unit', 'useWay'])->where(['in', 'id', $ids])->asArray()->all(); // $price = 0; // $totalNum = 0; // foreach ($medicine as $value){ // $drugNumber = (int) $value['number'] * (int) $dosage; // $totalNum += $drugNumber; // $price+=$value['number'] * $value['price'] * $dosage; // } if ($is_decoct == 1) { $process_rule_id = 6; $processRule = ProcessRule::find()->where(['id' => 6])->one(); $process_rule = '加工方式:汤剂-浓煎-' . $data['order']['volume'] . ',' . $processRule->price . '元/,共' . $dosage . '贴'; $process_price = $processRule->price * $dosage; $priceTotal += $process_price; } } if ($prescription_type == 1) { $prescription_no = 'ZY' . rand(111111, 999999) . time(); } elseif ($prescription_type == 2) { $prescription_no = 'XY' . rand(111111, 999999) . time(); } else { $prescription_no = 'GY' . rand(111111, 999999) . time(); } $prescription_content['prescription_no'] = $prescription_no; $prescription_content['repice'] = $data['order']['recipe']; $prescription_content['created_at'] = date('Y-m-d', time()); $prescription_content['doctor_order'] = $data['order']['doctor_order']; $prescription_content['clinical_diagnose'] = $data['order']['clinical_diagnose']; $prescription_content['category'] = '自费'; $prescription_content['patient'] = $userPatient; $prescription_content['patient']['age'] = FuncHelper::getAgeFromIdNo($userPatient->id_card); $prescription_content['doctor'] = DoctorInfo::find()->select('su_id,name,depart_id,title_id')->where(['su_id' => $data['order']['doctor_id']])->with(['depart', 'title'])->asArray()->one(); $prescription_content['total_pay_price'] = $priceTotal; $prescription = new Prescription(); $prescription->store_id = $storeUser->store_id ?? 11001; $prescription->register_id = 0; $prescription->prescription_no = $prescription_no; $prescription->online_prescription_no = $data['order']['prescription_no']; $prescription->su_id = $data['order']['doctor_id']; $prescription->user_id = $userPatient->user_id; $prescription->up_id = $userPatient->id; $prescription->status = 0; $prescription->type = 1;//普通方 $prescription->is_online = 1; $prescription->content = Json::encode($prescription_content); $prescription->prescription_type = $prescription_type; $prescription->category = 1; $prescription->process_rule_id = $process_rule_id; $prescription->process_rule = $process_rule; $prescription->process_rule_note = $process_rule_note; $over_time = \Yii::$app->params['prescription']['over_time']; $doctor_order = []; if (date('H') >= 16) { $doctor_order[] = '该处方有效期延长为三天内有效'; $over_time = 72 * 3600; } if ($repice[0]['dosage'] > 7) { $doctor_order[] = '患者需长期使用此药,开具超七天用量'; } $doctor_order[] = $data['order']['doctor_order']; $prescription->valid_hours = $over_time / 3600; $prescription->doctor_order = implode('|', $doctor_order); $prescription->clinical_diagnose = $data['order']['clinical_diagnose']; $prescription->total_pay_price = $priceTotal; $prescription->saveOrFail(); //获取支付方式配置 $payConfig = PayConfig::findOne(['status' => 1, 'current_use' => 1]); $productOrder = new ProductOrder(); $productOrder->store_id = $storeUser->store_id ?? 11001; $productOrder->is_online = 1; $productOrder->online_prescription_status = 0; $productOrder->dosage = isset($data['order']['dosage']) ? $data['order']['dosage'] : 0; $productOrder->su_id = $data['order']['doctor_id']; $productOrder->user_id = $data['order']['user_id']; $productOrder->up_id = $userPatient->id ?? 0; $productOrder->order_no = Carbon::now()->format('YmdHis') . rand(10000, 99999) . rand(10000, 99999); $productOrder->sync_order_no = $data['order']['order_no']; $productOrder->order_type = 2; //商城订单 $productOrder->prescription_type = $data['order']['prescription_type']; $productOrder->p_id = $prescription->id; $productOrder->status = 0; $productOrder->items_price = $data['order']['total_price']; $productOrder->process_price = $process_price; $productOrder->trans_expenses = 0; $productOrder->type = $payConfig->pay_type ?? 2;//1微信 2易票联 $totalPayPrice = $priceTotal; $userAddress = Address::find()->select('id,name,mobile,province,region,detail_address')->where(['user_id' => $data['order']['user_id']])->orderBy('is_default DESC')->asArray()->all(); if ($userAddress) { $productOrder->address_id = $userAddress[0]['id']; $productOrder->address = Json::encode($userAddress[0]); $productOrder->express_name = $userAddress[0]['name']; $productOrder->express_mobile = $userAddress[0]['mobile']; $productOrder->express_region = $userAddress[0]['region']; $productOrder->express_address = $userAddress[0]['detail_address']; $region = Region::find()->where(['name' => $userAddress[0]['province']])->one(); $productOrder->trans_expenses = $region->express_fee; $totalPayPrice = $totalPayPrice + $region->express_fee; } $productOrder->total_pay_price = $totalPayPrice; $productOrder->saveOrFail(); $market_price = '0'; foreach ($data['order']['goods'] as $v) { $drug = Drug::find()->alias('d')->where(['d.id' => $v['id']])->joinWith('drugStoreDrug')->one(); if (!$drug) { throw new Exception('基础药品不存在:' . $v['id']); } $item = new ProductOrderItems(); $item->product_order_id = $productOrder->id; $item->drug_id = $drug->id; $item->drug_image = $drug->image; $item->number = $v['number']; $item->type = $drug->type; $item->drug_no = $drug->drug_number; $item->price = $drug->drugStoreDrug->price; $item->buy_price = $drug->drugStoreDrug->market_price; $item->drug_name = $drug->drug_name; $item->small_info = $drug->small_info; $item->saveOrFail(); $itemMarketPrice = bcmul($v['number'],$drug->drugStoreDrug->market_price,2); $market_price = bcadd($market_price,$itemMarketPrice,2); } $productOrder->market_price = $market_price; $productOrder->saveOrFail(); //生成系统消息 $SystemNotice = new SystemNotice(); $SystemNotice->store_id = $storeUser->store_id ?? 11001; $SystemNotice->content = '您有一条在线问诊流转处方,请及时处理'; $SystemNotice->data = $prescription->id; $SystemNotice->base_type = SystemNoticeTypeEnum::ONLINE_PRESCRIPTION; $SystemNotice->scene_type = 2;//用户端 $SystemNotice->user_id = $data['order']['doctor_id']; $SystemNotice->notice_at = date('Y-m-d H:i:s', time()); $SystemNotice->saveOrFail(); //触发订单创建事件 $event = new ProductOrderEvent(); $event->order = $productOrder; $event->sender = $this; \Yii::$app->trigger(ProductOrder::EVENT_CREATED, $event); break; case 'prescription_pass'://处方通过 $sign = md5($data['order']['order_no'] . $data['time'] . $config['platform']['token'] . $data['type']); if ($sign != $data['sign']) { throw new Exception('sign不匹配'); } $isExist = ProductOrder::find()->where(['sync_order_no' => $data['order']['order_no'], 'is_online' => 1])->one(); if (!$isExist) { throw new Exception('产品订单不存在'); } $isExist->online_prescription_status = 1; $isExist->save(); break; case 'prescription_refuse'://处方拒绝 $sign = md5($data['order']['order_no'] . $data['time'] . $config['platform']['token'] . $data['type']); if ($sign != $data['sign']) { throw new Exception('sign不匹配'); } $isExist = ProductOrder::find()->where(['sync_order_no' => $data['order']['order_no'], 'is_online' => 1])->one(); if (!$isExist) { throw new Exception('产品订单不存在'); } $isExist->online_prescription_status = 2; $isExist->save(); //未付款订单取消/已付款订单退款 // 判断订单是否已付款且待发货,是则进行退款操作 if ($isExist->cancel_status == 0 && $isExist->refund_status == 0 && $isExist->status == 1 && $isExist->is_pay == 1) { // 自动退款 $ProductRefundForm = new ProductRefundForm(); $ProductRefundForm->refund([ 'order_id' => $isExist->id, 'user_id' => $isExist->user_id ]); } else { // 订单取消 $ProductCancelForm = new ProductCancelForm(); $ProductCancelForm->cancel([ 'order_id' => $isExist->id, 'user_id' => $isExist->user_id ], '处方未通过审核,订单取消'); } break; case 'doctor_approved': $sign = md5($data['su_id'] . $data['time'] . $config['platform']['token'] . $data['type']); if ($sign != $data['sign']) { throw new Exception('sign不匹配'); } $isExist = DoctorInfo::find()->where(['su_id' => $data['su_id']])->one(); if (!$isExist) { throw new Exception('医生不存在'); } $isExist->is_sync = 2; $isExist->save(); break; default: throw new Exception('错误的回调类型'); break; } $callback->status = 1; $callback->save(); $t->commit(); return true; } catch (Exception $e) { $t->rollBack(); $callback->message = $e->getMessage(); $callback->save(); Yii::$app->response->setStatusCode('400'); return false; } } }