Posts filed under 'Backend'

Lecayla, Ruby and Soap4r

I was tasked with incorporating our system with a 3rd party credit card processing company called Lecayla. Initially this was written using PHP which was extremely easy, but now I needed to do it with Ruby. Lecayla had examples written in PHP but it seemed that no one was using Ruby. This created all kinds of issues all of them dealing with Soap4r. Hopefully this will help some people out there using Lecayla and Ruby and other people who are fighting with getting Ruby and Soap to work together.

  • Documentation (or lack there of)

Soap4r is an implementation of Soap 1.1 for Ruby. One of the major problems is the complete lack of documentation. There are documentation entries for all the various classes but there isn’t any sort of explanation as to what does what. The only real way to figure all this stuff out is to use google and search other forums.

  • Caching

Soap isn’t very speedy and neither is Ruby. Soap4r doesn’t support caching of the wsdl and xsd files so every time you initialize the driver it will go out and get a new copy of the wsdl. This slows down the system tremendously. I implemented a really basic caching check into my class that solved this problem. I think this should be a part of Soap4r but it isn’t.

t_wsdl = 'config/lecayla.wsdl'
if (! FileTest.exists?('config/lecayla.wsdl')) || (! FileTest.exists?('config/lecayla.xsd'))
File.open('config/lecayla.wsdl', 'w') do |f|
f.write(Net::HTTP.get(URI.parse(billing.wsdl)))
end
File.open('config/lecayla.xsd', 'w') do |f|
f.write(Net::HTTP.get(URI.parse(billing.xsd)))
end
end
This will store the wsdl and xsd files in your config directory for use in your driver setup. If you don’t cache them in some form you will have a huge speed hit.

  • Multiple ports in the same wsdl file

In PHP soap you just tell php to use the wsdl and everything just works. It doesn’t matter if the calls you are making are designated within different ports or not. PHP just does its thing and you do yours. With Soap4r it isn’t quite as simple. For Lecayla there are 3 different ports in their wsdl file, ContractHttpPort, MeteringHttpPort, and SSOHttpPort. In your initialization of your class you need to specifically setup each one. I did this:

@contractDriver = SOAP::WSDLDriverFactory.new(t_wsdl).create_rpc_driver(nil,'ContractHttpPort')
@meteringDriver = SOAP::WSDLDriverFactory.new(t_wsdl).create_rpc_driver(nil,'MeteringHttpPort')
@ssoDriver = SOAP::WSDLDriverFactory.new(t_wsdl).create_rpc_driver(nil,'SSOHttpPort')

Now in your class if you for example want to add a user you simply do

@meteringDriver.registerUser(params)

This is another reason to cache your wsdl, otherwise for each of these it would go out and get the wsdl. You can guess as to how long just this process took.

  • Data structure formats

For Lecayla the structure of your hashes can be complex for the calls that you need to make, and it isn’t completely clear as to what the format should be for some of them. In PHP this was easy because they provided a sample and it was quick to get it up and running. In Ruby this took a little work figuring out. Soap4r contains a script called wsdl2ruby.rb that takes a wsdl file and outputs a driver file and a script that you can use to test based upon the xsd and wsdl that you give it. I found it a lot easier though to just read the wsdl and xsd files myself. The code generated by wsdl2ruby seemed to be extreme overkill for what I wanted. With some help from the Soap4r maintainer and some sorting out by myself. Here are some of the structure formats.

Also make sure you wrap your calls in begin blocks so you can catch any exceptions that come across. The Lecayla documentation on their web site for developers is extremely helpful for what you will get in return and what the errors mean.

Thats about it. The above should be enough to get you started really quickly with implementing Lecayla in your system. Hopefully this is also some help to those folks out there that have been given a wsdl and don’t know what to do with it in Ruby. There is a Google group for Soap4r that I found useful for asking questions. The maintainer of it actually answers questions which is a lot better than what some other maintainers of Ruby projects do.

Add comment December 7th, 2007 Author: Mike Alletto

More Flexible Rails Migrations

Before we moved from our own internally developed PHP framework to using Ruby on Rails, I had written a database migration library that mimics Rail’s with two key differences:

  1. It allowed for retroactive running of migrations with versions at or below the current database version.
  2. It allowed a developer to force run a migration, even if that migration had already been run before.

Point one solves the problem where you have multiple developers sharing the same development database and all writing migrations at the same time. For instance, you create a migration 002_blah, but before you run it and check it in, another developer created, ran and checked in migration 002_bleck. By default in Rail’s, your 002_blah migration will never be run because the database is already on version 002. My library instead says “ok, I’m on version 002, but lets see if there any new migrations at or below that version that have not been run yet.”

Point two is dangerous and indeed has lead our database to get all mucked up more than a few times, but hey, it’s a feature no one is forcing you to use. The “force run” feature lets you run a migration (either up or down) even if it has already been run before. This feature is nice for when you realize you made a mistake in an already run migration and instead of making a new migration, you just want to edit and fix the existing one. You “force down” it, edit/fix it, then “force up” it.

I made a plugin for Rails called Retroactive Migrations (r_migrations) that implements this behavior. For installation and documentation, please see my personal blog post about it.

Add comment October 22nd, 2007 Author: Christopher Bottaro

Python CGI for Ajax File Uploader


See the demo and now download the code too! Goto A Better File Upload Progress Bar using Python, Ajax Prototype, & JSON

The basic idea for the File Uploader was borrowed from MegaUpload. That’s all that was borrowed really, except for the empirically derived sleep value in the read loop.

So here’s the gist of how this whole thing works…

The File Uploader allows for sending multiple files at once. We group these files by a session id which is just some unique number. The browser starts sending the files and the CGI starts handling them, one CGI process per file. Each session gets it’s own directory somewhere on the CGI server’s filesystem (/tmp). The directory name is derived from the session id which can be pulled out of the query string by the CGI process.

Within each session dir, each file get its own directory. The name of this dir is specified by the HTML form and can be pulled out of the query string by the CGI process. Within each file’s directory, four files are made: cgi_data, file, form_data, meta_data.

The first thing written is the meta_data file, which contains starttime, totalsize, and pid. The AJAX poller can read this file for bytes/sec calcuations and to cancel the upload by killing the process.

The next thing that’s written is the cgi_data file. That is all of stdin that the CGI process reads. The AJAX poller can read the size of cgi_data and from that, combined with what it reads in meta_data, can determine bytes/sec and time remaining, etc.

As stdin is being read and cgi_data is being written, we scan it for interesting data points such as mime type and file name. We write these to the meta_data file as we come across them. As the AJAX poller sees these, it can take appropriate action (display the name of the file being uploaded, and give you a nice little icon corresponding to your mime type).

Once all of stdin has been read, we can parse it and extract the actual file contents from it… which is stored in the file named file. Then we scan that file for viruses and write another meta data file called form_data, which contains stuff like name, filename, mimetype, hasVirus?, virusName. I think form_data is a little redundant and probably can be merged into the meta_data file.

The AJAX poller knows we are done by the existance of the form_data file (also because the size of cgi_data is equal to totalsize in the meta_data file), and it can redirect us to our PHP handler. Once in our PHP handler, we have inputs for the session id, as well as the sub dirs for each file uploaded in that session. From that, the PHP handler can read all the meta data files as well as the file contents.

Add comment August 22nd, 2006 Author: Christopher Bottaro


Calendar

July 2010
M T W T F S S
« Oct    
 1234
567891011
12131415161718
19202122232425
262728293031  

Links

Posts by Month

Posts by Category