{
  "updatedAt": "2026-07-02T05:50:14.381Z",
  "createdAt": "2026-07-01T10:50:47.277Z",
  "id": "jw8PHzMFIYV9ULMp",
  "name": "\ub124\uc774\ubc84 \uc140\ub7ec \uc790\ub3d9\ud654 - \uc2e0\uaddc\uc8fc\ubb38\u2192\uc8fc\ubb38\uc0dd\uc131\u2192\ubc1c\uc8fc\ud655\uc778",
  "description": null,
  "active": true,
  "isArchived": false,
  "nodes": [
    {
      "parameters": {},
      "id": "d8b1217f-49ad-418f-ad2e-59e9303a083f",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -752,
        -496
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "50 * * * *"
            }
          ]
        }
      },
      "id": "30d63952-d66a-4c2c-9a36-d353ac22281c",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        -752,
        -272
      ]
    },
    {
      "parameters": {
        "endpoint": "={{ $env.GRAPHQL_URL }}",
        "query": "query Plugins { kakaoPlugin: plugin(id: \"saleor.plugins.kakao\") { configuration { name value } } }",
        "headerParametersUi": {
          "parameter": [
            {
              "name": "Authorization",
              "value": "={{ $env.AUTH_TOKEN }}"
            }
          ]
        }
      },
      "id": "6fe52dc7-8b98-486e-a0b4-1db7c0bb3d9a",
      "name": "\ud50c\ub7ec\uadf8\uc778 \ud0a4 \uc870\ud68c",
      "type": "n8n-nodes-base.graphql",
      "typeVersion": 1.1,
      "position": [
        -528,
        -384
      ]
    },
    {
      "parameters": {
        "jsCode": "const bcrypt = require('bcryptjs');\nconst axios = require('axios');\nconst ID = $env.NAVER_CLIENT_ID, SECRET = $env.NAVER_CLIENT_SECRET;\nif (!ID || !SECRET) throw new Error('\ub124\uc774\ubc84 \ud0a4 \uc5c6\uc74c: NAVER_CLIENT_ID / NAVER_CLIENT_SECRET env \ud655\uc778');\nconst ts = Date.now();\nconst sign = Buffer.from(bcrypt.hashSync(ID + '_' + ts, SECRET)).toString('base64');\nconst body = 'client_id=' + encodeURIComponent(ID) + '&timestamp=' + ts + '&client_secret_sign=' + encodeURIComponent(sign) + '&grant_type=client_credentials&type=SELF';\nconst res = await axios.post('https://api.commerce.naver.com/external/v1/oauth2/token', body, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } });\n// \ubcc0\uacbd\uc870\ud68c \uae30\uc900: \ucd5c\uadfc 3\uc2dc\uac04\nconst lastChangedFrom = new Date(Date.now() - 3 * 60 * 60 * 1000).toISOString();\nreturn [{ json: { token: res.data.access_token, lastChangedFrom } }];"
      },
      "id": "25000b29-2537-47f4-a477-2e76f17cc066",
      "name": "\ub124\uc774\ubc84 \ud1a0\ud070 \ubc1c\uae09",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -320,
        -384
      ]
    },
    {
      "parameters": {
        "url": "https://api.commerce.naver.com/external/v1/pay-order/seller/product-orders/last-changed-statuses",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "lastChangedFrom",
              "value": "={{ $json.lastChangedFrom }}"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ \"Bearer \" + $json.token }}"
            }
          ]
        },
        "options": {}
      },
      "id": "ac1f6a82-261d-478b-83f2-fb1f751c3bef",
      "name": "\ubcc0\uacbd \uc0c1\ud488\uc8fc\ubb38 \uc870\ud68c",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -96,
        -384
      ]
    },
    {
      "parameters": {
        "jsCode": "const list = ((($input.first().json || {}).data || {}).lastChangeStatuses) || [];\nconst productOrderIds = [...new Set(list.filter(x => x.productOrderStatus === 'PAYED').map(x => String(x.productOrderId)))];\nif (productOrderIds.length === 0) return [];   // \uc2e0\uaddc\uc8fc\ubb38 \uc5c6\uc74c\nreturn [{ json: { productOrderIds } }];"
      },
      "id": "807eed32-5ae6-4572-b68d-fdcdcdc09db2",
      "name": "PAYED \ucd94\ucd9c",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        128,
        -384
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.commerce.naver.com/external/v1/pay-order/seller/product-orders/query",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ \"Bearer \" + $('\ub124\uc774\ubc84 \ud1a0\ud070 \ubc1c\uae09').first().json.token }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { \"productOrderIds\": $json.productOrderIds } }}",
        "options": {}
      },
      "id": "3ec35206-b79b-4805-ad9e-3e37e4b57220",
      "name": "\uc0c1\ud488\uc8fc\ubb38 \uc0c1\uc138\uc870\ud68c",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        352,
        -384
      ]
    },
    {
      "parameters": {
        "jsCode": "const axios = require('axios');\nconst kakaoCfg = Object.fromEntries((((($('\ud50c\ub7ec\uadf8\uc778 \ud0a4 \uc870\ud68c').first().json || {}).data || {}).kakaoPlugin || {}).configuration || []).map(c => [c.name, c.value]));\nconst kakaoKey = kakaoCfg.restApiKey || '';\nasync function countryArea(a1) {\n  if (!a1 || !kakaoKey) return '';\n  try {\n    const r = await axios.get('https://dapi.kakao.com/v2/local/search/address.json', { params: { query: a1 }, headers: { Authorization: 'KakaoAK ' + kakaoKey } });\n    const d = ((r.data && r.data.documents) || [])[0];\n    const a = d && (d.address || d.road_address);\n    return a ? (a.region_1depth_name || '') : '';\n  } catch (e) { return ''; }\n}\n\n// \ubc1c\uc8fc\u524d \ud0dd\ubc30\uc8fc\ubb38\ub9cc: \uacb0\uc81c\uc644\ub8cc + \ubc1c\uc8fc\ud655\uc778\uc804 + \ud0dd\ubc30\nconst rows = (($input.first().json || {}).data) || [];\nconst picked = rows.filter(it => {\n  const po = it.productOrder || {};\n  return po.productOrderStatus === 'PAYED' && po.placeOrderStatus === 'NOT_YET' && po.expectedDeliveryMethod === 'DELIVERY';\n});\nif (picked.length === 0) return [];\n\n// order.orderId \ub85c \uadf8\ub8f9\ud551 (\ud55c \uc8fc\ubb38\uc5d0 \uc5ec\ub7ec \uc0c1\ud488\uc8fc\ubb38)\nconst groups = {};\nfor (const it of picked) {\n  const oid = String(it.order.orderId);\n  (groups[oid] = groups[oid] || { order: it.order, pos: [] }).pos.push(it.productOrder);\n}\n\nconst details = [];\nconst productOrderIds = [];\nfor (const oid of Object.keys(groups)) {\n  const addr = (groups[oid].pos[0] && groups[oid].pos[0].shippingAddress) || {};\n  const area = await countryArea(addr.baseAddress || '');\n  const orderLines = groups[oid].pos.map(po => {\n    productOrderIds.push(String(po.productOrderId));\n    const price = Number(po.unitPrice != null ? po.unitPrice : (po.totalProductAmount || 0));\n    const priceVat = (po.taxType === 'TAXATION') ? Math.round(price / 11) : 0;   // \uacfc\uc138=/11, \uba74\uc138=0\n    return { productSku: po.sellerProductCode, price, priceVat, qty: Number(po.quantity || 0), b2bDeliveryFeeExcludeVat: 0 };\n  });\n  details.push({\n    openMallName: '\ub124\uc774\ubc84',\n    openMallOrderNumber: oid,\n    fulfillType: null,\n    estimatedArrivalDate: null,\n    customerNote: '',\n    shippingAddress: {\n      country: 'KR',\n      countryArea: area,\n      firstName: addr.name || '',\n      phone: addr.tel1 || '',\n      postalCode: addr.zipCode || '',\n      streetAddress1: addr.baseAddress || '',\n      streetAddress2: addr.detailedAddress || '',\n    },\n    orderLines,\n  });\n}\nreturn [{ json: { details, productOrderIds } }];"
      },
      "id": "aa9265d9-4384-4daf-928b-9d605d00c3d2",
      "name": "\uc8fc\ubb38 \ub9e4\ud551",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        576,
        -384
      ]
    },
    {
      "parameters": {
        "endpoint": "={{ $env.GRAPHQL_URL }}",
        "query": "mutation OrderBulkCreateByStaff($type: OrderTypeEnum!, $input: OrderBulkCreateByStaffInput!) { orderBulkCreateByStaff(type: $type, input: $input) { orderCount errors: orderErrors { code message field } } }",
        "variables": "={{ { \"type\": \"BY_STAFF_FOR_BAD_STOCK\", \"input\": { \"details\": $json.details } } }}",
        "headerParametersUi": {
          "parameter": [
            {
              "name": "Authorization",
              "value": "={{ $env.AUTH_TOKEN }}"
            }
          ]
        }
      },
      "id": "f3fd31e2-5ddb-4bb6-a4f5-92b303e69516",
      "name": "saleor OrderBulkCreateByStaff",
      "type": "n8n-nodes-base.graphql",
      "typeVersion": 1.1,
      "position": [
        800,
        -384
      ]
    },
    {
      "parameters": {
        "jsCode": "const res = $input.first().json || {};\nif (res.errors && res.errors.length) throw new Error('Saleor GraphQL \uc5d0\ub7ec \u2192 \ubc1c\uc8fc\ud655\uc778 \uc911\ub2e8: ' + JSON.stringify(res.errors));\nconst r = ((res.data || {}).orderBulkCreateByStaff) || {};\nif ((r.errors || []).length) throw new Error('Saleor \uc8fc\ubb38 \uc0dd\uc131 \uc2e4\ud328 \u2192 \ubc1c\uc8fc\ud655\uc778 \uc911\ub2e8: ' + JSON.stringify(r.errors));\nif (!r.orderCount || r.orderCount < 1) throw new Error('Saleor \uc8fc\ubb38 \uc0dd\uc131 0\uac74 \u2192 \ubc1c\uc8fc\ud655\uc778 \uc911\ub2e8');\nreturn [{ json: { orderCount: r.orderCount } }];"
      },
      "id": "4c716b62-0e9a-4d6a-97d5-62008c1a5ae0",
      "name": "\uc8fc\ubb38 \uc0dd\uc131 \uacb0\uacfc \ud655\uc778",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1008,
        -384
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.commerce.naver.com/external/v1/pay-order/seller/product-orders/confirm",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ \"Bearer \" + $('\ub124\uc774\ubc84 \ud1a0\ud070 \ubc1c\uae09').first().json.token }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { \"productOrderIds\": $('\uc8fc\ubb38 \ub9e4\ud551').first().json.productOrderIds } }}",
        "options": {}
      },
      "id": "31002945-a696-4073-9977-9b01d9c86779",
      "name": "\ubc1c\uc8fc\ud655\uc778",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1232,
        -384
      ]
    },
    {
      "parameters": {
        "jsCode": "const d = (($input.first().json || {}).data) || {};\nconst ok = (d.successProductOrderInfos || []).length;\nconst fail = d.failProductOrderInfos || [];\nif (fail.length) console.log('[\ubc1c\uc8fc\ud655\uc778] \uc2e4\ud328 ' + fail.length + '\uac74: ' + JSON.stringify(fail));\nreturn [{ json: { confirmed: ok, failed: fail.length } }];"
      },
      "id": "1cc0b27f-86f8-4f2f-b111-b46f1d3088eb",
      "name": "\ubc1c\uc8fc\ud655\uc778 \uacb0\uacfc",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1456,
        -384
      ]
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "\ud50c\ub7ec\uadf8\uc778 \ud0a4 \uc870\ud68c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "\ud50c\ub7ec\uadf8\uc778 \ud0a4 \uc870\ud68c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud50c\ub7ec\uadf8\uc778 \ud0a4 \uc870\ud68c": {
      "main": [
        [
          {
            "node": "\ub124\uc774\ubc84 \ud1a0\ud070 \ubc1c\uae09",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ub124\uc774\ubc84 \ud1a0\ud070 \ubc1c\uae09": {
      "main": [
        [
          {
            "node": "\ubcc0\uacbd \uc0c1\ud488\uc8fc\ubb38 \uc870\ud68c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ubcc0\uacbd \uc0c1\ud488\uc8fc\ubb38 \uc870\ud68c": {
      "main": [
        [
          {
            "node": "PAYED \ucd94\ucd9c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PAYED \ucd94\ucd9c": {
      "main": [
        [
          {
            "node": "\uc0c1\ud488\uc8fc\ubb38 \uc0c1\uc138\uc870\ud68c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\uc0c1\ud488\uc8fc\ubb38 \uc0c1\uc138\uc870\ud68c": {
      "main": [
        [
          {
            "node": "\uc8fc\ubb38 \ub9e4\ud551",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\uc8fc\ubb38 \ub9e4\ud551": {
      "main": [
        [
          {
            "node": "saleor OrderBulkCreateByStaff",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "saleor OrderBulkCreateByStaff": {
      "main": [
        [
          {
            "node": "\uc8fc\ubb38 \uc0dd\uc131 \uacb0\uacfc \ud655\uc778",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\uc8fc\ubb38 \uc0dd\uc131 \uacb0\uacfc \ud655\uc778": {
      "main": [
        [
          {
            "node": "\ubc1c\uc8fc\ud655\uc778",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ubc1c\uc8fc\ud655\uc778": {
      "main": [
        [
          {
            "node": "\ubc1c\uc8fc\ud655\uc778 \uacb0\uacfc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": {
    "node:Schedule Trigger": {
      "recurrenceRules": []
    }
  },
  "meta": null,
  "versionId": "7957d99e-bc90-4312-a1bf-c97248bf904c",
  "activeVersionId": "7957d99e-bc90-4312-a1bf-c97248bf904c",
  "versionCounter": 18,
  "triggerCount": 1,
  "tags": [],
  "shared": [
    {
      "updatedAt": "2026-07-01T10:50:47.285Z",
      "createdAt": "2026-07-01T10:50:47.285Z",
      "role": "workflow:owner",
      "workflowId": "jw8PHzMFIYV9ULMp",
      "projectId": "PyrRNJYltDksNq22",
      "project": {
        "updatedAt": "2025-12-17T00:26:00.367Z",
        "createdAt": "2025-12-17T00:18:19.940Z",
        "id": "PyrRNJYltDksNq22",
        "name": "\ub3c4\ud604 \uae40 <dev-do@naver.com>",
        "type": "personal",
        "icon": null,
        "description": null
      }
    }
  ]
}