Handle SOAP API from Python (Zeep)

Introduction

Do you know the SOAP API? When creating an API, let's create it with SOAP API! This is rarely the case, but depending on the service you use, the SOAP API is rarely provided (personal impression). In this article, I would like to give you an overview of the SOAP API and introduce you to Zepp, Python's SOAP API Client.

SOAP API SOAP Simple Object Access Protocol (SOAP) is a protocol that uses Internet standard technologies such as HTTP and XML.

WSDL Web Services Description Language (WSDL) is an interface description language for web services written in XML. According to the following article (https://www.atmarkit.co.jp/ait/articles/0303/18/news003.html), letting the development tool read the WSDL document will generate the code for the web service module. Seems to have been expected to be

Target

Yahoo's Sponsord Search API is SOAP API, so I'd like to write this in python.

The sample is also php or java so it looks good

Zeep

Let's use Zepp immediately Specify the URL of the WSDL and create a Zepp client object. Let's specify ʻAccount Service` as an example

import zeep
client = zeep.Client(wsdl='https://ss.yahooapis.jp/services/V201901/AccountService?wsdl')

Information that can be read from the WSDL is added to the created object, and a method that calls a call available from the endpoint is also added.

>>> dir(client.service)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__self_class__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__thisclass__', 'get', 'mutate']

Next, check the argument to be passed to the method in WSDL. First, check the header to pass to the SOAP API. The element minOccurs = 1 is required, so be sure to specify it.

<complexType name="SoapHeader">
  <sequence>
    <element maxOccurs="1" minOccurs="1" name="license" type="xsd:string"/>
    <element maxOccurs="1" minOccurs="1" name="apiAccountId" type="xsd:string"/>
    <element maxOccurs="1" minOccurs="1" name="apiAccountPassword" type="xsd:string"/>
    <element maxOccurs="1" minOccurs="0" name="accountId" type="xsd:long"/>
    <element maxOccurs="1" minOccurs="0" name="onBehalfOfAccountId" type="xsd:string"/>
    <element maxOccurs="1" minOccurs="0" name="onBehalfOfPassword" type="xsd:string"/>
  </sequence>
</complexType>
header = {
    "RequestHeader": {
        "license": <LICENSE>,
        "apiAccountId": <API_ACCOUNT_ID>,
        "apiAccountPassword": <API_ACCOUNT_PASSWORD>
    }
}

Next, check the required arguments for the get method. You need to specify the selecter, but it seems you don't need to specify the elements inside the selector

<element name="get">
  <complexType>
    <sequence>
      <element maxOccurs="1" minOccurs="1" name="selector" type="tns:AccountSelector"/>
    </sequence>
  </complexType>
</element>
<complexType name="AccountSelector">
  <sequence>
    <element maxOccurs="unbounded" minOccurs="0" name="accountIds" type="xsd:long"/>
    <element maxOccurs="unbounded" minOccurs="0" name="accountTypes" type="tns:AccountType"/>
    <element maxOccurs="unbounded" minOccurs="0" name="accountStatuses" type="tns:AccountStatus"/>
    <element maxOccurs="1" minOccurs="0" name="paging" type="adv:Paging"/>
  </sequence>
</complexType>
request = {
    "selector": {}
}

Now that we have the arguments to pass to the method, we are ready to call the method, but looking back at the WSDL, we see the following description. You need to get the endpoint prefix from Location Service and switch endpoints. However, since Location Service needs to specify account ID as an argument, Location Service is not known when using Account Service to get the account IDlist. You cannot use. Therefore, specify a fixed value

<wsdl:service name="AccountService">
  <wsdl:port binding="tns:AccountServiceSoapBinding" name="AccountService">
    <wsdlsoap:address location="https://USE_ADDRESS_RETURNED_BY_LOCATION_SERVICE/services/V201901/AccountService"/>
  </wsdl:port>
</wsdl:service>

In Zepp, you can switch the endpoint of the client object by using the create_service method of the Client class. It seems good to switch between the prod environment and the sandbox environment, or connect with the test environment.

service = client.create_service(
    '{http://ss.yahooapis.jp/V201901/Account}AccountServiceSoapBinding',
    'https://ss.yahooapis.jp/services/V201901/AccountService'
)

Now that you have the necessary preparations, use get to get the account ID list. These are the items to check in the WSDL when hitting the SOAP API.

response = service.get(**request, _soapheaders=header)

ʻAccount Serviceswitches the endpoint with a fixed value, but other services switch to the endpoint acquired byLocation Service. For example, if you want to use Campaign Service`, follow the steps below.

location_client = zeep.Client(wsdl='https://ss.yahooapis.jp/services/V201901/LocationService?wsdl')

location_request = {
    "accountId": "{}".format(account_id)
}
res_location_service = location_client.service.get(**location_request, _soapheaders=header)
url_prefix = res_location_service['body']['rval']['value']

campaign_client = zeep.Client(wsdl='https://ss.yahooapis.jp/services/V201901/CampaignService?wsdl')

campaign_request = {
    "selector": {
        "accountId": "{}".format(account_id)
    }
}
campaign_service = campaign_client.create_service(
    '{http://ss.yahooapis.jp/V201901/Campaign}CampaignServiceSoapBinding',
    'https://{}/services/V201901/CampaignService'.format(url_prefix)
)
response_campaign_reports = campaign_service.get(**campaign_request, _soapheaders=header)

Impressions

As an article, it became an explanation of WSDL rather than an introduction to Python and Zepp ... I felt that it was difficult to understand which one was good as a client library for SOAP API, so I decided to consider Zepp when using python. I'm glad if it becomes

References

Recommended Posts

Handle SOAP API from Python (Zeep)
Get schedule from Garoon SOAP API with Python + Zeep
Use e-Stat API from Python
Use kabu Station® API from Python
Use the Flickr API from Python
Get upcoming weather from python weather api
Run Ansible from Python using API
Use Google Analytics API from Python
Collecting information from Twitter with Python (Twitter API)
[Python] Web application from 0! Hands-on (3) -API implementation-
Python: Reading JSON data from web API
Use Google Cloud Vision API from Python
I tried using UnityCloudBuild API from Python
API explanation to touch mastodon from python
Connect to coincheck's Websocket API from Python
sql from python
MeCab from Python
Try accessing the YQL API directly from Python 3
Touch MySQL from Python 3
Operate Filemaker from Python
Translator in Python from Visual Studio 2017 (Microsoft Translator Text API)
Access bitcoind from python
Changes from Python 3.0 to Python 3.5
Changes from Python 2 to Python 3.0
[Python] Get the text of the law from the e-GOV Law API
Python from or import
Push notifications from Python to Android using Google's API
Use MySQL from Python
Run python from excel
Execute command from Python
Handle Excel with python
OpenCV3 Python API list
Handle rabbimq with python
Handle markdown in python
Use MySQL from Python
Hit Watson's REST API from Python on IBM Bluemix
Operate LXC from Python
Manipulate riak from python
Force Python from Fortran
Handle Parquet in Python
Use BigQuery from python.
C API in Python 3
Execute command from python
[Python] Read From Stdin
A little bit from Python using the Jenkins API
Use mecab-ipadic-neologd from python
I tried to create API list.csv in Python from swagger.yaml
Image collection by calling Bing Image Search API v5 from Python
Get data from analytics API with Google API Client for python
Python: Extract file information from shared drive with Google Drive API
Hit Mastodon's API in Python
Flatten using Python yield from
Call CPLEX from Python (DO cplex)
Handle Ambient data in Python
Use Trello API with python
Post from Python to Slack
Cheating from PHP to Python
AWS CDK-Lambda + API Gateway (Python)
EXE Web API by Python
Make MeCab available from Python3
Use Twitter API with Python