{
  "name": "VietlinhAI | Tự gửi link tải file sau thanh toán WooCommerce",
  "nodes": [
    {
      "parameters": {
        "event": "order.updated"
      },
      "id": "ce3ac3a6-3780-4b8e-b90b-d6ac45635e66",
      "name": "WooCommerce Trigger",
      "type": "n8n-nodes-base.wooCommerceTrigger",
      "typeVersion": 1,
      "position": [
        -448,
        80
      ],
      "webhookId": "7bfa9dcd-4f58-48ba-a362-b2f718f8eaaf"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "cond-status",
              "leftValue": "={{$json[\"status\"]}}",
              "rightValue": "completed",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "4189ac36-1009-4124-97cc-56712eb263aa",
      "name": "IF - Đơn đã thanh toán",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        -208,
        80
      ],
      "notes": "Chỉ chạy khi đơn có status = 'completed' (đã thanh toán). Cổng thanh toán của bạn đặt trạng thái khác (vd 'processing') thì sửa rightValue cho khớp."
    },
    {
      "parameters": {
        "fieldToSplitOut": "line_items",
        "include": "allOtherFields",
        "options": {}
      },
      "id": "13c19d0b-117c-4d76-9c4f-edbb97c8247c",
      "name": "Tách từng sản phẩm trong đơn",
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "url": "=https://YOUR-SHOP.com/wp-json/wc/v3/products/{{$json[\"line_items\"][\"product_id\"]}}",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "wooCommerceApi",
        "options": {}
      },
      "id": "cdb2f2f9-e4b5-4f24-8482-e3f282dac0f2",
      "name": "Đọc Cloudinary meta của sản phẩm",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        224,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Tạo link tải có chữ ký cho file riêng tư trên Cloudinary (resource_type raw: .json, .zip...).\n// - Ghép public_id + \".\" + đuôi file trước khi ký, không truyền format riêng.\n// - attachment=true và type phải có trong CẢ chuỗi ký LẪN link, sắp theo bảng chữ cái.\n// Mỗi sản phẩm cần custom field: cloudinary_public_id, cloudinary_format (vd json, zip),\n// cloudinary_type (private hoặc authenticated, bỏ trống = private).\nconst crypto = require('crypto');\n\nconst apiKey = 'YOUR_API_KEY';\nconst apiSecret = 'YOUR_API_SECRET';\nconst cloudName = 'YOUR_CLOUD_NAME';\n\nif (!apiKey || !apiSecret || !cloudName) {\n  throw new Error('Thiếu thông tin Cloudinary (apiKey/apiSecret/cloudName) trong node này.');\n}\n\nconst results = [];\n\nfor (const item of $input.all()) {\n  const product = item.json;\n\n  // Custom field của sản phẩm nằm trong meta_data[] của WooCommerce REST API.\n  const meta = product.meta_data || [];\n  const field = (key) => (meta.find(m => m.key === key) || {}).value || '';\n  const publicId = product.cloudinary_public_id || field('cloudinary_public_id');\n  const ext = field('cloudinary_format');\n  const deliveryType = field('cloudinary_type') || 'private';\n\n  if (!publicId) {\n    throw new Error(`Sản phẩm ID ${product.id} (${product.name}) chưa có Cloudinary Public ID — không thể tạo link giao hàng.`);\n  }\n\n  const fullPublicId = ext ? `${publicId}.${ext}` : publicId;\n  const resourceType = 'raw';\n  const timestamp = Math.floor(Date.now() / 1000);\n\n  const paramsToSign = `attachment=true&public_id=${fullPublicId}&timestamp=${timestamp}&type=${deliveryType}`;\n  const signature = crypto\n    .createHash('sha1')\n    .update(paramsToSign + apiSecret)\n    .digest('hex');\n\n  const downloadUrl = `https://api.cloudinary.com/v1_1/${cloudName}/${resourceType}/download?attachment=true&public_id=${encodeURIComponent(fullPublicId)}&timestamp=${timestamp}&type=${encodeURIComponent(deliveryType)}&api_key=${apiKey}&signature=${signature}`;\n\n  results.push({\n    json: {\n      product_name: product.name,\n      download_url: downloadUrl,\n      delivery_type: deliveryType\n    },\n    pairedItem: item.pairedItem\n  });\n}\n\nreturn results;"
      },
      "id": "1a24e0ea-f16c-4c6e-aeee-88bd4549201d",
      "name": "Tạo signed URL Cloudinary",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        448,
        0
      ]
    },
    {
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "downloads",
        "options": {}
      },
      "id": "84667430-9dbc-4d47-8671-ace2edb352bd",
      "name": "Gộp lại theo đơn hàng",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        672,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "// Sửa 4 dòng này cho đúng shop của bạn.\nconst BRAND = '[TÊN SHOP CỦA BẠN]';\nconst SITE = 'https://your-shop.com';\nconst SUPPORT_EMAIL = 'you@example.com';\nconst TAGLINE = '[Câu giới thiệu ngắn của shop]';\n\n// Lấy thông tin đơn hàng gốc từ node Trigger (đáng tin cậy hơn dựa vào pairedItem qua Aggregate)\nconst order = $('WooCommerce Trigger').first().json;\nconst downloads = ($json.downloads || []).map(d => d.json || d);\n\nconst customerName = (order.billing && order.billing.first_name) || 'bạn';\nconst customerEmail = order.billing && order.billing.email;\nconst orderId = order.id;\nconst mienPhi = Number(order.total || 0) === 0;\nconst orderTotal = mienPhi ? '' : `${Number(order.total).toLocaleString('vi-VN')}${order.currency_symbol || 'đ'}`;\n\n// Workflow miễn phí và workflow trả phí: cùng một email, khác lời cảm ơn và tiêu đề\nconst loiCamOn = mienPhi\n  ? `Cảm ơn bạn đã tải sản phẩm miễn phí từ <b>${BRAND}</b>. Link tải ở ngay bên dưới.`\n  : `Cảm ơn bạn đã mua hàng tại <b>${BRAND}</b>. Đơn hàng đã <b>thanh toán thành công</b>, link tải ở ngay bên dưới.`;\nconst trangThai = mienPhi ? 'Miễn phí' : 'Đã thanh toán thành công';\nconst tieuDe = mienPhi\n  ? `Sản phẩm miễn phí của bạn đã sẵn sàng (${BRAND})`\n  : `Cảm ơn bạn đã mua hàng tại ${BRAND} (đơn #${orderId})`;\n\n// Mỗi sản phẩm 1 nút tải (nền cyan, chữ navy; đổi mã màu theo thương hiệu của bạn)\nconst downloadButtonsHtml = downloads.map(d => `\n  <a href=\"${d.download_url}\" style=\"display:block;background-color:#35C2FF;color:#0B1F3A;text-decoration:none;font-weight:700;font-size:15px;padding:14px 20px;border-radius:6px;margin-bottom:10px;text-align:center;font-family:'Be Vietnam Pro',Arial,sans-serif;\">⬇ Tải xuống: ${d.product_name}</a>\n`).join('');\n\nconst html = `\n<!DOCTYPE html>\n<html>\n<head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"></head>\n<body style=\"margin:0;padding:0;background-color:#F4F8FC;font-family:'Be Vietnam Pro',Arial,sans-serif;\">\n  <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"background-color:#F4F8FC;padding:32px 0;\">\n    <tr><td align=\"center\">\n      <table role=\"presentation\" width=\"600\" cellpadding=\"0\" cellspacing=\"0\" style=\"background-color:#ffffff;border-radius:8px;overflow:hidden;max-width:600px;\">\n        <tr>\n          <td style=\"background-color:#0B1F3A;padding:32px 40px;text-align:center;\">\n            <span style=\"font-size:26px;font-weight:800;color:#ffffff;font-family:'Be Vietnam Pro',Arial,sans-serif;\">${BRAND}</span>\n          </td>\n        </tr>\n        <tr>\n          <td style=\"padding:40px 40px 8px;\">\n            <p style=\"font-size:16px;color:#0B1F3A;margin:0 0 16px;\">Chào ${customerName},</p>\n            <p style=\"font-size:15px;color:#333333;line-height:1.6;margin:0 0 24px;\">${loiCamOn}</p>\n            <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"background-color:#F4F8FC;border-radius:6px;margin-bottom:28px;\">\n              <tr><td style=\"padding:16px 20px;font-size:14px;color:#123C73;line-height:1.8;\">\n                <b>Mã đơn hàng:</b> #${orderId}<br/>\n                ${orderTotal ? `<b>Tổng thanh toán:</b> ${orderTotal}<br/>` : ''}\n                <b>Trạng thái:</b> <span style=\"color:#1a8f4c;font-weight:700;\">${trangThai}</span>\n              </td></tr>\n            </table>\n            <p style=\"font-size:15px;color:#0B1F3A;font-weight:700;margin:0 0 14px;\">Link tải sản phẩm của bạn:</p>\n            ${downloadButtonsHtml}\n            <p style=\"font-size:13px;color:#666666;line-height:1.6;margin:20px 0 0;\">Lưu ý: vui lòng tải trong vòng 24 giờ kể từ khi nhận email này. Nếu không thấy email, hãy kiểm tra thư mục Spam/Quảng cáo.</p>\n          </td>\n        </tr>\n        <tr>\n          <td style=\"padding:8px 40px 40px;\">\n            <p style=\"font-size:14px;color:#333333;line-height:1.6;margin:0;\">Có thắc mắc gì trong quá trình sử dụng, bạn cứ phản hồi email này hoặc liên hệ ${BRAND}, chúng tôi luôn sẵn sàng hỗ trợ.</p>\n            ${mienPhi ? `<p style=\"font-size:14px;color:#333333;line-height:1.6;margin:12px 0 0;\">Xem thêm các sản phẩm khác tại <a href=\"${SITE}/shop/\" style=\"color:#123C73;font-weight:700;\">${SITE.replace(/^https?:\\/\\//, '')}/shop</a>.</p>` : ''}\n          </td>\n        </tr>\n        <tr>\n          <td style=\"background-color:#0B1F3A;padding:24px 40px;text-align:center;\">\n            <p style=\"font-size:13px;color:#D7E3F4;margin:0 0 4px;font-weight:600;\">${TAGLINE}</p>\n            <p style=\"font-size:12px;color:#7d93b8;margin:0;\">${BRAND} · ${SITE.replace(/^https?:\\/\\//, '')} · ${SUPPORT_EMAIL}</p>\n          </td>\n        </tr>\n      </table>\n    </td></tr>\n  </table>\n</body>\n</html>\n`;\n\nreturn [{\n  json: {\n    customer_email: customerEmail,\n    order_id: orderId,\n    email_subject: tieuDe,\n    email_html: html,\n    products_summary: downloads.map(d => d.product_name).join(', ')\n  }\n}];"
      },
      "id": "efef4ac9-c098-47f4-aaac-6069f1fbfdeb",
      "name": "Soạn nội dung email",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        880,
        80
      ]
    },
    {
      "parameters": {
        "fromEmail": "you@example.com",
        "toEmail": "={{$json[\"customer_email\"]}}",
        "subject": "={{$json[\"email_subject\"]}}",
        "html": "={{$json[\"email_html\"]}}",
        "options": {
          "appendAttribution": false
        }
      },
      "id": "5d7cd6b3-8a63-4de0-83f9-ac4864535d5c",
      "name": "Gửi email khách",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        1104,
        80
      ],
      "webhookId": "85d67de3-b7c5-49dc-b687-4880d4c96492"
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "",
          "mode": "url",
          "cachedResultName": "-- Chọn file của bạn --",
          "cachedResultUrl": ""
        },
        "sheetName": {
          "__rl": true,
          "value": "",
          "mode": "list",
          "cachedResultName": "-- Chọn trang tính của bạn --",
          "cachedResultUrl": ""
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Thời gian": "={{ $now.toFormat('yyyy-MM-dd HH:mm:ss') }}",
            "Email khách": "={{ $('Soạn nội dung email').first().json.customer_email }}",
            "Mã đơn hàng": "={{ $('Soạn nội dung email').first().json.order_id }}",
            "Sản phẩm đã mua": "={{ $('Soạn nội dung email').first().json.products_summary }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "Thời gian",
              "displayName": "Thời gian",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Email khách",
              "displayName": "Email khách",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Mã đơn hàng",
              "displayName": "Mã đơn hàng",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Sản phẩm đã mua",
              "displayName": "Sản phẩm đã mua",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "5ff0946d-68c7-460a-9beb-2d9576702698",
      "name": "Log Lead vào Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1328,
        80
      ]
    }
  ],
  "pinData": {},
  "connections": {
    "WooCommerce Trigger": {
      "main": [
        [
          {
            "node": "IF - Đơn đã thanh toán",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Đơn đã thanh toán": {
      "main": [
        [
          {
            "node": "Tách từng sản phẩm trong đơn",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tách từng sản phẩm trong đơn": {
      "main": [
        [
          {
            "node": "Đọc Cloudinary meta của sản phẩm",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Đọc Cloudinary meta của sản phẩm": {
      "main": [
        [
          {
            "node": "Tạo signed URL Cloudinary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tạo signed URL Cloudinary": {
      "main": [
        [
          {
            "node": "Gộp lại theo đơn hàng",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gộp lại theo đơn hàng": {
      "main": [
        [
          {
            "node": "Soạn nội dung email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Soạn nội dung email": {
      "main": [
        [
          {
            "node": "Gửi email khách",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gửi email khách": {
      "main": [
        [
          {
            "node": "Log Lead vào Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false
  },
  "nodeGroups": [],
  "tags": []
}