php调用webservice接口(soap)

2021-06-17
<?php

use SoapParam;
use SoapClient;

class Soap extends SoapClient
{
    /**
     * @var string 请求方法
     */
    private $_func;

    /**
     * @var array 请求方法的参数
     */
    private $_params = [];

    /**
     * @var bool 自定义xml
     */
    private $_is_custom;

    /**
     * @description: soap客户端
     * @param string|null $wsdl wsdl文件uri,空代表不使用wsdl模式
     * @param array $options 非wsdl模式下必须指定location(接口地址)和uri(与server端保持一致) 
     * @return {*}
     */
    public function __construct($wsdl, $options = [])
    {
        parent::__construct($wsdl, $options);
    }

    /**
     * @description: 请求SOAP请求,内置方法,调用soap请求时会自动执行此方法
     * @return {*}
     */
    public function __doRequest($request, $location, $action, $version, $oneWay = NULL)
    {
        if ($this->_is_custom) {
            $request = $this->_customXml();
        }
        return parent::__doRequest($request, $location, $action, $version, $oneWay);
    }

    /**
     * @description: 自定义xml,处理与服务端格式不符的问题
     * @return string
     */
    private function _customXml()
    {
        $xml = '<?xml version="1.0" encoding="UTF-8"?>
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
        <soapenv:Header/>
        <soapenv:Body>';
        
        $xml .= '<tem:'. $this->_func .'>';
        foreach ($this->_params as $key => $val) {
            $xml .= $this->_customXmlKey('tem', $key, $val);
        }

        $xml .= '</tem:'. $this->_func .'>';


        $xml .= '</soapenv:Body>
        </soapenv:Envelope>';

        return $xml;
    }

    /**
     * @description: 自定义xml中的参数设置
     * @param string $prefix 前缀
     * @param string $key
     * @param string $val
     * @return string
     */
    private function _customXmlKey($prefix, $key, $val)
    {
        return "<$prefix:$key>$val</$prefix:$key>";
    }

    /**
     * @description: 请求
     * @param string $func 请求方法
     * @param array $params 请求方法的参数,如果不自定义xml,需要在数组第一位加一个key,因为第一个key会丢失
     * @param bool $is_custom 是否自定义xml
     * @return json|xml
     */
    public function requests($func, $params = [], $is_custom = false)
    {
        $this->_func       = $func;
        $this->_params     = $params;
        $this->_is_custom  = $is_custom;
        try {
            $result1  = $this->$func(...$this->_dealParams($params)); //执行soap请求
            $varibale = $func . 'Result';
            $result   = $result1->$varibale;
            if (strpos($result, 'Could not connect to host') !== false) {
                 return json_encode(['code' => false, 'msg' => '请求失败']);
            }
            return $result;
        } catch (\Exception $e) {
            $result = $e->getMessage();
            return json_encode(['code' => false, 'msg' => '请求错误']);
        } finally {
            $this->_log($result);
        }
    }

    /**
     * @description: 预处理请求参数
     * @param array $params 参数
     * @return array
     */
    private function _dealParams($params)
    {
        $result = [];
        foreach ($params as $key => $param) {
            $result[] = new SoapParam($param, $key);
        }
        return $result;
    }

    /**
     * @description: 记录日志
     * @param {*} $result
     * @return {*}
     */
    private function _log($result)
    {
        error_log($this->_get_log_content($result), 3, $this->_generate_log_file());
    }

    /**
     * @description: 获取日志内容
     * @return string
     */
    private function _get_log_content($result)
    {
        return '[ '.date('Y-m-d H:i:s').' ] ' . $this->_func . ' ' . PHP_EOL .
                '[ REQUEST HEADER ] ' . $this->__getLastRequestHeaders() . PHP_EOL . 
                '[ PARAM ] ' . PHP_EOL . 
                json_encode($this->_params, JSON_UNESCAPED_UNICODE) . PHP_EOL . 
                '[ RESPONSE HEADER ] ' . PHP_EOL . 
                $this->__getLastResponseHeaders() . PHP_EOL .
                '[ RESPONSE BODY ] ' . PHP_EOL . 
                $result;
    }

    /**
     * @description: 获取日志文件路径
     * @return string
     */
    private function _generate_log_file()
    {
        $this->_log_path = './log/'.date('Ym').'/soap/';
        if (!is_dir($this->_log_path)) {
            mkdir($this->_log_path, 0777, true);
        }
        $log_file = $this->_log_path . date('d') . '.log';
        if (is_file($log_file) && filesize($log_file) > 2097152) {
            rename($log_file, $this->_log_path. date('dHis') . '_' . uniqid() . '.log');
        }
        return $log_file;
    }
}

调用

// trace启用对请求的跟踪,因此可以回溯故障,用于调试
$soap   = new Soap('http://xxx.xxxxxx.xx/xxx.asmx?WSDL', ['trace' => true]);
$result = $soap->requests($func, $param, true);

 

{/if}