- 12 min read

【Agentic Payment 系列 #4】從理論到實作:用 Golang 親手跑一遍 x402 支付流程

透過一個極簡的 Golang Demo 專案,從 Server(賣方)到 Client(買方)完整走過 x402 協議的 402 挑戰、離線簽署與鏈上結算流程 —— 把前三篇的協議設計變成可執行的程式碼。

AI AI Agent x402 Payments Blockchain Golang Agentic Payment Agentic Economy

本文為 Agentic Payment 系列第四篇。建議至少先閱讀第一篇,了解 x402 協議的設計哲學與交易流程: → 【Agentic Payment 系列 #1】HTTP 402 沉睡三十年後醒來:x402 如何讓支付成為網際網路的一等公民 → 【Agentic Payment 系列 #2】信任的代價:AP2 授權機制、A2A 支付整合與三大協議戰場劃分 → 【Agentic Payment 系列 #3】兆美元賽道:Agent 經濟的市場、合規與 Web 4.0 支付堆疊


前三篇文章,我們從協議設計、信任機制到市場預測,把 Agentic Payment Stack 的理論面貌剖析得相當透徹。

這篇文章的任務很簡單 —— 用一個極簡的 Golang Demo 專案,讓你親手走過 x402 協議從「402 挑戰」到「200 OK + 鏈上交易確認」的完整生命週期。不需要前端,不需要複雜的部署,兩個 Terminal 就能跑完。

專案原始碼:charles-hsiao/x402-demo


為什麼選 Golang?

x402 Foundation 的官方 SDK 提供了 TypeScript 與 Golang 兩種實作。選擇 Golang 有幾個工程上的理由:

  1. 單一二進位檔部署:編譯後丟到任何 Linux 機器上直接跑,不需要 Node.js Runtime 或 Docker,這對邊緣節點與嵌入式 Agent 場景尤其重要
  2. 強型別與編譯時檢查:支付相關的程式碼容不得型別混淆,Golang 的編譯器在你犯錯之前就會攔截
  3. 原生併發模型:Goroutine 的輕量級設計使 Server 得以低成本地處理數千個並發支付請求
  4. 因為筆者不會寫 TypeScript

當然,如果你的技術棧是 TypeScript,也可以試試看 x402 的 npm SDK。


專案結構:極簡的 Buyer-Seller 架構

x402-demo/
├── server/
│   └── main.go          # Gin HTTP Server(Seller / 賣方)
├── client/
│   ├── main.go          # Go HTTP Client(Buyer / 買方)
│   ├── builder_pattern.go
│   ├── mechanism_helper_registration.go
│   └── utils.go
├── .env.example         # 環境變數範本
├── Makefile             # 常用指令
└── README.md

整個 Demo 只有兩個角色:

角色對應目錄說明
Server(Seller)server/提供付費 API,收取 USDC
Client(Buyer)client/呼叫付費 API,自動完成簽署與支付

第三個角色 Facilitator(促成者) 由 x402 官方提供的公共服務擔任(https://x402.org/facilitator),負責鏈上驗證與結算,不需要自行部署。


前置準備

在開始之前,你需要準備:

  1. Go 1.26+(建議透過 asdf 管理版本)
  2. 兩個 EVM 錢包:一個收款(Server 端),一個付款(Client 端),下面會帶你用 Foundry 在一分鐘內建好
  3. Base Sepolia 測試網的 USDC:替付款錢包從 Circle Faucet 免費領取

建立錢包:用 Foundry 的 cast wallet new

Foundry(getfoundry.sh)是目前最主流的 EVM 開發工具套件,其中的 cast 指令讓你在 CLI 直接操作錢包,不需要安裝 MetaMask 或連接任何 GUI。

Step 1:安裝 Foundry

~$ curl -L https://foundry.paradigm.xyz | bash && foundryup

安裝完成後,確認工具已就緒:

~$ cast --version

Step 2:建立收款錢包(Server / 賣方)

~$ cast wallet new

輸出格式如下,Address 就是你的收款地址,這個錢包用在 Server 端,不需要私鑰也不需要有任何餘額:

Successfully created new keypair.
Address:     0xAAAA...(你的收款地址)
Private key: 0xBBBB...(妥善保存,此 demo 中 Server 端不需要用到)

把 Address 記下來,後面填入 EVM_PAYEE_ADDRESS。

Step 3:建立付款錢包(Client / 買方)

再執行一次,產生第二組金鑰;這把私鑰會讓 Agent 自動簽署支付:

~$ cast wallet new
Successfully created new keypair.
Address:     0xCCCC...(你的付款地址)
Private key: 0xDDDD...(填入 EVM_PRIVATE_KEY)

安全提醒:cast wallet new 產生的私鑰只顯示一次,請立刻複製到 .env。這是 Testnet 錢包,切勿將此私鑰用於主網或存入任何真實資產。

Step 4:領取測試網 USDC

付款錢包需要有 USDC 才能完成 x402 支付。前往 Circle Faucet(faucet.circle.com):

  1. 選擇網路:Base Sepolia
  2. 貼上你的付款錢包地址(0xCCCC...)
  3. 點擊 Send,約 30 秒後即可收到 20 USDC

Circle Faucet:選擇 Base Sepolia 並輸入付款錢包地址領取 20 USDC

確認 USDC 已到帳,直接在 Base Sepolia Scan 輸入你的付款錢包地址查詢,看到 Token Transfers 頁籤有 USDC 入帳記錄即代表領取成功:下圖範例錢包

Base Sepolia Scan Token Transfers 頁面確認 USDC 到帳


設定環境變數

有了兩個錢包地址與私鑰之後,設定 .env:

~$ cp .env.example .env
# Server(賣方)
EVM_PAYEE_ADDRESS=0xAAAA...你的收款地址  # 收款用的錢包地址
FACILITATOR_URL=https://x402.org/facilitator # 免費測試網 Facilitator

# Client(買方)
EVM_PRIVATE_KEY=0xDDDD...你的付款私鑰   # 測試網私鑰(切勿使用主網私鑰!)

再強調一次:此為 demo 專案,EVM_PRIVATE_KEY 只能使用測試網的私鑰。


Server 端:用 Middleware 把 API 變成付費資源

Server 端的核心概念只有一個:把 x402 Payment Middleware 套在你想收費的 Route 上。

這就像你在 Gin 框架裡加 Authentication Middleware 一樣,只是從「驗證身份」變成了「驗證付款」。

關鍵程式碼解析

// 建立 Facilitator Client —— 指向公共的驗證/結算服務
facilitatorClient := x402http.NewHTTPFacilitatorClient(&x402http.FacilitatorConfig{
    URL: facilitatorURL,
})

// 定義哪些 Route 需要付款、價格多少、接受哪些鏈與幣種
routes := x402http.RoutesConfig{
    "GET /weather": {
        Accepts: x402http.PaymentOptions{
            {
                Scheme:  "exact",
                Price:   "$0.001",
                Network: "eip155:84532",   // Base Sepolia
                PayTo:   evmAddress,
            },
            {
                Scheme:  "exact",
                Price:   "$0.001",
                Network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
                PayTo:   svmAddress,
            },
        },
        Description: "Get weather data for a city",
        MimeType:    "application/json",
    },
}

// 套用 Middleware:攔截請求、檢查付款、驗證結算
r.Use(ginmw.X402Payment(ginmw.Config{
    Routes:      routes,
    Facilitator: facilitatorClient,
    Schemes: []ginmw.SchemeConfig{
        {Network: "eip155:84532", Server: evm.NewExactEvmScheme()},
        {Network: "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", Server: svm.NewExactSvmScheme()},
    },
    Timeout: 30 * time.Second,
}))

幾個設計上值得注意的點:

支持多鏈。 Accepts 是一個陣列,同時接受 EVM(Base Sepolia)與 SVM(Solana Devnet)的付款。Client 可以根據自己持有的資產選擇最合適的支付路徑。這正是第一篇文章提到的「降低供需雙方耦合度」的具體實現。

定價直覺化。 Price: "$0.001":SDK 在內部自動處理 USDC 的小數轉換,開發者不需要手動計算。實際上 USDC 在鏈上以 6 位小數(decimals = 6)儲存,因此 1 USDC = 1,000,000 個最小單位;$0.001 = 千分之一美元,對應的最小單位數量便是 1,000,000 × 0.001 = 1000。

Middleware Pattern。 付費 Route 與免費 Route 的 Handler 程式碼完全相同,x402 的支付邏輯全部封裝在 Middleware 層。/weather 收費、/health 免費,差別只是 Middleware 裡的 Route Config,不是 Handler 的邏輯。

免費端點(不受 Middleware 保護)

r.GET("/health", func(c *ginfw.Context) {
    c.JSON(http.StatusOK, ginfw.H{
        "status":  "ok",
        "version": "2.0.0",
    })
})

Client 端:全自動的 402 → 簽署 → 重試

Client 端展示了 x402 SDK 的核心便利性 —— 開發者不需要手動處理 402 回應邏輯。SDK 的 HTTP Client Wrapper 自動完成:

  1. 發送請求 → 收到 402
  2. 解析 PAYMENT-REQUIRED Header
  3. 用 Private Key 簽署支付授權(EIP-3009,Gasless)
  4. 帶著簽名重送請求

Builder Pattern:細粒度控制

func createBuilderPatternClient(evmPrivateKey, svmPrivateKey, evmRpcURL string) (*x402.X402Client, error) {
    // 從私鑰建立簽名器
    evmSigner, err := evmsigners.NewClientSignerFromPrivateKey(evmPrivateKey)
    if err != nil {
        return nil, err
    }

    // 建立 x402 Client 並註冊支付機制
    client := x402.Newx402Client()

    // 用 Wildcard 匹配所有 EVM 網路
    client.Register("eip155:*", exactevm.NewExactEvmScheme(evmSigner, rpcConfig))
    client.Register("eip155:*", uptoevm.NewUptoEvmScheme(evmSigner, rpcConfig))

    // 如果有 Solana 私鑰,也註冊 SVM 支付機制
    if svmPrivateKey != "" {
        svmSigner, err := svmsigners.NewClientSignerFromPrivateKey(svmPrivateKey)
        if err != nil {
            return nil, err
        }
        client.Register("solana:*", exactsvm.NewExactSvmScheme(svmSigner))
    }

    return client, nil
}

Wildcard 網路註冊 是一個巧妙的抽象。"eip155:*" 表示「任何 EVM 相容鏈都用這把 Signer」,讓 Client 不需要提前知道 Server 會要求哪條鏈的付款。當 Server 未來新增 Polygon 或 Arbitrum 的支付選項時,Client 端不需要任何程式碼變更。

HTTP Client Wrapper:無縫整合

func wrapHTTPClient(x402Client *x402.X402Client) *http.Client {
    httpClient := x402http.Newx402HTTPClient(x402Client)
    return x402http.WrapHTTPClientWithPayment(http.DefaultClient, httpClient)
}

這三行程式碼完成的事情是:把標準的 http.Client 包裝成一個「會自動付錢」的 Client。之後你用 httpClient.Do(req) 發任何請求,如果目標 Server 回傳 402,SDK 會自動攔截、簽署、重試,對呼叫端的程式碼來說整個支付流程是透明的。

這就是 x402 宣稱的「支付像加一個 Header」的開發體驗。對比傳統支付整合動輒需要數百行的 Token 交換、Webhook 處理與錯誤恢復邏輯,這裡的程式碼量確實只有三行。


完整流程 Demo:從 402 到 200

Step 1:啟動 Server

~$ make server
Starting x402 Server...
cd server && go run main.go
🚀 Starting Gin x402 server...
   EVM Payee address: 0xb2F27822D005Cf511b373285Bbd469bD61FcE4f7
   SVM Payee address:
   EVM Network: eip155:84532
   SVM Network: solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1
   Facilitator: https://x402.org/facilitator

Step 2:觀察 402 回應(不帶付款)

~$ curl -si http://localhost:4021/weather | grep -i "HTTP\|payment"
HTTP/1.1 402 Payment Required
Payment-Required: eyJ4NDAyVmVyc2lvbiI6MiwiZXJyb3IiOiJQYXltZW50IHJlcXVpcmVkIiwicmVzb3VyY2UiOnsidXJsIjoiaHR0cDovL2xvY2FsaG9zdDo0MDIxL3dlYXRoZXIiLCJkZXNjcmlwdGlvbiI6IkdldCB3ZWF0aGVyIGRhdGEgZm9yIGEgY2l0eSIsIm1pbWVUeXBlIjoiYXBwbGljYXRpb24vanNvbiJ9LCJhY2NlcHRzIjpbeyJzY2hlbWUiOiJleGFjdCIsIm5ldHdvcmsiOiJlaXAxNTU6ODQ1MzIiLCJhc3NldCI6IjB4MDM2Q2JENTM4NDJjNTQyNjYzNGU3OTI5NTQxZUMyMzE4ZjNkQ0Y3ZSIsImFtb3VudCI6IjEwMDAiLCJwYXlUbyI6IjB4YjJGMjc4MjJEMDA1Q2Y1MTFiMzczMjg1QmJkNDY5YkQ2MUZjRTRmNyIsIm1heFRpbWVvdXRTZWNvbmRzIjo2MCwiZXh0cmEiOnsibmFtZSI6IlVTREMiLCJ2ZXJzaW9uIjoiMiJ9fSx7InNjaGVtZSI6ImV4YWN0IiwibmV0d29yayI6InNvbGFuYTpFdFdUUkFCWmFZcTZpTWZlWUtvdVJ1MTY2VlUyeHFhMSIsImFzc2V0IjoiNHpNTUM5c3J0NVJpNVgxNEdBZ1hoYUhpaTNHblBBRUVSWVBKZ1pKRG5jRFUiLCJhbW91bnQiOiIxMDAwIiwicGF5VG8iOiIiLCJtYXhUaW1lb3V0U2Vjb25kcyI6NjAsImV4dHJhIjp7ImZlZVBheWVyIjoiQ0tQS0pXTmRKRXFhODF4N0NrWjE0QlZQaVk2eTE2U3hzN293em5xdFdZcDUifX1dfQ==

Payment-Required 的值是 Base64 編碼的 JSON,解碼後可以看到完整的支付條件:

{
  "x402Version": 2,
  "error": "Payment required",
  "resource": {
    "url": "http://localhost:4021/weather",
    "description": "Get weather data for a city",
    "mimeType": "application/json"
  },
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:84532",
      "asset": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
      "amount": "1000",
      "payTo": "0xb2F27822D005Cf511b373285Bbd469bD61FcE4f7",
      "maxTimeoutSeconds": 60,
      "extra": { "name": "USDC", "version": "2" }
    },
    {
      "scheme": "exact",
      "network": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
      "asset": "4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",
      "amount": "1000",
      "payTo": "",
      "maxTimeoutSeconds": 60,
      "extra": { "feePayer": "CKPKJWNdJEqa81x7CkZ14BVPiY6y16Sxs7owznqtWYp5" }
    }
  ]
}

幾個欄位值得對照前面的程式碼確認:

  • amount: "1000":正是 $0.001 × 1,000,000 = 1000 個 USDC 最小單位
  • asset:EVM 端為 0x036CbD...,即 Base Sepolia 上的 USDC 合約地址
  • payTo:EVM 端填入 Server 的收款地址(EVM_PAYEE_ADDRESS);Solana 端為空,代表此 Demo 的 Server 沒有設定 SVM 收款地址
  • maxTimeoutSeconds: 60:Client 必須在 60 秒內完成簽署並重送請求,逾時則 Server 拒絕
  • accepts 是陣列:Client 可以選擇 EVM 或 Solana 任一路徑支付,SDK 會根據 Client 已註冊的 Scheme 自動挑選

Server 對未付款的請求回傳 402 Payment Required,Header 中包含完整的支付條件 —— 價格、受款地址、鏈 ID、代幣合約、Nonce。這就是第一篇文章提到的 Payment Discovery 機制在 HTTP 層的具體呈現。

Step 3:執行 Client(自動完成支付)

~$ make client
Running x402 Client...
cd client && go run .

Running example: builder-pattern

Making request to: http://localhost:4021/weather

✅ Response body:
  {
    "city": "San Francisco",
    "temperature": 60,
    "timestamp": "2026-05-07T18:44:47+08:00",
    "weather": "foggy"
  }

💰 Payment Details:
  Success: true
  Transaction: 0x3c4268ea2ba29a327aaba55efb08598b6a6803f2a0600e9bdadbc2f1955a16c8
  Network: eip155:84532
  Payer: 0x288fC773264840fD691b2c0049F35B925222AFbE

從使用者(開發者)的角度看,這就是一次普通的 HTTP GET 請求。SDK 在底層自動完成了:

  1. 第一次請求 → 收到 402
  2. 解析 PAYMENT-REQUIRED Header 中的支付條件
  3. 選擇匹配的 Scheme(EVM Exact)
  4. 用 EIP-3009 模式簽署支付授權(Gasless —— Client 不需要持有 ETH 來付 Gas)
  5. 帶著 PAYMENT-SIGNATURE Header 重送請求
  6. Server 轉發給 Facilitator 驗證 → Facilitator 發起鏈上 USDC 轉帳
  7. 驗證通過後回傳 200 OK + 資源內容 + PAYMENT-RESPONSE Header(含 Transaction Hash)

整個流程在約 1-2 秒內完成(Testnet 區塊確認時間)。回應中的 Transaction Hash 可以直接貼到 Base Sepolia Scan 查詢鏈上的結算紀錄;以本文的範例收款錢包為例,可以在 Token Transfers 頁面看到每一筆 USDC 入帳。

Base Sepolia Scan:收款錢包的 Token Transfers 頁面顯示 USDC 入帳紀錄

付款錢包(0x288fC773...,即 EVM_PRIVATE_KEY 對應的地址)同樣可以在 Base Sepolia Scan 查到對應的 USDC 轉出紀錄:

Base Sepolia Scan:付款錢包的 Token Transfers 頁面顯示 0.001 USDC 轉出


支付方案與 Scheme 機制

Demo 專案中使用了 exact Scheme(精確金額轉帳)。x402 SDK 同時支援 upto Scheme(預授權上限),適用於按量計費場景:

Scheme說明適用場景
exactClient 支付精確金額固定價格的 API 調用
uptoClient 預授權一個上限金額,Server 按實際用量結算Streaming、按量計費

在程式碼中,Client 透過同時註冊 exactevm 和 uptoevm 兩種 Scheme,讓 SDK 根據 Server 的 PAYMENT-REQUIRED 回應自動選擇對應的支付邏輯:

client.Register("eip155:*", exactevm.NewExactEvmScheme(evmSigner, rpcConfig))
client.Register("eip155:*", uptoevm.NewUptoEvmScheme(evmSigner, rpcConfig))

Facilitator 的角色:你不需要運行區塊鏈節點

Demo 中最容易被忽略但最關鍵的設計,是 Facilitator 完全由外部服務提供。Server 端只需要設定一個 URL:

FACILITATOR_URL=https://x402.org/facilitator

Facilitator 替 Server 完成了所有鏈上操作:驗證簽名有效性、確認 Nonce 未被重放、檢查 Client 餘額充足、發起 USDC 轉帳。Server 本身不需要連接 RPC 節點、不需要管理 Gas Fee、不需要理解 EIP-3009 的細節。

這就是第一篇文章中提到的「餐廳不需要理解 Visa 結算協議」的 Demo 驗證:Server 只管提供內容,Facilitator 處理一切金流。

FacilitatorURL適用環境備註
x402.org(官方免費)https://x402.org/facilitatorTestnet無需申請帳號
CDP(Coinbase Developer Platform)https://api.cdp.coinbase.com/platform/v2/x402Testnet + Mainnet需要 CDP API Keys

從 Testnet 到 Mainnet:一行設定的距離

切換到主網只需要修改兩個值:

// Testnet
Network: "eip155:84532"  // Base Sepolia

// Mainnet
Network: "eip155:8453"   // Base Mainnet

加上將 Facilitator 切換到 CDP 的主網端點(需要 API Keys)。但請記住:主網上的是真金白銀。在你對 Testnet 流程完全熟悉之前,不要碰 Mainnet。


對 Agent 開發者意味著什麼

如果你正在建構 AI Agent,x402 的 Golang SDK 讓你的 Agent 具備了「原生支付能力」,而且成本極低。

在 Base Sepolia(以及未來的 Mainnet)上,每筆 x402 交易的 Gas 成本低於 $0.0001。這意味著你的 Agent 可以:

  • 以 $0.001 調用一次氣象 API
  • 以 $0.005 抓取一篇新聞摘要
  • 以 $0.01 取得一份分析報告

而每一筆交易都有不可偽造的鏈上收據(Transaction Hash),可審計、可驗證、不可否認。

// 你的 Agent 程式碼 —— 就是這麼簡單
client := x402.Newx402Client()
client.Register("eip155:*", exactevm.NewExactEvmScheme(signer, nil))

httpClient := x402http.WrapHTTPClientWithPayment(http.DefaultClient, 
    x402http.Newx402HTTPClient(client))

resp, _ := httpClient.Do(req) // 自動處理付款

六行程式碼,你的 Agent 就從「只會免費呼叫 API 的程式」升級為「能在開放市場自主消費的經濟行為者」。

當付款的工程成本降到六行程式碼、經濟成本降到萬分之一美元,「為每次 API 調用收費」不再是架構上的奢侈,而是商業模式的預設選項。這對整個 API 經濟的定價模型,是一次根本性的重新校準。


動手試試

~$ git clone https://github.com/charles-hsiao/x402-demo.git
~$ cd x402-demo
~$ cp .env.example .env
# 編輯 .env,填入你的錢包地址與測試網私鑰
~$ make setup
~$ make server   # Terminal 1
~$ make client   # Terminal 2

五分鐘內,你就會看到你的第一筆 x402 鏈上支付完成。

如果暫時不想在本機跑環境,Cloudflare 提供了一個線上的 x402 Playground,可以直接在瀏覽器中觀察 402 挑戰、支付簽署與結算的互動過程。


小結

x402 的 Developer Experience 已經到了「跟加一個 Auth Middleware 差不多」的程度。當支付基礎設施的整合成本降到這個水平,擋在 Micropayments 前面的最後一道牆,就不再是技術門檻,而是想像力。

或許未來的電商支付、SaaS 產品 不再需要 Stripe、不再需要訂閱制、不再需要廣告 —— 只需要一個 402 回應、一個願意為價值付費的 Agent,以及一個你要用來收款的區塊鏈錢包。

區塊鏈技術在過去十年間,因為投機泡沫與監管爭議而背負了太多負面標籤。但 Agentic Payment 這個場景讓我重新看見了那個最初令人興奮的想像:一個價值可以像資訊一樣自由流動的世界。

網際網路的偉大之處,不在於它讓人們談論它,而在於它作為基礎設施靜靜地撐起了整個數位世界 —— 沒有人在傳送一封 Email 時會想到 TCP/IP。區塊鏈長期以來缺少的,正是這種「消失在背景中、讓上層應用發光」的角色定位。x402 讓我第一次清楚地感受到:這個時刻,或許正在到來。

不是 ICO,不是 NFT,而是 AI Agent 每秒發起的數百萬筆 $0.001 結算請求 —— 無聲地流過區塊鏈,就像封包流過路由器一樣自然。當區塊鏈真正成為網際網路的支付層,它就不再需要被討論,只需要被使用。


下一篇:【Agentic Payment 系列 #5】沒有人看到全貌:AP2 v0.2 用兩張 Mandate 重寫 Agent 的授權邊界

回顧系列全文: → 【Agentic Payment 系列 #1】HTTP 402 沉睡三十年後醒來:x402 如何讓支付成為網際網路的一等公民 → 【Agentic Payment 系列 #2】信任的代價:AP2 授權機制、A2A 支付整合與三大協議戰場劃分 → 【Agentic Payment 系列 #3】兆美元賽道:Agent 經濟的市場、合規與 Web 4.0 支付堆疊

如果這篇文章對你有幫助,歡迎分享給對 Agent 經濟與 Web3 支付感興趣的朋友。