如何防止 PHP SoapClient 将双精度值转换为科学计数法?

Posted

技术标签:

【中文标题】如何防止 PHP SoapClient 将双精度值转换为科学计数法?【英文标题】:How Can I Prevent PHP SoapClient From Converting Double Value to Scientific Notation? 【发布时间】:2011-08-19 19:03:59 【问题描述】:

我正在使用 php SoapClient 并将信用卡号作为值之一传递。这个数字正在通过soapCall 方法转换为指数格式。我正在传递 4321432143274321 并且服务器正在获取 <ccNumber xsi:type="xsd:double">4.3214321432743E+15</ccNumber>。我尝试将值转换为双精度和字符串无济于事。

我在任何地方都找不到有关此问题的任何提示!我找到的最接近的是:http://www.php.net/manual/en/soapclient.soapcall.php#75078,但“修复”并不是真正的修复。

这是我的代码:

    private function SetUpClient()
    
        try
        
            $options = array( 
                'soap_version'=>SOAP_1_2, 
                'exceptions'=>true, 
                'trace'=>1, 
                'cache_wsdl'=>WSDL_CACHE_NONE
            );

            $auth->username = $this->_username;
            $auth->password = $this->_password;

            $authValues = new SoapVar($auth, SOAP_ENC_OBJECT);
            $header =  new SoapHeader("http://v1.webservices", "authentication", $authValues, false);

            $this->_soapClient = new SoapClient( $this->_wsdlUrl );
            $this->_soapClient->__setSoapHeaders(array($header));
        
        catch( Exception $ex )
        
            var_dump($ex);
            return "An error occured: " .  $ex->getMessage();
        
    

    public function CallWebService($methodName, $arguments)
    
        try 
            $result = $this->_soapClient->__soapCall($methodName, $arguments);
         
        catch (Exception $e) 
            echo $e->getMessage();
            $result = false;
        

        return $result;
    

这是正在传递的 $arguments 数组:

    Array
    (
            [memberUid] => 123456789
            [items] => 1809,1,N,1821,1,N
            [shippingOption] => 40
            [name1] => Test15, Juan
            [name2] => 
            [address1] => 123 Test Street
            [address2] => 
            [address3] => 
            [address4] => 
            [city] => Anytown
            [stateCode] => NY
            [countryCode] => USA
            [postalCode] => 12345
            [subOrderType] => 041
            [entryDate] => 08/18/2011
            [ccType] => 3
            [ccHolder] => Juan Test
            [ccNumber] => 4321432143274321
            [ccExpDate] => 01/2014
            [externalOrderNumber] => 
            [orderSource] => 
    )    

最后是服务器看到的soap调用部分:

    <ns1:createOrder>
        <memberUid xsi:type="xsd:string">123456789</memberUid>
        <items xsi:type="xsd:string">1809,1,N,1821,1,N</items>
        <shippingOption xsi:type="xsd:double">40</shippingOption>
        <name1 xsi:type="xsd:string">Test, Juan</name1>
        <name2 xsi:type="xsd:string"/>
        <address1 xsi:type="xsd:string">123 Test Street</address1>
        <address2 xsi:type="xsd:string"/>
        <address3 xsi:type="xsd:string"/>
        <address4 xsi:type="xsd:string"/>
        <city xsi:type="xsd:string">Anytown</city>
        <stateCode xsi:type="xsd:string">NY</stateCode>
        <countryCode xsi:type="xsd:string">USA</countryCode>
        <postalCode xsi:type="xsd:string">12345</postalCode>
        <subOrderType xsi:type="xsd:string">041</subOrderType>
        <entryDate xsi:type="xsd:string">08/19/2011</entryDate>
        <ccType xsi:type="xsd:double">3</ccType>
        <ccHolder xsi:type="xsd:string">Juan Test</ccHolder>
        <ccNumber xsi:type="xsd:double">4.3214321432743E+15</ccNumber>
        <ccExpDate xsi:type="xsd:string">01/2014</ccExpDate>
        <externalOrderNumber xsi:type="xsd:string"/>
        <orderSource xsi:type="xsd:string"/>
    </ns1:createOrder>

【问题讨论】:

我发现了几个类似的问题:bugs.php.net/bug.php?id=43053(我使用的是 PHP 5.3.4)jitterbit.com/PhpBB/viewtopic.php?f=4&p=7319#p7317 【参考方案1】:

我找到了解决办法!

我更新了 php.ini 文件中的“精度”设置。我将该值从 14 增加到 16。16 位数是我需要的信用卡号码的最大值。相应地调整您的需求!

【讨论】:

最好简单地使用 ini_set("precision", "16");而不是更改 php.ini 文件。【参考方案2】:

将您的 ccNumber 转换为字符串以防止序列化使用浮点表示。

[ccNumber] => 4321432143274321 . ""

【讨论】:

【参考方案3】:

您可以使用number_format 函数将数字精确转换为字符串。默认情况下,它使用逗号作为千位分隔符。为避免这种情况,您必须显式覆盖它:

$ccNumber = number_format( 4321432143274321, 0, '', '' );

【讨论】:

这与简单地转换为字符串没有什么不同。该号码被原封不动地传递给 __soapCall()。我确信是 __soapCall() 中的某些东西在进行转换。

以上是关于如何防止 PHP SoapClient 将双精度值转换为科学计数法?的主要内容,如果未能解决你的问题,请参考以下文章

如何优化 spark 函数以将双精度值舍入到小数点后 2 位?

如何将双精度值格式化为点后两位小数且分隔符为千位的字符串?

将双精度值存储在二进制文件中并读取它

为啥要将双精度值分配给双精度值?导致 NaN

如何将双精度数组转换为 JS 数组?

函数将双精度值格式化为字符串