Setup LemonSqueezy
The LemonSqueezy integration in ShipFlutter consists of three main components:
Directoryapp/web/payment/
- lemon_squeezy.js // Web SDK integration
Directoryapp/lib/core/account/payments/web/
- web_payments_service.dart // Dart-JS interop
Directoryfunctions/src/payment/
- lemon_squeezy.ts // Webhook handler & API
Structure
-
Web SDK Integration (
lemon_squeezy.js
)- Loads the LemonSqueezy script dynamically
- Handles checkout flow and events
- Communicates purchase results back to Flutter
-
Dart Integration (
web_payments_service.dart
)- Platform-specific implementation for web
- Uses JS interop to communicate with LemonSqueezy SDK
- Handles purchase flow, entitlement updates and paywall retrival
-
Server Integration (
lemon_squeezy.ts
)- Processes webhook events (subscriptions, orders)
- Syncs products with Firestore
- Manages user entitlements
Setup
The LemonSqueezy integration has three main components:
- Creating a product (Paywall) and variants
- Setting up a webhook
- Enable API
Prerequisites
Creating a product (Paywall)
LemonSqueezy does not has a Paywall concept, but products are the equivalent. You can define a description and variants (pacakge).
A variant in LemonSqueezy can be a single payment option or a subscription (e.g weekly, monthly, etc..).
-
New product
-
Fill the name and description
-
Add a variant
-
Define the variant name and description
-
Select pricing model (single or subscription)
-
Fill mandatory info
-
Save and add other variatns if you want (e.g Weekly, Monthly, Yearly)
-
Ignore the rest of options and save the product.
Configure Webhooks
This is crucial to ensure entitlements are updated in the app.
-
Click the ’+’ button
-
Use your deployed Firebase Function as Callback URL
-
You can define a secret and check it matches in the function (ignored by default)
-
Select the event types based on your product type:
- order_created (for one-time payments)
- subscription_created
- subscription_updated
-
Save webhook.
Configure LemonSqueezy API
The LemonSqueezy API is required to sync the products from the store to the Firestore database.
-
Create an API key
-
Copy the API key and save it to the
functions/.env
file. -
Deploy Firebase functions
-
Call the
/api/v1/payment/sync/ls
endpoint with the product ID as a path parameter
Troubleshooting
Here are some common issues you might encounter:
Products not showing up
-
Missing API Key
Make sure you have added
KEY_LEMON_SQUEEZY_API
to yourfunctions/.env
file and deployed the functions. -
Test Mode Products
If you’re using test mode, make sure to:
- Use test mode product IDs
- Enable test mode in your store settings
- Test purchases with test card numbers
-
Product Sync Failed
- Check if the product ID is correct
- Verify the product is published and active
- Try syncing again with the update endpoint
Webhook Issues
-
Missing Events
Make sure you have:
- Selected all required events in webhook settings
- Configured the correct webhook URL
- Deployed the latest functions version
-
Invalid Signature
If you set a webhook secret:
- Add it to your
functions/.env
asKEY_LEMON_SQUEEZY_WEBHOOK_SECRET
- Deploy the functions again
- Add it to your
Purchase Flow Issues
-
Purchase Not Completing
- Check browser console for errors
- Verify you’re not mixing test/live mode
- Ensure the product is published
-
Entitlements Not Updating
- Check if webhooks are configured correctly
- Verify the Firebase Functions logs
- Try restoring purchases in the app