Edit: Short version:

I am writing a module that consumes SOAP services. I have a WSDL file. Which of these should I do to use it?

Should I use the Web service client module?

Should I use the PHP SOAP library directly?

Something else?

Where is there good documentation for using SOAP on Drupal?

---- Edit: Long version ----

So, I am looking at writing an integration module that uses a complex SOAP API to consume a service. I don't know much about SOAP yet, but there seem to be multiple ways to handle it. I'm hoping for direction on the best way to go with it. Can anyone advise?

The complex API has a complex WSDL file.

I spent some time Googling around about SOAP and WSDL, so I have a vague idea what they're about. I haven't found any good instructions on what to do with Drupal and SOAP, though.

I found references to different SOAP versions. Stuff in the WSDL file makes me think version 1.0 and 1.2, but I don't know how to tell for sure.

It seems to be possible to convert WSDL to PHP, whatever that means.

I found the SOAP Client module, but there is no version for Drupal 7.

I found the Web service client module. It sounds promising, but the documentation is sparse and pretty confusing. Is that a good way to go? It wants a link to a WSDL file. I don't know of any official link (yet). Should I put the WSDL file in my module?

Or...maybe I should just use the PHP SOAP library directly, since I'm not sure the Drupal module adds any functionality (unless I want to integrate this with Rules). Unfortunately, I've found no good overview of the PHP SoapClient class, so it's hard to tell.

I'd rather not spend a lot of time and effort programming, then discover that I'm using a bad approach. Does anyone know the right way to go, here?

Comments

goofus’s picture

Hello,
Are you serving and consuming SOAP services with Drupal? Or, are you simply consuming a SOAP web service running on a remote server.

This is a high level summary. SOAP is just XML which contains data and optionally processing commands.

In others words, SOAP is pretty similar to HTML. Lets take an examle, <p>I am a paragraph</p>, contains data "I am a paragraph" and an instruction "add a line break at the end because I am a paragraph."

So the question "convert WSDL to PHP" is like asking "convert HTML to PHP", it doesn't really make sense. You process SOAP messages with a computer language. So your question should read "How do I process SOAP messages with PHP". Next, I recommend you focus on my original question. Are you serving or (more likely) consuming a SOAP messages (AKA service). "Consuming" means you are a client, you request something like "I want a list of locations in Paris".

If you are just consuming the web service, then start breaking it down. You could be requesting one to many operations. I recommend starting with one single operation request. A SOAP provider should be able to provide the consumer with a sample request. The provider should tell you what type of http request you are making (E.G. GET/POST/PUT.etc). Many times the SOAP request is an XML message, hence the example request will contain XML.

I noticed you use Netbeans. I recommend installing the "web services" module. That will give you a set of real services you can consume (as a learning experience, E.G. Twitter, Google, etc.). Here's a quick example : http://wiki.netbeans.org/PHP_WS#SOAP_Client_in_PHP

To summarize, I would focus first on simply requesting a SOAP service with PHP. Once you feel comfortable processing the SOAP requests, then work in integrating the data in to your Drupal installation.

Hope that helps a little :)

DanZ’s picture

Thanks for the hints.

I am purely interested in making a client (consumer of the services). This is for Stamps.com, which offers a SOAP API for printing shipping labels. My module sends their server address, weight, and mail class information and gets back a URL that links to an image file of a shipping label (that can be printed). (There's a lot more to it than that, but you get the idea.) The whole thing is thoroughly documented, but platform-independent. I'm hoping for Drupal-dependent suggestions.

As far as I can tell, it's possible to use either the PHP library directly or the Drupal web service module to create an object based on a WSDL file. That object then has methods that represent the services offered. (Is that right?)

I couldn't find any good documentation about how to use either one: Nothing explained how the different data types are formatted, what the Drupal module does that the PHP class doesn't, what the typical program structure should be, etc.

So, what I'm hoping for right now is advice on which path to take in a Drupal environment. Pick one of the two modules? Write an XML parser (just kidding)? Something else?

Once I have a decent idea of which way to go, I can focus my research and learning on that way, and have some confidence I'm not spending effort on something that won't work well.

--
www.ztwistbooks.com. Math books that are actually fun.

goofus’s picture

Hello,
Thank you for the reply.

I took a quick look at "Stamps.com" (it's the United States Post Office (USPS)). So we now know what service you want to query. As expected the USPS provides many different logical services organized in to specific request/response pairs. However, I would carefully review your requirements.

In your reply, you narrowed the scope (thank you, that's really helps the discussion :) ). You want to request shipping labels. Is that the only request you require from the USPS service? The reason I am asking is, the following.

The USPS site's description of their web services is a little misleading. SOAP is specialized XML dialect. SOAP is an XML, but a highly specialized form of XML. The term "web service" just means message are sent across the internet in a platform independent format. For example. javascript object notation (JSON) is platform independent and can be used in a web service. Likewise, simple XML can also be used in a web service (e.g. <request="list_locations"><parm>Paris</parm></request>).

So my point is, the USPS site says you can request shipping labels in plain XML ( http://developer.stamps.com/developer/xml/). Note the section "Applications",

Ideal for batch processing labels—prepare the XML file to be processed throughout the day, then generate labels

So if you are limited to requesting shipping labels, wouldn't you be better off just making a plain XML request. XML is just a string? You would use drupal_http_request http://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_http_request/7

Personally, I prefer to start off by coding with the Drupal core API itself. The Drupal core API is almost always the most widely supported and documented API. Plus the base Drupal install is built with the core API. So plenty of examples. When you run in to an issue, you are limited to diagnosing PHP and the Drupal core API .

In contrast, if you start developing with contributed models, you've now added a layer of indirection. When you run in to an issue, you now have to diagnose, PHP. Drupal Core and contributed module(s). Thus, in general, I personally would not introduce contributed modules unless I had specific requirements those contributed modules fill.

We are in the development forum, thus this a discussion about how a programmer solves an issue. Not a discussion about how an end user configures a solution. The cost/benefit analysis for an end user is different than the cost/benefit analysis for a programmer :)

Hope that helps a little :)

DanZ’s picture

So if you are limited to requesting shipping labels, wouldn't you be better off just making a plain XML request.

I already did that. See https://drupal.org/project/uc_stamps. The user has to do a lot of import/export of the XML files to software that only runs on Windows. It's tedious. It requires working from Windows. It requires switching back and forth between the browser and the Stamps.com software. Long-term, SOAP is the way to have a fully-integrated solution.

It's not a small project, though.

In contrast, if you start developing with contributed models, you've now added a layer of indirection.

Right. However, one should use them if they add enough functionality. One should usually avoid re-inventing the wheel.

--
www.ztwistbooks.com. Math books that are actually fun.

DanZ’s picture

Ok, I added a summary to the top of my original message. Maybe having a short version will help.

--
www.ztwistbooks.com. Math books that are actually fun.

WorldFallz’s picture

i'm not sure there is a 'right' answer. using the drupal module will be easier as it seems you can go through the rules interface. However its still a fairly young module, with less than 1k reported installations so it's future could be uncertain (but then you could always switch to the php lib later if need be). It's really just a matter of personal pref in this case i think.

dman’s picture

I went through a lot of this last month. I also melted my brain slightly while trying to get a handle on "how many layers of this crap do I need to understand before I can use this service effectively".

Since then, I have resolved this in my own head.

It's not at all contradictory to "convert WSDL to PHP". A WSDL is a formal way of defining a set of data schemas and operations that can be done using them (eg fetching a list of data records). Chunks of PHP are also made up of data schemas (objects, attributes, or keyed arrays with special meanings) and operations that can be done on them (function definitions, with defined input and output data types). A few available WSDL-to-PHP scripts actually do a good job of this, and assist understanding of what is going on with WSDLs, if you already understand PHP. They may even serve the opposite purpose.

Anyway.
The PHP-core support for web services is pretty raw, and tricky to debug unless you already understand all the questions. PEAR and external libs are even worse.

As in the OP. The Drupal SOAP module is unsupported.
I did a code review and found a good amount of WebServiceClient architecture a good place to start from. It's done right. Though it's not yet living up to its full potential. This is probably due to not enough people pushing it in all the directions that it can potentially go yet.
I endorse it.

Anyway, here comes the plug:

I added a TESTER utility to WSClient (dev version only) which I'd suggest checking out. It was a tool I built just to help myself understand WSDLs and what they were trying to say.

As *my* use-case was about pulling data from a remote feed and fill in my local times, I then built http://drupal.org/project/wsclient_feeds which works exactly as I needed for read-only data population.

DanZ’s picture

Thank you, dman. These are the suggestions I was looking for. Based on what you wrote, I'm now leaning toward wsclient.

Could you explain the specific advantages of using wsclient over the raw PHP SOAP class?

The usage of the wsclient module is not well-documented. Would it be a good idea for me to look at your wsclient_feeds module as a code sample?

--
www.ztwistbooks.com. Math books that are actually fun.

dman’s picture

Frankly, the wsclient_feeds is a LOT more about talking to feeds than talking to wsclient. This demonstrates that - once you find the right calls to make - wsclient does all the hard stuff without you needing to understand it. So there is that.

What wsclient does do is provides something of a conceptual model of the remote web service - whatever it be.
You point wsclient at the remote WSDL, and wsclient then knows and lists the calls, arguments and return types of the service in a web UI.
Then, you do have to delve a little deeper to find the next steps, but eventually you'll be able to
* construct the arguments (yourself) in a nested array
* use wscleint to invoke() the call
* get back a big structured array of response data
wsclient has a small layer of error handling and logging that you'd otherwise have to do yourself, and that's always nice.

Now. It might be that your particular case (fetching image data?) may not actually fit into what wsclient is currently designed to handle. It could well be, that if your requirements are more than 30% different from what the module does well - you may very well be just as good doing your own thing by hand for now. I can't predict that fully.
When I tried messing with the PHP SOAP routines directly, I *could* get them to work, but realized I was hard-coding a bunch of exceptions into it (API version, encoding work-arounds, fixed data structures) that seemed to work for this one special case I was coding right now, but I wasn't going to end up with something that would be resilient to change. If the remote end changed their API slightly, my whole thing would have to be redone from scratch. I don't like code like that.

So I found that the abstraction that wsclient provided protected me from a bunch of that - or at least *surfaced* those concerns in my code so I could tell the difference clearly between implementation details - the weirdness I had to send the SOAP client and didn't really understand why it worked ... and the business rules that were relevant to me and my endpoint.

If you want write-once, run-once code, then by all means do it on the bare metal with the PHP_SOAP. It's a worthy learning exercise, and you'll come out knowing more about web services and protocols. If all goes well, it will just work.
If you want to be able to maintain or re-use or share your solution, then stand on the shoulders of .. well, not giants but at least get a leg-up from a peer ... and see if you can't integrate with wsclient.
Once you've figured it, you will *write less code* and that's always a good sign.

DanZ’s picture

Awesome. Thanks for the tips. Wsclient is clearly worth looking into further.

It's not really important, but the Stamps.com service returns a URL to an image file of a shipping label. Fetching the actual image file is a separate step that doesn't involve the Web service.

--
www.ztwistbooks.com. Math books that are actually fun.

WorldFallz’s picture

holy parsers batman-- i hadn't stumbled across wsclient_feeds... brilliant! For that reason alone I switch my vote to using wsclient.