LemonSqueezy payment gateway integration for Frappe/ERPNext. Allows processing payments, managing subscriptions, and receiving webhooks from LemonSqueezy.
- β Payment processing through LemonSqueezy
- β Subscription management
- β Webhooks for payment and subscription events
- β Support for custom pricing
- β Integration with Frappe Payment Requests
- β Webhook log recording
- β HMAC signature validation
# Navigate to the bench directory
cd frappe-bench
# Get the app from GitHub
bench get-app https://github.com/ernestoruiz89/lemonsqueezy.git
# Install the app on your site (skip assets since this app has no frontend JS/CSS)
bench --site [site-name] install-app lemonsqueezy --skip-assets
# Migrate
bench --site [site-name] migratebench restart- Log in to LemonSqueezy
- Go to Settings β API
- Create a new API Key
- Copy your Store ID (you can find it in the store section)
- In LemonSqueezy, go to Settings β Webhooks
- Create a new webhook pointing to:
https://your-site.com/api/method/lemonsqueezy.lemonsqueezy.api.handle_webhook - Select the events you want to receive:
order_createdsubscription_createdsubscription_updatedsubscription_cancelledsubscription_resumedsubscription_expiredsubscription_pausedsubscription_unpaused
- Copy the Signing Secret
- Go to LemonSqueezy Settings
- Create a new document:
- Enabled: β
- Gateway Name:
Standard(or your preferred name) - API Key: Paste your API key
- Store ID: Paste your Store ID
- Webhook Secret: Paste the webhook signing secret
- Default Variant ID (optional): Variant ID for generic payments
- Save the document
import frappe
# Get the Payment Request
pr = frappe.get_doc("Payment Request", "PR-00001")
# Generate checkout URL
gateway_controller = frappe.get_doc("LemonSqueezy Settings", "LemonSqueezy-Standard")
checkout_url = gateway_controller.get_api_checkout_url(
amount=pr.grand_total,
currency=pr.currency,
payer_email=pr.email_to,
payer_name="John Doe",
reference_doctype="Payment Request",
reference_docname=pr.name,
order_id=pr.name,
variant_id="123456" # Optional
)
print(checkout_url)import frappe
# Get subscription
subscription = frappe.get_doc("LemonSqueezy Subscription", "SUB-12345")
# Check if it's active
if subscription.is_active():
print("Active subscription")
# Get customer portal URL
portal_url = subscription.get_portal_url()
print(f"Portal: {portal_url}")
# Get status color
color = subscription.get_status_color()
print(f"Indicator color: {color}")Get customer portal URL from frontend:
frappe.call({
method: "lemonsqueezy.lemonsqueezy.doctype.lemonsqueezy_settings.lemonsqueezy_settings.get_customer_portal_url_api",
args: {
subscription_id: "12345"
},
callback: function(r) {
if (r.message) {
window.open(r.message, '_blank');
}
}
});Webhooks are automatically processed and logged in LemonSqueezy Webhook Log.
| Event | Description |
|---|---|
order_created |
An order is created (updates Payment Request to "Paid") |
subscription_created |
A subscription is created |
subscription_updated |
A subscription is updated |
subscription_cancelled |
A subscription is cancelled |
subscription_resumed |
A subscription is resumed |
subscription_expired |
A subscription expires |
subscription_paused |
A subscription is paused |
subscription_unpaused |
A paused subscription is resumed |
active- Activeon_trial- On trial periodpaused- Pausedpast_due- Past due paymentunpaid- Unpaidcancelled- Cancelledexpired- Expired
- Verify that the webhook URL is publicly accessible
- Check Error Log in Frappe to see errors
- Verify that the webhook is enabled in LemonSqueezy
- Make sure the Signing Secret is correct
- Verify that the Webhook Secret in Settings is correct
- Make sure to copy the complete secret without spaces
- Verify that the API Key and Store ID are correct
- Make sure the Variant ID exists in your store
- If using custom pricing, verify that the variant allows it
- Check Error Log for more details
- Verify that the
order_createdwebhook is configured - Make sure to pass
order_idorpayment_request_idin the checkout - Check LemonSqueezy Webhook Log to see if the event was received
Payment gateway configuration.
Stores subscription information synchronized from LemonSqueezy.
Log of all received webhooks with their payload and status.
- β HMAC signature validation on webhooks
- β Secure API key storage (Password fields)
- β Error logging without exposing sensitive data
β οΈ Recommendation: Implement rate limiting in production
# Unit tests (when available)
bench --site [site-name] run-tests --app lemonsqueezyReview application logs:
# Error logs
bench --site [site-name] console
>>> frappe.get_all("Error Log", filters={"error": ["like", "%LemonSqueezy%"]}, limit=10)
# Webhook logs
>>> frappe.get_all("LemonSqueezy Webhook Log", limit=10)- LemonSqueezy Documentation: https://docs.lemonsqueezy.com
- API Reference: https://docs.lemonsqueezy.com/api
- Frappe Framework: https://frappeframework.com/docs
MIT License
Contributions are welcome. Please:
- Fork the project
- Create a branch for your feature (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Basic integration with LemonSqueezy API
- Payment and subscription processing
- Webhook handling
- Payment Request integration