You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP生成指定SOAP请求遇Bad Request错误,求解决方案

PHP生成指定SOAP请求返回Bad Request的解决方案

问题背景

需要生成的目标SOAP请求如下:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:post="http://post.ondot.at" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:core="http://Core.Model" xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/">
    <soapenv:Header/>
    <soapenv:Body>
        <post:ImportShipment>
            <!--Optional:-->
            <post:row>
            <post:DeliveryServiceThirdPartyID>10</post:DeliveryServiceThirdPartyID>
                <post:OURecipientAddress>
                    <post:AddressLine1>Teststrasse</post:AddressLine1>
                    <post:AddressLine2/>
                    <post:City>Wien</post:City>
                    <post:CountryID>AT</post:CountryID>
                    <post:Email/>
                    <post:HouseNumber>1</post:HouseNumber>
                    <post:Name1>Test Recipient</post:Name1>
                    <post:PostalCode>1030</post:PostalCode>
                </post:OURecipientAddress>
                <post:OUShipperAddress>
                    <post:AddressLine1>Musergasse</post:AddressLine1>
                    <post:City>Wien</post:City>
                    <post:CountryID>AT</post:CountryID>
                    <post:Name1>test &amp; test</post:Name1>
                    <post:Name2/>
                    <post:PostalCode>1010</post:PostalCode>
                </post:OUShipperAddress>
                <post:PrinterObject>
                    <post:LabelFormatID>100x150</post:LabelFormatID>
                    <post:LanguageID>PDF</post:LanguageID>
                    <post:PaperLayoutID>A5</post:PaperLayoutID>
                </post:PrinterObject>
            </post:row>
        </post:ImportShipment>
    </soapenv:Body>
</soapenv:Envelope>

尝试的PHP代码:

$parcelData = [
    'row' => [
        'DeliveryServiceThirdPartyID' => 10,
        'OURecipientAddress' => [
            'AddressLine1' => 'Teststrasse',
            'City' => 'Wien',
            'CountryID' => 'AT',
            'HouseNumber' => '1',
            'Name1' => 'Test Recipient',
            'PostalCode' => '1030',
        ],
        'OUShipperAddress' => [
            'AddressLine1' => 'Musergasse',
            'City' => 'Wien',
            'CountryID' => 'AT',
            'Name1' => 'test & test',
            'PostalCode' => '1010',
        ],
        'PrinterObject' => [
            'LabelFormatID' => '100x150',
            'LanguageID' => 'PDF',
            'PaperLayoutID' => 'A5',
        ],
    ],
];

$response = $this->client->ImportShipment($parcelData);

执行后始终返回Bad Request错误。

解决方案

1. 启用调试模式对比实际请求

开启SoapClient的trace功能,打印实际发送的XML,和目标请求对比差异,这是排查SOAP问题最直接的方法:

// 初始化客户端时开启trace和异常捕获
$client = new SoapClient('你的WSDL地址', [
    'trace' => true,
    'exceptions' => true,
    'encoding' => 'UTF-8',
]);

try {
    $response = $client->ImportShipment($parcelData);
} catch (SoapFault $e) {
    // 打印实际发送的请求XML
    echo "实际请求XML:\n" . htmlspecialchars($client->__getLastRequest()) . "\n";
    // 打印错误信息
    echo "错误详情: " . $e->getMessage();
}

2. 补全可选空节点

目标请求中包含<post:AddressLine2/>、<post:Email/>等空节点,部分SOAP服务要求显式传递这些可选字段的空值,而非省略。调整参数结构:

$parcelData = [
    'row' => [
        'DeliveryServiceThirdPartyID' => 10,
        'OURecipientAddress' => [
            'AddressLine1' => 'Teststrasse',
            'AddressLine2' => '', // 显式传递空值
            'City' => 'Wien',
            'CountryID' => 'AT',
            'Email' => '', // 显式传递空值
            'HouseNumber' => '1',
            'Name1' => 'Test Recipient',
            'PostalCode' => '1030',
        ],
        'OUShipperAddress' => [
            'AddressLine1' => 'Musergasse',
            'City' => 'Wien',
            'CountryID' => 'AT',
            'Name1' => 'test & test',
            'Name2' => '', // 显式传递空值
            'PostalCode' => '1010',
        ],
        'PrinterObject' => [
            'LabelFormatID' => '100x150',
            'LanguageID' => 'PDF',
            'PaperLayoutID' => 'A5',
        ],
    ],
];

3. 检查参数是否为数组类型

部分WSDL定义中,row参数要求是数组(即使仅单条数据),需将row包裹在数组中:

$parcelData = [
    'row' => [
        [
            'DeliveryServiceThirdPartyID' => 10,
            'OURecipientAddress' => [...], // 地址参数同前
            'OUShipperAddress' => [...],
            'PrinterObject' => [...],
        ]
    ]
];

4. 确认命名空间与WSDL匹配

检查WSDL中ImportShipment方法的参数命名空间,若需要指定命名空间前缀,可通过SoapVar显式声明:

$rowData = [
    'DeliveryServiceThirdPartyID' => 10,
    'OURecipientAddress' => [...],
    'OUShipperAddress' => [...],
    'PrinterObject' => [...],
];

// 用SoapVar指定命名空间
$soapRow = new SoapVar($rowData, SOAP_ENC_OBJECT, null, null, 'row', 'http://post.ondot.at');
$parcelData = ['row' => $soapRow];

$response = $client->ImportShipment($parcelData);

5. 处理特殊字符

目标请求中的test &amp; test是XML转义后的结果,PHP数组中直接写test & test即可,SoapClient会自动完成转义,避免手动写&amp;导致双重转义。

内容的提问来源于stack exchange,提问作者Its.Phil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 13:58:12