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.
238 lines
8.1 KiB
238 lines
8.1 KiB
2 weeks ago
|
<?php
|
||
|
declare(strict_types = 1);
|
||
|
|
||
|
namespace App\Http\Logics\Outpatient;
|
||
|
|
||
|
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\Services\HisHttp\Client;
|
||
|
use App\Utils\Traits\Logger;
|
||
|
use App\Utils\Traits\MiniProgramAuth;
|
||
|
use Illuminate\Auth\AuthenticationException;
|
||
|
use ReflectionException;
|
||
|
use Symfony\Component\HttpFoundation\Response;
|
||
|
use UnifyPayment\Cores\Exceptions\InvalidConfigException;
|
||
|
use UnifyPayment\Cores\Exceptions\RuntimeException;
|
||
|
use UnifyPayment\Cores\Struct\CreateOrder;
|
||
|
use UnifyPayment\Unify;
|
||
|
|
||
|
class PaymentLogic
|
||
|
{
|
||
|
use Logger;
|
||
|
use MiniProgramAuth;
|
||
|
|
||
|
private Client $his_client;
|
||
|
|
||
|
private Order $order_model;
|
||
|
|
||
|
/**
|
||
|
* PaymentLogic Construct
|
||
|
* @throws AuthenticationException
|
||
|
*/
|
||
|
public function __construct()
|
||
|
{
|
||
|
$this->authInitialize();
|
||
|
$this->setChannel('outpatient');
|
||
|
$this->his_client = app('HisHttpService');
|
||
|
$this->order_model = new Order();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 支付
|
||
|
* @param string $patient_id
|
||
|
* @param string $serial_no
|
||
|
* @param string $prescription_ids
|
||
|
* @param string $reg_id
|
||
|
* @return array
|
||
|
* @throws GeneralException
|
||
|
*/
|
||
|
public function payment(string $patient_id, string $serial_no, string $prescription_ids, string $reg_id): array
|
||
|
{
|
||
|
// 基础信息
|
||
|
$patient_info = $this->getPatientInfo($patient_id, $this->open_id);
|
||
|
$pending_info = $this->getPendingPrescriptionDetails($patient_id, $serial_no, $prescription_ids, $reg_id);
|
||
|
|
||
|
// 创建订单
|
||
|
$order_type = Type::OUTPATIENT_PAYMENT;
|
||
|
$pay_type = PayType::WECHAT_PAY;
|
||
|
$order_id = $this->order_model->getOrderId($pay_type, 'M');
|
||
|
$total_fee = (float)(string) array_sum(array_column($pending_info['prescription_lists'], 'ZFJE'));
|
||
|
|
||
|
$order = $this->createOrder($order_id, $pay_type, $total_fee, $order_type, $patient_info, $pending_info);
|
||
|
|
||
|
// 申请支付
|
||
|
$pay_data = $this->applyPayment($order_type, $order_id, $total_fee, $patient_info['PATIENTID'], $patient_info['NAME']);
|
||
|
|
||
|
// 去除无用数据
|
||
|
unset($pay_data['merchantId'], $pay_data['merchantName'], $pay_data['channelId'], $pay_data['channelName']);
|
||
|
|
||
|
return $pay_data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取患者信息
|
||
|
* @param string $patient_id
|
||
|
* @param string $open_id
|
||
|
* @return mixed
|
||
|
* @throws GeneralException
|
||
|
*/
|
||
|
protected function getPatientInfo(string $patient_id, string $open_id): mixed
|
||
|
{
|
||
|
$info = $this->patient_model->getBindPatientInfo($open_id, $patient_id);
|
||
|
if (empty($info)) {
|
||
|
throw new GeneralException('找不到患者信息,请重新再试!', Response::HTTP_BAD_REQUEST);
|
||
|
}
|
||
|
|
||
|
$patient_info = $this->his_client->getPatientInfo($info['patient_id'], CardType::OUTPATIENT_NO, $info['name']);
|
||
|
if (!isset($patient_info['RESULTCODE']) || $patient_info['RESULTCODE'] !== '0') {
|
||
|
throw new GeneralException($patient_info['ERRORMSG'] ?? '找不到患者信息,请重新再试!', Response::HTTP_SERVICE_UNAVAILABLE);
|
||
|
}
|
||
|
|
||
|
// 添加Patient 表ID
|
||
|
$patient_info['id'] = $info['id'];
|
||
|
|
||
|
$this->info('缴费患者信息', $info);
|
||
|
return $info;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 获取缴费处方详情
|
||
|
* @param string $patient_id
|
||
|
* @param string $serial_no
|
||
|
* @param string $prescription_ids
|
||
|
* @param string $reg_id
|
||
|
* @return array
|
||
|
* @
|
||
|
* @throws GeneralException
|
||
|
*/
|
||
|
protected function getPendingPrescriptionDetails(string $patient_id, string $serial_no, string $prescription_ids, string $reg_id): array
|
||
|
{
|
||
|
$response = $this->his_client->getPendingLists($patient_id);
|
||
|
|
||
|
if (!isset($response['RESULTCODE']) || $response['RESULTCODE'] !== '0') {
|
||
|
throw new GeneralException($response['ERRORMSG'] ?? '暂无相关缴费记录!', Response::HTTP_SERVICE_UNAVAILABLE);
|
||
|
}
|
||
|
|
||
|
// 获取具体的缴费详情
|
||
|
$response = xmlArrayToListByKey($response, 'ITEM');
|
||
|
foreach ($response['ITEM'] as $v) {
|
||
|
if ($v['JZXH'] === $serial_no) {
|
||
|
$info = $v;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (empty($info)) {
|
||
|
throw new GeneralException('查询不到待缴费处方,请重新再试!', Response::HTTP_SERVICE_UNAVAILABLE);
|
||
|
}
|
||
|
|
||
|
$response = $this->his_client->getPendingDetails($prescription_ids, $serial_no, $reg_id);
|
||
|
if (!isset($response['RESULTCODE']) || $response['RESULTCODE'] !== '0') {
|
||
|
throw new GeneralException($response['ERRORMSG'] ?? '暂无相关缴费记录!', Response::HTTP_SERVICE_UNAVAILABLE);
|
||
|
}
|
||
|
|
||
|
// 获取具体的缴费详情
|
||
|
$response = xmlArrayToListByKey($response, 'ITEM');
|
||
|
foreach ($response['ITEM'] as $v) {
|
||
|
if (strpos($prescription_ids, $v['CFID'])) {
|
||
|
$info['prescription_lists'][] = $v;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (empty($info['prescription_lists'])) {
|
||
|
throw new GeneralException('查询不到待缴费处方详情,请重新再试!', Response::HTTP_SERVICE_UNAVAILABLE);
|
||
|
}
|
||
|
|
||
|
$info['prescription_ids'] = $prescription_ids;
|
||
|
return $info;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 创建订单表
|
||
|
* @param string $order_id
|
||
|
* @param PayType $pay_type
|
||
|
* @param float $total_fee
|
||
|
* @param Type $order_type
|
||
|
* @param array $patient_info
|
||
|
* @param array $pending_info
|
||
|
* @return mixed
|
||
|
* @throws GeneralException
|
||
|
*/
|
||
|
protected function createOrder(string $order_id, PayType $pay_type, float $total_fee, Type $order_type, array $patient_info, array $pending_info): mixed
|
||
|
{
|
||
|
|
||
|
// 挂号记录表
|
||
|
$pay_record_data = [
|
||
|
'relate_patient_id' => $patient_info['id'],
|
||
|
'dept_id' => $pending_info['BQDM'],
|
||
|
'dept_name' => $pending_info['BQMC'],
|
||
|
'doctor_id' => $pending_info['YSGH'],
|
||
|
'doctor_name' => $pending_info['YSMC'],
|
||
|
'visit_date' => date('Y-m-d', strtotime($pending_info['JZRQ'])),
|
||
|
'total_amount' => $total_fee,
|
||
|
'pre_settle_status' => 0,
|
||
|
'extra_info' => json_encode($pending_info, JSON_UNESCAPED_UNICODE),
|
||
|
];
|
||
|
|
||
|
$order = $this->order_model->createOrder(
|
||
|
$order_id,
|
||
|
$pay_type,
|
||
|
$total_fee * 100,
|
||
|
$this->open_id,
|
||
|
$patient_info['PATIENTID'],
|
||
|
$patient_info['NAME'],
|
||
|
$order_type,
|
||
|
SourceId::MINI_PROGRAM,
|
||
|
$pay_record_data
|
||
|
);
|
||
|
if (empty($order)) {
|
||
|
throw new GeneralException('创建缴费单失败,请重新再试!');
|
||
|
}
|
||
|
|
||
|
$this->info('创建订单,ID:'. $order_id->id);
|
||
|
return $order;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 申请支付
|
||
|
* @param Type $order_type
|
||
|
* @param string $order_id
|
||
|
* @param float $reg_fee
|
||
|
* @param string $patient_id
|
||
|
* @param string $patient_name
|
||
|
* @return array
|
||
|
* @throws GeneralException
|
||
|
*/
|
||
|
protected function applyPayment(Type $order_type, string $order_id, float $reg_fee, string $patient_id, string $patient_name): array
|
||
|
{
|
||
|
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(env('unify'))->mini->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);
|
||
|
}
|
||
|
}
|
||
|
}
|