プログラマ38の日記

主にプログラムメモです。

Salesforce: 直接XMLでSalesforce APIを操作する

WebServiceSOAPメッセージのデバッグについて書きました。

 

crmprogrammer38.hatenablog.com

 

これを行うことで、SOAPメッセージが拾えるので、xmlをpostして、xmlで結果が返ってくるというシンプルな処理でSOAP APIを行うことができます。wsdlクライアントが使えない場合でも、SOAP APIを操作することができるようになります。

 

例えば、たくさんリストビューを作る作業を考えます。

それぞれのリストビューは「ビュー名」、「一意の名前」、「条件」、「公開先のグループ」が異なるものとします。

1.雛形とするビューを作成します。

2.一度xmlを取得するため次のプログラムを実行します。(wscでの作成しました)

import com.sforce.soap.metadata.ListView;
import com.sforce.soap.metadata.Metadata;
import com.sforce.soap.metadata.MetadataConnection;
import com.sforce.soap.metadata.ReadResult;
import com.sforce.soap.metadata.UpsertResult;
import com.sforce.soap.partner.LoginResult;
import com.sforce.soap.partner.PartnerConnection;
import com.sforce.ws.ConnectorConfig;


public class DebugSoapMessage {

public static void main(String[] args) throws Exception{

ConnectorConfig soapConfig = new ConnectorConfig();
soapConfig.setManualLogin(true);
soapConfig.setPrettyPrintXml(true);
//soapConfig.setTraceMessage(true);
soapConfig.setServiceEndpoint("https://login.salesforce.com/services/Soap/u/40.0");

PartnerConnection pCon = new PartnerConnection(soapConfig);

LoginResult lResult = pCon.login("sample@sample.user", "samplepassword");
pCon.setSessionHeader(lResult.getSessionId());
soapConfig.setServiceEndpoint(lResult.getServerUrl());


ConnectorConfig metaConfig = new ConnectorConfig();
metaConfig.setServiceEndpoint(lResult.getMetadataServerUrl());
metaConfig.setSessionId(lResult.getSessionId());
metaConfig.setPrettyPrintXml(true);

MetadataConnection mCon = new MetadataConnection(metaConfig);
//雛形のビューを指定する。
ReadResult rResult = mCon.readMetadata("ListView", new String[]{"Object1__c.v01"});

ListView lView = (ListView)rResult.getRecords()[0];

//upsert時に送るSOAPメッセージをデバッグ
metaConfig.setTraceMessage(true);

UpsertResult[] result = mCon.upsertMetadata(new Metadata[]{lView});
}
}

3.実行結果のxmlを取得します

WSC: Creating a new connection to https://insntanceurl/services/Soap/m/40.0/metaurlsuffix Proxy = DIRECT username null
------------ Request start ----------
<?xml version="1.0" encoding="UTF-8"?><env:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Header>
<SessionHeader xmlns="http://soap.sforce.com/2006/04/metadata">
<sessionId>sessionidstring</sessionId>
</SessionHeader>
</env:Header>
<env:Body>
<m:upsertMetadata xmlns:m="http://soap.sforce.com/2006/04/metadata" xmlns:sobj="null">
<m:metadata xsi:type="m:ListView">
<m:fullName>Object1__c.v01</m:fullName>
<m:booleanFilter>1 AND (2 or 3)</m:booleanFilter>
<m:columns>NAME</m:columns>
<m:columns>TextField__c</m:columns>
<m:columns>ango__c</m:columns>
<m:columns>NumberField__c</m:columns>
<m:filterScope>Mine</m:filterScope>
<m:filters>
<m:field>TextField__c</m:field>
<m:operation>notEqual</m:operation>
</m:filters>
<m:filters>
<m:field>NumberField__c</m:field>
<m:operation>equals</m:operation>
</m:filters>
<m:filters>
<m:field>NumberField__c</m:field>
<m:operation>greaterThan</m:operation>
<m:value>100</m:value>
</m:filters>
<m:label>ビューラベル名</m:label>
<m:language>ja</m:language>
<m:sharedTo>
<m:allInternalUsers></m:allInternalUsers>
</m:sharedTo>
</m:metadata>
</m:upsertMetadata>
</env:Body>
</env:Envelope>
------------ Request end ----------
Transfer-Encoding=[chunked]
null=[HTTP/1.1 200 OK]
Content-Encoding=[gzip]
Vary=[Accept-Encoding]
Set-Cookie=[BrowserId=pEJTCUgNTt-2qJS20bKByA;Path=/;Domain=.salesforce.com;Expires=Fri, 06-Oct-2017 03:45:53 GMT]
Expires=[Thu, 01 Jan 1970 00:00:00 GMT]
Date=[Mon, 07 Aug 2017 03:45:53 GMT]
Content-Type=[text/xml; charset=utf-8]
------------ Response start ----------
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://soap.sforce.com/2006/04/metadata">
<soapenv:Body>
<upsertMetadataResponse>
<result>
<created>false</created>
<fullName>Object1__c.v01</fullName>
<success>true</success>
</result>
</upsertMetadataResponse>
</soapenv:Body>
</soapenv:Envelope>
------------ Response end ----------

4.3で取得したリクエストのxmlで置き換えたい箇所の値を変えれば、同じようなリストビューを機械的に作成できます。置き換える値(変える可能性の高い値)は赤文字にしています。

Excelのマクロで"WinHttp.WinHttpRequest"を使うと便利です。

もちろん、マクロ内では、endponitのURLの指定と共に、httpヘッダに

Content-Type: text/xml; charset=utf-8
SOAPAction: ""

の指定が必要です。(Excelマクロでtls1.1以上の通信ができる前提ですが)

 

所感

例としてリストビューでしたが、カスタム項目のxmlなど様々なxmlを取得することで便利なツールをExcelマクロで作成できるようになります。

複雑な設定に対応しようとするとマクロも複雑になるのである程度シンプルなものだけツールにして、それ以外は手動で画面から作成するのがいいのだと思います。