Platform

Webhooks for GoCommerce

A Go package that delivers the store’s events to somebody else’s server. Register a URL and the events it cares about, and every matching event is POSTed to it, signed with HMAC-SHA256, retried with backoff for up to twelve attempts, and recorded in a delivery log an operator can read.

What it does

In the package’s own words it is “the door for a consumer that is not written in Go”. The engine’s events are durable and in-process; this module turns each one into an HTTP POST for every endpoint that asked for it.

An endpoint is a URL, a list of event patterns — an exact name such as order.paid, a prefix such as order.*, or * for everything — an active flag, and a signing secret the store generates. The body is the engine’s own event: its id, name, version, time, what it is about, and its data.

Subscribing and sending are kept apart on purpose. The subscriber writes one delivery row per matching endpoint and returns; a background worker does the sending. A slow or unreachable server therefore never holds up the engine’s outbox, and never makes another subscriber — invoices, notifications — run a second time.

Configuration

One setting, with a default. Endpoints are not configuration: they are rows an operator creates on the admin’s Webhooks screen or through the API, each with its own secret.

Webhooks module settings — 1 setting, 0 required
SettingEnvironment variableRequiredWhat it does
Timeout — No Bounds one POST to one endpoint: 10 seconds when zero. Short on purpose — in the package’s words, a merchant that takes longer is doing work it should have queued. Go only.

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

  1. Install the modulePass webhooks.New to gocommerce.New, as below, or start the reference binary with -webhooks. It adds two tables and a delivery worker.
  2. Register an endpointOn the admin’s Settings › Webhooks screen, or POST /api/admin/x/webhooks/endpoints with a url and events such as order.*. The reply carries the signing secret — the only time it is shown.
  3. Verify the signatureYour server recomputes HMAC-SHA256 over the timestamp, a dot and the raw body with that secret, and compares it with v1 in the X-GoCommerce-Signature header.
  4. Watch the logGET /api/admin/x/webhooks/deliveries lists each delivery as pending, delivered or dead, with its last status and error. A dead one can be queued again by hand.

main.go

import (
	"github.com/itswadesh/gocommerce/core"
	webhooks "github.com/itswadesh/gocommerce/ext/webhooks"
)

app, err := gocommerce.New(cfg,
	// Timeout bounds one POST to one endpoint; zero means 10 seconds.
	webhooks.New(webhooks.Config{}),
)

The package doc has no example of its own; this is how the reference binary’s -webhooks flag installs it. cfg is your gocommerce.Config. Import path github.com/itswadesh/gocommerce/ext/webhooks.

How it works

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.

FAQ

Questions about the Webhooks module

Which events can I subscribe to?

Every event the engine emits: order.created, order.paid, order.shipped, order.delivered, order.cancelled, order.refunded, order.edited and order.returned, the reversals order.unpaid, order.unshipped, order.undelivered and order.unreturned, cart.abandoned, product.created, product.updated, product.deleted and collection.updated. An endpoint names exact events, prefixes such as order.*, or * for all.

How do I verify a delivery?

Split X-GoCommerce-Signature into t and v1, compute HMAC-SHA256 with the endpoint’s secret over t, a dot and the raw request body, and compare it with v1 in constant time. Refuse a t that is too old, so a captured request cannot be replayed.

What happens when my server is down?

Each delivery is retried, the wait doubling up to 15 minutes, for twelve attempts in all. Then it is marked dead but kept; the delivery log shows it, and an operator can queue it again from the admin or with POST /api/admin/x/webhooks/deliveries/{id}/retry.

Who can register an endpoint?

An operator with webhooks.write — the owner, until the right is granted to another role — or anyone holding a static admin token. Reading endpoints and the delivery log needs webhooks.read.

Source

Everything on this page is read from ext/webhooks in the GoCommerce repository, MIT licensed. When this page and the code disagree, the code is right and this page is out of date.

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.

Chat on WhatsApp