香洲二院小程序
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.
mini_xzey/app/Utils/Transfer/SoapTransferAbstract.php

259 lines
7.7 KiB

<?php
declare(strict_types=1);
namespace App\Utils\Transfer;
use Exception;
use Illuminate\Support\Facades\Config;
use InvalidArgumentException;
use WsdlToPhp\PackageBase\AbstractSoapClientBase;
use WsdlToPhp\PackageBase\SoapClientInterface;
abstract class SoapTransferAbstract
{
// his客户端
private AbstractSoapClientBase $client;
// His接口配置数据
private array $his_config;
// 映射类的命名空间
protected string $service_type_namespace;
// 映射方法的命名空间
protected string $struct_type_namespace;
// 调用接口名称
public string $transfer_name;
// 调用接口参数
public mixed $transfer_parameter;
// 调用返回结果
public mixed $transfer_response;
// 运行时间
public array $request_time;
/**
* Transfer constructor.
* @param string $his_name
* @throws InvalidArgumentException
*/
public function __construct(string $his_name = "")
{
// 判断传入的配置名称是否存在
$config = Config::get('hisservice.'. $his_name);
if (!isset($config)) {
throw new InvalidArgumentException($his_name);
}
// 获取配置文件中的“WSDL”文档URL
$this->his_config = $config;
$this->his_config['his_name'] = $his_name;
$this->service_type_namespace = $this->his_config['service_type_namespace'];
$this->struct_type_namespace = $this->his_config['struct_type_namespace'];
$this->initialize();
}
/**
* 初始化
*/
public function initialize(){}
/**
* 获取配置
* @param string $key
* @return mixed|null
*/
public function getHisConfigByKey(string $key): mixed
{
if (isset($this->his_config[$key])) {
return $this->his_config[$key];
}
return false;
}
/**
* 设置客户端选项
* @return array
*/
abstract public function clientOption(): array;
/**
* 设置返回值
* @return string
*/
abstract public function transferResponseStr(): string;
/**
* 需要调用类
* @param string $class_name
* @return $this
* @throws InvalidArgumentException
*/
public function transferClass(string $class_name): self
{
// 实例化具体操作类
$class_name = $this->service_type_namespace . $class_name;
if (!class_exists($class_name)) {
throw new InvalidArgumentException($class_name. ' CLASS NOT FOUND.');
}
$this->client = new $class_name($this->clientOption());
return $this;
}
/**
* 需要调用的方法
* @param string $method_name
* @param array $request_data
* @return $this
* @throws InvalidArgumentException
* @throws Exception
*/
public function transferMethod(string $method_name, array $request_data = []): self
{
// 需要调用的方法的对象名
$method_name_string = $this->struct_type_namespace . $method_name;
// 记录调用的接口名称和参数
$this->transfer_name = $method_name;
$this->transfer_parameter = $request_data;
if (!class_exists($method_name_string)) {
throw new InvalidArgumentException($method_name_string. ' CLASS NOT FOUND.');
}
try {
$this->request_time['start_time'] = microtime(true);
$this->transfer_response = $this->client->{$method_name}(new $method_name_string(...$request_data));
$this->request_time['end_time'] = microtime(true);
} catch (Exception $e) {
!isset($this->request_time['end_time']) && $this->request_time['end_time'] = microtime(true);
$this->transfer_response = "{$e->getFile()}:{$e->getLine()}:{$e->getMessage()}";
$this->recordLog();
throw new InvalidArgumentException($e->getMessage());
}
// 获取soap错误
if ($this->transfer_response === false) {
$this->recordLog();
$soap_fault = $this->client->getLastError();
if (!empty($soap_fault)) {
$soap_fault = reset($soap_fault);
throw new Exception($soap_fault->getMessage());
}
throw new Exception('请求接口失败,请稍后再试');
}
$this->recordLog();
return $this;
}
/**
* 获取返回值
* @param bool $is_format
* @return mixed
* @throws Exception
*/
public function getResult(bool $is_format = true): mixed
{
$response_class_str = $this->struct_type_namespace . $this->transfer_name . 'Response';
if (!class_exists($response_class_str)) {
throw new Exception("Transfer Class Error: $response_class_str not found");
}
$res_str = $this->transferResponseStr();
if (!property_exists($this->transfer_response, $res_str)) {
throw new Exception("Transfer Attribute Error: transfer_response->$res_str not found");
}
$result_attr_str ='get'. ucfirst($res_str);
$this->transfer_response = new $response_class_str($this->transfer_response->$res_str);
$this->transfer_response = $this->transfer_response->$result_attr_str();
if ($is_format) {
return $this->responseFormat($this->transfer_response);
}
return $this->transfer_response;
}
/**
* 响应格式化
* @param $data
*/
abstract public function responseFormat($data);
/**
* 保存日志记录
* @param string $his_name
* @param string $content
*/
public function recordRequestLog(string $his_name, string $content): void
{
date_default_timezone_set("Asia/Shanghai");
$dirname = $this->his_config['his_name'];
$path = app()->storagePath(). DIRECTORY_SEPARATOR. $dirname. DIRECTORY_SEPARATOR;
$file_path = $path. $his_name. '_log'. DIRECTORY_SEPARATOR. date('Ym'). DIRECTORY_SEPARATOR;
$file_name = date('d'). ".log";
!is_dir($file_path) && mkdir($file_path, 0755, true);
$msg = "[".date('Y-m-d H:i:s')."]". PHP_EOL . $content . PHP_EOL . PHP_EOL;
file_put_contents( $file_path. $file_name, $msg, FILE_APPEND);
}
/**
* 魔术方法实现动态调用方法
* @param $function
* @param $args
* @return $this
* @throws InvalidArgumentException
*/
public function __call($function, $args): self
{
IF (method_exists($this, $function)) {
throw new InvalidArgumentException(__CLASS__ . '类的"'. $function .'"方法不存在');
}
$this->client = call_user_func($function, ...$args);
return $this;
}
/**
* 记录日志
*/
public function recordLog(): void
{
// 判断“是否设置日志参数”和“当前调用的方法是否记录到日志”
if (!empty($this->transfer_name)) {
$run_time = sprintf("%.6f", ($this->request_time['end_time'] - $this->request_time['start_time']));
if (
empty($this->his_config['not_log_arr']) ||
!in_array($this->transfer_name, $this->his_config['not_log_arr'])
) {
// 记录入参和结果
$content = '[METHOD NAME] '. $this->transfer_name. PHP_EOL.
'[REQUEST PARAM] '. json_encode($this->transfer_parameter, JSON_UNESCAPED_UNICODE). PHP_EOL.
'[RESPONSE PARAM] '. json_encode($this->transfer_response, JSON_UNESCAPED_UNICODE). PHP_EOL.
'[RUN TIME] '. $run_time . "/s";
$this->recordRequestLog($this->his_config['his_name'], $content);
}
}
}
}