SMART LLC

SOAP APIと通信する方法(PHP)

公開日:2015/08/11

PHPでSOAPを使用する方法をメモする。
今回もwww.webservicex.netのConversionRateを試してみる。
VB.NET版は.NETアプリケーションでSOAP通信する方法を参照。

SOAPデータの生成

SoapVarクラスを使う。

$soap_param = new SoapVar(array (
	new SoapVar('USD', XSD_STRING, null, null, 'FromCurrency','http://www.webserviceX.NET/'),
	new SoapVar('JPY', XSD_STRING, null, null, 'ToCurrency','http://www.webserviceX.NET/')
),SOAP_ENC_OBJECT);

コンストラクタのパラメータがややこしい。
第一パラメータは値で第五パラメータがキー。
第二パラメータは文字列の要素の場合はXSD_STRING、配列の要素の場合はSOAP_ENC_OBJECTを指定すればOK(言い方が正しいか微妙)
第三パラメータ、第四パラメータはわからないからnullでOK。
第六パラメータは名前空間のURL。

SOAPデータの送信

SoapClientクラスを使う。

$soap_client = new SoapClient('http://www.webservicex.net/CurrencyConvertor.asmx?WSDL');
$soap_client->__setLocation('http://www.webservicex.net/CurrencyConvertor.asmx');
$result = $soap_client->ConversionRate($soap_param);

コンストラクタでWSDLファイルの場所を指定。
__setLocation()でエンドポイントを指定。
ConversionRateは呼び出すメソッド名。ここにSoapVarを指定すればOK。

送信リクエストの確認

リクエストの内容を確認してみる。

$soap_client = new SoapClient('http://www.webservicex.net/CurrencyConvertor.asmx?WSDL', array('trace' => true));
$soap_client->__setLocation('http://www.webservicex.net/CurrencyConvertor.asmx');
$result = $soap_client->ConversionRate($soap_param);
echo $soap_client->__getLastRequest() ;

SoapClientのコンストラクタの第二パラメータでオプションを指定できる。
traceオプションをtrueにすると__getLastRequest()で直近のリクエストの内容を出力することができる。

できてる。

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.webserviceX.NET/">
 <SOAP-ENV:Body>
  <ns1:ConversionRate>
   <ns1:FromCurrency>USD</ns1:FromCurrency>
   <ns1:ToCurrency>JPY</ns1:ToCurrency>
  </ns1:ConversionRate>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

__getLastResponse()で直近のレスポンスの内容を出力することも可。

受信結果を使用する場合

こんな感じ。

$result = $soap_client->ConversionRate($soap_param);
echo $result->ConversionRateResult;

戻り値はstdClassなので->を使ってアクセスする。
stdClassの形はAPIによって違うのでvar_dumpか何かで確認しながら目的のクラスにアクセスすればいい。

例外処理

SoapFaultクラスを使う。

$soap_client = new SoapClient('http://www.webservicex.net/CurrencyConvertor.asmx?WSDL', array('exceptions' => true));
$soap_client->__setLocation('http://www.webservicex.net/CurrencyConvertor.asmx');

try{
	$result = $soap_client->ConversionRate($soap_param);
} catch(SoapFault $fault){
	throw new Exception('SOAP error: (' .$fault->getCode().')'.$fault->getMessage());
}

オプションでexceptionsにtrueを指定すると、例外が発生した場合にSoapFaultがcatchできるようになる。
catchしたらgetCode()とかgetMessage()でエラーの内容を出力すればいい。

Content-Typeでエラーになる場合

オプションでSOAPのバージョンを指定してやる。

$soap_client = new SoapClient('http://www.webservicex.net/CurrencyConvertor.asmx?WSDL', array('soap_version' => SOAP_1_2));

soap_versionでSOAPのバージョンを指定できる。
デフォルトは1.1。
1.2にする場合はSOAP_1_2を指定する。
1.1だとContent-Typeがtext/xmlになる。
1.2だとContent-Typeがapplication/soap+xmlになる。

要素を自分で書きたい場合

こんな感じ。

new SoapVar('<ns1:test i:nil="true" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>',XSD_ANYXML)

要素にNULLとか属性を持たせたいとか自分で書きたい場合はXSD_ANYXMLを指定すれば文字列でそのまま組み込むことができる。

SOAPヘッダが必要な場合

SOAPヘッダでActionとかToとか指定する必要がある場合はSoapHeaderクラスを使う。

$header = array(
new SoapHeader([名前空間のURL],'Action',[URL],true),
new SoapHeader([名前空間のURL],'To',[URL],true)
);
$soap_client->__setSoapHeaders($header);

1つの場合はそのまま、複数の場合も配列にしてsetSoapHeaders()で設定する。

少し複雑なSOAPデータ

こんな風に書くと…(今回のAPIでは形が違うのでエラーになるけど書き方だけ)

$soap_param = new SoapVar(array (
	new SoapVar('aaa', XSD_STRING, null, null, 'test1'),
	new SoapVar(array(
	    new SoapVar(array(
			new SoapVar('bbb', XSD_STRING, null, null, 'test4'),
			new SoapVar('ccc', XSD_STRING, null, null, 'test5')
		),SOAP_ENC_OBJECT,null,null, 'test3'),
	),SOAP_ENC_OBJECT,null,null, 'test2')
),SOAP_ENC_OBJECT);

こうなる。

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://MyDictionary.jp/SOAPServiceV11">
 <env:Body>
  <ns1:ConversionRate>
   <test1>aaa</test1>
   <test2>
    <test3>
     <test4>bbb</test4>
     <test5>ccc</test5>
    </test3>
   </test2>
  </ns1:ConversionRate>
 </env:Body>
</env:Envelope>

.NETでSOAPプログラム作る時はWSDLから全自動でクラス作ってくれるから簡単だったのにPHPは大変。
WSDLをアップロードするとPHPのクラスつくってくれるサイトとかプログラム公開してる人もいるけど
公式のツールじゃないしあまり得体の知れないものを仕事で使うわけにはいかないから.NETで作ってくれるクラス見ながら自力で書いてる。
なんかもっといい方法あるのかな_(:3 」∠)_

SHARE