Working with the Authorize.net WebService I ran into some XSD issues. This is because WebDev is more restrictive with the XSD definition than PHP. Technically it isn’t a bug, but since most WebServices are targeted and tested on PHP it can definitely cause issues. In this weeks Webinar and Article, I will show you how I worked around these issues, so please read on.
Let’s establish a little background first. Webservices generally come in one of two flavors, RESTful or SOAP.
RESTful webservices, are just stateless HTTP Post and Gets to predefined URL endpoints. In order to us a RESTful API you have to rely on the documentation provided by the developer, to know what the URL endpoints are and the format of the parameters, and results.
SOAP Webservices on the other hand, attempt to solve all of that by establishing a standardized interface for publishing the methods of the webservice, along with their parameters and results. This is done via a WSDL (Web Services Description Language), pronounced Wiz-dull (if you want to sound like one of the cool kids).
So it would seem SOAP based webservices, would be easier to use. But as we know the road to damnation is paved with good intentions, and SOAP is no exception. I don’t know if its just the nature of SOAP, or the development environment (many SOAP based webservices are developed via .NET), or ?. But generally speaking when I deal with a SOAP based webservice it is a little more work to get it figured out and working.
The methods and their results and parameters, always seemed to be a little more convoluted, and the documentation is usually not as good. I have a few theories about why this is. First as mentioned, many are developed with .NET and folks from that world are just use to dealing with layers upon layers of complexity, and it bubbles up into their interfaces. Second, it seems that many developers, have bought into the “Silver Bullet” of the WSDL as the documentation, where RESTful developers are forced to write complete documentation, because there is no other way to know what the calls are. Trust me giving you a list of method names, and what the parameters and results are, is NOT documentation!
Sure I have used SOAP based webservices that were simple to use, and I have used RESTful services that were a nightmare, but generally speaking I have found it easier to work with RESTful services, but then again there may be a reason they call me “Old School”
So now that we got that out of the way, lets move on to today’s topic, which is how to get around a issue I ran into working with the Authorize.net API. As you might have guessed it is a SOAP based API, and it is a great example of how SOAP development can be made more difficult that necessary. In fact their documentation is in BETA, how the hell is documentation Beta?
So let’s get started, as I mentioned, we should have a WSDL, and we do, in fact we have two, one for production and one for sandbox. We are going to use the sandbox one today which is located at https://apitest.authorize.net/soap/v1/Service.asmx?WSDL. To incorporate the Webservice into our WX app, we need to import the WSDL. So in the project explorer, right click on Webservices and choose “Use a Webservice in this project”
The next screen is informational so you can just next through it.
The next screen lets you specify the location of the WSDL. Usually this is a webaddress, and as you see that is what I have specified here. And my first knock against Authorize.net it took me a bit of digging to come up with that URL. The URL for the WSDL should be the very first thing listed in any documentation!!!!
Once imported, you will see the webservice in the project explorer and can expand it to see all the methods, and their parameters etc. As you can see in the screen shot, Authorize.net chose to call their webservice, Service. Do I really need to explain how awful that is?
Today’s topic is not about the specifics of using the Authorize.net webservice, so I am not going to go into details about all of the calls etc., we will save that for another day. Today we are talking about a specific issue I ran into, and how to resolve it.
You are able to store your customers credit card information on the Authorize.net service, and then just use a “token” to charge them. This avoids you storing the data on your server and dealing with PCI issues. As you might imaging when retrieving the information from Authorize.net the data is “Masked”. So instead of getting the entire Credit Card Number you get “XXXX1234”. Where our problem comes in is Authorize.net also decided to mask the Expiration Date as XXXX.
Where we run into issues is when we need to update a payment profile. For instance, say a customer has changed their billing address. That needs to be updated at Authorize.net so that the next payment will process correctly without have a failure due to AVS issues. With must webservices, when you update information, it only updates the fields that you submit, so in order to update the billing address, I would only need to submit those fields, and all the other fields, such as credit card number would not be updated. However, Authorize.net decided to do it differently! Anytime you issue an update you must resubmit all the fields, if you don’t submit a field it will be cleared.
The challenge with that is remember we don’t actually have the credit card number or expiration date, we only have a mask of that data. Well digging around in documentation, remember its in Beta, I eventually found that what they want is for me to return it in masked format if I don’t want to update it.
So armed with that information I wrote a function similar to this:
Again we are not going into all the details of the Authorize.net webservice today, but you can probably follow that what we are doing in this code is updating a payment profile for a customer, and as you can see we are sending the expiration date back in Masked format, because all we really want to do is update the billing address. However if we run this procedure we get the following error:
Oh no, trouble in paradise? What the heck does that mean? Well we can see its complaining about the value of XXXX and we know that is what we are sending in for the expiration date, so it is related to that. Remember SOAP is XML based, and XSD is how you specific the format for all the elements in your XML document, and that is really what the WSDL is doing. In fact if we take the web address for the WSDL and put it in a browser we can actually see the XML code:
And if we search for expiration date we find that it is defined three times in the document.
Once as a YearMonth
And twice as a string
So what is happening is pcSoft is seeing that the field is defined as a YearMonth, however we are trying to place “XXXX” in it, which is not a YearMonth, and it is therefore generating an error. Technically this is absolutely correct. Our problem is that most webservices are only tested with PHP, and PHP is much more forgiving about XSD issues, therefore this doesn’t generate an error in PHP and Authorize.net feels that they don’t have a bug. They are not following their own rules, they want us to put something other than a YearMonth into expiration date and PHP would happily let us do that. pcSoft on the other hand says if you give me a rule, they I am going to enforce it!
So how do we get around this issue. Well it seems there are three ways.
1. Convince pcSoft that they are wrong and shouldn’t enforce the rule.
2. Convince Authorize.net that they are wrong and that they need to adjust their code.
3. Deal with it and figure out a work around.
Well, my clients don’t care who’s fault it is they just want a solution, and options 1 and 2 don’t seem like they would lead to a quick solution, so its on to option 3.
Since as we have seen the WSDL is just an XML file we can save it to disk.
We can then open the file with Notepad and edit the definition that is causing our issue and change it to a string.
Now we delete the existing WSDL from our project
And add it again, however this time, we tell it to use the WSDL file on disk that we just modified.
Note: the interface can be a bit flaky at times, especially if you are using the SCM and it may take 2 tries to get the new WSDL to import.
Now if we run the service we no longer it an error and it completes successfully.
Problem solved, clients happy, on to the next issue!
Modifying the WSDL is not something that should be taken lightly. You can definitely cause yourself a lot of grief. But in this instance it was the best work around available. Remember if you do modify the WSDL it is going to be your responsibility to maintain that modification every time the webservice releases a new version. So be sure to document what you have done well!
Webservices have a few properties exposed by pcSoft, and one of those is IgnoreError
However as you can see in the screen shot, our only options are for ignoring HTTP errors, I have made a suggestion that has been submitted to programming, to include an option to ignore XSD errors. Not sure if they will incorporate this our not, since it isn’t technically a bug. But my argument is, since most of the webservice world revolves around PHP and it works in PHP, we need a way to mirror that in WX.
Hopefully this has given you some foundation, that might help you down the road if you run into an similar issue with a webservice.
Uncle Pete’s Corner is webinar series on all things WX, to watch the watch the Uncle Pete’s corner webinar that is the companion to this article, and many other WX related webinars go to the WinDev US YouTube Channel and be sure to also join the WxLive – US Communityon Google+ to get notices about upcoming webinars. On the Google+ community you will find a active group developers discussing all things WX.