Добрый вечер всем. Недавно пришлось столкнуться с технологией SOAP. Перечитал много ДОК по данному вопросу, основы понял. Но при реализации возникли проблемы следующего характера. Есть скрипт в котором использую подключение к сервису типа: PHP: $client = new SoapClient("https://*********/PayService?wsdl"); и отправку параметров PHP: $sc = $client->__call( "checkPaymentAbility", array( new SoapParam( "test", "paymentSystem" )), array ( new SoapParam( "57971", "contractCode" )), array ( new SoapParam( "bb", "service" )) ); print_r ($sc); Тут выдает ошибку: Fatal error: SoapClient::__call() [<a href='soapclient.--call'>soapclient.--call</a>]: Invalid SOAP header при этом ссылаясь на "))". По поиску, тут на форуме, нашел еще один вариант отправки запроса, более красивее PHP: $param = array ("paymentSystemtest"=>"test", "contractCode"=>"57971", "service"=>"bb"); $result = $client->__soapCall("checkPaymentAbility", $param); при таком вариант ругается: Fatal error: Uncaught SoapFault exception: [env] Invalid number of payload elements: 3 in E:\server\htdocs\www\soap\soap.php:20 Stack trace: #0 E:\server\htdocs\www\soap\soap.php(20): SoapClient->__soapCall('checkPaymentAbi...', Array) #1 {main} thrown in хотя параметры указаны правильно. В чем может быть проблема? крайне буду благодарен за помощь
Возьми wsdl файл с сайта и посмотри что ты должен отдать в пакете. У тебя с заголовками что-то не але.
Если не затруднит может подскажешь?... вот код wsdl-документа: [css] - <definitions name="PayService" targetNamespace="https://******/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="https://******/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> - <types> - <xs:schema targetNamespace="https://******/" version="1.0" xmlns:tns="https://******/" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="checkContractByCode" type="tns:checkContractByCode" /> <xs:element name="checkContractByCodeResponse" type="tns:checkContractByCodeResponse" /> <xs:element name="checkPaymentAbility" type="tns:checkPaymentAbility" /> <xs:element name="checkPaymentAbilityResponse" type="tns:checkPaymentAbilityResponse" /> <xs:element name="getBillList" type="tns:getBillList" /> <xs:element name="getBillListResponse" type="tns:getBillListResponse" /> <xs:element name="getPayment" type="tns:getPayment" /> <xs:element name="getPaymentResponse" type="tns:getPaymentResponse" /> <xs:element name="getPaymentsList" type="tns:getPaymentsList" /> <xs:element name="getPaymentsListResponse" type="tns:getPaymentsListResponse" /> <xs:element name="setPayment" type="tns:setPayment" /> <xs:element name="setPaymentResponse" type="tns:setPaymentResponse" /> - <xs:complexType name="checkPaymentAbility"> - <xs:sequence> <xs:element minOccurs="0" name="request" type="tns:abilityRequest" /> </xs:sequence> </xs:complexType> - <xs:complexType name="abilityRequest"> - <xs:complexContent> - <xs:extension base="tns:baseRequest"> - <xs:sequence> <xs:element name="amount" type="xs:float" /> <xs:element minOccurs="0" name="contractCode" type="xs:string" /> <xs:element minOccurs="0" name="createDate" type="xs:dateTime" /> <xs:element minOccurs="0" name="firmCode" type="xs:string" /> <xs:element minOccurs="0" name="foreignId" type="xs:string" /> <xs:element minOccurs="0" name="service" type="xs:string" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType abstract="true" name="baseRequest"> - <xs:sequence> <xs:element minOccurs="0" name="paymentSystem" type="xs:string" /> </xs:sequence> </xs:complexType> - <xs:complexType name="checkPaymentAbilityResponse"> - <xs:sequence> <xs:element minOccurs="0" name="return" type="tns:abilityResponse" /> </xs:sequence> </xs:complexType> - <xs:complexType name="abilityResponse"> - <xs:complexContent> - <xs:extension base="tns:baseResponse"> <xs:sequence /> </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType abstract="true" name="baseResponse"> - <xs:sequence> <xs:element minOccurs="0" name="paymentSystem" type="xs:string" /> <xs:element minOccurs="0" name="requestStatus" type="tns:requestStatus" /> </xs:sequence> </xs:complexType> - <xs:complexType name="requestStatus"> - <xs:sequence> <xs:element name="id" type="xs:int" /> <xs:element minOccurs="0" name="name" type="xs:string" /> </xs:sequence> </xs:complexType> - <xs:complexType name="setPayment"> - <xs:sequence> <xs:element minOccurs="0" name="request" type="tnsaymentRequest" /> </xs:sequence> </xs:complexType> - <xs:complexType name="paymentRequest"> - <xs:complexContent> - <xs:extension base="tns:abilityRequest"> <xs:sequence /> </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType name="setPaymentResponse"> - <xs:sequence> <xs:element minOccurs="0" name="return" type="tnsaymentResponse" /> </xs:sequence> </xs:complexType> - <xs:complexType name="paymentResponse"> - <xs:complexContent> - <xs:extension base="tns:abilityResponse"> - <xs:sequence> <xs:element minOccurs="0" name="payment" type="tnsayment" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType name="payment"> - <xs:sequence> <xs:element name="amount" type="xs:float" /> <xs:element minOccurs="0" name="contractCode" type="xs:string" /> <xs:element minOccurs="0" name="createDate" type="xs:dateTime" /> <xs:element minOccurs="0" name="execDate" type="xs:dateTime" /> <xs:element minOccurs="0" name="firmCode" type="xs:string" /> <xs:element minOccurs="0" name="foreignId" type="xs:string" /> <xs:element name="id" type="xs:long" /> <xs:element minOccurs="0" name="paymentStatus" type="tnsaymentStatus" /> <xs:element minOccurs="0" name="paymentSystem" type="tnsaymentSystem" /> <xs:element minOccurs="0" name="service" type="tns:service" /> </xs:sequence> </xs:complexType> - <xs:complexType name="paymentStatus"> - <xs:sequence> <xs:element name="id" type="xs:int" /> <xs:element minOccurs="0" name="name" type="xs:string" /> </xs:sequence> </xs:complexType> - <xs:complexType name="paymentSystem"> - <xs:sequence> <xs:element name="id" type="xs:int" /> <xs:element minOccurs="0" name="name" type="xs:string" /> </xs:sequence> </xs:complexType> - <xs:complexType name="service"> - <xs:sequence> <xs:element name="id" type="xs:long" /> <xs:element minOccurs="0" name="shortName" type="xs:string" /> </xs:sequence> </xs:complexType> - <xs:complexType name="getPayment"> - <xs:sequence> <xs:element minOccurs="0" name="request" type="tns:statusRequest" /> </xs:sequence> </xs:complexType> - <xs:complexType name="statusRequest"> - <xs:complexContent> - <xs:extension base="tnsaymentRequest"> - <xs:sequence> <xs:element minOccurs="0" name="payment" type="tnsayment" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType name="getPaymentResponse"> - <xs:sequence> <xs:element minOccurs="0" name="return" type="tns:statusResponse" /> </xs:sequence> </xs:complexType> - <xs:complexType name="statusResponse"> - <xs:complexContent> - <xs:extension base="tnsaymentResponse"> <xs:sequence /> </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType name="getPaymentsList"> - <xs:sequence> <xs:element minOccurs="0" name="request" type="tnsaymentsListRequest" /> </xs:sequence> </xs:complexType> - <xs:complexType name="paymentsListRequest"> - <xs:complexContent> - <xs:extension base="tns:baseRequest"> - <xs:sequence> <xs:element minOccurs="0" name="endDate" type="xs:dateTime" /> <xs:element minOccurs="0" name="firmCode" type="xs:string" /> <xs:element minOccurs="0" name="service" type="xs:string" /> <xs:element minOccurs="0" name="startDate" type="xs:dateTime" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType name="getPaymentsListResponse"> - <xs:sequence> <xs:element minOccurs="0" name="return" type="tnsaymentsListResponse" /> </xs:sequence> </xs:complexType> - <xs:complexType name="paymentsListResponse"> - <xs:complexContent> - <xs:extension base="tns:baseResponse"> - <xs:sequence> <xs:element maxOccurs="unbounded" minOccurs="0" name="payments" nillable="true" type="tnsayment" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType name="getBillList"> - <xs:sequence> <xs:element minOccurs="0" name="request" type="tns:billListRequest" /> </xs:sequence> </xs:complexType> - <xs:complexType name="billListRequest"> - <xs:complexContent> - <xs:extension base="tnsaymentsListRequest"> - <xs:sequence> <xs:element minOccurs="0" name="contractCode" type="xs:string" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType name="getBillListResponse"> - <xs:sequence> <xs:element minOccurs="0" name="return" type="tns:billListResponse" /> </xs:sequence> </xs:complexType> - <xs:complexType name="billListResponse"> - <xs:complexContent> - <xs:extension base="tns:baseResponse"> - <xs:sequence> <xs:element maxOccurs="unbounded" minOccurs="0" name="bills" nillable="true" type="tns:bill" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> - <xs:complexType name="bill"> - <xs:sequence> <xs:element name="amount" type="xs:float" /> <xs:element minOccurs="0" name="barcode" type="xs:string" /> <xs:element minOccurs="0" name="beginDate" type="xs:dateTime" /> <xs:element minOccurs="0" name="contractCode" type="xs:string" /> <xs:element name="debt" type="xs:float" /> <xs:element minOccurs="0" name="endDate" type="xs:dateTime" /> <xs:element minOccurs="0" name="firmCode" type="xs:string" /> <xs:element name="id" type="xs:long" /> <xs:element minOccurs="0" name="sentDate" type="xs:dateTime" /> <xs:element minOccurs="0" name="service" type="tns:service" /> </xs:sequence> </xs:complexType> - <xs:complexType name="checkContractByCode"> - <xs:sequence> <xs:element minOccurs="0" name="code" type="xs:string" /> </xs:sequence> </xs:complexType> - <xs:complexType name="checkContractByCodeResponse"> - <xs:sequence> <xs:element minOccurs="0" name="return" type="tns:checkContractResponse" /> </xs:sequence> </xs:complexType> - <xs:complexType name="checkContractResponse"> - <xs:sequence> <xs:element minOccurs="0" name="address" type="xs:string" /> <xs:element minOccurs="0" name="city" type="xs:string" /> <xs:element minOccurs="0" name="contractCode" type="xs:string" /> <xs:element minOccurs="0" name="requestStatus" type="tns:requestStatus" /> <xs:element minOccurs="0" name="subscriberFullName" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:schema> </types> - <message name="PayService_setPayment"> <part element="tns:setPayment" name="setPayment" /> </message> - <message name="PayService_getPayment"> <part element="tns:getPayment" name="getPayment" /> </message> - <message name="PayService_getPaymentsList"> <part element="tns:getPaymentsList" name="getPaymentsList" /> </message> - <message name="PayService_checkPaymentAbilityResponse"> <part element="tns:checkPaymentAbilityResponse" name="checkPaymentAbilityResponse" /> </message> - <message name="PayService_checkContractByCode"> <part element="tns:checkContractByCode" name="checkContractByCode" /> </message> - <message name="PayService_setPaymentResponse"> <part element="tns:setPaymentResponse" name="setPaymentResponse" /> </message> - <message name="PayService_getPaymentResponse"> <part element="tns:getPaymentResponse" name="getPaymentResponse" /> </message> - <message name="PayService_getBillListResponse"> <part element="tns:getBillListResponse" name="getBillListResponse" /> </message> - <message name="PayService_getBillList"> <part element="tns:getBillList" name="getBillList" /> </message> - <message name="PayService_checkPaymentAbility"> <part element="tns:checkPaymentAbility" name="checkPaymentAbility" /> </message> - <message name="PayService_checkContractByCodeResponse"> <part element="tns:checkContractByCodeResponse" name="checkContractByCodeResponse" /> </message> - <message name="PayService_getPaymentsListResponse"> <part element="tns:getPaymentsListResponse" name="getPaymentsListResponse" /> </message> - <portType name="PayService"> - <operation name="checkContractByCode" parameterOrder="checkContractByCode"> <input message="tnsayService_checkContractByCode" /> <output message="tnsayService_checkContractByCodeResponse" /> </operation> - <operation name="checkPaymentAbility" parameterOrder="checkPaymentAbility"> <input message="tnsayService_checkPaymentAbility" /> <output message="tnsayService_checkPaymentAbilityResponse" /> </operation> - <operation name="getBillList" parameterOrder="getBillList"> <input message="tnsayService_getBillList" /> <output message="tnsayService_getBillListResponse" /> </operation> - <operation name="getPayment" parameterOrder="getPayment"> <input message="tnsayService_getPayment" /> <output message="tnsayService_getPaymentResponse" /> </operation> - <operation name="getPaymentsList" parameterOrder="getPaymentsList"> <input message="tnsayService_getPaymentsList" /> <output message="tnsayService_getPaymentsListResponse" /> </operation> - <operation name="setPayment" parameterOrder="setPayment"> <input message="tnsayService_setPayment" /> <output message="tnsayService_setPaymentResponse" /> </operation> </portType> - <binding name="PayServiceBinding" type="tnsayService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> - <operation name="checkContractByCode"> <soapperation soapAction="" /> - <input> <soap:body use="literal" /> </input> - <output> <soap:body use="literal" /> </output> </operation> - <operation name="checkPaymentAbility"> <soapperation soapAction="" /> - <input> <soap:body use="literal" /> </input> - <output> <soap:body use="literal" /> </output> </operation> - <operation name="getBillList"> <soapperation soapAction="" /> - <input> <soap:body use="literal" /> </input> - <output> <soap:body use="literal" /> </output> </operation> - <operation name="getPayment"> <soapperation soapAction="" /> - <input> <soap:body use="literal" /> </input> - <output> <soap:body use="literal" /> </output> </operation> - <operation name="getPaymentsList"> <soapperation soapAction="" /> - <input> <soap:body use="literal" /> </input> - <output> <soap:body use="literal" /> </output> </operation> - <operation name="setPayment"> <soapperation soapAction="" /> - <input> <soap:body use="literal" /> </input> - <output> <soap:body use="literal" /> </output> </operation> </binding> - <service name="PayService"> - <port binding="tnsayServiceBinding" name="PayServicePort"> <soap:address location="https://******/PayService" /> </port> </service> </definitions> [/css] буду весьма признателен
Я уже пытался работать с ней нескольку раз. Пока остались одни негативные отзывы. Даже где-то читал, что soap - это epic fail, всем только мозг трахает.
Вы гоните оба. Kreker тут Единственная там сложность это комплексные типы chiffa тут ты полагаешь что wsdl удобно читать в том виде как ты дал? Это то, что ты должен им отправить. checkPaymentAbility Бери создавай запрос и смотри xml который он формирует. Пока не будет соответствовать описанию в wsdl ничего у тебя не заработает. Это то, что тебе придет в ответ. checkPaymentAbilityResponse P.S. поставь Eclipse, там есть инструменты для работы с wsdl
Спасибо за ответ! Но я ведь и отправляю checkPaymentAbility... $sc = $client->__call( "checkPaymentAbility", не подскажешь как я могу вывести отправляемый запрос?....
Да, но это не совсем так Я в свое время имел многонедельный секс с этим вопросом и мне так и не удалось затолкнуть некоторые значения в атрибуты пришлось формировать XML ручками Подскажу. http://ua2.php.net/soap Смотреть Код (Text): getLastRequest() getLastRequestHeaders() getLastResponse() getLastResponseHeaders()
chiffa И да, вот в чем ерунда еще Там есть checkPaymentAbility - метод сервиса и checkPaymentAbility - тип данных Я говорил о втором. [css] <xs:complexType name="checkPaymentAbility"> <xs:sequence> <xs:element minOccurs="0" name="request" type="tns:abilityRequest" /> </xs:sequence> </xs:complexType> <xs:complexType name="abilityRequest"> <xs:complexContent> <xs:extension base="tns:baseRequest"> <xs:sequence> <xs:element name="amount" type="xs:float" /> <xs:element minOccurs="0" name="contractCode" type="xs:string" /> <xs:element minOccurs="0" name="createDate" type="xs:dateTime" /> <xs:element minOccurs="0" name="firmCode" type="xs:string" /> <xs:element minOccurs="0" name="foreignId" type="xs:string" /> <xs:element minOccurs="0" name="service" type="xs:string" /> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType>[/css]
А как их правильно разделить?... тоесть как указать что мне нужно отправлять тип данных, а не метод сервиса?.....
и PHP: echo "Request :<br>". $soapClient->__getLastRequest(). "<br>"; echo "Response :<br>". $soapClient->__getLastResponse(). "<br>"; ничего не возвращяет....
Брр. Чтобы они что-то вернули, надо что-то отправить для начала. PHP: <?php $soap->login($user, $pass); var_dump($soap->__getLastRequest()); Плюс стоит все же читать документацию http://ua2.php.net/manual/en/soapclient.soapclient.php Код (Text): SoapClient("some.wsdl", array('trace' => 1));
метод это то что ты вызываешь Код (Text): $soap->callmethod($callparam); А тип данных это относится к $callparam
попробуй открыть в браузере https://*********/PayService?wsdl если сервис реализован на .Net, то откроется вполне вменяемая документация к нему. во всяком случае будет видно, какие параметры он ждет.. кмк, гораздо удобнее вызывать $client->checkPaymentAbility( params ); в php-коде выглядит куда более читаемо и низкоуровневую работу берет на себя php_soap
Вот это не совсем соответсвует действительности параметры таки надо будет формировать хитрым образом.
под "низкоуровневой работой" - понимается проверка параметров, запарсивание данных в валидный хмль и распарсивание ответа... то есть ты просто передаешь правильные параметры (при этом даже тип неособо важен ... все само переварится как надо), и используешь ответ ... php_soap - мощная штука ! нужно только смотреть как передаешь параметры иногда передать массива [array ("paymentSystemtest"=>"test", "contractCode"=>"57971", "service"=>"bb")] недостаточно , а надо еще раз упаковать все в массив [array('request'=>array ("paymentSystemtest"=>"test", "contractCode"=>"57971", "service"=>"bb"))] - для этого достаточно посмотреть на всдль (при достаточном опыте) или просто попробовать ... кстати есть еще фокус - при httpS, если сертификат не валидный может произойти отказ работы сервиса, и тогда надо настройками подрулить (мне тут админ помог, что-то там разрешил, и всдль я получил )
знаю знаю, а вот ты не знаешь потому и понтуешься ;-)- но ведь сейчас не тот случай ... ошибка "Invalid number of payload elements:" говорит о неверной передачи параметров ...
Вот именно об этом я и говорю. И всего лишь "еще раз упаковать в массив" - не все там так просто PHP: <?php $ppo = new StdClass(); $ppo->login = 'aaa'; $ppo->role = 'bbb'; $ppo->pass = 'ccc'; $var = new SoapVar( $ppo, SOAP_ENC_OBJECT, 'passport', 'https://webservices.netsuite.com/xsd/platform/v2008_1_0/core.xsd', 'passport', '' . $this->urnMessages . '' ); $wrapper = new SoapParam($var, "passport"); $inp = new SoapHeader('' . $this->urnMessages . '', 'loginResponse'); self::$client->__SoapCall('login', array($wrapper), array('soapaction' => 'login'), null, $inp); Малость отличается от просто упаковать в массив не так ли?
Simpliest - есть и такие ситуации - насколько понял при кривом всдлье приходится прибегать к этому методу , у меня получилось этого избежать (сначала я делал так, а потом опробовал просто массив впихнуть и он схавал , допускаю что не во всех сервисах это прокатит) ой у тебя вроде не на базе всдлья .....
Да был там wsdl хитросделанный. Я так и не понял по какому правилу свойства одного уровня некоторые идут в атрибуты xml, а некоторые в ноды Вобщем массивы на 4-5 уровней вложенностей у меня были, и не сильно помогли. Вечно какой-нибудь гаденыш выскакивал в ноду, вместо атрибута и наоборот Так что wsdl пришлось отключить.
Simpliest - ;-) понимаю меня пока бог миловал - я просто пока разбирался малек поднабрался - вообще соап несложен - отладка и мозг ...
Несостыковка =) Если не сложно - напиши какой-нибудь мануал. В инете примеров крайне мало. Пробовал сам тыкаться, на форуме спрашивал. Но так и не решил проблему. Так и не понял, чья вина: моя или сервера (у нас своя система, связаться с программером не удалось).