Skip to content

Payment Gateways: Merchant of record ​

This page covers gateways where the payment provider is the merchant of record. See Payment Gateways for how these gateways work in general and for the general go-live checklist.

What is a merchant of record? ​

With a merchant of record (MoR), the provider is the legal seller of your product, not you. The provider:

  • sells to the customer in its own name and appears on the customer's invoice and card statement;
  • calculates, collects and pays VAT and sales tax in every country where it sells, so you do not have to register for tax in those countries;
  • may add that tax on top of the order total, so the customer can pay more than the total shown in your store;
  • handles refunds, chargebacks and fraud, and pays out to you (minus its fees and the tax).

This fits well for digital products: software licenses, downloads, e-books, courses and memberships sold worldwide. It usually does not fit physical goods with shipping, or stores that already handle their own tax registration: the provider decides the tax, and most MoR providers only accept the product types listed in their terms. Check the provider's terms before you start.

Lemon Squeezy ​

Lemon Squeezy is a merchant of record for digital products, worldwide. The customer pays on a Lemon Squeezy hosted checkout, with cards, PayPal and the other methods Lemon Squeezy offers. Payments are always in the currency of your Lemon Squeezy store; orders in another currency are refused at checkout.

Available from v3.13.0

payment_gateway="lemon_squeezy"

Setup ​

Lemon Squeezy has a test mode and a live mode, toggled in the dashboard. API keys and webhooks are created per mode, so do the steps below once in test mode and once in live mode.

  1. Log in to app.lemonsqueezy.com.
  2. Under Settings → Stores, note the store id. Its currency must be the currency of your EE store.
  3. Create one product with a single payment variant (any price) and note its variant id. This variant is used for every order: its price is replaced by the order total, and the order description is used as the product name.
  4. Under Settings → API, create an API key (in test mode for the test key, in live mode for the live key).
  5. Under Settings → Webhooks, add the webhook, see Webhook below.

Then configure Lemon Squeezy in the payment gateway settings in the CP:

FieldDescription
Debug modeOn uses the test fields, off uses the live fields
Store IDThe id of your Lemon Squeezy store (Settings → Stores). Used for test and live
Test Variant IDThe variant id of your single payment product, in test mode
Test API KeyAPI key created in test mode
Test Webhook Signing SecretThe signing secret of the test mode webhook
Live Variant IDThe variant id of your single payment product, in live mode
Live API KeyAPI key created in live mode
Live Webhook Signing SecretThe signing secret of the live mode webhook

The checkout sends the order total including the tax your store calculated as the price. Lemon Squeezy may then add its own tax on top. If your store also adds tax to these orders, the customer pays tax twice; with Lemon Squeezy you normally leave the tax to Lemon Squeezy.

Webhook ​

The webhook is required for this gateway. A Lemon Squeezy checkout has no link to the order it creates; only the webhook tells the module which Lemon Squeezy order belongs to which store order.

In Lemon Squeezy, go to Settings → Webhooks and add a webhook with:

  • the notify URL shown in the CP as the callback URL;
  • the events order_created and order_refunded;
  • a signing secret of your choice. Copy it into the matching Webhook Signing Secret field in the CP.

Add one webhook in test mode and one in live mode, each with its own signing secret.

Without a signing secret, every webhook is refused and an error is logged (no webhook signing secret configured, webhook refused). Webhooks with an invalid signature, of another store or of another event are ignored. An order can only be linked to one Lemon Squeezy order.

How the payment works ​

  • On checkout, the module creates a Lemon Squeezy checkout with the order total as price and sends the customer to it. The name, email and billing country/zip are prefilled. Lemon Squeezy discount codes are disabled, because they would lower the amount paid.
  • After paying, Lemon Squeezy sends the customer back to the order page. If the order_created webhook has not arrived yet, the order is pending; the webhook then completes it.
  • The order only becomes complete when the Lemon Squeezy order is paid, for the configured store, variant and mode, in the order's currency, and its total is not lower than the order total. Otherwise the order is set to pending with an error in the log, for you to check manually.
  • The amount charged and the tax Lemon Squeezy added are stored with the order's transaction data, together with the Lemon Squeezy order number.
  • Refunds from the CP refund the full Lemon Squeezy order, so including the tax Lemon Squeezy added. A refund made in the Lemon Squeezy dashboard sets the order to refunded via the order_refunded webhook; a partial refund there leaves the order complete.

Limitations ​

  • One currency: the currency of your Lemon Squeezy store. Orders in other currencies cannot be paid with this gateway.
  • The customer can pay more than the order total, because Lemon Squeezy may add tax. Your payout is the charged amount minus Lemon Squeezy's fees and the tax.
  • There is no cancel URL: a customer who leaves the Lemon Squeezy checkout is not sent back to your checkout, and the order is not set to cancelled.
  • A refund from the CP is only possible after the webhook has linked the Lemon Squeezy order.
  • Only products Lemon Squeezy accepts (digital products, software, licenses). Check their terms.

Test checklist ​

Turn on test mode in Lemon Squeezy and Debug mode in the CP. Use the test cards from the Lemon Squeezy test mode docs.

  • [ ] Do one test checkout with a known amount (for example 12.34) and check that Lemon Squeezy shows exactly that price, not 100 times more or less (the price is sent in cents).
  • [ ] Check that the currency and total of the Lemon Squeezy order equal your store currency and order total, and are not converted to the buyer's local currency.
  • [ ] If your Lemon Squeezy prices are tax-inclusive, check that the charged total equals the order total and the order becomes complete; if tax is added on top, check that the order still becomes complete and the charged tax is stored with the order.
  • [ ] Check that the test and live webhooks are two separate webhooks with separate signing secrets, each in the matching CP field. Leave a secret empty once and check that the webhook is refused (error in the Store log).
  • [ ] Refund an order in the Lemon Squeezy dashboard and check that the order_refunded webhook still carries the custom data (meta.custom_data) and sets the order to refunded.
  • [ ] Check what happens after payment: Lemon Squeezy should send the browser straight back to your order page, or only show a confirmation with a button back. Make sure customers find their way back either way.
  • [ ] Return to the site before the webhook arrives (for example by temporarily disabling the webhook): the order must show as pending, and become complete once the webhook is delivered (you can resend it from the Lemon Squeezy dashboard).
  • [ ] Refund an order from the CP and check that the full amount charged, including the tax Lemon Squeezy added, is refunded.

Paddle ​

Paddle is not supported as a gateway (yet). Paddle's checkout only runs through Paddle.js on a page of your own, Paddle-approved website, so it cannot work as a hosted redirect like the other gateways on these pages.

It could be added as an on-site integration, like the Stripe (on-site, card) gateway. If you need Paddle, please let me know.