【问题标题】:Why does __soapcall translate xs:decimal to "true"?为什么 __soapcall 将 xs:decimal 翻译为“真”?
【发布时间】:2019-05-12 06:56:29
【问题描述】:

我正在使用 PHP Soap。

这是从 __getLastRequest() 获得的 sn-p。我不知道为什么“版本”显示为“真”而不是我设置的值:“1.0”?

事实上,不仅我的版本有问题,我的时间戳也有问题。我为此设置的值是 \DateTime::ATOM。不知道为什么它会在 2019 年问世。

<ns1:OTA_CruiseSailAvailRQ TimeStamp="2019" Version="true" 

SOAP 服务器拒绝接受我的 XML,SoapFault 如下所示。我已经在 SOAP UI 中手动形成 XML 并发布,一切都按预期工作。但是,当我使用 PHP Soap 执行此操作时,我得到了这个 SoapFault,唯一不同的是版本和时间戳。

 [faultstring] => 
Internal Error (from server)

    [faultcode] => 
env:Receiver

这里有更多的 XML:

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://www.opentravel.org/OTA/2003/05/alpha" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="http://services.rccl.com/Interfaces/SailingList">

 <env:Body>

   <ns2:getSailingList>

     <ns1:OTA_CruiseSailAvailRQ TimeStamp="2019" Version="true"


在 WSDL 中,TimeStamp 和 Version 的定义如下:

WSDL

<xs:attribute name="Version" type="xs:decimal" use="required">
            <xs:annotation>
                <xs:documentation xml:lang="en">For all OTA versioned messages, the version of the message is indicated by a decimal value.</xs:documentation>
            </xs:annotation>
</xs:attribute>

<xs:attribute name="TimeStamp" type="xs:dateTime" use="optional">
            <xs:annotation>
                <xs:documentation xml:lang="en">Indicates the creation date and time of the message in UTC using the following format specified by ISO 8601; YYYY-MM-DDThh:mm:ssZ with time values using the 24 hour clock (e.g. 20 November 2003, 1:59:38 pm UTC becomes 2003-11-20T13:59:38Z).</xs:documentation>
            </xs:annotation>
</xs:attribute>

这是我设置值和启动 SOAP 调用的方式

$test = new MyNamespace\OTA_CruiseSailAvailRQ();
$d = new DateTime('NOW');

$test->setTimeStamp($d);
$test->setVersion(1.0);    


$sailCall = new MyNamespace\Cruise_FIT_External(['trace' => 1,
                                   'exception' => 0,
                                   'login' => 'xxxxxxx', 
                                   'password' => 'xxxxxxxx',
                                  'soap_version' => SOAP_1_2]);


$resp = $sailCall->getSailingList(new MyNamespace\getSailingList($test));

我已使用Wsdl2PhpGenerator 从我的 WSDL 生成我的类。这就是为什么您看到 Cruise_FIT_External 而看不到 SoapClient 的直接实例的原因。但它正在扩展 SoapClient。所以我们在那里很好。

namespace MyNamespace;

class Cruise_FIT_External extends \SoapClient
{
    /**
     * @param getSailingList $parameters
     * @return getSailingListResponse
     */
    public function getSailingList(getSailingList $parameters)
    {

      return $this->__soapCall('getSailingList', array($parameters));
    }
}

这就是 setTimestamp 和 SetVersion 函数的定义方式。同样,这是 Wsdl2PhpGenerator 输出的代码。所以我觉得挺好的。


namespace MyNamespace;

class OTA_CruiseSailAvailRQ
{

    /**
     * @var float $Version
     */
    protected $Version = null;

    /**
     * @var \DateTime $TimeStamp
     */
    protected $TimeStamp = null;

    /**
     * @param \DateTime $TimeStamp
     * @return \MyNamespace\OTA_CruiseSailAvailRQ
     */
    public function setTimeStamp(\DateTime $TimeStamp)
    {
      $this->TimeStamp = $TimeStamp->format(\DateTime::ATOM);
      return $this;
    }


    /**
     * @return \DateTime
     */
    public function getTimeStamp()
    {
      if ($this->TimeStamp == null) {
        return null;
      } else {
        try {
            return DateTime::createFromFormat(\DateTime::ATOM, $this->TimeStamp); 
          // this below was the original line. didn't work. changed it to the line above. that didn't work either.
          //return new \DateTime($this->TimeStamp); 
           return $this->TimeStamp;
        } catch (\Exception $e) {
          return false;
        }
      }
    }

    /**
     * @return float
     */
    public function getVersion()
    {
      return $this->Version;
    }

    /**
     * @param float $Version
     * @return \MyNamespace\OTA_CruiseSailAvailRQ
     */
    public function setVersion($Version)
    {
      $this->Version = $Version;
      return $this;
    }

如果解决了这个问题,预期的输出应该如下所示。我知道这是可行的,因为当我使用 SOAP UI 并手动创建 XML 并发布时,一切都按预期工作。

<ns1:OTA_CruiseSailAvailRQ TimeStamp="2019-05-11T15:30:41-05:00" Version="1.0" 

提前感谢您的帮助!

【问题讨论】:

    标签: php soap wsdl soap-client


    【解决方案1】:

    很高兴找到另一种方法来调用这些 SOAP API,而不是使用类和 SoapClient

    在 Stackoverflow 帖子中使用了 this technique - 改为使用 Curl。这样的救星!

    一切正常!

    【讨论】:

      【解决方案2】:

      这可能会帮助其他遇到相同问题的人,在 PHP7.2 中,SoapClient 会将十进制值转换为 true。输入17.017.0017,017,00 或仅输入17 都没有关系。迁移到 PHP7.4 为我解决了这个问题。 PHP7.2的SoapClient好像有个小bug。

      希望这对任何人都有帮助!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-05-01
        • 2012-02-22
        • 1970-01-01
        • 1970-01-01
        • 2021-05-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多