Automatisierte Zalo OA-Token-Verwaltung, Integration von OAuth und Webhook

Fortgeschritten

Dies ist ein Engineering, DevOps, Multimodal AI-Bereich Automatisierungsworkflow mit 10 Nodes. Hauptsächlich werden Set, Code, Webhook, HttpRequest, ScheduleTrigger und andere Nodes verwendet. Automatisches Zalo OA-Token-Management, integriert mit OAuth und Webhook

Voraussetzungen
  • HTTP Webhook-Endpunkt (wird von n8n automatisch generiert)
  • Möglicherweise sind Ziel-API-Anmeldedaten erforderlich
Workflow-Vorschau
Visualisierung der Node-Verbindungen, mit Zoom und Pan
Workflow exportieren
Kopieren Sie die folgende JSON-Konfiguration und importieren Sie sie in n8n
{
  "meta": {
    "instanceId": "9a562c06a632241f66aadd52a495ad98e76b760ef5cfce9c319a4759c47cd94e"
  },
  "nodes": [
    {
      "id": "df8fb435-f49e-4dec-8ed5-0b5b536ceab3",
      "name": "In SD speichern & Token weitergeben",
      "type": "n8n-nodes-base.code",
      "position": [
        336,
        0
      ],
      "parameters": {
        "jsCode": "const sd = $getWorkflowStaticData('global');\nconst r = $input.first().json || {};\nconst now = Date.now();\nsd.zalo = sd.zalo || {};\nif (r.access_token) sd.zalo.access_token = r.access_token;\nif (r.refresh_token) sd.zalo.refresh_token = r.refresh_token;\nconst exp = parseInt(r.expires_in, 10);\nif (!isNaN(exp)) sd.zalo.access_expires_at = now + exp * 1000;\nconst rExp = parseInt(r.refresh_token_expires_in, 10);\nif (!isNaN(rExp)) sd.zalo.refresh_expires_at = now + rExp * 1000;\n// IMPORTANT: return the refreshed token in the CURRENT ITEM\nreturn [{ json: {\n  source: \"refreshed\",\n  access_token: sd.zalo.access_token,\n  access_expires_at: sd.zalo.access_expires_at\n}}];"
      },
      "typeVersion": 2
    },
    {
      "id": "5676141d-7a9e-4872-900a-48d7a7c59cc2",
      "name": "Token aktualisieren (Zalo v4)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        64,
        0
      ],
      "parameters": {
        "url": "https://oauth.zaloapp.com/v4/oa/access_token",
        "method": "POST",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendBody": true,
        "contentType": "form-urlencoded",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "refresh_token",
              "value": "={{ $json.refresh_token }}"
            },
            {
              "name": "app_id",
              "value": "={{ $json.app_id }}"
            },
            {
              "name": "grant_type",
              "value": "refresh_token"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "secret_key",
              "value": "={{ $('Set Refresh Token and App ID').item.json.secret_key }}"
            }
          ]
        }
      },
      "typeVersion": 3
    },
    {
      "id": "65bbbd29-24ae-475d-80d2-674da63db2eb",
      "name": "Zeitplan-Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -848,
        16
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 12
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "62cbb107-ef08-4b09-b061-ecb9ae02c626",
      "name": "Execute_Node",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -848,
        -176
      ],
      "webhookId": "99397651-be96-4106-9017-3e62f0ddf03e",
      "parameters": {
        "path": "99397651-be96-4106-9017-3e62f0ddf03e",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "21029f3c-0080-4950-80f5-965cc4259239",
      "name": "Zalo Static Data bereinigen",
      "type": "n8n-nodes-base.code",
      "position": [
        -608,
        -176
      ],
      "parameters": {
        "jsCode": "const sd = $getWorkflowStaticData('global');\ndelete sd['zalo'];\nreturn [{ json: { cleared: true } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d80a21bf-9e3a-4125-9657-38520907f78a",
      "name": "Refresh Token und App ID setzen",
      "type": "n8n-nodes-base.set",
      "position": [
        -384,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "125b6083-9cac-4c88-b1c9-968cfe06a5d3",
              "name": "refresh_token",
              "type": "string",
              "value": "refresh_token_initial_refesh_token"
            },
            {
              "id": "d8e706c2-9609-4780-95d7-e3c5297a0cee",
              "name": "app_id",
              "type": "string",
              "value": "your_oa_app_id"
            },
            {
              "id": "8230a16f-3100-4fdb-9125-317f1c63fd23",
              "name": "secret_key",
              "type": "string",
              "value": "your_app_secret_key"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "37a79c0a-08c2-4a9b-9655-aa2e49c2f36c",
      "name": "In Static Data laden",
      "type": "n8n-nodes-base.code",
      "position": [
        -176,
        0
      ],
      "parameters": {
        "jsCode": "const sd = $getWorkflowStaticData('global');\nconst now = Date.now();\nconst bufferMs = 90 * 1000; // refresh 90s early\nsd.zalo =    sd.zalo || {};\nconsole.log('new code #### here this is',sd.zalo);\n// Seed refresh token on very first run\nif (!sd.zalo.refresh_token) {\n  sd.zalo.refresh_token =  $input.first().json.refresh_token;\n}\n\nconst hasAccess = !!sd.zalo.access_token;\nconst notExpired = !!sd.zalo.access_expires_at && (sd.zalo.access_expires_at - bufferMs) > now;\nconst needs_refresh = !(hasAccess && notExpired);\n\nreturn [{\n  json: {\n    needs_refresh,\n    access_token: sd.zalo.access_token || null,\n    access_expires_at: sd.zalo.access_expires_at || null,\n    refresh_token: sd.zalo.refresh_token || null,\n    app_id: $input.first().json.app_id\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "25f68c0d-9eef-43be-accc-60bae7d62065",
      "name": "Webhook-Trigger",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -848,
        240
      ],
      "webhookId": "5afc66e9-136e-4fb2-9263-9aaa1c1037ef",
      "parameters": {
        "path": "zalo-intergration-v1",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "e96e8fdf-e031-4afc-b1ab-b6f1b9837158",
      "name": "Access Token laden",
      "type": "n8n-nodes-base.code",
      "position": [
        -592,
        240
      ],
      "parameters": {
        "jsCode": "const sd = $getWorkflowStaticData('global');\nsd.zalo =    sd.zalo || {};\nreturn [{\n  json: {\n    access_token: sd.zalo.access_token || null,\n    access_expires_at: sd.zalo.access_expires_at || null,\n    refresh_token: sd.zalo.refresh_token || null,\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "43e752b8-ec85-4764-addb-71383e69217d",
      "name": "Notiz",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1856,
        -848
      ],
      "parameters": {
        "width": 944,
        "height": 1712,
        "content": "# Zalo OA Token Auto-Refresh (n8n)\n\n## What this workflow does\n- Maintains a fresh Zalo OA access token using Workflow Static Data (global).\n- Supports both scheduled refresh and a manual “reset & re-seed” path.\n- Exposes a lightweight webhook to read the currently cached token for other integrations.\n\n---\n\n## High-level flow\nSchedule Trigger → Set Refresh Token & App ID → Load to Static Data → Refresh Token (Zalo v4) → Store to SD & Pass token\n\nManual reset path: Execute_Node (Webhook) → Clean Zalo Static Data → Set Refresh Token & App ID → … (continues flow above)\n\nToken peek path: Webhook (zalo-intergration-v1) → Load Access Token (returns cached token)\n\n---\n\n## Node-by-node\n\n### 1) Schedule Trigger\nRuns the auto-refresh flow on a fixed interval (every 12 hours) so the access token stays valid.\n\n### 2) Execute_Node (Webhook)\nManual entry point to trigger a reset of cached tokens during testing or when rotating credentials.\n\n### 3) Clean Zalo Static Data\nClears the token cache from Workflow Static Data so the next run re-seeds and refreshes from provided inputs.\n\n### 4) Set Refresh Token and App ID\nProvides the required identifiers and secrets to the flow (refresh token, app ID, secret key).  \nTip: In production, reference environment variables instead of hardcoding.\n\n### 5) Load to Static Data\nInitializes the token cache on first run, checks if a valid access token already exists, and flags whether a refresh is needed (early-refresh buffer applied).  \nNote: With the current wiring, the flow proceeds to refresh on every run.\n\n### 6) Refresh Token (Zalo v4)\nCalls Zalo OAuth to exchange the refresh token for a new access token and returns updated expiry information.\n\n### 7) Store to SD & Pass token\nPersists the latest token and expiry timestamps into Workflow Static Data and passes the current access token forward for immediate downstream use.\n\n### 8) Webhook (zalo-intergration-v1)\nSimple endpoint to request whatever token is currently cached (useful for other services/workflows).\n\n### 9) Load Access Token\nReads the cached access token and its expiry from Workflow Static Data and returns them to the caller of the integration webhook.\n\n---\n\n## Behavior & usage notes\n- The token cache is scoped to this workflow. Other workflows should call this one or use the integration webhook to retrieve the token.\n- An early-refresh buffer reduces the chance of token expiry during active API calls.\n- Secure the manual reset webhook (e.g., IP allowlist or secret) and move sensitive values to environment variables.\n- Optional optimization: insert an IF condition after “Load to Static Data” to skip the refresh call when the cached token is still valid.\n"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "e96e8fdf-e031-4afc-b1ab-b6f1b9837158",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "62cbb107-ef08-4b09-b061-ecb9ae02c626": {
      "main": [
        [
          {
            "node": "21029f3c-0080-4950-80f5-965cc4259239",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "65bbbd29-24ae-475d-80d2-674da63db2eb": {
      "main": [
        [
          {
            "node": "d80a21bf-9e3a-4125-9657-38520907f78a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "37a79c0a-08c2-4a9b-9655-aa2e49c2f36c": {
      "main": [
        [
          {
            "node": "5676141d-7a9e-4872-900a-48d7a7c59cc2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "21029f3c-0080-4950-80f5-965cc4259239": {
      "main": [
        [
          {
            "node": "d80a21bf-9e3a-4125-9657-38520907f78a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5676141d-7a9e-4872-900a-48d7a7c59cc2": {
      "main": [
        [
          {
            "node": "df8fb435-f49e-4dec-8ed5-0b5b536ceab3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d80a21bf-9e3a-4125-9657-38520907f78a": {
      "main": [
        [
          {
            "node": "37a79c0a-08c2-4a9b-9655-aa2e49c2f36c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Häufig gestellte Fragen

Wie verwende ich diesen Workflow?

Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.

Für welche Szenarien ist dieser Workflow geeignet?

Fortgeschritten - Engineering, DevOps, Multimodales KI

Ist es kostenpflichtig?

Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.

Workflow-Informationen
Schwierigkeitsgrad
Fortgeschritten
Anzahl der Nodes10
Kategorie3
Node-Typen6
Schwierigkeitsbeschreibung

Für erfahrene Benutzer, mittelkomplexe Workflows mit 6-15 Nodes

Autor
Le Nguyen

Le Nguyen

@leeseifer

Salesforce Architect with 10+ years of experience in CRM, integrations, and automation. Skilled in Apex, LWC, REST APIs, and full-stack dev (JavaScript, .NET). I build secure, scalable workflows in n8n—connecting Salesforce, Stripe, and more. Passionate about lead scoring, data sync, and secure field masking. Certified Application Architect with deep expertise in platform, integration, and data architecture.

Externe Links
Auf n8n.io ansehen

Diesen Workflow teilen

Kategorien

Kategorien: 34