Générer et décoder des DIGIPIN
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
- •Point de terminaison HTTP Webhook (généré automatiquement par n8n)
Nœuds utilisés (12)
Catégorie
{
"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
}
]
]
}
}
}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.
Workflows recommandés
Srinivasan KB
@srinivasankbProduct 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.
Partager ce workflow