8
n8n 한국어amn8n.com

DIGIPIN 생성 및 디코딩

중급

이것은Engineering분야의자동화 워크플로우로, 12개의 노드를 포함합니다.주로 Code, Switch, Webhook, RespondToWebhook 등의 노드를 사용하며. 인도 정확한 위치 맵핑을 위한 오프라인 DIGIPIN 미니서비스 API를 만듭니다.

사전 요구사항
  • HTTP Webhook 엔드포인트(n8n이 자동으로 생성)

카테고리

워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "id": "OcAQrF91wzWH3rOw",
  "meta": {
    "instanceId": "97cf5417030d41ab2642f97a3d99e6a9359587b310a5d986917e2d084e12ce17"
  },
  "name": "Generate and Decode DIGIPIN",
  "tags": [],
  "nodes": [
    {
      "id": "882aa556-8ea2-4582-8230-7b0e13ad2fd1",
      "name": "Webhook 응답 - 성공",
      "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": "Webhook 응답 - 오류",
      "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": "스위치 - 성공 확인",
      "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_생성_코드",
      "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_디코드_코드",
      "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": "인코드_웹훅",
      "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": "디코드_웹훅",
      "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": "스위치 2 - 성공 확인1",
      "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": "Webhook 응답 - 성공 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": "Webhook 응답 - 오류 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": "스티키 노트",
      "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": "스티키 노트1",
      "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
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

중급 - 엔지니어링

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
중급
노드 수12
카테고리1
노드 유형5
난이도 설명

일정 경험을 가진 사용자를 위한 6-15개 노드의 중간 복잡도 워크플로우

저자
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.

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34