Générer et décoder des DIGIPIN

Intermédiaire

Ceci est unEngineeringworkflow d'automatisation du domainecontenant 12 nœuds.Utilise principalement des nœuds comme Code, Switch, Webhook, RespondToWebhook. Créer une API de microservice offline DIGIPIN pour la cartographie de localisation précise en Inde

Prérequis
  • Point de terminaison HTTP Webhook (généré automatiquement par n8n)

Catégorie

Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "id": "OcAQrF91wzWH3rOw",
  "meta": {
    "instanceId": "97cf5417030d41ab2642f97a3d99e6a9359587b310a5d986917e2d084e12ce17"
  },
  "name": "Generate and Decode DIGIPIN",
  "tags": [],
  "nodes": [
    {
      "id": "882aa556-8ea2-4582-8230-7b0e13ad2fd1",
      "name": "Répondre à Webhook - Succès",
      "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": "Répondre à Webhook - Erreur",
      "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 - Vérifier le succès",
      "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": "DIGIPIN_Generation_Code",
      "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": "DIGIPIN_Decode_Code",
      "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": "Encode_Webhook",
      "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": "Decode_Webhook",
      "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 - Vérifier le succès1",
      "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": "Répondre à Webhook - Succès 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": "Répondre à Webhook - Erreur 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": "Note adhésive",
      "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": "Note adhésive1",
      "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
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Intermédiaire - Ingénierie

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Intermédiaire
Nombre de nœuds12
Catégorie1
Types de nœuds5
Description de la difficulté

Adapté aux utilisateurs expérimentés, avec des workflows de complexité moyenne contenant 6-15 nœuds

Auteur
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.

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34