Skip to content

Webhooks & Signature Verification ​

Shopier dispatches event notifications via HTTP POST to your configured Notification URL. To guarantee authenticity and prevent tampering, every webhook payload is signed with HS256 (HMAC-SHA256) using your app's webhook secret token.


Webhook Headers ​

HeaderDescription
Shopier-SignatureHMAC-SHA256 signature string (hex or base64)
Shopier-EventEvent type identifier (e.g., order.created)
Shopier-Webhook-IdUnique ID of the notification event
Shopier-TimestampUnix timestamp in seconds (UTC)
Shopier-Account-IdThe shop account ID associated with the event
Shopier-Api-VersionAPI version string

Supported Events ​

Event ConstantEvent NamePayload ModelTrigger Scenario
webhook.EventOrderCreatedorder.created*shopier.OrderA new order is paid and placed
webhook.EventOrderAddressUpdatedorder.addressUpdated*shopier.OrderBuyer shipping address is updated
webhook.EventOrderFulfilledorder.fulfilled*shopier.OrderOrder is closed and marked shipped
webhook.EventProductCreatedproduct.created*shopier.ProductA new product listing is published
webhook.EventProductUpdatedproduct.updated*shopier.ProductAn existing product is updated
webhook.EventRefundRequestedrefund.requested*shopier.RefundA seller requests an order refund
webhook.EventRefundUpdatedrefund.updated*shopier.RefundRefund succeeds or fails

Webhook Event Models ​

webhook.Event ​

go
type Event struct {
	Header     Header // HTTP header metadata
	RawPayload []byte // Raw unparsed JSON payload
}

Helper Methods: ​

  • evt.Order() -> (*shopier.Order, error): Parses payload into shopier.Order.
  • evt.Product() -> (*shopier.Product, error): Parses payload into shopier.Product.
  • evt.Refund() -> (*shopier.Refund, error): Parses payload into shopier.Refund.

webhook.Header ​

FieldTypeHeader KeyDescription
WebhookIDstringShopier-Webhook-IdUnique notification identifier
EventstringShopier-EventEvent identifier (e.g. order.created)
Timestampint64Shopier-TimestampEvent dispatch time in Unix seconds (UTC)
SignaturestringShopier-SignatureHMAC-SHA256 signature string
AccountIDstringShopier-Account-IdAssociated Shopier shop account ID
APIVersionstringShopier-Api-VersionAPI version string

1. Using the Built-in http.Handler Adapter ​

The fastest way to mount a production-ready webhook endpoint in Go:

go
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/AdisGroup/shopier-go/webhook"
)

func main() {
	secret := os.Getenv("SHOPIER_WEBHOOK_SECRET")

	handler := webhook.NewHandler(secret, func(ctx context.Context, evt *webhook.Event) error {
		log.Printf("Received event: %s (ID: %s)", evt.Header.Event, evt.Header.WebhookID)

		switch evt.Header.Event {
		case webhook.EventOrderCreated:
			order, err := evt.Order()
			if err != nil {
				return err
			}
			fmt.Printf("New Order #%s for %s %s\n", order.ID, order.Totals.Total, order.Currency)

		case webhook.EventRefundRequested:
			refund, err := evt.Refund()
			if err != nil {
				return err
			}
			fmt.Printf("Refund requested: #%s (Order: %s)\n", refund.ID, refund.OrderID)
		}

		return nil
	})

	http.Handle("/webhooks/shopier", handler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

2. Manual Verification in Web Frameworks (Gin, Chi, Fiber) ​

Standard webhook.Parse ​

You can verify and parse any *http.Request directly:

go
event, err := webhook.Parse(r, webhookSecret)
if err != nil {
	http.Error(w, "Unauthorized: "+err.Error(), http.StatusUnauthorized)
	return
}

order, _ := event.Order()

Direct Byte Verification (webhook.VerifySignature) ​

For frameworks like Fiber that do not expose standard *http.Request:

go
// Fiber example
app.Post("/webhooks/shopier", func(c *fiber.Ctx) error {
	sig := c.Get("Shopier-Signature")
	body := c.Body()

	if !webhook.VerifySignature(body, sig, webhookSecret) {
		return c.Status(fiber.StatusUnauthorized).SendString("Invalid signature")
	}

	// Process payload...
	return c.SendStatus(fiber.StatusOK)
})