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.
258 lines
7.7 KiB
258 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|