Fewer mistakes, invoice number with Credit Card Terminal

November 20th, 2008 by Derek & Ryan

We’re happy to announce that Credit Card Terminal version 2.2 is now available in the App Store.

What’s new in this version:

  • Card Number is larger and easier to read, including number groups
  • Expiration Date automatically inserts a / to improve readability
  • When setting up the Transaction Key (on the settings screen), you can see the whole value when you first enter it
  • Added the Invoice Number field (on the More Fields screen, tap the blue arrow)

Great new rates for Credit Card Terminal

November 11th, 2008 by Derek & Ryan

When we launched Credit Card Terminal, we received some feedback from small merchants that setting up the Authorize.Net® and merchant accounts for credit card processing was too complicated and too expensive, including some penalties that were hard on small merchants.

At this time, we’re very happy to announce that we’ve secured much better credit card processing rates for our Credit Card Terminal customers.

As a small business ourselves, we understand the importance of clear, predictable rates. And we hate paying for setup or termination — it puts a lot of pressure on up-front decision making instead of letting us try things out. We hope our new offering will make it easier and cheaper than ever to try Credit Card Terminal.

When you take advantage of our new Authorize.Net + Merchant Account sign-up, there are no application, sign-up, or termination fees, and no monthly minimum processing fee. Getting rid of the minimum processing fee is a big win for small merchants, since it results in a predictable monthly bill with no worries of paying penalties for months of low or no volume.

Here’s a comparison table, assuming you need to sign up for both Authorize.Net and a merchant account:

Up-front Monthly* Per-transaction Per-transaction %
New Fees $0.00 $25.00 First 250 $0.19
251+ $0.24
Qualified 2.09%
Old Fees $99.99 $27.90–$52.90 $0.35 Qualified 2.19%

* Range in monthly fee reflects the $25 minimum processing fee as part of the old rates. The new merchant account has no monthly minimum, so there is no penalty for charging less on a monthly basis.

Credit Card Terminal is in the App Store!

November 3rd, 2008 by Derek & Ryan

Credit Card Terminal is now for sale in the App Store. Thank you to everyone who participated in our Early Customer Program!

To go with our release, we’ve put together some additional information that will help you to get started with Credit Card Terminal.

iPhone Screenshot Terminal iPhone Screenshot More Fields

Got Flash? Got Silverlight? Make a FlashLight!

July 28th, 2008 by Ryan

With Photosleeve, one of our core ideas is to reduce the work and time required to share photos. One way we do this is by creating smaller sized photos and uploading them first, which makes the initial sharing process and email generation pretty quick.

Doing this is straightforward with our Windows desktop application. But we have always been interested in finding a cross-platform browser-based way of doing the same thing. Our hope was to increase user adoption two ways: by supporting the increasingly-popular Mac platform, and by eliminating the requirement that first time uploaders download and install software.

Some of the things we considered: ActiveX, Firefox Plugin, Java applet, Flash, Adobe AIR, and Silverlight. We wanted a solution that was cross-browser and cross-platform, worked in the browser rather than a separate install, had a reasonable first-time user experience, and didn’t require the user to click through any scary security warnings.

After eliminating those that didn’t meet our criteria, we were down to Flash and Silverlight. To do what we wanted, we needed to be able to have the user select multiple files, read the bytes locally, compute a SHA1 hash, load the bytes into an image and perform manipulations like rotation and scaling, re-encode the resulting images to JPEG, and upload them to our server. Unfortunately, Flash can’t read the bytes locally, and Silverlight can’t do image manipulations or re-encode to JPEG.

At this point we thought we were out of luck. For a while we chatted about this problem with others to see if they had insights, and we’d always jokingly conclude that you’d really need to build a hybrid Flash/Silverlight application to do what we wanted. There would always be jolly consensus that such an idea was too silly to pursue. We even came up with a silly name for the “new” RIA platform: FlashLight.

But as we thought about it more, we found it less and less silly. If we could think of Flash and Silverlight as Javascript libraries instead of monolithic app platforms, there was really no reason that we couldn’t use the functionality from both to achieve our goals. It probably wouldn’t be a happy developer-tool supported experience, but — hey — we like writing code.

So next we tried to figure out if we could use Javascript as the core and call into Flash and Silverlight as needed. It turns out Silverlight provides really great Javascript connectivity. Essentially, you just decorate your types with attributes to make them accessible from Javascript. Flash’s Javascript interaction looked painful at first, but then I found this great add-on from the Flex SDK called FABridge that made it easy.

The plan was to use Silverlight to read the JPEG files, then pass those bytes over to Flash for image processing. But in the middle is Javascript, and Javascript doesn’t deal with binary data very well. Keeping it simple, we decided to base64 encode the bytes and pass them through Javascript as strings. Both Silverlight and Flash have libraries to deal with base64-encoded data.

Once we had the pieces in place, we were able to crank out our web-based uploader in about a week by writing a little bit of C#, and moderate amounts of Javascript and ActionScript. You can see the results on Photosleeve. (You’ll have to sign up for an account and click on Add Photos in the upper right.)

Thinking of Flash and Silverlight as complementary Javascript libraries instead of competing app platforms allowed us to build an app that leveraged Silverlight’s client-side file access and Flash’s client-side image manipulation.

Have other exciting apps been built using this technique? Are there others waiting to be built?

Simple maintenance mode scripts for lighttpd

June 10th, 2008 by Ryan

We recently switched to using lighttpd 1.5. Under lighttpd 1.4, we had a custom 500 page configured for our “maintenance mode”. We’d just take down the fastcgi daemon and if there were any requests while it was down, lighttpd would stop trying to talk to it for 5 seconds and instead serve out our maintenance page. Seemed ok.

Well, with lighttpd 1.5, it doesn’t try to talk to the fastcgi backend again for 60 seconds, and instead of serving back an error it would just leave the socket open, so the user’s browser would essentially hang. Not good. As a result, we wrote a script to swap out our live fastcgi process without dropping any requests (for hot swapping), and we also came up with a real “maintenance mode” for lighttpd (for real downtime like a complicated DB schema upgrade). I’ll share the fastcgi hot-swap script in a future post. Today I’ll discuss our lighttpd maintenance mode.

Our scheme doesn’t require lighttpd 1.5, but it does require that lighttpd be built with LUA support. If you do `lighttpd -V` you should see a line like ‘+ LUA support’. Kevin Worthington has built lighttpd 1.5.0 r1992 RPMs that have LUA/mod_magnet support compiled in.

We got the idea to use mod_magnet like this from John Leach’s blog post on maintenance pages status codes and lighttpd, but we removed all logic from the LUA script and provided a workaround for a lighttpd bug.

The interface to our maintenance functionality is going to be two shell scripts. Turn on maintenance mode with /etc/lighttpd/down and go back live with /etc/lighttpd/up. This simple interface is easy to use, and it abstracts away the exact method of turning things on and off so if we decide to change things later (say, touch and rm a special file or something), we can make the changes in one place.

In lighttpd.conf, we need to load mod_magnet and make sure that our maint.lua script runs for all requests.

# /etc/lighttpd/lighttpd.conf (Sample Code)
server.modules += ( "mod_magnet" )
magnet.attract-raw-url-to = ( "/etc/lighttpd/maint.lua" )

Now I make the maint.lua.up file. It does nothing. We could instead have our script run logic to determine whether or not to serve out the maintenance page, but I don’t really want LUA code running on every request if I can help it. And since I can’t claim to properly know LUA anyway, I want to keep things as simple as possible.

-- /etc/lighttpd/maint.lua.up (Sample Code)
-- This file is deliberately empty.

Now for maint.lua.down. It just serves out /etc/lighttpd/maint.html. Simple, huh? Well, actually, we need to work around lighttpd ticket #1420, so we have that hacky div in there. Oh, and I throw in a header to make it easy to distinguish this planned 503 from other kinds of wild unexpected 503s. /etc/lighttpd/maint.lua.down:

-- /etc/lighttpd/maint.lua.down (Sample Code)
lighty.header["X-Maintenance-Mode"] = "1"
lighty.content = {
    { filename = "/etc/lighttpd/maint.html" },
    "<div style=\"display:none\">",
    <!-- work around lighttpd ticket 1420 -->"
}
return 503

As for /etc/lighttpd/maint.html, put whatever you want in there. That’s your maintenance page.

Now we just need two super simple scripts to swap things out:

#!/bin/bash
# /etc/lighttpd/up (Sample Code)
cp /etc/lighttpd/maint.lua.up /etc/lighttpd/maint.lua
sleep 8
#!/bin/bash
# /etc/lighttpd/down (Sample Code)
cp /etc/lighttpd/maint.lua.down /etc/lighttpd/maint.lua
sleep 8

Why ‘sleep 8’? Well, since we’re going to want to do things like call /etc/lighttpd/down just before bringing down the backend, we want some kind of real guarantee that nobody is going to get the unresponsive browser behavior. We did some tests and it seemed like it took 8 seconds for all the relevant caches to flush so that we consistently got back a 503 from the server. I imagine that would be different for other people.

So that’s it. I hope it’s disappointingly (or perhaps refreshingly) simple. Two simple shell scripts, an exceedingly simple LUA script, and no LUA code to run unless you’re in maintenance mode. The only overhead here is that lighttpd will stat the LUA file occasionally, but it’s good at doing that unobtrusively.

Using FABridge and swfobject together

June 5th, 2008 by Ryan

Although there’s no visible Flash on Photosleeve, we use some of the Flash image processing capabilities when you upload photos through the site.

There are all sorts of different ways to include Flash, but after some research and poking around, we decided to go with swfobject.

All was swell at first, as we were using ExternalInterface to call between Flash and JavaScript. But that got pretty burdensome once we got past the proof-of-concept phase. Thankfully, we found the Adobe Flash AJAX Bridge (hereafter FABridge), which automatically handles exposing things, marshalling params, etc. It’s really great, actually.

So we had everything working great in IE, but Firefox was a no go. After debugging through things for a while (thanks, Firebug!) I realized that FABridge requires you to use the ‘embed tag within an object tag’ method (is that the one called Flash Satay?). Since I was using swfobject, no dice.

I found that the fix was just to comment out the bit of code in FABridge.js that looked for the Embed tag for certain user agents (see diff at the bottom of this post).

Incidentally, I also discovered that if you have more than one object tag on the page, you must include the bridgeName flashvar for FABridge to figure things out. The syntax for swfobject looks like this:

// swfobject_fabridge_example.js (Sample Code)
swfobject.embedSWF(
    mySwfFile,
    mySwfAlternateContent,
    myWidth,
    myHeight,
    myMinFlashVersion,
    myExpressInstallUri,
    { bridgeName: 'myBridgeName' },
    { allowScriptAccess: 'always' }
);
// and later ...
var flash = FABridge.myBridgeName.root();

You have to get rid of lines 113 and 148-169, below is a diff. FABridge.js has the MIT License blazened at the top, so have no fear when deleting huge portions of it.

--- a/fabridge/src/bridge/FABridge.js 2008-02-11 06:44:57.000000000 -0800
+++ b/fabridge/src/bridge/FABridge.js 2008-05-13 18:17:25.000000000 -0700
@@ -110,7 +110,7 @@
 {
     var searchStr = "bridgeName="+ bridgeName;

-    if (/Explorer/.test(navigator.appName) || /Konqueror|Safari|KHTML/.test(navigator.appVersion))
     {
         var flashInstances = document.getElementsByTagName("object");
         if (flashInstances.length == 1)
@@ -145,28 +145,28 @@
             }
         }
     }
-    else
-    {
-        var flashInstances = document.getElementsByTagName("embed");
-        if (flashInstances.length == 1)
-        {
-            FABridge.attachBridge(flashInstances[0], bridgeName);
-        }
-        else
-        {
-            for(var i = 0; i < flashInstances.length; i++)
-            {
-                var inst = flashInstances[i];
-                var flashVars = inst.attributes.getNamedItem("flashVars").nodeValue;
-                if (flashVars.indexOf(searchStr) >= 0)
-                {
-                    FABridge.attachBridge(inst, bridgeName);
-                }
-
-            }
-        }
-    }
-    return true;
 }

 // used to track multiple bridge instances, since callbacks from AS are global across the page.

Presto! Move content to S3 with no code changes

May 31st, 2008 by Ryan

Our initial version of Photosleeve stored the full-resolution images locally on our server. Clearly this was a temporary measure, and we’re happy to announce that we’ve moved things to Amazon S3 now. But we did it without changing any of our existing back-end code, which I think is kind of interesting.

We had anticipated the move to S3, so storage was appropriately abstracted in our codebase. My original intention was to swap out “FileStorage” for “S3Storage” and be done. But as I read about S3, I saw that it was important to plan for potential periods of unresponsiveness. For example, the Net::Amazon::S3 CPAN module recommends the use of the “retry” parameter, which will use exponential backoff in the event Amazon cannot be contacted.

Well, my customer just spent several minutes uploading his multi-megabyte full-resolution original image to my server. I don’t want to leave him hanging while I desperately wait for Amazon S3 to respond.

The solution was to leave the back-end code alone. It continued to stash the files someplace locally that our webserver could serve them out as static content. Instead, I wrote a perl daemon that watched the location the back-end dropped the files, and every so often pushed the files up to S3. Only when it was certain the files had been properly transmitted to S3, the daemon would delete the local copies (ok, actually it archived them to another offline location because we’re paranoid and didn’t want to mess up anybody’s photos).

So now the trick was getting our existing “original photo” URLs to serve out local content if available or redirect to S3 if it wasn’t. Well, that should be easy, I just need to find the blog of a rewrite rule wizard, and … Oh, wait. We use lighttpd.

We’re big admirers of lighttpd. With almost no tweaking it handles incredible amounts of traffic with almost no load. Maybe you can get Apache to do that, but we don’t know how and probably don’t have the time to figure it out. With this problem, though, I know Apache’s mod_rewrite would be an easy fix. Well, as easily as Apache rewrite rules ever are, I mean. With lighttpd, we clearly had support for redirects, but we couldn’t express the kind of conditional that we needed to redirect only if the file didn’t exist locally.

Enter mod_magnet. With it and LUA, we were able to write an extremely simple script that does exactly what we want. And — bonus! — I bet just about anybody can understand how it works. (I know rewrite rules are powerful arcane magic, worth learning, but I’ve never found the time and find the syntax completely impenetrable.)

-- /etc/lighttpd/s3.lua (Sample Code)
local filename = lighty.env["physical.path"]
local stat = lighty.stat( filename )
if not stat then
    local static_name = string.match( filename, "static/([^/]+)$" )
    lighty.header["Location"] = "http://s3.photosleeve.com/original/" .. static_name
    return 302
end

Get the filename, ok. Stat the file, sure. If it’s not there, capture a regex match group, and set the location header. Return a 302. Wow. It’s not all on one line, but I sure understand how it works.

Now we just have to hook it up to lighttpd. This does require that LUA support is compiled in. Run `lighttpd -V` and make sure you have the line “+ LUA support”. Kevin Worthington has built lighttpd 1.5.0 r1992 RPMs that have LUA/mod_magnet support compiled in.

# /etc/lighttpd/lighttpd.conf (Sample Code)
server.modules += ( "mod_magnet" )
$HTTP["url"] =~ "^/static/" {
    server.document-root = var.photosleeve-static
    $HTTP["url"] =~ "^/static/[^/]+[.]jpg([?].*)?$" {
        magnet.attract-physical-path-to = ( "/etc/lighttpd/s3.lua" )
    }
}

I specifically only run the LUA code for the precise sort of URLs that I might want to redirect. That should reduce overhead in general. As far as having the redirects in the first place, I don’t think a little less responsiveness is an issue when you’re going to download a multi-megabyte file. And coming through my server also gives me an opportunity to see the request before Amazon. Perhaps later I’ll want to be smart and cache some of the data locally based on traffic trends. Or I could add access control mechanisms (in which case the redirect would contain a signed S3 request). So many cool possibilities. And in the meantime, lighttpd handles the request without bothering my back-end perl processes.

So that’s it. Now our back-end works as it always has, dropping the content locally and generating URLs back to ourselves. But when it’s not looking a sneaky little daemon shifts things around, and the webserver takes care of hiding the mess.

Huh? What does the perl daemon look like? Fodder for another post, I think.

The innerfence blog, by the Photosleeve guys

May 31st, 2008 by Derek & Ryan

Ok, so there’s the innerfence blog, the Photosleeve blog, and then the actual Photosleeve website. What’s the relationship?

Inner Fence is the company that develops and runs Photosleeve. The Photosleeve blog is for product-related announcements; things that users of Photosleeve might be interested in. This blog, the innerfence blog, is about our experiences starting up a consumer web site. Here we share business and engineering experiences with the startup and web development community at large — the kinds of details that our Photosleeve customers are unlikely to be interested in.

Some of the articles here will be very technical, and may include code. We’ve been somewhat frustrated with how other public forums “share” code, since the licensing tends to be very unclear. In contrast, we want to be absolutely clear that you are free to use our code.

We plan to share our experiences with front-end engineering, search engine optimization, modern Perl backend development with the Catalyst MVC framework, AJAX development using YUI, hosting using lighttpd and FastCGI, etc.

It’s just the two of us running around doing everything, so we try to keep things as simple as possible, even though we have our thumbs in a lot of different technology pies. Hopefully we’ll come up with a gold nugget or two that others will find useful.

Inner Fence is Derek Del Conte and Ryan D Johnson. We live in Seattle. If you must make a distinction, Derek is the “business guy” and Ryan is the “technical guy”, but we only get along because both of us are interested in both things.