Mac App Store

Now that I’d decided on a game plan, I had to put my code where my mouth was.
I thought it best to begin with the one thing that could make or break my entire endeavor: integrating my backend with my new Merchant of Record, Paddle.

Paddle Billing

Paddle Billing is very obviously targeted at recurring payments (“subscriptions”) rather than one-time purchases, underlined by the fact that Paddle Classic did have direct support for creating and/or handling license keys, whereas Paddle Billing does not. I know subscriptions are all the rage these days, but I just don’t like them.
A Quick-Start guide on how to handle one-time purchases would have been nice, or at least some sort of direction on what API to look into. The documentation in general is very good and detailed, but it isn’t outright obvious how all the pieces fit and work together. It feels like each piece is described nicely on its own, but how it all fits into a whole flow of a user purchasing something is up for the developer to figure out.
I would have preferred a use-case approach. Like, for subscriptions, what does a typical, recurring payment flow look like from first billing, to recurring billing, to the eventual cancellation by the customer? What does a one-time purchase flow look like? What APIs are involved? How are refunds handled? What are the caveats, and what should I pay close attention to? That would have helped a lot here.
Being a developer myself, I understand the situation too well. When you develop an app, you know it inside and out. That’s good, but it makes you prone to omitting the very fundamentals of your product when explaining it to others, because it’s second nature and obvious to you. Like, when a 3-Michelin-star-chef explains cooking soup to you by talking about how to plate it up and make it look nice, and you’re there wondering how to tell when the water is boiling.

Anyway, I did figure it out – Paddle’s sandbox environment made it beautifully painless. And once I did, I was very positively surprised by how extensive the API is and what you can build with it. It’s based on events and webhooks, where your server endpoints get called when certain events in your checkout flow happen. For instance, when a customer completes a purchase of a product, you get a transaction.complete event, which means you can now fulfill the order – by sending a license key, for example. That transaction persists on their server, so you can use it again to implement a “re-send license” feature, when a customer loses the email you sent. Neat.
You could also use this to implement a reminder feature, where you mail potential customers with an incomplete transaction, asking them if they’d like to complete their order. (Local and international laws apply, of course. And if you go down this route, do it very sparingly. Most people nowadays hate getting nag-mail out of the blue).


I went about implementing my backend using…

PHP, the old (t)rusty

Apparently, PHP is dead. Every year anew, it seems. And yet, it’s always been there when I needed it.
It has a huge community of very helpful developers behind it, is very well documented, and there’s a vast library of frameworks and code to take inspiration from. Personally, I love it. It’s also well integrated into and supported by my web server, regularly maintained and updated, so it was a no-brainer for me to use it for this implementation.

But I am not a backend developer. I usually leave backend development to those who really know it. That being said, I didn’t want to hand off something so crucial to be implemented by someone else; I would have little control over the code, I would have had to give them access to at least my Paddle credentials, and to parts of my web server – I’d rather never eat Käseleberkäse again. And I love Käseleberkäse. When it comes to my work, I keep it all as much first-party as I possibly can.
Does that mean a task that would have taken a professional fifteen minutes takes me three hours?

Yes.
But I sleep so much better at night.

I second-guessed every line of PHP code I wrote to ensure it runs smoothly and safely.
Cross every ‘t’, dot every ‘i’, and htmlspecialcharacter every ‘<‘.
And PDO. Why had I never heard about PDO before? In the past, I always interfaced with databases directly using mysqli (carefully, of course), but now, with PDO (PHP Data Objects), it’s way better – and allegedly safer.

To sell ScreenFloat and, in time, my other apps directly from my website (in addition to the Mac App Store), I had to implement the following:
The Backend
– Get a webhook callback from Paddle when a successful purchase occurs
– – Validate the callback, create the license(s) from the information in the transaction and send them to the customer
– – Save minimum information in a database for the license activation, deactivation, resetting, and recovery mechanisms
– Get a webhook callback from Paddle for refunds, to disable licenses created from that purchase transaction

The Website
– Integrate Paddle’s overlay into my website for checkout
– – Have a checkout “preflight”, where customers enter their name, email, and the type of license they want to purchase, to set up the transaction used in the Paddle checkout overlay

The App
– Make ScreenFloat accept licenses to be registered with
– – Have a license reset and lost-license-retrieval mechanism in-app

What was important to me here was that (a) I could easily include other apps for purchase later, (b) the license creation and all associated functions were independent of Paddle, so I could use it with other platforms (for bundles, mostly) and subsequently (c), if ever need be, switch from Paddle to a different Merchant of Record without having to re-implement everything.


Setting up the webhook on Paddle is straight forward. Select the events you’re interested in getting, supply your server endpoint for them, and it’s done.

After I verify the call is actually coming from Paddle and contains a valid transaction payload, I create the cryptographically signed license(s) from the customer’s information in that transaction, along with app-related information. After I verify it is signed correctly, I send it off to the customer in a nicely formatted plain-text and html-text multi-part email.
Initially I played around with encrypting the entire license and decrypting it in the app for validation and unlocking, but in the end settled on just signing a more-or-less plaintext payload to keep it simple.

Like I said in the first part of this blog post series, personal licenses can be used to register two copies of my app (on accounts on the same Mac, or on different Macs), whereas commercial licenses can be used to register one copy, but used by any account on that Mac.
There’s quite a bit of overhead in the implementation here. If you want to keep track of activations, you need a way to do that (a database and an “API” to manage all the necessary info), and will have to have a way to reset individual or all activations of a license: if a customer gets a new Mac, they might want to move their registration over from the old one, for example.
When it comes to commercial licenses, I figured administrators wouldn’t want employees to be able to mess with a copy’s registration, so those require a “key” to be reset, which is individually created and sent alongside the license keys.


For the customer to get to that part, I first needed some sort of checkout on my website. Paddle provides a drop-in storefront, which handles it all. Sweet. I wanted to precede that with a simple form where the customer can select what type of license they want (personal; personal as a gift for someone else; commercial), and enter their name and email, to make sure a name is supplied for the license to be personalized with.

Here comes Paddle’s API into play – I create a new transaction from the supplied information and pass it on to the Paddle storefront, with all information already set. All that’s left then is for the customer to enter their payment details, and they’re done.

This “preflight” also allows me to provide special discounts for Apple employees, like I’ve already been doing for Yoink for Mac, (although in a very different way). I do plan to transition that over to Paddle and licenses as well, just to have it all in one place, handled by the same mechanic in the background.
I thought about implementing Paddle’s storefront in-app directly, too, but I decided against that – I believe users feel safer and more comfortable entering payment details when they’re in the browser of their choice.


All that work is useless if users can’t use a license in my app to unlock it. I already offer trial versions for most of my Mac apps as downloads from my website, with ScreenFloat being no exception, so I already had a head start in creating an out-of-app-store branch. All that was missing from it was the license validation and app-registration that removes the trial limitations.

The license a user receives by mail is a custom app-url-scheme link which, when clicked, automatically launches my app and fills out the required license key field, for the user to be confirmed for registration. Alternatively, I also include a download link for a license file. I figured some people might like a backup copy of it somewhere, and it can make it easier to share a gifted license.

Since licenses aren’t stored anywhere, that download link is basically the same as the custom app-url-scheme link that has the payload as a url query parameter, but instead of pointing to my app, it’s pointing to an endpoint on my server – a PHP script that turns that query parameter into a file download. I found that to be a neat workaround.
Naturally, that file can be double-clicked to register the app, if it’s already installed.
The app itself then verifies the payload locally and with the server and, if everything checks out, unlocks itself.


Next Time

There’s still the matter of self-updating the app, displaying release notes, and verifying app update downloads, so that’s what we’ll go over next time. I hope to see you then!


Read more

It has been I-don’t-even-know-how-long (that is: an eternity) since I last offered any of my apps for purchase outside of the App Stores.
GimmeSomeTune was donationware (handled by PayPal), but there was no licensing, so that doesn’t count.
For a software-bundle (I can’t remember the name, and I don’t believe it’s around anymore), I created a non-updatable version of ScreenFloat 1.x that customers received, yet also without licenses, so that doesn’t count either.
I think the only app I ever really sold properly and had a license scheme for and handled sales myself was flickery, which I sold from my website through PayPal before the Mac App Store arrived.
But once the Mac App Store hit, I transitioned all my apps to it pretty much right away.
It’s just so convenient: no license creation, no license verification (apart from receipt validation, but that has become more convenient recently), easy updating, no handling of payments, invoices, refunds, and the potential of getting featured to lots and lots of users.


Why do it, then?

Besides all that, it was high time I set up a way to also sell my apps outside of the Mac App Store.
Without a licensing system for my apps, I’ve been unable to participate in software-bundles and/or collections. Lots of companies and corporations cannot purchase apps from the Mac App Store due to policies. Individuals who want to purchase my apps for work are unable to do so because of those same policies. I also am unable to give individual discounts to customers when need be.
And while I am a strong proponent of the Mac App Store, I also believe in giving people a choice. Customers should have the choice of purchasing my apps on the App Store, or directly* from me. *: I don’t handle any of the payment and invoicing myself, that’s done by my Merchant of Record, Paddle.
Also, it certainly cannot hurt to have an alternate route to sell my apps.
What if the Mac App Store goes belly-up? Not likely, but still, I’d go belly-up along with it.
What if Apple doesn’t want my apps anymore? It could happen (it has been close before), and then I’d be screwed.

All that is just a long-winded way of saying: it makes sense to have some redundancy. A second way of selling my apps. One I have a bit more control over.

Now, I did slack off on this for a long time. I’ve been getting requests to participate in bundles for years (!) and still couldn’t bring myself to set it up. I don’t know why. I guess I thought my time was better spent working on my apps instead of backend stuff.
But then there were all these recent inquiries from companies, and users affected by policies of companies, who cannot purchase apps from the Mac App Store. For some reason, there’s been an uptick there, and requests have become more and more frequent.
So I hunkered down and finally started looking into all the things that needed to get done so I could sell my apps outside of the Mac App Store as well:

  • Decide on a Merchant of Record
    (crucial for the “selling” part)
  • Come up with and implement a license key scheme
    (crucial for legitimating purchases of my app)
  • Freshen up my PHP, HTML and JavaScript “skills” and integrate my backend with the merchant’s
    (crucial for everything)
  • Implement a way for the app to update itself
    (pretty much standard nowadays)
  • In that vein, implement a safer way to download files than just a plain file-straight-from-server download
    (so the app can verify the update is legit)

Getting a Merchant of Record or Payment Processor

A “Merchant of Record” is a company that handles payments, invoicing, refunds, taxes, etc for indie software developers and other businesses. Payment processors “just” handle the payment part, but you’re pretty much responsible for everything else.
There are actually quite a few to choose from: FastSpring, PayPal, Paddle, Stripe, and Gumroad, just to name a few.

  • PayPal I didn’t want to use because I remember its API from back in the day and it just gave me headaches. I’m actually amazed I pulled it off for flickery way back when. Also, and I might be wrong about this, but, I believe it still doesn’t handle taxes and stuff for you, and I just won’t do that myself anymore.
  • Gumroad seemed to me like more of a hobby thing? Anyway, I couldn’t see myself selling software through them.
  • FastSpring is a popular choice, loved for its extensive feature set.
  • Stripe seemed out of my league. Like, it’s a fancy masquerade ball, and I’m in the dark corner wearing sweats, eventually getting asked to leave because I make people “uncomfortable”.
Put the Paddle to the Metal

So I went with Paddle. I don’t feel frowned upon here in my sweats. And in my calculations, it seemed a bit less expensive than FastSpring. Plus, I’ve heard good things about it. The API is well-documented* and their support seemed… supportive.
Why’s there an ominous asterisk next to “well-documented”? I’m glad you asked!
There’s Paddle Classic, and as of recently, there’s the new Paddle Billing, with a completely different API.
Guess what this idiot (read: me) did. Yup, I spent 3 days looking into and partially implementing Paddle Classic, only to find out it’s no longer available for new signups. Fun!
Hey, Paddle, I have a suggestion: Instead of that tiny, friendly light-blue indicator at the top of the Paddle Classic API documentation page that you can easily overlook and even dismiss, why not make it a big, red, bold-letter banner? That would have saved me tons of time.
Instead, I sat there wondering why none of my test-calls from the Paddle dashboard worked. (Side note: Debugging remote PHP scripts is a freaking pain. Especially the way I do it – which might be the wrong way.)
But that’s alright. Every story needs its ups and downs. Why not begin with a down outright? Who knows, it could be all uphill from here!

For selling through Paddle, you need their approval. They take a look at your website and make sure everything’s on the up-and-up regarding your Privacy Policy, Terms of Service, payment flow, checkout and whatnot.
The entire process was fairly straight-forward. It might have helped that I’m already selling my apps through the Mac App Store, so they could see that I’m serious about my endeavors. For my Terms of Service I looked into the websites of other indies selling software through Paddle, which I thought made sense, since they’re already approved by them.
It took about three weeks with a bit of back and forth to get the approval, but that was no time lost, since I used it to start implementing the correct API on the backend.


Scheming up a License Key

A vital part of an app sold outside of the Mac App Store is requiring the user to have a license key in order to keep using it past its trial limitations. If you don’t have that, anyone could just use your app without paying for it. That’s fine for freeware or donationware and the like, but for an app you want to sell, it’s counterproductive.

Obviously, you want to be the only one able to create these license keys. Back in the day, for flickery, I had a very traditional format: a 32-odd-character dash-separated string, like FLKRY-ABA1-ABA2-ABA3…
It was just a salted MD5 hash of a certain order of transformed and salted md5 hashes of the customer’s name and email. In the app, the user would enter their name, email and the license key and flickery would re-create the license key itself from the supplied info and see if it matches up with the one the user supplied. If it did, the app was registered, if not, then not.
In order to forge a key, one would have to know the salts, the transformations and the order I used to create a valid key. Someone with a lot of time on their hands could eventually figure it out and create a key generator. Or hack the flickery binary and figure it out that way.
The salts were actually more pepper than salt, as they were hopefully secret. As a side note, I don’t think the license generation was ever cracked. The app itself was, though.

I’ve decided to go a different way this time around. The license now is a cryptographically signed payload (signed using a private key), consisting of the user’s data, app information and transactional data. All the app does is use the corresponding public key to verify the signature. If it’s valid, it can proceed with further activation steps. If not, something’s wrong with the license. As long as the private key actually stays private, there’s no feasible way to forge a license at this point in time.

I also wanted to make sure a license can only be active on a limited number of Macs or user accounts at a time, and have a way of blocklisting license keys infringing on my Terms of Service.
This is also where license types come into play.
There’s the “personal license” for individuals, which can be used to activate the app a limited amount of times (on any Mac or user account);
and the “commercial license”, which can be activated on a single Mac, but used with an unlimited amount of accounts on that Mac – a “seat” license.
With managing and limiting the activations comes the need to unregister individual copies of an app, or reset the entire license, so you can free up a slot to activate the app on a different Mac or user account. More work on the backend!

Consequently, in order to activate a copy of my app with a license key, an internet connection is required. But you also need an internet connection to download the app in the first place, so I don’t see a downside there. And there’s no always-online requirement. Only once in a while, the app will demand a connection to make sure the license and its activation are still good.

What was important to me about all this though is that none of the user’s information, not even the license key, is stored on my server. Yes, Paddle stores user data, because they have to. But I didn’t see the need to have user data be present on my server as well. It holds only the information it absolutely requires to activate, deactivate, reset, re-issue and refund licenses.

Most of this is handled on the backend, which took most of my time to implement and test. Even though I have been using PHP (with MySQL for database integration) on and off over the years, I’m by no means “fluent”, so I repeatedly had to consult different guides to figure out the best practices, and how to code safely, for everyone involved. JavaScript I’d never really used before (but had to for the Checkout pages), and HTML with CSS, well… my checkout pages are as pretty as they’re going to get, to put it bluntly.
But I learned a lot. I like doing server/website stuff for some reason. Maybe because it’s not my area of expertise, and I get to understand the workings of the internet a little bit better and learn so much. It just has a certain allure I can’t explain.


Next Time

In the next part, I’ll go over the integration with Paddle, and my backend implementation. I hope you’ll join me!


Read more

ScreenFloat v2.2.1, a free update for existing customers, is now available on the Mac App Store and includes numerous improvements for cutting recordings, automation, and more.


What is ScreenFloat?

ScreenFloat is your Screenshot All-Rounder.
Capture screenshots and recordings that float above other windows, allowing you to reference anything on your screen, anywhere. It’s like Picture-in-Picture, only for screen captures.
It keeps your Desktop clutter-free, as every capture you make is stored in its Shots Browser, where you can manage, organize and find your shots. They’re also synced across your Macs.
Easily copy the non-copyable, as ScreenFloat recognizes text, barcode and faces in your shots, which also allows you to effortlessly redact sensitive parts of your screenshots.
Add non-destructive annotations, redactions and markup, crop, “fold“, resize, or de-retinize your shots, or trim, cut or mute your recordings. Quickly pick colors.
Create shareable and embeddable links for your captures using iCloud, ImageKit.io or Cloudinary.com.
And so much more.

A screenshot is just a screenshot. Until you use ScreenFloat.

Tip: Check out the Get to Know ScreenFloat 2 Blog Post series for a deep-dive into its functionality and what it can do for you.


What’s New in ScreenFloat v2.2.1?

  • When you cut your recordings, you now get more info about the resulting video, where the playhead is, and how long your individual cuts are.
    Also, preview playback has been improved, as well as scrubbing through the recording.
  • There’s now an easier way to make new cuts, by holding down X on your keyboard as you play back your recording:
  • Standby Window Capture (macOS 14 or newer required) – grab a screenshot of any window from its green resize button, or from the Capture item in your menu bar.
  • AppleScripts and Shortcuts can now be run on floating shots directly, in addition to the already existing Double-Click Workflow Actions.
  • The new Permissions overview gives you all the details you need to know about why, how and when ScreenFloat makes use of certain privileges you grant it
  • You’re now able to set a floating shot’s visibility not only to the currently active app, but any currently running app
  • And many more minor improvements and bugfixes, like the Shortcuts app no longer launching right away when setting up a new Double-Click action, or the cutting window remembering its size.

Links and Availability

ScreenFloat is a one-time purchase, exclusively available on the Mac App Store for USD 15.99 / EUR 14,99 / GBP 15.99 , and a free update for existing customers.
A free, 28-day trial is available for download from the website.
It requires macOS 12 Monterey (macOS 14 Sonoma recommended for full functionality)
A (free) iCloud account is required if you want to sync your ScreenFloat library across your Macs.
ScreenFloat is currently localized in English, German, Chinese (Simplified), and Dutch.

ScreenFloat Website + Free Trial
ScreenFloat on the Mac App Store
Eternal Storms Software Productivity Bundle on the Mac App Store (includes ScreenFloat, Yoink for Mac and Transloader at ~25% off)

Get to Know ScreenFloat 2 Blog Post Series
ScreenFloat 2 Usage Tips

Contact & Connect


I hope you enjoy ScreenFloat (and my other apps) : )

Read more

As a sort-of follow up to my post about Apple’s macOS Engineers running out of places to put new permission dialogs in, I had a thought, because, I do have those from time to time.

Here’s what’s up: In macOS, when you want to, for example, create a screenshot app and want it to be able to actually take screenshots, you’ll have to get permission from the user for it. With the upcoming macOS 15 Sequoia, that is going to be upped to two dialogs. One: the initial permission request, and two: a weekly reminder, asking if you want to continue to allow this app to capture your screen.
Here’s where my aforementioned thought comes in: Wouldn’t it be nice if a screenshot app from the Mac App Store was able to, like, take screenshots, right out of the box, without any permission dialogs?
I feel like apps on the Mac App Store should get some perks for being reviewed and vetted by Apple’s App Review.

So here’s my thought, wrapped into a couple of examples, to really drive my point home ad nauseam:
– A developer of a screenshot app that has successfully gone through App Review to be published on the Mac App Store should be able to request a default screen capture entitlement for it, which lets macOS know that no permission dialogs need to be presented, or asked for weekly, at all. It can just take screenshots right after download, because, you know, it’s a screenshot app, and that’s what the user downloaded it for.

– A developer of an audio recording app that has been reviewed by App Review to be released on the Mac App Store should be able to request a default Microphone recording entitlement, so it can record audio right after download, because, you know, it’s an audio recording app, and that’s what the user downloaded it for.

– A developer of an app that uses the user’s current location for core features that has successfully been reviewed by App Review to be released on the Mac App Store should be able to request a default Location entitlement so it can get its work done right after download, because that’s what the user downloaded it for.

Shouldn’t that be sort of the point of App Review?
I kind of understand making apps obtained from outside the Mac App Store jump through permission dialogs (to an extent, I just hate the new weekly permission reminders so much), but I feel like apps obtained from the Mac App Store could appear so much more user-friendly and polished without them, and would definitely make apps obtained from there feel special.

I guess what I’m saying is: Apple, please stop this Tour-de-farce security permission dialog onslaught and give users and developers some credit.


P.S.: I do realize it’s a pipe-dream. With all the ways stuff can be kept from App Review – which has happened time and time again – it’s not a system fit for such an implementation. Which, in turn, draws App Review’s reason for existing into question altogether.

Read more