如何用PHP调用Workday SOAP WebService?能否直接发送XML请求?
嘿,既然你已经能用SOAP UI和Boomerang成功跑通请求拿到正确结果,那用PHP实现起来其实挺顺手的,给你两种实用方案,你按需选就行:
先贴一下你已经验证过的测试XML请求,方便后续对照:
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
env:Header
xsd:sample_Common_Header
xsd:Include_Reference_Descriptors_In_Responsefalse</xsd:Include_Reference_Descriptors_In_Response>
</xsd:sample_Common_Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
wsse:UsernameToken
wsse:UsernameAssessment@tenant</wsse:Username>
wsse:PasswordTest@1234</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</env:Header>
env:Body
<wd:Get_Assess_Candidate_Request xmlns:wd="urn:com.sample/bsvc" wd:version="v29.0">
wd:Request_Criteria
wd:Candidate_Criteria_Data
wd:Candidate_Reference
<wd:ID wd:type="Candidate_ID">C0000417</wd:ID>
</wd:Candidate_Reference>
</wd:Candidate_Criteria_Data>
</wd:Request_Criteria>
wd:Response_Filter
wd:As_Of_Effective_Date2018-01-16</wd:As_Of_Effective_Date>
wd:As_Of_Entry_DateTime2018-01-16T11:17:34</wd:As_Of_Entry_DateTime>
wd:Page1</wd:Page>
wd:Count100</wd:Count>
</wd:Response_Filter>
</wd:Get_Assess_Candidate_Request>
</env:Body>
</env:Envelope>
方案一:直接发送现成的XML请求
这种方式最省心,完全复用你已经验证过的XML,不需要折腾对象或数组转换,适合快速实现。
步骤说明
- 把静态XML里的动态参数(比如候选人ID、日期、用户名密码)换成PHP变量,方便动态修改
- 用cURL发送POST请求到WebService的端点URL(注意不是WSDL地址,你可以从WSDL文件里找到
soap:address location="..."的值) - 设置正确的HTTP请求头,尤其是
Content-Type和SOAPAction(SOAPAction的值可以从SOAP UI的请求头里直接复制)
代码示例
// 替换成你的服务端点URL $endpoint = 'http://your-service-endpoint-url'; // 动态参数配置 $username = 'Assessment@tenant'; $password = 'Test@1234'; $candidateId = 'C0000417'; $effectiveDate = '2018-01-16'; $entryDateTime = '2018-01-16T11:17:34'; // 拼接XML请求,替换动态变量 $xmlRequest = <<<XML <?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <env:Header> <xsd:sample_Common_Header> <xsd:Include_Reference_Descriptors_In_Response>false</xsd:Include_Reference_Descriptors_In_Response> </xsd:sample_Common_Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <wsse:UsernameToken> <wsse:Username>$username</wsse:Username> <wsse:Password>$password</wsse:Password> </wsse:UsernameToken> </wsse:Security> </env:Header> <env:Body> <wd:Get_Assess_Candidate_Request xmlns:wd="urn:com.sample/bsvc" wd:version="v29.0"> <wd:Request_Criteria> <wd:Candidate_Criteria_Data> <wd:Candidate_Reference> <wd:ID wd:type="Candidate_ID">$candidateId</wd:ID> </wd:Candidate_Reference> </wd:Candidate_Criteria_Data> </wd:Request_Criteria> <wd:Response_Filter> <wd:As_Of_Effective_Date>$effectiveDate</wd:As_Of_Effective_Date> <wd:As_Of_Entry_DateTime>$entryDateTime</wd:As_Of_Entry_DateTime> <wd:Page>1</wd:Page> <wd:Count>100</wd:Count> </wd:Response_Filter> </wd:Get_Assess_Candidate_Request> </env:Body> </env:Envelope> XML; // 初始化cURL请求 $ch = curl_init($endpoint); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: text/xml; charset=utf-8', // 替换成你从SOAP UI里看到的SOAPAction值 'SOAPAction: "urn:com.sample/bsvc/Get_Assess_Candidate_Request"' ]); // 执行请求并处理结果 $response = curl_exec($ch); if (curl_errno($ch)) { echo 'cURL错误: ' . curl_error($ch); } else { // 把响应转换成SimpleXMLElement方便处理 $xmlResponse = simplexml_load_string($response); print_r($xmlResponse); } curl_close($ch);
方案二:用PHP SOAP扩展构建请求
这种方式更规范,适合长期维护,PHP会自动帮你处理XML序列化和命名空间,不用手动拼接XML字符串。
前提条件
确保你的PHP环境已经开启了SOAP扩展:
- 打开
php.ini文件,找到;extension=soap,去掉前面的分号 - 重启你的Web服务器(比如Apache/Nginx)
步骤说明
- 创建
SoapClient实例,传入WSDL URL和登录信息、调试开关等选项 - 把XML里的请求参数转换成数组(或对象),对应XML的结构
- 调用服务对应的方法,捕获可能的错误
代码示例
// 替换成你的WSDL URL $wsdlUrl = 'http://your-wsdl-url'; try { // 创建SoapClient实例,开启trace方便调试 $client = new SoapClient($wsdlUrl, [ 'trace' => true, 'login' => 'Assessment@tenant', 'password' => 'Test@1234', 'soap_version' => SOAP_1_1, // 大部分SOAP服务用1.1,按需调整 'exceptions' => true ]); // 设置SOAP Header(对应XML里的sample_Common_Header) $header = new SoapHeader( 'http://www.w3.org/2001/XMLSchema', 'sample_Common_Header', [ 'Include_Reference_Descriptors_In_Response' => false ] ); $client->__setSoapHeaders($header); // 构建请求参数数组,对应XML里的结构 $params = [ 'Request_Criteria' => [ 'Candidate_Criteria_Data' => [ 'Candidate_Reference' => [ 'ID' => [ '_' => 'C0000417', // 节点文本内容 'type' => 'Candidate_ID' // 节点属性 ] ] ] ], 'Response_Filter' => [ 'As_Of_Effective_Date' => '2018-01-16', 'As_Of_Entry_DateTime' => '2018-01-16T11:17:34', 'Page' => 1, 'Count' => 100 ] ]; // 调用服务方法,方法名要和XML里的Get_Assess_Candidate_Request一致 $response = $client->Get_Assess_Candidate_Request($params); // 处理响应结果 print_r($response); // 调试时可以打印实际发送的请求XML // echo "\n请求XML: " . $client->__getLastRequest(); } catch (SoapFault $e) { echo "SOAP错误: " . $e->getMessage(); // 调试时打印请求XML排查问题 echo "\n请求XML: " . $client->__getLastRequest(); }
关于你的疑问解答
- 是否可以直接发送XML请求? 当然可以,方案一就是这种方式,SOAP本质就是通过HTTP POST发送XML,只要请求格式正确就能拿到响应。
- 如何利用现有XML构建SOAP请求? 两种思路:要么直接复用XML字符串替换动态参数(方案一),要么把XML里的参数结构转换成数组/对象给SoapClient使用(方案二)。
- 是否需要将XML解析为对象或数组? 不一定:用方案一的话完全不需要解析,直接用现成的XML;用方案二的话,只需要把XML里的参数部分提取出来转换成数组/对象,不用解析整个XML。
内容的提问来源于stack exchange,提问作者Suraj Kumar

