跳到主要內容

WalletHandlers

WalletHandlers 類別是一個高階實用工具,旨在將 DID Connect 工作流程無縫整合到 Express.js 或類似的伺服器端框架中。它會自動為給定的操作設定所有必要的 API 端點,處理您的應用程式和使用者 DID 錢包之間的通訊。

它與 WalletAuthenticator 協同工作,後者管理訊息的加密簽章和驗證。由於 WalletHandlers 是基於 Node.js 的 EventEmitter 建立的,因此您可以在權杖儲存中的會話狀態改變時,監聽各種生命週期事件。

建構函式

建立 DID Connect 處理程式的實例。此實例會協調處理 DID Connect 流程的 HTTP 請求。

DID Connect 處理程式設定

javascript
const { WalletHandlers } = require('@did-connect/handler');
const { WalletAuthenticator } = require('@did-connect/authenticator');
const { FileStorage } = require('@did-connect/storage-file');

// 1. 使用您應用程式的錢包和資訊初始化驗證器
const authenticator = new WalletAuthenticator({ wallet, appInfo, chainInfo });

// 2. 初始化一個儲存適配器來管理會話狀態
const tokenStorage = new FileStorage({ dbPath: './sessions.json' });

// 3. 建立處理程式實例
const handlers = new WalletHandlers({
  authenticator,
  tokenStorage,
});

參數

  • config object (required) — WalletHandlers 實例的設定物件。
    • authenticator WalletAuthenticator (required) — 負責加密操作的 WalletAuthenticator 實例。
    • tokenStorage object (required) — 處理會話狀態的權杖儲存實例(例如 FileStorage、MongoStorage)。
    • pathTransformer function — 一個可選函式,用於轉換錢包回呼的 URL 路徑名稱,在代理或複雜的路由情境中很有用。
    • onConnect function — 一個可選的全域回呼函式,在錢包掃描 QR code 後、驗證請求發送前執行。它可用於全域權限檢查。拋出錯誤以中止流程。
    • options object — 一個可選物件,用於自訂處理程式的行為。
      • prefix string (default: /api/did) — 所有產生的端點的 URL 前綴。
      • cleanupDelay number (default: 60000) — 從儲存中清除已完成的會話前等待的時間(毫秒)。
      • tokenKey string (default: _t_) — 會話權杖的查詢參數鍵。
      • encKey string (default: _ek_) — 加密金鑰的查詢參數鍵。
      • versionKey string (default: _v_) — 協定版本的查詢參數鍵。

方法

attach(config)

這是 WalletHandlers 類別的主要方法。它為特定使用者操作(例如'登入'、'支付')將必要的 DID Connect 路由附加到您的 Express 應用程式中。此方法建立了一整套端點來處理整個連線生命週期,從權杖產生到錢包回應處理。

附加後,會為給定的 action 建立以下路由:

  • GET {prefix}/{action}/token: 建立新的會話權杖。
  • POST {prefix}/{action}/token: 建立新的會話權杖。
  • GET {prefix}/{action}/status: 檢查會話權杖的狀態(例如,等待中、已掃描、已批准)。
  • GET {prefix}/{action}/timeout: 手動使會話權杖過期。
  • GET {prefix}/{action}/auth: 錢包用來擷取驗證需求的端點。
  • POST {prefix}/{action}/auth: 錢包用來提交已簽章回應的端點。

參數

  • config object (required) — 用於附加路由的設定物件。
    • app object (required) — Express 應用程式實例。
    • action string (required) — 此工作流程的唯一名稱(例如,'login'、'claim-asset')。這將成為 URL 的一部分。
    • onAuth function (required) — 在使用者成功完成其錢包中的流程後執行的回呼函式。您可以在此處處理已驗證的資料。
    • claims object[] — 一個可選的聲明陣列,用於向使用者請求(例如,個人資料、簽章)。
    • onStart function — 一個可選的回呼函式,在新會話開始時執行。
    • onConnect function — 一個可選的回呼函式,在錢包掃描代碼時執行。它會覆寫此特定操作的建構函式中的 onConnect。
    • onDecline function — 一個可選的回呼函式,如果使用者在其錢包中拒絕請求,則會執行。
    • onComplete function — 一個可選的回呼函式,在整個工作流程完成且會話權杖被銷毀後執行。
    • onExpire function — 一個可選的回呼函式,用於處理會話權杖過期的情況。
    • onError function (default: console.error) — 一個可選的回呼函式,用於處理流程中的任何錯誤。
    • authPrincipal boolean | string (default: true) — 是否先請求 authPrincipal 聲明以建立使用者的 DID。
    • persistentDynamicClaims boolean (default: false) — 是否在會話儲存中持久化動態產生的聲明。

範例

附加登入處理程式

javascript
const express = require('express');
// ... 從建構函式範例中設定 authenticator 和 tokenStorage

const app = express();
const handlers = new WalletHandlers({ authenticator, tokenStorage });

handlers.attach({
  app,
  action: 'login',
  claims: [{ type: 'profile' }], // 請求使用者的個人資料
  onAuth: async ({ userDid, claims }) => {
    // 成功登入後的核心邏輯。
    // 在您的資料庫中使用 userDid 尋找或建立使用者。
    const profile = claims.find(x => x.type === 'profile');
    console.log(`使用者 ${userDid} 已登入,名稱為:${profile.fullName}。`);
    // 現在您可以為使用者的 Web 會話設定 cookie 或 JWT。
  },
  onComplete: ({ token }) => {
    console.log(`會話 ${token} 已完成並已清除。`);
  },
  onError: ({ error }) => {
    console.error('登入流程中發生錯誤:', error);
  }
});

app.listen(3000, () => {
  console.log('DID Connect 伺服器正在 3000 連接埠上執行');
});

事件

由於 WalletHandlers 擴充了 EventEmitter 並監聽 tokenStorage 實例,您可以訂閱事件以監控會話的生命週期。這對於向使用者提供即時回饋特別有用,例如,使用 WebSockets 在掃描 QR code 時更新 UI。

EventPayloadDescription
createdobject當建立新會話權杖時發出。負載包含權杖和初始會話資料。
updatedobject當會話更新時發出。負載包含更新後的會話資料。常見用途是檢查 status: 'scanned'。
deletedobject當會話權杖被銷毀時發出,無論是完成、過期或手動超時。負載包含被移除的權杖。

範例

監聽會話事件

javascript
// 假設 'io' 是附加到您 Express 應用程式的 Socket.IO 伺服器實例
handlers.on('updated', (payload) => {
  // 通知特定 Web 客戶端 QR code 已被掃描
  if (payload.status === 'scanned') {
    console.log(`錢包已掃描權杖:${payload.token}`);
    // 'sid' (socket ID) 應在會話建立時儲存於會話中
    if (payload.sid) {
      io.to(payload.sid).emit('wallet_scanned');
    }
  }
});

handlers.on('deleted', ({ token }) => {
  console.log(`權杖 ${token} 已從儲存中刪除。`);
});