Billing access to your Laravel apps with Gumroad
Tags: tutorial, laravel
Published: 2020-10-06 14:14:03

---
title: Billing access to your Laravel apps with Gumroad
description: A simple guide detailing how to use Gumroad to sell access to your Laravel apps
published: true
date: 2020-10-04 00:00:00 UTC
tags: [Tutorial, Laravel]
canonical_url: https://miguelpiedrafita.com/laravel-gumroad
cover_image: https://miguelpiedrafita.com/images/laravel-gumroad/cover.jpg
---

I recently worked on a project where users made a one-time purchase for access to the application. Following the lead of other sites with this exact system (like [Tailwind UI](https://tailwindui.com)), we decided to go with [Gumroad](https://i.m1guelpf.me/gumroad). Here's how we made it work with Laravel.

First, you'll need to [create a Gumroad account](https://i.m1guelpf.me/gumroad). Then, create a new product and fill out all the required fields. On the **Content** section, you'll need to make sure the checkbox that says `Generate a unique license key per sale` is checked. You will also need to set the content to a URL instead of a file. In my case, this URL will be the registration page.

![Gumroad Options](https://miguelpiedrafita.com/images/laravel-gumroad/gumroad-options.png)

Let's move over to the Laravel side now. The first thing we need is a way to connect with Gumroad. Instead of downloading any packages, we can use the new `Http` client on Laravel 7.x to interact with the Gumroad API. Here's a simple class that will make our lives easier.

```php
<?php

namespace App\Utils;

use Illuminate\Http\Client\PendingRequest;

class Gumroad
{
    protected PendingRequest $client;

    public function __construct(PendingRequest $client)
    {
        $this->client = $client->baseUrl('https://api.gumroad.com/v2/')->withToken(config('services.gumroad.token'));
    }

    public function getSale(string $id) : array
    {
        return $this->client->get("/sales/{$id}")->throw()->json();
    }

    public function verifyLicense(string $license) : array
    {
        return $this->client->post('/licenses/verify', [
            'product_permalink' => config('services.microlink.product'),
            'license_key' => $license,
        ])->throw()->json();
    }
}
```

With this out of the way, we can now start working on validating the license key on registration. For this purpose, I've created a custom validation rule you can just add into the validation array on your `RegisterController` (or `CreateNewUser` if you're using Fortify). This rule will not only make sure that the license key exists, but also that it hasn't been used before and hasn't been refunded or cancelled in any way.

```php
<?php

namespace App\Rules;

use Facades\App\Utils\Gumroad;
use Illuminate\Contracts\Validation\Rule;

class GumroadLicense implements Rule
{
    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        $license = Gumroad::verifyLicense($value);

        return
                $license['success'] &&
                $license['uses'] == 1 &&
                !$license['purchase']['refunded'] &&
                !$license['purchase']['disputed'] &&
                !$license['purchase']['chargebacked'];
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The provided license is invalid or has expired.';
    }
}
```

We could stop here, but _we can still improve the experience of our users a little more_. See, when someone completes the purchase, they get redirected to the URL we specified earlier with a special query parameter called `sale_id`, which we can use to retrieve the license key and pre-fill the input. This will save the user searching for the email Gumroad sends with their key and copying, resulting in a better experience. To implement this, just run this code before returning the registration view.

```php
if (request()->query('sale_id')) {
    $sale = Gumroad::getSale($request->query('sale_id'))['sale'];

    request()->session()->flashInput(['email' => $sale['email'], 'license_key' => $sale['license_key']]);
}
```

And that's everything you need to start billing for access to your Laravel apps with Gumroad!