I'm trying to make the SOAP api of tradetracker to use with typescript node-soap. Thus far, I only managed to connect and authenticate using their authenticate method. But as soon as the second request takes place, authentication is lost and error "Not yet authenticated" returns.
I will provide as much info as I can to give context. Here the WDSL link
I have a working prototype using python:
from decimal import Decimal
from zeep import Client
from zeep.plugins import HistoryPlugin
from zeep.helpers import serialize_object
import json
from xml.etree import ElementTree
history = HistoryPlugin()
# Convert Decimal to float
def decimal_to_float(obj):
if isinstance(obj, Decimal):
return float(obj)
raise TypeError(f"Object of type {obj.__class__.__name__} is not serializable")
def object_to_dict(obj):
if isinstance(obj, list):
return [object_to_dict(item) for item in obj]
if isinstance(obj, dict):
return {key: object_to_dict(value) for key, value in obj.items()}
if isinstance(obj, Decimal):
return float(obj)
if hasattr(obj, '__dict__'):
return object_to_dict(obj.__dict__)
return obj
# Tradetracker credentials
customer_id = 'xxxxxx'
password = 'mysupersecretpasswordhere'
affiliate_site_id = 000000
# URL TradeTracker SOAP-service
wsdl_url = ''
# Create the SOAP client
client = Client(wsdl=wsdl_url, plugins=[history])
# Define auth params/header
auth_params = {
'customerID': customer_id,
'passphrase': password,
'sandbox': False,
'locale': 'nl_NL',
'demo': False
}
try:
# Authenticate using their SOAP authenticate method
client.service.authenticate(
customerID=auth_params['customerID'],
passphrase=auth_params['passphrase'],
sandbox=auth_params['sandbox'],
locale=auth_params['locale'],
demo=auth_params['demo']
)
print("Authentication Succeeded")
# Print the raw SOAP request XML sent
raw_request = ElementTree.tostring(history.last_sent['envelope'], encoding='utf-8').decode('utf-8')
# print("SOAP Request:", raw_request)
print("Last request:", history.last_sent)
# Options for product feed
feedProductsOptions = {
'limit': 5
}
# Get site categories
categories = client.service.getAffiliateSiteCategories()
print(categories)
except Exception as e:
print(f"Error with authentification or method call: {e}")
The above python code is 100% working. It authenticates and gets the affiliate site categories. No problem.
Here is the output (i replaced sensitive data):
zeep.transports: Loading remote data from:
zeep.transports: Loading remote data from: /
zeep.transports: HTTP Post to :
<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="/"><soap-env:Body><ns0:authenticate xmlns:ns0=";><customerID>000000</customerID><passphrase>mysupersecretpassphrase</passphrase><sandbox>false</sandbox><locale>nl_NL</locale><demo>false</demo></ns0:authenticate></soap-env:Body></soap-env:Envelope>
zeep.transports: HTTP Response from (status: 200):
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="/" xmlns:ns1="; xmlns:xsd="; xmlns:SOAP-ENC="/" SOAP-ENV:encodingStyle="/"><SOAP-ENV:Body><ns1:authenticateResponse/></SOAP-ENV:Body></SOAP-ENV:Envelope>
Authentication Succeeded
zeep.transports: HTTP Post to :
<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="/"><soap-env:Body><ns0:getAffiliateSiteCategories xmlns:ns0=";/></soap-env:Body></soap-env:Envelope>
zeep.transports: HTTP Response from (status: 200):
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="/" xmlns:ns1="; xmlns:SOAP-ENC="/" xmlns:xsd="; xmlns:xsi="; SOAP-ENV:encodingStyle="/"><SOAP-ENV:Body><ns1:getAffiliateSiteCategoriesResponse><affiliateSiteCategories SOAP-ENC:arrayType="ns1:AffiliateSiteCategory[33]" xsi:type="ns1:AffiliateSiteCategories"><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">1</ID><name xsi:type="xsd:normalizedString">Auto's en motoren</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">140</ID><name xsi:type="xsd:normalizedString">Baby en kinderen</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">2</ID><name xsi:type="xsd:normalizedString">Boeken en tijdschriften</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">3</ID><name xsi:type="xsd:normalizedString">Boten en watersport</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">142</ID><name xsi:type="xsd:normalizedString">Dagaanbiedingen en Groepdeals</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">138</ID><name xsi:type="xsd:normalizedString">Dating</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">5</ID><name xsi:type="xsd:normalizedString">Dieren, planten, natuur en landbouw</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">6</ID><name xsi:type="xsd:normalizedString">E-commerce en shopping</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">32</ID><name xsi:type="xsd:normalizedString">Erotiek</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">141</ID><name xsi:type="xsd:normalizedString">Eten en drinken</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">7</ID><name xsi:type="xsd:normalizedString">Familie en gezondheid</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">8</ID><name xsi:type="xsd:normalizedString">Film, radio en televisie</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">9</ID><name xsi:type="xsd:normalizedString">Financiële producten</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">10</ID><name xsi:type="xsd:normalizedString">Games</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">12</ID><name xsi:type="xsd:normalizedString">Goede doelen</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">139</ID><name xsi:type="xsd:normalizedString">Gokken</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">13</ID><name xsi:type="xsd:normalizedString">Hard- en software</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">14</ID><name xsi:type="xsd:normalizedString">Hobby's, speelgoed en clubs</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">16</ID><name xsi:type="xsd:normalizedString">Kunst en lifestyle</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">131</ID><name xsi:type="xsd:normalizedString">Mode en accessoires</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">18</ID><name xsi:type="xsd:normalizedString">Muziek, video en DVD</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">19</ID><name xsi:type="xsd:normalizedString">Nieuws, kranten en tijdschriften</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">20</ID><name xsi:type="xsd:normalizedString">Overige</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">21</ID><name xsi:type="xsd:normalizedString">Persoonlijke internetdiensten</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">22</ID><name xsi:type="xsd:normalizedString">Reizen en vakanties</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">23</ID><name xsi:type="xsd:normalizedString">Sport en recreatie</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">24</ID><name xsi:type="xsd:normalizedString">Techniek en wetenschap</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">25</ID><name xsi:type="xsd:normalizedString">Telecommunicatie</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">26</ID><name xsi:type="xsd:normalizedString">Uitgaan, entertainment en humor</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">28</ID><name xsi:type="xsd:normalizedString">Werk, opleiding en carrière</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">29</ID><name xsi:type="xsd:normalizedString">Wonen en huizen</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">30</ID><name xsi:type="xsd:normalizedString">Zakelijke dienstverlening</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">31</ID><name xsi:type="xsd:normalizedString">Zakelijke internetdiensten</name></item></affiliateSiteCategories></ns1:getAffiliateSiteCategoriesResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
Now I tried to implement this in typescript / node-soap, but for the hell of it, it's just not working. I want this to work in typescript. The resultat this moment is that the authentication method returns 'undefined' (i guess it worked, not sure if it should return undefined though, theres no info on that), and then the response for the next method request, whatever it may be, is always an error: "Not yet authenticated
". But it just clearly did!? I know that because if i change the passphrase, I get a different error: "Failed to authenticate
".
Here is my typescript test code:
import * as soap from 'soap';
const WSDL_URL = '';
const credentials = {
customerID: 'xxxxxx',
passphrase: 'mysupersecretpasswordhere',
sandbox: false,
locale: 'nl_NL',
demo: false,
};
class TradeTrackerClient {
private client: soap.Client | null = null;
async initialize(): Promise<void> {
try {
// Create the SOAP client
this.client = await soap.createClientAsync(WSDL_URL, {
envelopeKey: 'soap-env',
forceSoap12Headers: false,
});
if (!this.client) {
throw new Error('Failed to create SOAP client');
}
// Perform authentication
console.log('Authenticating...');
this.client.addHttpHeader(
'SOAPAction',
'',
);
const options: soap.IOptions = {
wsdl_headers: {
SOAPAction: '',
},
};
await this.client.authenticateAsync(credentials, options);
console.log('Authentication successful');
console.log('Last request (authenticate):', this.client.lastRequest);
// Test subsequent request
console.log('Fetching affiliate site categories...');
const [categories] =
await this.client.getAffiliateSiteCategoriesAsync(null);
console.log('Categories:', categories);
console.log('Last request (categories):', this.client.lastRequest);
} catch (error) {
console.error('Error:', error.message);
if (this.client?.lastRequest) {
console.error('Last request:', this.client.lastRequest);
}
}
}
}
const client = new TradeTrackerClient();
client.initialize();
This doesn't work. Here is the output (i removed sensitive data):
Authenticating...
Authentication successful
Last request (authenticate): <?xml version="1.0" encoding="utf-8"?><soap-env:Envelope xmlns:soap-env="/" xmlns:xsi="; xmlns:tns=";><soap-env:Body><tns:authenticate><customerID>000000</customerID><passphrase>supersecretpassword</passphrase><sandbox>false</sandbox><locale>nl_NL</locale><demo>false</demo></tns:authenticate></soap-env:Body></soap-env:Envelope>
Fetching affiliate site categories...
Error: SOAP-ENV:Client: Not yet authenticated.
Last request: <?xml version="1.0" encoding="utf-8"?><soap-env:Envelope xmlns:soap-env="/" xmlns:xsi="; xmlns:tns=";><soap-env:Body><tns:getAffiliateSiteCategories></tns:getAffiliateSiteCategories></soap-env:Body></soap-env:Envelope>
Their (very limited) docs tell me this about the authentication method:
Description
void authenticate ( nonNegativeInteger $customerID, normalizedString $passphrase, boolean $sandbox, Locale $locale, boolean $demo )
This method is used in the header section of the SOAP request and contains the authentication parameters.
Can anyone help me out on this one? Are the headers wrong? What does python zeep do, soap doesn't?
I'm trying to make the SOAP api of tradetracker to use with typescript node-soap. Thus far, I only managed to connect and authenticate using their authenticate method. But as soon as the second request takes place, authentication is lost and error "Not yet authenticated" returns.
I will provide as much info as I can to give context. Here the WDSL link
I have a working prototype using python:
from decimal import Decimal
from zeep import Client
from zeep.plugins import HistoryPlugin
from zeep.helpers import serialize_object
import json
from xml.etree import ElementTree
history = HistoryPlugin()
# Convert Decimal to float
def decimal_to_float(obj):
if isinstance(obj, Decimal):
return float(obj)
raise TypeError(f"Object of type {obj.__class__.__name__} is not serializable")
def object_to_dict(obj):
if isinstance(obj, list):
return [object_to_dict(item) for item in obj]
if isinstance(obj, dict):
return {key: object_to_dict(value) for key, value in obj.items()}
if isinstance(obj, Decimal):
return float(obj)
if hasattr(obj, '__dict__'):
return object_to_dict(obj.__dict__)
return obj
# Tradetracker credentials
customer_id = 'xxxxxx'
password = 'mysupersecretpasswordhere'
affiliate_site_id = 000000
# URL TradeTracker SOAP-service
wsdl_url = 'https://ws.tradetracker/soap/affiliate?wsdl'
# Create the SOAP client
client = Client(wsdl=wsdl_url, plugins=[history])
# Define auth params/header
auth_params = {
'customerID': customer_id,
'passphrase': password,
'sandbox': False,
'locale': 'nl_NL',
'demo': False
}
try:
# Authenticate using their SOAP authenticate method
client.service.authenticate(
customerID=auth_params['customerID'],
passphrase=auth_params['passphrase'],
sandbox=auth_params['sandbox'],
locale=auth_params['locale'],
demo=auth_params['demo']
)
print("Authentication Succeeded")
# Print the raw SOAP request XML sent
raw_request = ElementTree.tostring(history.last_sent['envelope'], encoding='utf-8').decode('utf-8')
# print("SOAP Request:", raw_request)
print("Last request:", history.last_sent)
# Options for product feed
feedProductsOptions = {
'limit': 5
}
# Get site categories
categories = client.service.getAffiliateSiteCategories()
print(categories)
except Exception as e:
print(f"Error with authentification or method call: {e}")
The above python code is 100% working. It authenticates and gets the affiliate site categories. No problem.
Here is the output (i replaced sensitive data):
zeep.transports: Loading remote data from: https://ws.tradetracker/soap/affiliate?wsdl
zeep.transports: Loading remote data from: http://schemas.xmlsoap./soap/encoding/
zeep.transports: HTTP Post to https://ws.tradetracker/soap/affiliate:
<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap./soap/envelope/"><soap-env:Body><ns0:authenticate xmlns:ns0="https://ws.tradetracker/soap/affiliate"><customerID>000000</customerID><passphrase>mysupersecretpassphrase</passphrase><sandbox>false</sandbox><locale>nl_NL</locale><demo>false</demo></ns0:authenticate></soap-env:Body></soap-env:Envelope>
zeep.transports: HTTP Response from https://ws.tradetracker/soap/affiliate (status: 200):
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap./soap/envelope/" xmlns:ns1="https://ws.tradetracker/soap/affiliate" xmlns:xsd="http://www.w3./2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap./soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap./soap/encoding/"><SOAP-ENV:Body><ns1:authenticateResponse/></SOAP-ENV:Body></SOAP-ENV:Envelope>
Authentication Succeeded
zeep.transports: HTTP Post to https://ws.tradetracker/soap/affiliate:
<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap./soap/envelope/"><soap-env:Body><ns0:getAffiliateSiteCategories xmlns:ns0="https://ws.tradetracker/soap/affiliate"/></soap-env:Body></soap-env:Envelope>
zeep.transports: HTTP Response from https://ws.tradetracker/soap/affiliate (status: 200):
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap./soap/envelope/" xmlns:ns1="https://ws.tradetracker/soap/affiliate" xmlns:SOAP-ENC="http://schemas.xmlsoap./soap/encoding/" xmlns:xsd="http://www.w3./2001/XMLSchema" xmlns:xsi="http://www.w3./2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap./soap/encoding/"><SOAP-ENV:Body><ns1:getAffiliateSiteCategoriesResponse><affiliateSiteCategories SOAP-ENC:arrayType="ns1:AffiliateSiteCategory[33]" xsi:type="ns1:AffiliateSiteCategories"><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">1</ID><name xsi:type="xsd:normalizedString">Auto's en motoren</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">140</ID><name xsi:type="xsd:normalizedString">Baby en kinderen</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">2</ID><name xsi:type="xsd:normalizedString">Boeken en tijdschriften</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">3</ID><name xsi:type="xsd:normalizedString">Boten en watersport</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">142</ID><name xsi:type="xsd:normalizedString">Dagaanbiedingen en Groepdeals</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">138</ID><name xsi:type="xsd:normalizedString">Dating</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">5</ID><name xsi:type="xsd:normalizedString">Dieren, planten, natuur en landbouw</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">6</ID><name xsi:type="xsd:normalizedString">E-commerce en shopping</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">32</ID><name xsi:type="xsd:normalizedString">Erotiek</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">141</ID><name xsi:type="xsd:normalizedString">Eten en drinken</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">7</ID><name xsi:type="xsd:normalizedString">Familie en gezondheid</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">8</ID><name xsi:type="xsd:normalizedString">Film, radio en televisie</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">9</ID><name xsi:type="xsd:normalizedString">Financiële producten</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">10</ID><name xsi:type="xsd:normalizedString">Games</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">12</ID><name xsi:type="xsd:normalizedString">Goede doelen</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">139</ID><name xsi:type="xsd:normalizedString">Gokken</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">13</ID><name xsi:type="xsd:normalizedString">Hard- en software</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">14</ID><name xsi:type="xsd:normalizedString">Hobby's, speelgoed en clubs</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">16</ID><name xsi:type="xsd:normalizedString">Kunst en lifestyle</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">131</ID><name xsi:type="xsd:normalizedString">Mode en accessoires</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">18</ID><name xsi:type="xsd:normalizedString">Muziek, video en DVD</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">19</ID><name xsi:type="xsd:normalizedString">Nieuws, kranten en tijdschriften</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">20</ID><name xsi:type="xsd:normalizedString">Overige</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">21</ID><name xsi:type="xsd:normalizedString">Persoonlijke internetdiensten</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">22</ID><name xsi:type="xsd:normalizedString">Reizen en vakanties</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">23</ID><name xsi:type="xsd:normalizedString">Sport en recreatie</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">24</ID><name xsi:type="xsd:normalizedString">Techniek en wetenschap</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">25</ID><name xsi:type="xsd:normalizedString">Telecommunicatie</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">26</ID><name xsi:type="xsd:normalizedString">Uitgaan, entertainment en humor</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">28</ID><name xsi:type="xsd:normalizedString">Werk, opleiding en carrière</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">29</ID><name xsi:type="xsd:normalizedString">Wonen en huizen</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">30</ID><name xsi:type="xsd:normalizedString">Zakelijke dienstverlening</name></item><item xsi:type="ns1:AffiliateSiteCategory"><ID xsi:type="xsd:nonNegativeInteger">31</ID><name xsi:type="xsd:normalizedString">Zakelijke internetdiensten</name></item></affiliateSiteCategories></ns1:getAffiliateSiteCategoriesResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
Now I tried to implement this in typescript / node-soap, but for the hell of it, it's just not working. I want this to work in typescript. The resultat this moment is that the authentication method returns 'undefined' (i guess it worked, not sure if it should return undefined though, theres no info on that), and then the response for the next method request, whatever it may be, is always an error: "Not yet authenticated
". But it just clearly did!? I know that because if i change the passphrase, I get a different error: "Failed to authenticate
".
Here is my typescript test code:
import * as soap from 'soap';
const WSDL_URL = 'http://ws.tradetracker/soap/affiliate?wsdl';
const credentials = {
customerID: 'xxxxxx',
passphrase: 'mysupersecretpasswordhere',
sandbox: false,
locale: 'nl_NL',
demo: false,
};
class TradeTrackerClient {
private client: soap.Client | null = null;
async initialize(): Promise<void> {
try {
// Create the SOAP client
this.client = await soap.createClientAsync(WSDL_URL, {
envelopeKey: 'soap-env',
forceSoap12Headers: false,
});
if (!this.client) {
throw new Error('Failed to create SOAP client');
}
// Perform authentication
console.log('Authenticating...');
this.client.addHttpHeader(
'SOAPAction',
'http://ws.tradetracker/soap/affiliate/authenticate',
);
const options: soap.IOptions = {
wsdl_headers: {
SOAPAction: 'http://ws.tradetracker/soap/affiliate/authenticate',
},
};
await this.client.authenticateAsync(credentials, options);
console.log('Authentication successful');
console.log('Last request (authenticate):', this.client.lastRequest);
// Test subsequent request
console.log('Fetching affiliate site categories...');
const [categories] =
await this.client.getAffiliateSiteCategoriesAsync(null);
console.log('Categories:', categories);
console.log('Last request (categories):', this.client.lastRequest);
} catch (error) {
console.error('Error:', error.message);
if (this.client?.lastRequest) {
console.error('Last request:', this.client.lastRequest);
}
}
}
}
const client = new TradeTrackerClient();
client.initialize();
This doesn't work. Here is the output (i removed sensitive data):
Authenticating...
Authentication successful
Last request (authenticate): <?xml version="1.0" encoding="utf-8"?><soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap./soap/envelope/" xmlns:xsi="http://www.w3./2001/XMLSchema-instance" xmlns:tns="http://ws.tradetracker/soap/affiliate"><soap-env:Body><tns:authenticate><customerID>000000</customerID><passphrase>supersecretpassword</passphrase><sandbox>false</sandbox><locale>nl_NL</locale><demo>false</demo></tns:authenticate></soap-env:Body></soap-env:Envelope>
Fetching affiliate site categories...
Error: SOAP-ENV:Client: Not yet authenticated.
Last request: <?xml version="1.0" encoding="utf-8"?><soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap./soap/envelope/" xmlns:xsi="http://www.w3./2001/XMLSchema-instance" xmlns:tns="http://ws.tradetracker/soap/affiliate"><soap-env:Body><tns:getAffiliateSiteCategories></tns:getAffiliateSiteCategories></soap-env:Body></soap-env:Envelope>
Their (very limited) docs tell me this about the authentication method:
Description
void authenticate ( nonNegativeInteger $customerID, normalizedString $passphrase, boolean $sandbox, Locale $locale, boolean $demo )
This method is used in the header section of the SOAP request and contains the authentication parameters.
Can anyone help me out on this one? Are the headers wrong? What does python zeep do, soap doesn't?
I got it to work using cookies. My bad:
import * as soap from 'soap';
import { IncomingHttpHeaders } from 'http';
const WSDL_URL = 'http://ws.tradetracker/soap/affiliate?wsdl';
const credentials = {
customerID: '00000',
passphrase: 'mysecretpassphrase',
sandbox: false,
locale: 'nl_NL',
demo: false,
};
class TradeTrackerClient {
private client: soap.Client | null = null;
private cookie: string | null = null;
async initialize(): Promise<void> {
try {
// Create the SOAP client
this.client = await soap.createClientAsync(WSDL_URL, {
envelopeKey: 'soap-env',
forceSoap12Headers: false,
});
if (!this.client) {
throw new Error('Failed to create SOAP client');
}
// Listen for responses and capture cookies
this.client.on('response', (body: any, response: any) => {
if (response && response.headers) {
this.extractCookie(response.headers);
}
});
// Perform authentication
console.log('Authenticating...');
const [authResponse] = await this.client.authenticateAsync(credentials);
console.log('Authentication successful:', authResponse);
console.log('Last request (authenticate):', this.client.lastRequest);
// Ensure the session cookie is stored before making further requests
if (!this.cookie) {
throw new Error('Authentication did not return a session cookie');
}
// Attach cookie for future requests
this.client.addHttpHeader('Cookie', this.cookie);
// Test subsequent request
console.log('Fetching affiliate site categories...');
const [categories] = await this.client.getAffiliateSiteCategoriesAsync(null);
console.log('Categories:', categories);
console.log('Last request (categories):', this.client.lastRequest);
} catch (error) {
console.error('Error:', error.message);
if (this.client?.lastRequest) {
console.error('Last request:', this.client.lastRequest);
}
}
}
private extractCookie(headers: IncomingHttpHeaders): void {
const setCookieHeader = headers['set-cookie'];
if (setCookieHeader && setCookieHeader.length > 0) {
this.cookie = setCookieHeader[0].split(';')[0]; // Extract SID=value
console.log('Extracted Cookie:', this.cookie);
}
}
}
const client = new TradeTrackerClient();
client.initialize();