Generar y decodificar DIGIPIN

Intermedio

Este es unEngineeringflujo de automatización del dominio deautomatización que contiene 12 nodos.Utiliza principalmente nodos como Code, Switch, Webhook, RespondToWebhook. Crear una microservicio de API de DIGIPIN para mapeo de ubicación precisa fuera de línea para la India

Requisitos previos
  • Punto final de HTTP Webhook (n8n generará automáticamente)

Categoría

Vista previa del flujo de trabajo
Visualización de las conexiones entre nodos, con soporte para zoom y panorámica
Exportar flujo de trabajo
Copie la siguiente configuración JSON en n8n para importar y usar este flujo de trabajo
{
  "id": "OcAQrF91wzWH3rOw",
  "meta": {
    "instanceId": "97cf5417030d41ab2642f97a3d99e6a9359587b310a5d986917e2d084e12ce17"
  },
  "name": "Generate and Decode DIGIPIN",
  "tags": [],
  "nodes": [
    {
      "id": "882aa556-8ea2-4582-8230-7b0e13ad2fd1",
      "name": "Responder a Webhook - Éxito",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        340,
        -140
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "json",
        "responseBody": "={\n  \"status\": \"Success\",\n  \"lat\": \"{{ $json.query.lat }}\",\n  \"lon\": \"{{ $json.query.lon }}\",\n  \"digipin\": \"{{ $json.digipin }}\"\n} "
      },
      "typeVersion": 1.4
    },
    {
      "id": "368240b0-cecf-46e7-9509-bfcb1afe7610",
      "name": "Responder a Webhook - Error",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        340,
        60
      ],
      "parameters": {
        "options": {
          "responseCode": 422
        },
        "respondWith": "json",
        "responseBody": "={\n  \"status\": \"Failed\",\n  \"lat\": \"{{ $json.query.lat }}\",\n  \"lon\": \"{{ $json.query.lon }}\",\n  \"error\": \"{{ $json.error }}\"\n} "
      },
      "typeVersion": 1.4
    },
    {
      "id": "b6c70cd6-3d5f-4215-989c-8a5e6a896564",
      "name": "Switch - Verificar éxito",
      "type": "n8n-nodes-base.switch",
      "position": [
        120,
        -40
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "digipin",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "3656e246-523a-4611-b563-8e66ae078d67",
                    "operator": {
                      "type": "string",
                      "operation": "exists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.digipin }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "9b5ef11d-7833-41c3-8611-56cf11df2dcc",
                    "operator": {
                      "type": "string",
                      "operation": "exists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.error }}",
                    "rightValue": ""
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "3a7dc7a2-9d19-467c-b651-143187d852d9",
      "name": "Código de generación DIGIPIN",
      "type": "n8n-nodes-base.code",
      "position": [
        -100,
        -40
      ],
      "parameters": {
        "jsCode": "// --- DIGIPIN Generation Logic ---\n\n// Constants for DIGIPIN generation\nconst DIGIPIN_GRID = [\n    ['F', 'C', '9', '8'],\n    ['J', '3', '2', '7'],\n    ['K', '4', '5', '6'],\n    ['L', 'M', 'P', 'T']\n];\n\nconst BOUNDS = {\n    minLat: 2.5,\n    maxLat: 38.5,\n    minLon: 63.5,\n    maxLon: 99.5\n};\n\n/**\n * Encodes latitude and longitude into a DIGIPIN.\n * @param {number} lat The latitude.\n * @param {number} lon The longitude.\n * @returns {string} The generated DIGIPIN.\n * @throws {Error} If coordinates are out of bounds.\n */\nfunction generateDigiPin(lat, lon) {\n    if (lat < BOUNDS.minLat || lat > BOUNDS.maxLat || lon < BOUNDS.minLon || lon > BOUNDS.maxLon) {\n        throw new Error(`Coordinates (Lat: ${lat}, Lon: ${lon}) are out of the valid range.`);\n    }\n\n    let minLat = BOUNDS.minLat, maxLat = BOUNDS.maxLat;\n    let minLon = BOUNDS.minLon, maxLon = BOUNDS.maxLon;\n    let digiPin = '';\n\n    for (let level = 1; level <= 10; level++) {\n        const latDiv = (maxLat - minLat) / 4;\n        const lonDiv = (maxLon - minLon) / 4;\n        let row = 3 - Math.floor((lat - minLat) / latDiv);\n        let col = Math.floor((lon - minLon) / lonDiv);\n        row = Math.max(0, Math.min(row, 3));\n        col = Math.max(0, Math.min(col, 3));\n        digiPin += DIGIPIN_GRID[row][col];\n        if (level === 3 || level === 6) {\n            digiPin += '-';\n        }\n        maxLat = minLat + latDiv * (4 - row);\n        minLat = minLat + latDiv * (3 - row);\n        minLon = minLon + lonDiv * col;\n        maxLon = minLon + lonDiv;\n    }\n    return digiPin;\n}\n\n\n// --- n8n Item Processing ---\n// Loop through each input item provided to the node.\nfor (const item of items) {\n    try {\n        // Get latitude and longitude from the input item's JSON data.\n        // Assumes the previous node provides these fields.\n        const lat = $input.first().json.query.lat;\n        const lon = $input.first().json.query.lon;\n\n        if (lat === undefined || lon === undefined) {\n            throw new Error(\"Input item is missing 'latitude' or 'longitude' field.\");\n        }\n\n        // Generate the DIGIPIN.\n        const digipinResult = generateDigiPin(lat, lon);\n\n        // Add the result to a new field called 'digipin' in the item's JSON.\n        item.json.digipin = digipinResult;\n\n    } catch (error) {\n        // If an error occurs, add an 'error' field to the item.\n        // This helps with debugging in the n8n UI.\n        item.json.error = error.message;\n    }\n}\n\n// Return all the modified items to the next node in the workflow.\nreturn items;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "33aab4da-4b77-44fa-85c4-0ed165b416d3",
      "name": "Código de decodificación DIGIPIN",
      "type": "n8n-nodes-base.code",
      "position": [
        -100,
        420
      ],
      "parameters": {
        "jsCode": "/**\n * Decodes a DIGIPIN into latitude and longitude coordinates.\n * @param {string} digiPin The DIGIPIN to decode.\n * @returns {{latitude: string, longitude: string}} An object containing the latitude and longitude,\n * each formatted to 6 decimal places.\n * @throws {Error} If the DIGIPIN is invalid or contains invalid characters.\n */\nconst DIGIPIN_GRID = [\n    ['F', 'C', '9', '8'],\n    ['J', '3', '2', '7'],\n    ['K', '4', '5', '6'],\n    ['L', 'M', 'P', 'T']\n];\n\n\nconst BOUNDS = {\n    minLat: 2.5,\n    maxLat: 38.5,\n    minLon: 63.5,\n    maxLon: 99.5\n};\nfunction getLatLngFromDigiPin(digiPin) {\n    const pin = digiPin.replace(/-/g, ''); // Remove hyphens for processing\n    if (pin.length !== 10) throw new Error('Invalid DIGIPIN: Must be 10 characters long after removing hyphens.');\n\n    let minLat = BOUNDS.minLat;\n    let maxLat = BOUNDS.maxLat;\n    let minLon = BOUNDS.minLon;\n    let maxLon = BOUNDS.minLon; // Corrected initial value here, should be BOUNDS.minLon\n\n    // Recalculate maxLon for accurate initial bounds\n    // Based on the original DIGIPIN generation, it should cover the whole range initially.\n    maxLon = BOUNDS.maxLon;\n\n\n    for (let i = 0; i < 10; i++) {\n        const char = pin[i];\n        let found = false;\n        let ri = -1, ci = -1;\n\n        for (let r = 0; r < 4; r++) {\n            for (let c = 0; c < 4; c++) {\n                if (DIGIPIN_GRID[r][c] === char) {\n                    ri = r;\n                    ci = c;\n                    found = true;\n                    break;\n                }\n            }\n            if (found) break;\n        }\n\n        if (!found) throw new Error(`Invalid character '${char}' in DIGIPIN.`);\n\n        const latDiv = (maxLat - minLat) / 4;\n        const lonDiv = (maxLon - minLon) / 4;\n\n        const lat1 = maxLat - latDiv * (ri + 1);\n        const lat2 = maxLat - latDiv * ri;\n        const lon1 = minLon + lonDiv * ci;\n        const lon2 = minLon + lonDiv * (ci + 1);\n\n        minLat = lat1;\n        maxLat = lat2;\n        minLon = lon1;\n        maxLon = lon2;\n    }\n\n    const centerLat = (minLat + maxLat) / 2;\n    const centerLon = (minLon + maxLon) / 2;\n\n    return {\n        latitude: centerLat.toFixed(6),\n        longitude: centerLon.toFixed(6)\n    };\n}\n\n\nconst MY_DIGIPIN = $input.first().json.query.digipin; // <--- REPLACE THIS with your desired DIGIPIN\n\n// Ensure there's at least one item to process, or create a dummy one\nlet outputItems = [];\nif (items.length === 0) {\n    // If no items come into the node, create a blank one to attach results to\n    outputItems.push({ json: {} });\n} else {\n    // If items exist, clone them to add results\n    outputItems = JSON.parse(JSON.stringify(items));\n}\n\nfor (const item of outputItems) {\n    try {\n        const digipinToProcess = MY_DIGIPIN;\n\n        if (!digipinToProcess) {\n            throw new Error(\"No DIGIPIN specified for processing.\");\n        }\n\n        // Decode the DIGIPIN\n        const decodedCoords = getLatLngFromDigiPin(digipinToProcess);\n\n        // Add the result to new fields in the item's JSON\n        item.json.processedDigipin = digipinToProcess; // Optional: To see which digipin was processed\n        item.json.decodedLatitude = decodedCoords.latitude;\n        item.json.decodedLongitude = decodedCoords.longitude;\n\n    } catch (error) {\n        // If an error occurs, add an 'error' field to the item.\n        item.json.error = error.message;\n    }\n}\n\n// Return all the modified items to the next node in the workflow.\nreturn outputItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "6da5b090-caf7-4a8b-a254-a90ac9b97610",
      "name": "Webhook de codificación",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -320,
        -40
      ],
      "webhookId": "8f08f857-3a7e-4b46-97fb-7de6812e9204",
      "parameters": {
        "path": "generate-digipin",
        "options": {},
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "99a30d16-696a-4c2c-941d-7b66a6591d54",
      "name": "Webhook de decodificación",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -320,
        420
      ],
      "webhookId": "8f08f857-3a7e-4b46-97fb-7de6812e9204",
      "parameters": {
        "path": "decode-digipin",
        "options": {},
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "ab871baf-aae7-4060-83af-7794974dce18",
      "name": "Switch 2 - Verificar éxito1",
      "type": "n8n-nodes-base.switch",
      "position": [
        120,
        420
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "coordinates",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "3656e246-523a-4611-b563-8e66ae078d67",
                    "operator": {
                      "type": "string",
                      "operation": "exists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.decodedLatitude }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "9b5ef11d-7833-41c3-8611-56cf11df2dcc",
                    "operator": {
                      "type": "string",
                      "operation": "exists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.error }}",
                    "rightValue": ""
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "64409e6c-e4aa-41b2-abcf-a016e729ea37",
      "name": "Responder a Webhook - Éxito 2",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        340,
        320
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "json",
        "responseBody": "={\n  \"status\": \"Success\",\n  \"digipin\": \"{{ $json.query.digipin }}\",\n  \"lat\": \"{{ $json.decodedLatitude }}\",\n  \"lon\": \"{{ $json.decodedLongitude }}\"\n} "
      },
      "typeVersion": 1.4
    },
    {
      "id": "d37184ce-7060-4d06-b039-dd8572e7d3e8",
      "name": "Responder a Webhook - Error 2",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        340,
        520
      ],
      "parameters": {
        "options": {
          "responseCode": 422
        },
        "respondWith": "json",
        "responseBody": "={\n  \"status\": \"Failed\",\n  \"digipin\": \"{{ $json.query.digipin }}\",\n  \"error\": \"{{ $json.error }}\"\n} "
      },
      "typeVersion": 1.4
    },
    {
      "id": "8d745b4f-f993-4865-a96f-e3f1e28a0cc2",
      "name": "Nota adhesiva",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        660,
        360
      ],
      "parameters": {
        "color": 4,
        "width": 920,
        "height": 320,
        "content": "## Example usage \n\nGenerate a DIGIPIN:\n```\ncurl --request GET \\\n  --url 'https://n8n.example.in/webhook/generate-digipin?lat=27.175063&lon=78.042169'\n```\n\nDecode a DIGIPIN:\n```\ncurl --request GET \\\n  --url 'https://n8n.example.in/webhook/decode-digipin?digipin=32C-849-5CJ6'\n```"
      },
      "typeVersion": 1
    },
    {
      "id": "3cb47a09-ce41-4d2d-a413-885510ebda96",
      "name": "Nota adhesiva1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        660,
        -160
      ],
      "parameters": {
        "width": 920,
        "height": 440,
        "content": "## DIGIPIN Generator and Decoder\n\nThis n8n workflow lets you **generate and decode DIGIPINs** using only JavaScript - no external APIs involved.\n\nDIGIPIN is India Post’s geolocation code system that encodes latitude and longitude into a 10-character alphanumeric string, like `32C-849-5CJ6`. It helps simplify precise location sharing across India.\n\n### 🔧 What it does\n- `/generate-digipin?lat=...&lon=...` → returns the DIGIPIN for given coordinates\n- `/decode-digipin?digipin=...` → returns the coordinates for a given DIGIPIN\n\nUseful for: check-in systems, last-mile delivery, digital address verification, or simple location sharing.\n\n### ⚙️ How to use\n- Add your own webhook URLs or run locally\n- Pass query parameters to trigger either route\n- Both encode/decode logic is handled inside Function nodes\n\nNo credentials, APIs, or setup required.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "9226c009-d942-4f3c-b982-9f7dbb73d710",
  "connections": {
    "99a30d16-696a-4c2c-941d-7b66a6591d54": {
      "main": [
        [
          {
            "node": "33aab4da-4b77-44fa-85c4-0ed165b416d3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6da5b090-caf7-4a8b-a254-a90ac9b97610": {
      "main": [
        [
          {
            "node": "3a7dc7a2-9d19-467c-b651-143187d852d9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "33aab4da-4b77-44fa-85c4-0ed165b416d3": {
      "main": [
        [
          {
            "node": "ab871baf-aae7-4060-83af-7794974dce18",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3a7dc7a2-9d19-467c-b651-143187d852d9": {
      "main": [
        [
          {
            "node": "b6c70cd6-3d5f-4215-989c-8a5e6a896564",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b6c70cd6-3d5f-4215-989c-8a5e6a896564": {
      "main": [
        [
          {
            "node": "882aa556-8ea2-4582-8230-7b0e13ad2fd1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "368240b0-cecf-46e7-9509-bfcb1afe7610",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ab871baf-aae7-4060-83af-7794974dce18": {
      "main": [
        [
          {
            "node": "64409e6c-e4aa-41b2-abcf-a016e729ea37",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "d37184ce-7060-4d06-b039-dd8572e7d3e8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Preguntas frecuentes

¿Cómo usar este flujo de trabajo?

Copie el código de configuración JSON de arriba, cree un nuevo flujo de trabajo en su instancia de n8n y seleccione "Importar desde JSON", pegue la configuración y luego modifique la configuración de credenciales según sea necesario.

¿En qué escenarios es adecuado este flujo de trabajo?

Intermedio - Ingeniería

¿Es de pago?

Este flujo de trabajo es completamente gratuito, puede importarlo y usarlo directamente. Sin embargo, tenga en cuenta que los servicios de terceros utilizados en el flujo de trabajo (como la API de OpenAI) pueden requerir un pago por su cuenta.

Información del flujo de trabajo
Nivel de dificultad
Intermedio
Número de nodos12
Categoría1
Tipos de nodos5
Descripción de la dificultad

Adecuado para usuarios con experiencia intermedia, flujos de trabajo de complejidad media con 6-15 nodos

Autor
Srinivasan KB

Srinivasan KB

@srinivasankb

Product Manager in B2B SaaS product focused on CX management. Interested in building AI powered workflows that can automate or simplify the routine and complex tasks.

Enlaces externos
Ver en n8n.io

Compartir este flujo de trabajo

Categorías

Categorías: 34