8
n8n 中文网amn8n.com

x402 + Ollama

高级

这是一个Engineering, AI Chatbot领域的自动化工作流,包含 18 个节点。主要使用 If, Code, Webhook, OneShot, OneShotSynch 等节点。 使用x402和Ollama实现私有LLM模型货币化

前置要求
  • HTTP Webhook 端点(n8n 会自动生成)
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "WRRtIr0VKNu7ZXuk",
  "meta": {
    "instanceId": "62f017ec8f130d172e2e5f39bbf09515036bfd403dfa60fe06f5ab14b78705d0",
    "templateCredsSetupCompleted": true
  },
  "name": "x402 + Ollama",
  "tags": [],
  "nodes": [
    {
      "id": "e2f6ea01-eab4-4b6c-810b-db3392dbd1aa",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -340,
        20
      ],
      "webhookId": "92c5ca23-99a7-437d-85da-84aef8bd2a25",
      "parameters": {
        "path": "92c5ca23-99a7-437d-85da-84aef8bd2a25",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "7af658fb-b731-47f1-8889-2f16af976155",
      "name": "检查是否存在 X-HEADER",
      "type": "n8n-nodes-base.if",
      "position": [
        -120,
        20
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2ff83590-61f3-41d8-8500-a96103c3844c",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.headers['x-payment'] }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a28240bc-ee9b-4f1b-8b74-8e380232fa0a",
      "name": "解码和验证 X-Payment",
      "type": "n8n-nodes-base.code",
      "position": [
        100,
        -60
      ],
      "parameters": {
        "jsCode": "try {\n    // Decode the x-payment header from base64\n    const xPaymentHeader = $input.first().json.headers['x-payment'];\n    const decodedXPayment = Buffer.from(xPaymentHeader, 'base64').toString('utf-8');\n\n    // Parse the decoded value into a JSON object\n    const decodedXPaymentJson = JSON.parse(decodedXPayment);\n\n    // Add the parsed JSON object to the input\n    $input.first().json.decodedXPayment = decodedXPaymentJson;\n\n    return $input.all();\n} catch (error) {\n    // Return an error object if the token format is invalid\n    return { error: \"invalid token format\" };\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "0f1efa84-3779-4f6c-87a3-844e25bba57a",
      "name": "模拟支付",
      "type": "n8n-nodes-1shot.oneShot",
      "position": [
        540,
        -100
      ],
      "parameters": {
        "params": "={\n  \"from\": \"{{ $json.decodedXPayment.from }}\",\n  \"to\": \"{{ $json.decodedXPayment.to }}\",\n  \"value\": \"{{ $json.decodedXPayment.value }}\",\n  \"validAfter\": \"{{ $json.decodedXPayment.validAfter }}\",\n  \"validBefore\": \"{{ $json.decodedXPayment.validBefore }}\",\n  \"nonce\": \"{{ $json.decodedXPayment.nonce }}\",\n  \"signature\": \"{{ $json.decodedXPayment.signature }}\"\n} ",
        "operation": "simulate",
        "contractMethodId": "b63aaaa1-059d-4c38-928a-33ad17d66827"
      },
      "credentials": {
        "oneShotOAuth2Api": {
          "id": "nkfF9AitCKUCrErK",
          "name": "1Shot account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "437d945e-5d8b-4dc2-9e66-3675802ebc66",
      "name": "支付模拟成功时",
      "type": "n8n-nodes-base.if",
      "position": [
        760,
        -100
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "81c67679-e256-4fd2-bed7-8f4272c2392b",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.success.toString() }}",
              "rightValue": "true"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2a555b8d-be2a-4df7-9178-a30a78afef11",
      "name": "1Shot API 提交并等待",
      "type": "n8n-nodes-1shot.oneShotSynch",
      "position": [
        980,
        -180
      ],
      "parameters": {
        "params": "={\n\"from\": \"{{ $('Decode & Validate X-Payment').item.json.decodedXPayment.from }}\",\n\"to\": \"{{ $('Decode & Validate X-Payment').item.json.decodedXPayment.to }}\",\n\"value\": \"{{ $('Decode & Validate X-Payment').item.json.decodedXPayment.value }}\",\n\"validAfter\": \"{{ $('Decode & Validate X-Payment').item.json.decodedXPayment.validAfter }}\",\n\"validBefore\": \"{{ $('Decode & Validate X-Payment').item.json.decodedXPayment.validBefore }}\",\n\"nonce\": \"{{ $('Decode & Validate X-Payment').item.json.decodedXPayment.nonce }}\",\n\"signature\": \"{{ $('Decode & Validate X-Payment').item.json.decodedXPayment.signature }}\"\n}",
        "additionalFields": {},
        "contractMethodId": "b63aaaa1-059d-4c38-928a-33ad17d66827"
      },
      "credentials": {
        "oneShotOAuth2Api": {
          "id": "nkfF9AitCKUCrErK",
          "name": "1Shot account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0311b436-3d0d-4958-a298-c3da32b3eb8e",
      "name": "确保支付载荷格式正确",
      "type": "n8n-nodes-base.if",
      "position": [
        320,
        -60
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "6666e1f6-5e99-49d4-9f9a-a5a35cde4f74",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.decodedXPayment.signature }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "49394dfa-5ba3-4394-bde4-8c98efcd3927",
      "name": "响应:缺少或无效的支付头",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        540,
        120
      ],
      "parameters": {
        "options": {
          "responseCode": 402
        },
        "respondWith": "json",
        "responseBody": "{\n  \"x402Version\": \"1\",\n  \"error\": \"X-PAYMENT header has incorrect format\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "358ced9b-8e97-4347-8a0d-f18745e9c8a5",
      "name": "响应:支付无效",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1200,
        0
      ],
      "parameters": {
        "options": {
          "responseCode": 402
        },
        "respondWith": "json",
        "responseBody": "{\n  \"x402Version\": \"1\",\n  \"error\": \"X-PAYMENT header did not verify\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "e859f032-9493-4aae-aa3f-06dbf6a60a27",
      "name": "响应:200 - 支付成功",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1700,
        -200
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "text",
        "responseBody": "={ \"response\": \"{{ $json.text }}\" }"
      },
      "typeVersion": 1.3
    },
    {
      "id": "255c6a09-42bf-40d8-8622-d9f8a1916b07",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -440,
        -260
      ],
      "parameters": {
        "width": 360,
        "height": 220,
        "content": "## x402 支付端点"
      },
      "typeVersion": 1
    },
    {
      "id": "ea3a1463-dd21-462b-9900-d103eba38849",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        580,
        -340
      ],
      "parameters": {
        "width": 360,
        "content": "## 任何 EVM 上的任何 ERC-20"
      },
      "typeVersion": 1
    },
    {
      "id": "af875673-eab4-46c8-8e0f-d550be13a45a",
      "name": "便签 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1240,
        -440
      ],
      "parameters": {
        "width": 320,
        "height": 200,
        "content": "## x402 + Ollama 推理"
      },
      "typeVersion": 1
    },
    {
      "id": "2335ca81-fa1b-4a52-9d2a-030ac7ead35f",
      "name": "便签 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -820,
        220
      ],
      "parameters": {
        "width": 840,
        "height": 380,
        "content": "## 示例 Curl 命令"
      },
      "typeVersion": 1
    },
    {
      "id": "f2fff145-fb18-4b3f-a166-f8dc4a61bf69",
      "name": "便签 4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        140,
        -360
      ],
      "parameters": {
        "width": 360,
        "height": 260,
        "content": "## 确保必需的支付详情"
      },
      "typeVersion": 1
    },
    {
      "id": "07acfe27-d146-4e9a-8dc8-76e581bce92d",
      "name": "便签 5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1500,
        160
      ],
      "parameters": {
        "width": 700,
        "height": 840,
        "content": "## Ollama + ngrok Docker 堆栈"
      },
      "typeVersion": 1
    },
    {
      "id": "6d080c36-2af1-434e-99ba-d4415051b020",
      "name": "私有模型推理",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        1280,
        -200
      ],
      "parameters": {
        "text": "={{ $('Webhook').item.json.body.query }}",
        "batching": {},
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "700dcb57-88df-4b50-84bb-5947353407e5",
      "name": "Ollama 引擎",
      "type": "@n8n/n8n-nodes-langchain.lmOllama",
      "notes": "This example assumes your n8n session is hosted separately from your Ollama instance. You can use ngrok to create a secure tunnel between your n8n workflow and your Ollama instance\n\n1. Create a free account at ngrok.com.\n2. Generate a free static URL under the Domains tab.\n3. Grab your ngrok auth token \n4. Spin up an Ollama + ngrok stack so that n8n can reach your private Ollama model: \n\nsudo NGROK_AUTHTOKEN=... TUNNEL_BASE_URL=https://your-static-url.ngrok-free.app docker compose up -d\n\nHere is your docker-compose.yaml: \n\nservices:\n  ngrok:\n    image: ngrok/ngrok:latest\n    container_name: ngrok\n    command:\n      - \"http\"\n      - \"http://ollama:11434\"\n      - \"--url=${TUNNEL_BASE_URL}\"\n    environment:\n      NGROK_AUTHTOKEN: ${NGROK_AUTHTOKEN}\n      TUNNEL_BASE_URL: ${TUNNEL_BASE_URL}\n    ports:\n      - 4040:4040\n\n  ollama-service:\n    image: ollama/ollama:latest\n    container_name: ollama\n    volumes:\n      - ./ollama-volume:/root/.ollama\n    ports:\n      - \"1337:11434\"\n    deploy:\n      resources:\n        reservations:\n          devices:\n            - driver: nvidia\n              count: 1\n              capabilities: [gpu]",
      "position": [
        1540,
        20
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "ollamaApi": {
          "id": "NBdbAGPqAH3NrEGk",
          "name": "Ollama account"
        }
      },
      "notesInFlow": true,
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "66d65719-7558-404e-8e94-b4fbf9f322dc",
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Check for presence of X-HEADER",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ollama Engine": {
      "ai_languageModel": [
        [
          {
            "node": "Private Model Inference",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Simulate Payment": {
      "main": [
        [
          {
            "node": "On Successful Payment Simulation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1Shot API Submit & Wait": {
      "main": [
        [
          {
            "node": "Private Model Inference",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Response: Payment Invalid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Private Model Inference": {
      "main": [
        [
          {
            "node": "Response: 200 - Payment Successful",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Decode & Validate X-Payment": {
      "main": [
        [
          {
            "node": "Ensure Well Formatted Payment Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for presence of X-HEADER": {
      "main": [
        [
          {
            "node": "Decode & Validate X-Payment",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Response: Missing or Invalid Payment Headers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On Successful Payment Simulation": {
      "main": [
        [
          {
            "node": "1Shot API Submit & Wait",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Response: Payment Invalid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ensure Well Formatted Payment Payload": {
      "main": [
        [
          {
            "node": "Simulate Payment",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Response: Missing or Invalid Payment Headers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - 工程, AI 聊天机器人

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量18
分类2
节点类型9
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

作者
1Shot API

1Shot API

@oneshotapi

1Shot API lets you bring onchain actions into your n8n workflows.

外部链接
在 n8n.io 查看

分享此工作流