Skip to content

JesrigPineda/commerce-ops-webhook-bridge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Commerce Ops Webhook Bridge

Small integration service that receives Shopify order webhooks, verifies authenticity, validates and transforms the payload into an internal SalesOrder contract, applies business rules, prevents duplicate processing, and stores the processed event.

Why this project exists

Commerce and operations teams often receive raw order events from ecommerce platforms, but those payloads are not always ready to use for internal workflows such as fulfillment, invoicing, CRM, or operational reporting.

This project shows how to:

  • Receive external webhook events
  • Verify webhook authenticity
  • Validate incoming payloads
  • Transform external data into an internal business contract
  • Apply operational business rules
  • Prevent duplicate processing
  • Store processed events for traceability

Main flow

Shopify Webhook
   ↓
POST /webhooks/shopify/orders-created
   ↓
Verify HMAC signature
   ↓
Validate payload with Zod
   ↓
Map to internal SalesOrder
   ↓
Apply business rules
   ↓
Check idempotency
   ↓
Store processed event
   ↓
Return structured response

Tech stack

  • Node.js
  • TypeScript
  • Express
  • Zod
  • Pino
  • Firebase Admin / Firestore
  • Vitest

Implemented features

  • Health check endpoint
  • Shopify webhook endpoint
  • Raw body capture for HMAC verification
  • HMAC signature validation
  • Payload validation with Zod
  • Mapping to internal SalesOrder
  • Business rules:
    • invoiceRequired
    • customerType
    • priority
    • containsConsumables
  • Idempotency using webhookId or order fallback
  • Event persistence
  • Event query endpoints
  • Unit tests

Endpoints

GET /health

Returns service health information.

POST /webhooks/shopify/orders-created

Receives a Shopify order webhook, validates it, transforms it, and stores the processed event.

GET /events

Returns stored processed events.

GET /events/:idempotencyKey

Returns a processed event by idempotency key.

Example internal contract

{
  "source": "shopify",
  "sourceOrderId": "1001",
  "sourceOrderName": "#1001",
  "channel": "ecommerce",
  "createdAt": "2026-03-12T10:00:00Z",
  "customer": {
    "fullName": "Juan Pérez",
    "email": "cliente@test.com",
    "type": "business"
  },
  "totals": {
    "currency": "MXN",
    "totalAmount": 2499
  },
  "flags": {
    "invoiceRequired": true,
    "priority": "high",
    "containsConsumables": true
  },
  "shippingAddress": {
    "city": "CDMX",
    "state": "Ciudad de México",
    "country": "Mexico",
    "zipCode": "06000"
  },
  "items": [
    {
      "sku": "ALX-FILTER-01",
      "name": "Filtro ALX1 PCC",
      "quantity": 2,
      "unitPrice": 999.5
    }
  ]
}

Local setup

Install dependencies

npm install

Environment variables

Create a .env file based on .env.example.

Run locally

npm run dev

Firestore setup

This project supports two persistence modes:

  • file
  • firestore

Set this in .env:

EVENT_REPOSITORY=firestore

For local Firestore access, provide Google Application Default Credentials:

export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"

Testing

Run unit tests with:

npm test

Example webhook payload

A sample payload is included in:

examples/shopify-order-created.json

Project structure

src/
  config/
  controllers/
  domain/
    mappers/
    schemas/
  lib/
  repositories/
  routes/
  services/
  types/
tests/
  unit/
examples/
storage/
scripts/

Design decisions

  • No frontend
  • No dashboard
  • No user authentication
  • No multi-provider support in v1
  • No queues or event bus in v1

The goal is to keep the project small, realistic, and focused on integration and operational workflows.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors