使用PHP和SOAP调用Saba java web服务


Invoking a Saba java web service using PHP and SOAP

我目前正在开发一种方法,在Saba中使用"忘记密码"功能与SSO结合使用,但无需直接在Saba网站上。

我在尝试访问Saba web服务时遇到了一个问题,目前处于一个砖墙。

我得到的var_dump错误如下:

string(544) " ns1:Server.NoService The AXIS engine could not find a target service to invoke! targetService is InfoService/cspsRetrievePassword "

详情如下:

Saba的构建方式使我们不能在自定义web服务上使用REST,只能使用SOAP。我在表单提交上调用以下函数:

public function doPasswordRetrieval($pId, $pAction, $pNewPassword, $pOldPassword, $pIsOldPasswordHashed, $pSecretQ, $pSecretA, $pSendMail){
    if($this->isAuthenticated()) {
        $soapenv = 'http://schemas.xmlsoap.org/soap/envelope/';
        $soapcommand = 'cspsRetrievePassword';
        $soapurl = "https://mydomain/axis/services/InfoService";
        $soapcert = $this->getCertificate();
        $soapqryid = $pId;
        $soapqryact = $pAction;
        $soapqrynewp = $pNewPassword;
        $soapqryoldp = $pOldPassword;
        $soapqryphash = $pIsOldPasswordHashed;
        $soapqrysecq = $pSecretQ;
        $soapqryseca = $pSecretA;
        $soapqrymail = $pSendMail;

        $soapqry = '<?xml version="1.0" encoding="utf-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="' . $soapenv . '">';
        $soapqry .= '<SOAP-ENV:Body>';
        $soapqry .= '<saba:' . $soapcommand . ' xmlns:saba="' . $soapurl . '">';
        $soapqry .= '<certificate>' . $soapcert . '</certificate>';
        $soapqry .= '<id>' . $soapqryid . '</id>';
        $soapqry .= '<action>' . $soapqryact . '</action>';
        $soapqry .= '<newPass>' . $soapqrynewp . '</newPass>';
        $soapqry .= '<oldPass>' . $soapqryoldp . '</oldPass>';
        $soapqry .= '<isOldPasswordHashed>' . $soapqryphash . '</isOldPasswordHashed>';
        $soapqry .= '<secretQuestion>' . $soapqrysecq . '</secretQuestion>';
        $soapqry .= '<secretAnswer>' . $soapqryseca . '</secretAnswer>';
        $soapqry .= '<sendMail>' . $soapqrymail . '</sendMail>';
        $soapqry .= '</saba:' . $soapcommand . '>';
        $soapqry .= '</SOAP-ENV:Body>';
        $soapqry .= '</SOAP-ENV:Envelope>';
        $url = $soapurl . '/' . $soapcommand;
        $headers = array(
                    "Content-type: text/xml;charset='"utf-8'"",
                    "Accept: text/xml",
                    "Cache-Control: no-cache",
                    "Pragma: no-cache",
                    "SOAPAction: " . $url, 
                    "Content-length: " . strlen($soapqry),
                );

        $handle = curl_init();
        curl_setopt($handle, CURLOPT_URL, $url);
        curl_setopt($handle, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 10000);
        curl_setopt($handle, CURLOPT_POST, true);
        curl_setopt($handle, CURLOPT_POSTFIELDS, $soapqry);
        $response = curl_exec($handle);
        curl_close($handle);
        var_dump($response);
        //return $response;
    }
}

SOAP包装器和XML可以以不同的方式编写,而不是添加到字符串中,但我目前正在开发中,只是试图使其工作。

我的第一反应是web服务不存在,但它确实存在。

在saba中,web服务部分:

Name* cspsRetrievePassword
Java Class* csps.CspsRetrievePasswordCommand

如果需要,我可以粘贴我的自定义java类,但主要部分都是

public class CspsRetrievePasswordCommand extends SabaWebCommand
public CspsRetrievePasswordCommand()
    throws SabaException
{
    addInParam("id", String.class, " person id");
    addInParam("action", String.class, "action value");
    addInParam("newPass", String.class, " new password ");
    addInParam("oldPass", String.class, " old password ");
    addInParam("isOldPasswordHashed", String.class, " is old password in hashed format");
    addInParam("secretQuestion", String.class, " secret question");
    addInParam("secretAnswer", String.class, " secret answer");
    addInParam("sendMail", String.class, " send Mail?");
}
public void doExecute(HttpServletRequest request, IXMLVisitor visitor)

我的第二个反应是$url语法不正确。

我尝试了以下操作,但没有成功:

  • /轴/服务/InfoService/cspsRetrievePassword
  • /轴/服务/InfoService吗?cspsRetrievePassword
  • /轴/服务/InfoService

最后一个,调用web服务而没有在URL中包含命令,并且只在SOAP查询中,给了我一个不同的错误:

string(436) " (70034) Exception in executing info service: @001 java.lang.NullPointerException "

任何帮助都将是非常感激的。

谢谢!

我终于找到了解决问题的办法。

首先要做的就是向CURLOPT_POSTFIELDS

添加一个元素

$soapqry应该如下所示:(注意<查询>)

        $soapqry = '<?xml version="1.0" encoding="utf-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="' . $soapenv . '">';
        $soapqry .= '<SOAP-ENV:Body>';
        $soapqry .= '<saba:' . $soapcommand . ' xmlns:saba="' . $soapurl . '">';
        $soapqry .= '<certificate>' . $soapcert . '</certificate>';
        $soapqry .= '<query>';
        $soapqry .= '<id>' . $soapqryid . '</id>';
        $soapqry .= '<action>' . $soapqryact . '</action>';
        $soapqry .= '<newPass>' . $soapqrynewp . '</newPass>';
        $soapqry .= '<oldPass>' . $soapqryoldp . '</oldPass>';
        $soapqry .= '<isOldPasswordHashed>' . $soapqryphash . '</isOldPasswordHashed>';
        $soapqry .= '<secretQuestion>' . $soapqrysecq . '</secretQuestion>';
        $soapqry .= '<secretAnswer>' . $soapqryseca . '</secretAnswer>';
        $soapqry .= '<sendMail>' . $soapqrymail . '</sendMail>';
        $soapqry .= '</query>';
        $soapqry .= '</saba:' . $soapcommand . '>';
        $soapqry .= '</SOAP-ENV:Body>';
        $soapqry .= '</SOAP-ENV:Envelope>';

第二步是确保CURLOPT_URL只是/infoservice url,没有命令

$url = "https://mydomain/axis/services/InfoService";
curl_setopt($handle, CURLOPT_URL, $url);

第三种方法是将CURLOPT_HTTPHEADER中的SOAPAction设置为命令本身,不带url

$headers = array(
    "Content-type: text/xml;charset='"utf-8'"",
    "Accept: text/xml",
    "Cache-Control: no-cache",
    "Pragma: no-cache",
    "SOAPAction: " . $soapcommand, 
    "Content-length: " . strlen($soapqry)
);

希望这将帮助其他人如何使用SABA web服务与PHP