{
  "name": "Lancer: verified webhook",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "lancer",
        "responseMode": "onReceived",
        "options": {}
      },
      "id": "5f0b6f0e-1c1a-4a63-9a0c-0a3c1f1d0001",
      "name": "Lancer webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [0, 0],
      "webhookId": "lancer"
    },
    {
      "parameters": {
        "jsCode": "// Verify Lancer's signature: sha256=HMAC(secret, timestamp + '.' + body).\nconst crypto = require('crypto');\nconst secret = $env.LANCER_WEBHOOK_SECRET;\nif (!secret) throw new Error('Set LANCER_WEBHOOK_SECRET (Settings → API ו-Webhooks → הצגת הסוד)');\n\nreturn $input.all().map((item) => {\n  const headers = item.json.headers || {};\n  const timestamp = headers['x-lancer-timestamp'];\n  const signature = headers['x-lancer-signature'] || '';\n  const body = JSON.stringify(item.json.body);\n  const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${body}`).digest('hex');\n  const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300;\n  const same = signature.length === expected.length && crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));\n  if (!fresh || !same) throw new Error('Invalid Lancer signature');\n  return { json: item.json.body };\n});"
      },
      "id": "5f0b6f0e-1c1a-4a63-9a0c-0a3c1f1d0002",
      "name": "Verify signature",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [240, 0]
    },
    {
      "parameters": {
        "conditions": {
          "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" },
          "conditions": [
            {
              "id": "c1",
              "leftValue": "={{ $json.event }}",
              "rightValue": "payment.succeeded",
              "operator": { "type": "string", "operation": "equals" }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "5f0b6f0e-1c1a-4a63-9a0c-0a3c1f1d0003",
      "name": "Payment received?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [480, 0]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            { "id": "a1", "name": "clientId", "value": "={{ $json.data.clientId }}", "type": "string" },
            { "id": "a2", "name": "amountShekels", "value": "={{ $json.data.amountAgorot / 100 }}", "type": "number" },
            { "id": "a3", "name": "paidAt", "value": "={{ $json.data.paidAt }}", "type": "string" }
          ]
        },
        "options": {}
      },
      "id": "5f0b6f0e-1c1a-4a63-9a0c-0a3c1f1d0004",
      "name": "Payment fields (replace with your action)",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [720, -100]
    },
    {
      "parameters": {},
      "id": "5f0b6f0e-1c1a-4a63-9a0c-0a3c1f1d0005",
      "name": "Other events",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [720, 100]
    }
  ],
  "connections": {
    "Lancer webhook": { "main": [[{ "node": "Verify signature", "type": "main", "index": 0 }]] },
    "Verify signature": { "main": [[{ "node": "Payment received?", "type": "main", "index": 0 }]] },
    "Payment received?": {
      "main": [
        [{ "node": "Payment fields (replace with your action)", "type": "main", "index": 0 }],
        [{ "node": "Other events", "type": "main", "index": 0 }]
      ]
    }
  },
  "settings": { "executionOrder": "v1" },
  "pinData": {}
}
