支付方式

单次支付#

概述#

单次支付是 Onchain OS Payment 最基础的支付模式:买家每次请求付费资源时,独立完成一次完整的支付流程。一次请求,即时结算,即时交付。

适用场景#

  • 单笔调用有明确价格,交付后不可撤回(如报告生成、文件下载)
  • 需要拿到链上确认(txHash)后再交付资源
  • 单笔金额较高的 API 调用,需要即时的链上结算确定性

卖家接入流程#

Node.js

Typescript
import { x402ResourceServer } from "@okxweb3/x402-core/server";
import { ExactEvmScheme } from "@okxweb3/x402-evm/exact/server";
import { OKXFacilitatorClient } from "@okxweb3/x402-core";

const facilitator = new OKXFacilitatorClient({
    apiKey: "xxx",
    secretKey: "xxx",
    passphrase: "xxx",
    syncSettle: false,
});

const server = new x402ResourceServer(facilitator);
// 注册单次收款scheme
server.register("eip155:196", new ExactEvmScheme());
// 设置收款路由
const routes = {
    "GET /api/data": {
      accepts: [{
        scheme: "exact",
        network: "eip155:196",
        payTo: "0xSellerWallet",
        price: "$0.01",
      }],
      description: "Premium data endpoint",
      mimeType: "application/json",
    },
  };

app.use(paymentMiddleware(routes, server));

Go

Go
package main

import (
    "fmt"
    "net/http"
    "os"
    "time"

    x402http "github.com/okx/payments/go/http"
    ginmw "github.com/okx/payments/go/http/gin"
    exact "github.com/okx/payments/go/mechanisms/evm/exact/server"
    ginfw "github.com/gin-gonic/gin"
)

func main() {
    syncClient, err := x402http.NewOKXFacilitatorClient(&x402http.OKXFacilitatorConfig{
        Auth: x402http.OKXAuthConfig{
            APIKey:     "OKX_API_KEY",
            SecretKey:  "OKX_SECRET_KEY",
            Passphrase: "OKX_PASSPHRASE",
        },
        BaseURL: "https://web3.okx.com",
    })
    if err != nil {
        fmt.Printf("Failed to create client: %v\n", err)
        os.Exit(1)
    }

    routes := x402http.RoutesConfig{
        "GET /api/data": {
            Accepts: x402http.PaymentOptions{
                {Scheme: "exact", Price: "$0.01", Network: "eip155:196", PayTo: "SellerWallet"},
            },
            Description: "Premium data endpoint",
            MimeType:    "application/json",
        },
    }

    schemes := []ginmw.SchemeConfig{
        {Network: "eip155:196", Server: exact.NewExactEvmScheme()},
    }

    r := ginfw.Default()
    apiGroup := r.Group("/")
    apiGroup.Use(ginmw.X402Payment(ginmw.Config{
        Routes:      routes,
        Facilitator: syncClient,
        Schemes:     schemes,
        Timeout:     30 * time.Second,
    }))
    apiGroup.GET("/api/data", func(c *ginfw.Context) {
        c.JSON(http.StatusOK, ginfw.H{
            "data":  "premium content",
            "price": "$0.01",
        })
    })

    r.Run(":3000")
}

Rust

Rust
use std::collections::HashMap;                                                                                                                                                                        
use axum::{routing::get, Json, Router};                                                                                                                                                               
use serde_json::{json, Value};                                                                                                                                                                        
                                                                                                                                                                                                    
use x402_axum::{payment_middleware, AcceptConfig, RoutePaymentConfig};                                                                                                                                
use x402_core::http::OkxHttpFacilitatorClient;
use x402_core::server::X402ResourceServer;                                                                                                                                                            
use x402_evm::ExactEvmScheme;
                                                                                                                                                                                                    
#[tokio::main]  
async fn main() {
    // 1. Configure OKX Facilitator client with API credentials
    let facilitator = OkxHttpFacilitatorClient::new(
      "OKX_API_KEY",                                                                                                                                                                                
      "OKX_SECRET_KEY",
      "OKX_PASSPHRASE",                                                                                                                                                                             
    )           
    .expect("Failed to create facilitator client");
    
    // 2. Create resource server and register the "exact" payment scheme on X Layer                                                                                                                   
    let mut server = X402ResourceServer::new(facilitator)
      .register("eip155:196", ExactEvmScheme::new());                                                                                                                                               
              
    // 3. Initialize server (fetches supported schemes from facilitator)                                                                                                                              
    server      
      .initialize()                                                                                                                                                                                 
      .await  
      .expect("Failed to initialize: check facilitator connectivity");
    
    // 4. Define which routes require payment and their pricing                                                                                                                                       
    let routes = HashMap::from([(
      "GET /api/data".to_string(),                                                                                                                                                                  
      RoutePaymentConfig {
          accepts: vec![AcceptConfig {
              scheme: "exact".into(),
              price: "$0.01".into(),           // $0.01 per request
              network: "eip155:196".into(),     // X Layer network                                                                                                                                  
              pay_to: "SellerWallet".into(),    // Seller's wallet address
              max_timeout_seconds: None,        // Default: 300s (5 min)                                                                                                                            
              extra: None,                                                                                                                                                                          
          }],                                                                                                                                                                                       
          description: "Premium data endpoint".into(),                                                                                                                                              
          mime_type: "application/json".into(),
          sync_settle: None,                    // Default: async settle
      },                                                                                                                                                                                            
    )]);
                                                                                                                                                                                                    
    // 5. Build Axum router with payment middleware
    let app = Router::new()
      .route("/api/data", get(|| async { Json(json!({"data": "premium"})) }))
      .layer(payment_middleware(routes, server));                                                                                                                                                   
    
    // 6. Start the server                                                                                                                                                                            
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}       

同步结算 vs 异步结算#

调用 /settle 后,Facilitator 将交易提交到链上。路由配置中的 syncSettle 字段控制结算行为:

模式参数值Facilitator 行为适用场景
同步true提交交易并等待链上确认后返回 txHash高价值交易,需确认到账后再交付资源
异步false提交交易后立即返回 txHash,不等确认中等价值,对响应速度有要求

异步结算存在时序风险:资源可能在链上支付最终确认前就已交付。高价值交易建议使用同步结算。

买家接入流程#

买家安装 OKX Agentic Wallet 后,Agent 会自动完成 402 协商和签名支付。具体请参考 我是买家