You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
317 lines
11 KiB
317 lines
11 KiB
<?php
|
|
declare(strict_types = 1);
|
|
|
|
namespace App\Http\Logics\Registration;
|
|
|
|
use App\Dictionary\Order\PayType;
|
|
use App\Dictionary\Order\SourceId;
|
|
use App\Dictionary\Order\Type;
|
|
use App\Dictionary\Patient\CardType;
|
|
use App\Exceptions\GeneralException;
|
|
use App\Models\Order;
|
|
use App\Models\Patient;
|
|
use App\Services\HisHttp\Client;
|
|
use App\Utils\Traits\Logger;
|
|
use App\Utils\Traits\MiniProgramAuth;
|
|
use App\Utils\Traits\SendSubscribeMessage;
|
|
use Illuminate\Auth\AuthenticationException;
|
|
use Illuminate\Support\Facades\Redis;
|
|
use ReflectionException;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use UnifyPayment\Cores\Exceptions\InvalidConfigException;
|
|
use UnifyPayment\Cores\Exceptions\RuntimeException;
|
|
use UnifyPayment\Cores\Struct\CreateOrder;
|
|
use UnifyPayment\Mock\CreateOrderHandler;
|
|
use UnifyPayment\Unify;
|
|
|
|
class RegisterLogic
|
|
{
|
|
use Logger;
|
|
use MiniProgramAuth;
|
|
use SendSubscribeMessage;
|
|
|
|
private Client $his_client;
|
|
|
|
private Order $order_model;
|
|
|
|
private Patient $patient_model;
|
|
|
|
/**
|
|
* RegisterLogic Construct
|
|
* @throws AuthenticationException
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->authInitialize();
|
|
$this->setChannel('registration');
|
|
$this->his_client = app('HisHttpService');
|
|
$this->order_model = new Order();
|
|
$this->patient_model = new Patient();
|
|
}
|
|
|
|
/**
|
|
* 挂号
|
|
* @param string $patient_number
|
|
* @param string $date
|
|
* @param string $dept_id
|
|
* @param string $doctor_id
|
|
* @param string $reg_id
|
|
* @return array
|
|
* @throws GeneralException
|
|
*/
|
|
public function register(string $patient_number, string $date, string $dept_id, string $doctor_id, string $reg_id): array
|
|
{
|
|
// 基础信息
|
|
$patient_info = $this->getPatientInfo($this->open_id, $patient_number);
|
|
$schedule_info = $this->getRegisterScheduleDetails($date, $dept_id, $doctor_id, $reg_id);
|
|
|
|
// 创建订单
|
|
$order_type = $date === date('Y-m-d') ? Type::TODAY_REGISTRATION : Type::APPOINTMENT_REGISTRATION;
|
|
$pay_type = PayType::WECHAT_PAY;
|
|
$order_id = $this->order_model->getOrderId($pay_type, 'M');
|
|
$reg_fee = (float)(string) $schedule_info['scheduleInfo']['fee'];
|
|
|
|
$order = $this->createOrder($order_id, $pay_type, $reg_fee, $order_type, $patient_info, $schedule_info);
|
|
|
|
// 挂号金额为 0 元
|
|
if ($reg_fee === 0.0) {
|
|
return $this->freeRegistrationConfirm($order);
|
|
}
|
|
|
|
// 申请支付
|
|
$pay_data = $this->applyPayment($order_type, $order_id, $reg_fee, $patient_info['patientNumber'], $patient_info['name']);
|
|
|
|
// 去除无用数据
|
|
unset($pay_data['merchantId'], $pay_data['merchantName'], $pay_data['channelId'], $pay_data['channelName']);
|
|
|
|
return $pay_data;
|
|
}
|
|
|
|
/**
|
|
* 获取患者信息
|
|
* @param string $open_id
|
|
* @param string $patient_number
|
|
* @return mixed
|
|
* @throws GeneralException
|
|
*/
|
|
protected function getPatientInfo(string $open_id, string $patient_number): mixed
|
|
{
|
|
$info = $this->patient_model->getBindPatientInfoByPatientNumber($open_id, $patient_number);
|
|
if (empty($info)) {
|
|
throw new GeneralException('找不到患者信息,请重新再试!', Response::HTTP_BAD_REQUEST);
|
|
}
|
|
|
|
$response = $this->his_client->getPatientInfo($info['patient_id'], CardType::OUTPATIENT_NO, $info['name']);
|
|
if (!isset($response['success']) || !$response['success']) {
|
|
throw new GeneralException($response['msg'] ?? '找不到患者信息,请重新再试!', Response::HTTP_SERVICE_UNAVAILABLE);
|
|
}
|
|
|
|
// 添加Patient 表ID
|
|
$patient_info = &$response['response'];
|
|
$patient_info['id'] = $info['id'];
|
|
|
|
$this->info('挂号患者信息', $patient_info);
|
|
return $patient_info;
|
|
}
|
|
|
|
/**
|
|
* 获取挂号信息
|
|
* @param string $date
|
|
* @param string $dept_id
|
|
* @param string $doctor_id
|
|
* @param string $reg_id
|
|
* @return array
|
|
* @throws GeneralException
|
|
*/
|
|
protected function getRegisterScheduleDetails(string $date, string $dept_id, string $doctor_id, string $reg_id): array
|
|
{
|
|
// 获取排班医生信息
|
|
$is_today = $dept_id === date('Y-m-d') ? '3' : '1';
|
|
$schedule_info = $this->his_client->getDoctorLists($dept_id, $is_today, '', $date);
|
|
if (!isset($schedule_info['success']) || !$schedule_info['success']) {
|
|
throw new GeneralException($schedule_info['msg'] ?? '找不到该号源,请重新再试!', Response::HTTP_SERVICE_UNAVAILABLE);
|
|
}
|
|
|
|
// 获取号源信息
|
|
foreach ($schedule_info['response'] as $v) {
|
|
if ($v['doctId'] === $doctor_id) {
|
|
foreach ($v['doctotVisitInfoList'] as $v2) {
|
|
if ($v2['regId'] === $reg_id && $v2['visitDate'] === $date) {
|
|
$v['scheduleInfo'] = $v2;
|
|
unset($v['doctotVisitInfoList']);
|
|
$info = $v;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (empty($info)) {
|
|
throw new GeneralException('找不到该号源,请重新再试!', Response::HTTP_BAD_REQUEST);
|
|
}
|
|
|
|
if (!isset($info['scheduleInfo']['regCount']) || $info['scheduleInfo']['regCount'] <= 0) {
|
|
throw new GeneralException('该号源已挂完,请重新选择号源!', Response::HTTP_BAD_REQUEST);
|
|
}
|
|
|
|
// 获取科室名称
|
|
if (Redis::exists('departments.'. $date)) {
|
|
$dept_lists = Redis::get('departments.'. $date);
|
|
$dept_lists = json_decode($dept_lists, true);
|
|
} else {
|
|
$dept_lists = $this->his_client->getDepType('', '','01', $date);
|
|
|
|
if (!isset($dept_lists['success']) || !$dept_lists['success']) {
|
|
throw new GeneralException($schedule_info['msg'] ?? '找不到该号源,请重新再试!', Response::HTTP_SERVICE_UNAVAILABLE);
|
|
}
|
|
}
|
|
|
|
foreach ($dept_lists['response'] as $v) {
|
|
if ($v['typeId'] === $dept_id) {
|
|
$info['dept_id'] = $v['typeId'];
|
|
$info['dept_name'] = $v['typeName'];
|
|
}
|
|
}
|
|
|
|
$this->info('挂号排班信息', $info);
|
|
return $info;
|
|
}
|
|
|
|
/**
|
|
* 创建订单表
|
|
* @param string $order_id
|
|
* @param PayType $pay_type
|
|
* @param float $reg_fee
|
|
* @param Type $order_type
|
|
* @param array $patient_info
|
|
* @param array $schedule_info
|
|
* @return mixed
|
|
* @throws GeneralException
|
|
*/
|
|
protected function createOrder(string $order_id, PayType $pay_type, float $reg_fee, Type $order_type, array $patient_info, array $schedule_info): mixed
|
|
{
|
|
// 挂号记录表
|
|
$reg_record_data = [
|
|
'relate_patient_id' => $patient_info['id'],
|
|
'reg_id' => $schedule_info['scheduleInfo']['regId'],
|
|
'dept_id' => $schedule_info['dept_id'],
|
|
'dept_name' => $schedule_info['dept_name'],
|
|
'dept_location' => '',
|
|
'doctor_id' => $schedule_info['doctId'],
|
|
'doctor_name' => $schedule_info['doctName'],
|
|
'visit_date' => date('Y-m-d', strtotime($schedule_info['scheduleInfo']['visitDate'])),
|
|
'begin_time' => $schedule_info['scheduleInfo']['startTime'],
|
|
'end_time' => $schedule_info['scheduleInfo']['endTime'],
|
|
'lock_status' => 0,
|
|
'extra_info' => json_encode($schedule_info, JSON_UNESCAPED_UNICODE),
|
|
];
|
|
|
|
$order = $this->order_model->createOrder(
|
|
$patient_info['id'],
|
|
$order_id,
|
|
$pay_type,
|
|
$reg_fee * 100,
|
|
0,
|
|
$this->open_id,
|
|
$patient_info['patientId'],
|
|
$patient_info['name'],
|
|
$order_type,
|
|
SourceId::MINI_PROGRAM,
|
|
$reg_record_data
|
|
);
|
|
if (empty($order)) {
|
|
throw new GeneralException('创建挂号单失败,请重新再试!');
|
|
}
|
|
|
|
$this->info('创建订单,ID:'. $order->id);
|
|
return $order;
|
|
}
|
|
|
|
/**
|
|
* 免费挂号确认
|
|
* @param Order $order
|
|
* @return array
|
|
* @throws GeneralException
|
|
*/
|
|
protected function freeRegistrationConfirm(Order $order): array
|
|
{
|
|
// 挂号确认
|
|
$record = &$order->registrationRecord;
|
|
$extra = json_decode($record->extra_info, true);
|
|
|
|
$data = [
|
|
$order->patient_id,
|
|
$order->patient_name,
|
|
$record->dept_id,
|
|
$record->doctor_id,
|
|
$record->reg_id,
|
|
$extra['scheduleInfo']['rankId'],
|
|
$record->visit_date,
|
|
PayType::WECHAT_PAY->hisCode(),
|
|
$order->order_id,
|
|
'',
|
|
'',
|
|
'',
|
|
'',
|
|
'0',
|
|
''
|
|
];
|
|
$response = $this->his_client->registerConfirm(... $data);
|
|
$this->info('挂号订单出入参:'.$order->order_id, [$data, $response]);
|
|
|
|
if (isset($response['success']) && $response['success'] === true) {
|
|
// 成功流程
|
|
$order->orderConfirm($order->order_id, $response['response']['visitNo'], $response['response']);
|
|
|
|
// 推送成功
|
|
$this->sendRegistrationSuccessMessage($order);
|
|
|
|
// 返回数据
|
|
return [
|
|
'order_id' => $order->order_id,
|
|
'reg_serial_no' => $response['response']['visitNo']
|
|
];
|
|
} else {
|
|
// 推送失败
|
|
$this->sendRegistrationFailureMessage($order);
|
|
|
|
throw new GeneralException('挂号失败,失败原因:'. ($response['msg'] ?? '数据异常'). ',请重新再试!');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 申请支付
|
|
* @param Type $order_type
|
|
* @param string $order_id
|
|
* @param float $reg_fee
|
|
* @param string $patient_id
|
|
* @param string $patient_name
|
|
* @return array|string
|
|
* @throws GeneralException
|
|
*/
|
|
protected function applyPayment(Type $order_type, string $order_id, float $reg_fee, string $patient_id, string $patient_name): array|string
|
|
{
|
|
try {
|
|
$order_obj = new CreateOrder(
|
|
$order_type->label(),
|
|
$order_id,
|
|
(string) $reg_fee,
|
|
'1',
|
|
$patient_id. '|'. $patient_name,
|
|
'A',
|
|
$this->open_id,
|
|
url('/Api/Notify', [], true)
|
|
);
|
|
|
|
$response = Unify::pay(config('unify'))->mini->setMockHandler([new CreateOrderHandler(true)])->jsapi($order_obj);
|
|
$this->info('jsapi 支付参数', $response);
|
|
|
|
if (!$response['success'] && empty($response['response'])) {
|
|
throw new GeneralException('申请支付失败,请重新再试!', Response::HTTP_SERVICE_UNAVAILABLE);
|
|
}
|
|
|
|
return $response['response'];
|
|
} catch (InvalidConfigException|RuntimeException|ReflectionException $e) {
|
|
throw new GeneralException('申请支付失败,请重新再试!', Response::HTTP_INTERNAL_SERVER_ERROR);
|
|
}
|
|
}
|
|
}
|
|
|