lmsqueezy / laravel

A package to easily integrate your Laravel application with Lemon Squeezy.
https://lemonsqueezy.com
MIT License
521 stars 51 forks source link

Listen command throws error #77

Closed driesvints closed 8 months ago

driesvints commented 8 months ago

Lemon Squeezy for Laravel Version

1.5.0

Laravel Version

10.x

PHP Version

8.3

Description

There's an issue with the listen command and a signing secret. For some reason it's throwing an error on a first run on a fresh install. Need to investigate this... would love some insights from anyone if able to.

Steps To Reproduce

https://youtu.be/Zx6VhRzOMkQ?t=486

heyjorgedev commented 8 months ago

I tried to reproduce it by doing the following steps (with Herd):

  1. Ran laravel new example
  2. composer require lemonsqueezy/laravel
  3. Set the environment variables LEMON_SQUEEZY_API_KEY, LEMON_SQUEEZY_STORE, LEMON_SQUEEZY_SIGNING_SECRET on my .env
  4. Running php artisan lmsqueezy:listen expose
  5. Everything worked

I was watching the video and I don't see any issue, in the video he forgot to set the LEMON_SQUEEZY_SIGNING_SECRET before running the listen command, getting the "The LEMON_SQUEEZY_SIGNING_SECRET environment variable is required." validation error.

There is a rule in place on the entrypoint of the command (https://github.com/lmsqueezy/laravel/blob/main/src/Console/ListenCommand.php#L88): 'signing_secret' => [ 'required' ],

driesvints commented 8 months ago

@heyjorgedev but the idea of the lmsqueezy:listen command is that it just creates the webhook for you. You don't have any webhook yet on a fresh install and thus also no signing secret. So there's nothing for you to set.

driesvints commented 8 months ago

Maybe I'm not seeing the full picture. The command indeed seems to require the signing secret up front. But at the same time that defeats the entire purpose of the command itself. Maybe the original author @DanielHudson has any ideas?

heyjorgedev commented 8 months ago

You don't need to create a webhook on lemonsqueezy to run the listen command, you just need to set the signing secret env variable, the command itself will create the webhook and point it to the expose url when you run it, the command also deletes the webhook from lemonsqueezy when it finishes or gets stopped

driesvints commented 8 months ago

But you can't get the signing secret without explicitly creating a webhook on Lemon Squeezy? Which defeats the entire purpose of the command? I don't know, maybe I'm stupid and just not seeing something 😅

DanielHudson commented 8 months ago

You beat me to it @heyjorgedev 👍

That's correct, you could set the signing secret to anything in development, it just uses the key for setting up the temporary webhooks.

https://github.com/lmsqueezy/laravel/blob/main/src/Console/ListenCommand.php#L272

driesvints commented 8 months ago

I think I finally understand @DanielHudson. You're saying you need to provide this yourself by filling out anything at all as the LEMON_SQUEEZY_SIGNING_SECRET value?

In that case, is it an idea that we maybe generate a random value for it ourselves if there's nothing filled out yet by the user and display that as an info message to the user so they fill it in on LEMON_SQUEEZY_SIGNING_SECRET?

'secret' => config('lemon-squeezy.signing_secret') ?: ($secret = str_random(24)),

DanielHudson commented 8 months ago

I also thought about giving random fallback, but I suspect the key will need to persist between requests, and the config is not likely to be cached in development so it wouldn't always work?

How about something along the lines of falling back to a hash of the value of LEMON_SQUEEZY_STORE (possibly also only if the app is not in production)

driesvints commented 8 months ago

Yeah that can definitely work. Tbh I don't think you'd never use this command in production to begin with. We have separate instructions for that as well.

Also wondering if we couldn't just write to the .env file if the secret isn't set yet.

DanielHudson commented 8 months ago
if (! App::environment('local')) {
            error('lmsqueezy:listen can only be used in local environment.');

            exit(Command::FAILURE);
        }

The command wouldn't ever be used in production due to the above 😜

I was more concerned about the falling back to a hash of the LEMON_SQUEEZY_STORE presenting the opportunity for someone else to guess the secret if someone forgets to configure the LEMON_SQUEEZY_SIGNING_SECRET in production - hence why only fall back on local.

'signing_secret' => env('LEMON_SQUEEZY_SIGNING_SECRET') ?: (app()->isLocal() ? sha1(env('APP_NAME')) : ''),

bit verbose though...

driesvints commented 8 months ago

Tagged a new release with the fix. Thanks @DanielHudson and @heyjorgedev!