0x00 はじめに
私は最近インターフェイスを書いています。これまで、インターフェイスのデータ送信は json または xml 形式を使用して送信または取得されていました。しかし今回、サードパーティと共同でデバッグする際に、彼らは wsdl 形式を提供してくれました。すぐに SB に変更されました...
テスト コードを Google で検索すると、テストはサードパーティのインターフェイスを呼び出してステータス 200 を返します。このまま何も起こらなければ終わるだろうと思っていたのですが、近づいてみると、インターフェースをいくら呼び出しても正しいデータが返ってこないことが分かりました。その後、ログを確認したところ、渡されたパラメータをまったく受け取っていないことがわかり、問題を解決するまで、午後から夕方まで混乱していました。なかなか興味深い内容だったので、まずは書いてみました。
0x01 wsdl とは何ですか? 誰かの話によると、Web サーバーの定義を記述するために使用される XML 形式のドキュメント、つまり Web サーバーのメソッドとパラメーターの記述です。
参照: http://baike.baidu.com/link?url=R7x3FdekxbndR4SlzQLZE_2m1ebpt_SWt9IMjoHSErvLlbZ3-hwhR3ERrinXS1xZaDvkYFpxWnUchrk34_WkZq
http://api.test.cn/xwebservice をリクエストする場合「wsdl」、このように終わるのはいつですか? wsdl の URL を設定すると、一連の XML 構造化データが提供されます。
そうです、ただのしこりです…
次に、それをどう理解するか、それに書かれている方法が鍵で、それ以外は無駄です。
0x02 説明ドキュメントの理解
この XML ドキュメントを最初に見たとき、私は混乱しましたが、PHP 拡張機能を使用した後、より明確になりました。
<?php $client = new SoapClient('http://api.test.cn/xwebservices/testServer?wsdl'); print "\n提供的方法\n"; print_r($client->__getFunctions()); print "相关的数据结构\n"; print_r($client->__getTypes()); print "\n\n";
ここではSOAP拡張機能を使用します。この拡張機能は、最終的には、パラメータの送信を実現するためにも使用されます。
上の図からわかるように、このインターフェイスには次の 3 つのメソッドが用意されています。
xxxxUserInfo
xxxxResumeNum
download**
関連するデータ構造は、メソッド内のパラメータ名とパラメータ タイプを参照します。たとえば、xxxxUserInfo メソッドには 3 つの文字列型パラメータが必要です。それぞれ in0、in1、in2 に対応します。
注意
ここでのパラメーター キーは in0 である必要があります。これは、配列を必要としない任意のパラメーター名であり、ユーザー定義か、双方が合意したものです。インターフェイス メソッドの作成を開始したとき、err_msg (エラー情報を示す)、err_code (エラー コーディングを示す)、および date (送信される最終データ) など、インターフェイス コピーに指定されているパラメーターの説明に基づいて送信を実行しました。次に、それを順序付き配列に変更し、対応するパラメータを 1 つずつ入力します。このとき、キーは 0 ~ 2 です。しかし、試してみてもやはりうまくいきませんでした。最後に、試してみようという気持ちで、キー名として int0 を、値として対応する err_msg の内容を使用してみました。 OK~、完璧な解決策です。
コード:
<?php /** * @author 0x584A * 获取WSDL接口数据 */ class getwsdlTest extends PHPUnit_Framework_TestCase { public $apiurl = 'http://api.test.cn/xwebservices/testServer?wsdl'; private static $soapClientHandler; private $infoArr = [ 'err_msg' => 'false', 'err_code' => '0', 'date' => '此处是要传输的数据' ]; public function setUp() { $client = new SoapClient('http://api.test.cn/xwebservices/testServer?wsdl'); print "提供的方法\n"; print_r($client->__getFunctions()); print "相关的数据结构\n"; print_r($client->__getTypes()); print "\n\n"; } /** * xxxxUserInfo方法 */ public function testxxxxUserInfoData() { try { $ApiInfo = $this->infoArr; //set request param $parameter = array( 'in0' => $ApiInfo['err_msg'], 'in1' => $ApiInfo['err_code'], 'in2' => $ApiInfo['date'] ); $result = $this->getSoapClientHandler()->synchUserInfo($parameter); //调用结果返回异常 if (!$result instanceof stdClass) { throw new Exception("调用synchUserInfo结果出现异常:" . json_encode($result)); } //调用接口状态码,输出对应错误详情 if ($result->out == '01') { throw new Exception("调用synchUserInfo=>error:" . $result->out . ",msg:接口数据异常"); } $xml_parser = xml_parser_create(); if (!xml_parse($xml_parser, $result->out, true)) { xml_parser_free($xml_parser); throw new Exception("调用synchUserInfo返回的不是一个xml结构体"); } xml_parser_free($xml_parser); //XXE libxml_disable_entity_loader(true); $xml = simplexml_load_string($result->out, 'SimpleXMLElement', LIBXML_NOCDATA); // 输出参数 var_dump($xml->data); echo " 成功".PHP_EOL; } catch (SoapFault $soapFault) { throw new Exception($soapFault->getMessage() . $this->getSoapClientHandler()->__getLastResponse()); } } /** * @description getSoapClientHandler */ public function getSoapClientHandler() { if (!self::$soapClientHandler) { self::$soapClientHandler = new SoapClient($this->getSynchApi()); } return self::$soapClientHandler; } /** * @description getSynchApi */ public function getSynchApi() { return $this->apiurl; } } ?>