User login |
MSN adCenter API v5.1 Client Proxy Code
Skills Used
I was asked by TradeDoubler to write some PHP proxy code for the MSN adCenter v5.2 API to allow them to integrate their application with the new API, they were still on v4 API and had received an extension from MSN until the 1st of October when support for the older API would be switched off. I would have 6 weeks to complete the work and would be based from their offices in Victoria, London. I was familiar with most of TradeDoubler's development environment from being employed by them for over 2 years about 5 months previous, there were a few changes to get used to but within the end of the first day everything was setup and I was ready to go. I had done a number of API integrations for them while I was employed, back then we would use nuSOAP but seeing as development was not particularly active on it anymore we decided to look into using the built-in PHP SOAP. This would mean that PHP needed recompiling on the platform and would also cause nuSOAP to break as they share the same classname 'soapclient', we had full control over the nuSOAP code so it wouldn't be to hard to change the classname and update the API's depending on it. The built-in SOAP client is written in C and also maps complex types to and from PHP objects so would mean better performance and faster code development, the benefits far outweighed the inconvenience of recompiling PHP and changing nuSOAP so we decided this was the route we would go down. When I used to write API proxy code for TradeDoubler I also tended to do the integration into the application so would test the functionality as I went, this time though I would not be able to so decided I would write a set of unit tests prior to writing any API code. I chose PHPUnit to build the unit tests on as it is well supported and very popular, each service from the adCenter API (5 in all) had its own set of tests testing the the outputs of each individual operation. Each operation call uses a certain amount of quota and seeing as TradeDoubler had a requirement for that quota to be recorded there was an assertion, common to every test, that checked the quota used had been written to a database. In addition to the operation tests there were also tests to check debugging output and exception handling. After confirming all the written tests failed I set about writing the code until they all passed. Knowing that Java & .NET developers enjoy automatic proxy code generation from WSDL's I set about looking for a PHP utility that would give me the same sort of functionality. After a lot of searching and trying out a couple of different scripts I settled on PST! (PHP SOAP Toolkit) which provided me with a command line utility that I could pass a WSDL location and get back a class containing all the operations in the WSDL and a set of classes representing all the complex types defined within. PST! generates XML so to customise the generated PHP code you can provide you own XSL files, I used my own so that each generated PHP class was prefixed with 'Msn' and for each of the 5 adCenter services I got a corresponding PHP class that extended a base class. With the code generated the tests were now at least running but all were still failing which I discovered was largely due to MSN's choice of WSDL style - Document/Literal (Wrapped). It's the 'wrapped' part of this that gives the problem, it basically means the inputs and outputs of each operation are wrapped up in a single object, it makes the Document/Literal style WS-I compliant but was breaking my tests. PST! had been smart enough to detect this was the style of WSDL and had sorted out all the input arguments to the operations but PHP SOAP was returning the wrapped object for the result of the operations. Another problem was MS seem to like using 'ArrayOf' complex types wherever arrays are needed in operations or types my tests were expecting to find normal PHP arrays rather than these ArrayOf wrapper objects. All operation calls on the service proxy classes use the 'call' method on the base class which in turn calls __soapCall on the PHP SOAP SoapClient object, so by adding some reflection into this method I was able to fix both problems. I used reflection to inspect the data returned from __soapCall to remove the wrapper object and seek out any 'ArrayOf' obects and turn them into normal arrays. All that was left to do to make all of the tests pass was, in each operation, record the amount of quota used and enable some debugging functionality to allow developers to switch the services to use the adCenter sandbox and see the raw request and response of each SOAP call. All in all the whole contract took just 2 of the allocated 6 weeks to complete and the developers were able to integrate their application into the API ahead of the deadline. |