Payments
RevenueCat Web Billing for GoCommerce
A Go package that builds a RevenueCat Web Purchase Link for each order and marks the GoCommerce order paid when RevenueCat’s webhook reports a purchase matching the order total to the minor unit. For digital goods only, and with no refunds through GoCommerce.
- Payments module
- 4 settings
- 10 tests
- ext/payments-revenuecat
What it does
The module registers “revenuecat” as a payment method. At checkout it makes no API call at all: it builds the purchase link — your link token, then the order number as RevenueCat’s app user id, with the shopper’s email and the currency as query parameters — and answers with a redirect intent carrying it. A storefront can preselect a package by sending package_id in the checkout’s payment data.
RevenueCat then calls POST /api/checkout/revenuecat/webhook. The module checks the Authorization header, and the HMAC signature too when one is configured. On INITIAL_PURCHASE or NON_RENEWING_PURCHASE it finds the order by its number and marks it paid — but only if what RevenueCat charged equals the order’s total and currency.
The package is candid about the fit. RevenueCat sells a product from its own catalogue at its own price, so the store does not set the price at checkout; RevenueCat does. And, citing RevenueCat’s documentation, Web Billing does not collect a shipping address, does not support B2B sales and is not available to merchants in India. This provider is for downloads, licences and memberships.
Configuration
Two settings are required: the Web Purchase Link token and the exact Authorization header RevenueCat is configured to send. Set them in Config from your own main(), or under Settings › Payment methods.
| Setting | Environment variable | Required | What it does |
|---|---|---|---|
LinkTokenWeb Purchase Link token | REVENUECAT_LINK_TOKEN | Yes | The path segment in https://pay.rev.cat/<token>. |
WebhookAuthorizationWebhook Authorization header | REVENUECAT_WEBHOOK_AUTHORIZATION | Yes | Exactly what RevenueCat sends in the Authorization header, compared in constant time. Required because, as the code puts it, without it any caller could mark orders paid. |
SigningSecretWebhook signing secret | — | No | Adds HMAC verification when the webhook has signing switched on in RevenueCat. The package calls it worth it: the header alone is a bearer secret every delivery repeats. |
BaseURLPurchase link host | — | No | Overrides https://pay.rev.cat, for tests. Empty for production. |
The module reads its Config struct, not the environment. The variable names are the ones the package’s own example or the reference binary uses; in your own main() you choose where each value comes from. Where a setting has a panel label, the admin’s settings drawer can hold it too, and a value typed there wins over Config.
Setting it up
- Match the priceIn RevenueCat, the product’s price must equal the order total — so leave GoCommerce’s tax rates empty, as for a merchant of record.
- Configure the webhookPoint RevenueCat’s webhook at https://your-api-host/api/checkout/revenuecat/webhook, set its Authorization header, and switch signing on.
- Install and configurePass revenuecat.New to gocommerce.New as below, or run the reference binary with -gateways and fill in Settings › Payment methods.
- Take a paymentPOST /api/checkout/revenuecat answers with a redirect intent whose url is the purchase link. A matching purchase event marks the order paid.
main.go
import (
"os"
"github.com/itswadesh/gocommerce/core"
revenuecat "github.com/itswadesh/gocommerce/ext/payments-revenuecat"
)
app, err := gocommerce.New(cfg,
revenuecat.New(revenuecat.Config{
LinkToken: os.Getenv("REVENUECAT_LINK_TOKEN"),
WebhookAuthorization: os.Getenv("REVENUECAT_WEBHOOK_AUTHORIZATION"),
}),
) The package doc’s own example, with its imports; cfg is your gocommerce.Config. Add SigningSecret when the webhook has signing on. Import path github.com/itswadesh/gocommerce/ext/payments-revenuecat.
How it works
-
No API call at checkout
The purchase link is a URL the module builds from the link token, the order number, the email and the currency. RevenueCat hears about the order only when the shopper pays.
-
Two layers of verification
The Authorization header must match exactly, in constant time. With a signing secret set, X-RevenueCat-Webhook-Signature must also verify: t=…,v1=…, an HMAC-SHA256 over the timestamp and the body, within five minutes.
-
The price is checked
RevenueCat reports the price as a decimal. The module converts it to minor units — zero- and three-decimal currencies such as JPY and KWD included — and settles only on an exact match with the order’s total and currency.
-
Each event once
Claims are keyed on RevenueCat’s event id. A redelivery is answered 200; a TEST event from the dashboard is acknowledged and nothing else.
-
A failed update is retried
If marking the order paid fails, the claim is released and the webhook answers 500, so RevenueCat’s retry finds work to do.
-
Warnings where they help
An order with a shipping address logs a warning at checkout, because Web Billing will not carry it. A CANCELLATION logs that the order still reads as paid.
What it does not do
Read these before an order depends on it. No store is known to run GoCommerce in production yet, so these come from the code, not from anyone’s experience.
- No refundsRevenueCat has no API to refund a Web Billing purchase, so the module does not claim the capability. A refund from the admin is answered 409 — the payment method does not support refunds. Refund in RevenueCat or the underlying processor.
- The price is RevenueCat’sThe link carries no amount. If the product’s price and the order total differ by one minor unit, the order is not settled and the mismatch is logged for an operator.
- Digital goods onlyPer the package, Web Billing collects no shipping address and does not support B2B sales. A store that ships parcels should use another provider.
- Not for merchants in IndiaThe package cites RevenueCat’s documentation: Web Billing is not available to merchants in India.
- One customer per orderThe order number is the app user id, so each order is a new RevenueCat customer. A project that also sells subscriptions to the same people would need to alias them in RevenueCat; the module does not.
- Cancellations are only loggedA CANCELLATION — how RevenueCat reports a refund — is logged, and the GoCommerce order keeps reading as paid.
FAQ
Questions about the RevenueCat module
Can I refund a RevenueCat order from GoCommerce?
No. RevenueCat has no API for refunding a Web Billing purchase, so the module does not implement refunds — for the same reason cash on delivery does not. The engine answers a refund with 409. Refund in RevenueCat’s dashboard or the underlying processor.
Why must the product price equal the order total?
A purchase link carries no amount; RevenueCat charges the price configured on its product. The module compares what was charged with the order total, in minor units and currency, and settles only when they agree. In practice that means GoCommerce’s tax rates stay empty.
Can I sell physical goods with it?
The package says not to. Citing RevenueCat’s documentation, Web Billing collects no shipping address, does not support B2B sales and is not available to merchants in India. It is for downloads, licences and memberships.
Is this a RevenueCat partnership?
No. The module builds RevenueCat’s public purchase links and reads its webhooks with credentials you supply. RevenueCat does not endorse GoCommerce, and no store is known to run this module in production yet.
Source
Everything on this page is read from ext/payments-revenuecat in the GoCommerce repository, MIT licensed. When this page and the code disagree, the code is right and this page is out of date.RevenueCat is a trademark of its owner; this module talks to its public API and implies no endorsement. See trademarks.
Try it against a store of your own
The one-command stack gives you GoCommerce’s API and admin on your own machine in minutes. Add this module to it and try it on test orders before a real one depends on it.