Androidのアプリケーションから1C Webサービスを操作します

カフェフロントで作業しているときに、Androidで開発されたアプリケーションから1C Webサービスにアクセスするというタスクが発生しました。 Googleは、 ksoap2-androidライブラリを使用して一般的にSOAPを操作する方法のトピックに関するいくつかの答えをくれました。 彼らは単純な型を渡すのに役立ちましたが、配列を渡すことになると、少し考えなければなりませんでした。



1C側のWebサービス



1C構成では、WriteSaleメソッドを使用したWebサービスが作成されました。 このメソッドはいくつかのパラメーターを取り、そのうちの1つはアイテムで、ItemsSold(XDTO構成パッケージで指定)タイプです。 残りのパラメーターは単純型(文字列、日時)です。 画面構成:







ItemsSold型には、Maximum Quantityプロパティが-1に設定されている単一のItemsプロパティがあり、配列であることを示します。 このプロパティのタイプはItemSoldです。 画面:







ItemSoldには、単純型のすべてのプロパティがあります。 WebサービスのWriteSaleメソッドには次のコードがあります。



 WriteSale(id, date, clientCardNumber, discountRate, items, deptId, bonuses, premiumBonuses)  = "OK";   = (clientCardNumber);  = (discountRate);  = (deptId); //...  = (date, (id), );   ()   = ..(); . = date; . = id;   = .(); ; . = (bonuses); //... ..(); //       item  items.Items   = (item.Code);  = ..(); . = (item.Quantity); //... ; .(.);   = (); ("Cafe.WriteSale - : " + , .); ; ; //     ""  ; 
      
      







Androidクライアント





AndroidアプリケーションからWebサービスにアクセスするために、次のコードを作成しました( 単純なクライアントの良い例に従って)。



 protected String call() throws Exception { result = null; HttpTransportSE httpTransport = new HttpTransportSE(uri); httpTransport.debug = true; String resultString; SoapObject request = new SoapObject(namespace, methodName); request.addProperty("id", sale.getId()); SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss"); request.addProperty("date", dateFormat.format(sale.getDate())); request.addProperty("clientCardNumber", sale.getCardNumber()); request.addProperty("bonuses", Double.toString(sale.getBonuses())); //... // see - http://code.google.com/p/ksoap2-android/wiki/CodingTipsAndTricks#Adding_an_array_of_complex_objects_to_the_request SoapObject sales = new SoapObject(namespace, "items"); for (SaleItemInformation item : sale.getSales()) { SoapObject itemSoap = new SoapObject(namespace, "Items"); itemSoap.addProperty("Code", item.getItem().getSourceCode()); itemSoap.addProperty("Quantity", Double.toString(item.getQuantity())); //... sales.addSoapObject(itemSoap); } request.addSoapObject(sales); SoapSerializationEnvelope envelope = new SoapSerializationEnvelope( SoapEnvelope.VER11); //    -       xml envelope.implicitTypes = true; envelope.setOutputSoapObject(request); try { httpTransport.call(soapAction, envelope); } catch (Exception e) { e.printStackTrace(); throw e; } resultString = envelope.getResponse().toString(); return resultString; }
      
      







コードは正しく見え、美しいxml-requestを生成しているようです:



 <v:Envelope xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://www.w3.org/2001/XMLSchema" xmlns:c="http://schemas.xmlsoap.org/soap/encoding/" xmlns:v="http://schemas.xmlsoap.org/soap/envelope/"> <v:Header /> <v:Body> <n0:WriteSale id="o0" c:root="1" xmlns:n0="http://www.xxxxx.ru"> <date i:type="d:string">Thu May 31 16:13:08 YEKST 2012</date> <clientCardNumber i:type="d:string">120</clientCardNumber> <discountRate i:type="d:string">5.0</discountRate> <id i:type="d:long">11</id> <n0:items i:type="n0:items"> <n0:Items i:type="n0:Items"> <Code i:type="d:string">3000</Code> <Price i:type="d:string">100.0</Price> <Quantity i:type="d:string">2.0</Quantity> <Sum i:type="d:string">200.0</Sum> </n0:Items> <n0:Items i:type="n0:Items"> <Code i:type="d:string">3001</Code> <Price i:type="d:string">110.0</Price> <Quantity i:type="d:string">1.0</Quantity> <Sum i:type="d:string">110.0</Sum> </n0:Items> </n0:items> </n0:WriteSale> </v:Body> </v:Envelope>
      
      







ただし、Webサービスは500番目のエラーで応答します。 同時に、同じWebサービスで単純なタイプのパラメーターを持つ別のメソッドを参照すると、正しい答えが得られます。 さらに、上記のWebサービスメソッドへのWSリンクを介して別の1Cデータベースから参照すると、Webサービス側で正しい答えと必要なアクションを取得します。 したがって、別の1Cベースによって生成された要求をインターセプトする必要がありました。 フィードラーを使用してこれを行うことはできませんでした。XMLを使用してリクエストの本文を何らかの形で切断し、Webサービスに渡さなかったためです。 通常、 WireSharkの助けを借りてのみリクエストをインターセプトすることができました。 したがって、1Cからのリクエストテキスト:



 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header/> <soap:Body> <m:WriteSale xmlns:m="http://www.xxxxx.ru"> <m:id xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">1</m:id> <m:date xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">2</m:date> <m:clientCardNumber xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">3</m:clientCardNumber> <m:discountRate xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">4</m:discountRate> <m:items xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <m:Items> <m:Code>123</m:Code> <m:Price>12.2</m:Price> <m:Quantity>2</m:Quantity> <m:Sum>2</m:Sum> </m:Items> <m:Items> <m:Code>2</m:Code> <m:Price>1</m:Price> <m:Quantity>2</m:Quantity> <m:Sum>2</m:Sum> </m:Items> </m:items> </m:WriteSale></soap:Body> </soap:Envelope>
      
      







配列のネストされた要素(コード、価格など)については、ksoap2-androidライブラリが名前空間の接頭辞を持たないことに気付くのは簡単です。 ルート要素(id、date ...)についても、それらは付加されませんが、この事実は1Cをst迷に導入しません。 また、サブ要素にそれらが存在しないと、プログラムは入力データの正確性を疑います;それらを読み取ることはできません。



ライブラリコードを調べた後、 SoapObject#addProperty(String、Object)メソッドを次のように変更することが最も合理的であると判断しました。



 public static class SoapObjectCustom extends SoapObject { public SoapObjectCustom(String namespace, String name) { super(namespace, name); } @Override public SoapObject addProperty(String name, Object value) { PropertyInfo propertyInfo = new PropertyInfo(); propertyInfo.name = name; propertyInfo.type = value == null ? PropertyInfo.OBJECT_CLASS : value.getClass(); propertyInfo.setValue(value); //    propertyInfo.setNamespace(this.namespace); return addProperty(propertyInfo); } }
      
      







ソースコードでは、次の場所でSoapObjectをSoapObjectCustomに置き換えました。



 //... SoapObjectCustom request = new SoapObjectCustom(namespace, methodName); //... SoapObject sales = new SoapObject(namespace, "items"); for (SaleItemInformation item : sale.getSales()) { SoapObjectCustom itemSoap = new SoapObjectCustom(namespace, "Items"); //... } //...
      
      







おわりに





おそらく、著者が要素のプロパティに名前空間プレフィックスを含めなかったことは理にかなっています。 また、他のWebサービスと連携する際に、このような調整がプログラムの不適切な動作につながる可能性は十分にあります。 それでも、この方法は1C Webサービスで機能します。この説明が誰かの仕事に役立つことを願っています。



上記は、1C v.8.2.15.294およびAndroid 12(3.0)でテストされました。



All Articles