跳到主要內容

處理錢包回應

在您如 請求聲明 指南中所示定義了 DID Connect 會話的聲明後,下一個關鍵步驟是處理來自使用者 DID 錢包的回應。@arcblock/did-connect-js 函式庫提供了一套全面的生命週期回呼,以管理會話的每種可能結果,無論是使用者批准、拒絕,還是會話逾時。

在您如 請求聲明 指南中所示定義了 DID Connect 會話的聲明後,下一個關鍵步驟是處理來自使用者 DID 錢包的回應。@arcblock/did-connect-js 函式庫提供了一套全面的生命週期回呼,以管理會話的每種可能結果,無論是使用者批准、拒絕,還是會話逾時。

這些回呼作為函數傳遞給 handlers.attach() 方法,並為您提供特定的掛鉤,以便在驗證過程中執行您的業務邏輯。

DID Connect 生命週期

一個典型的 DID Connect 會話遵循一個清晰的事件序列。下圖說明了此流程,並指出了每個主要生命週期回呼的觸發時機。

Handling Wallet Responses

生命週期回呼

以下是可用於處理整個 DID Connect 會話生命週期的回呼的詳細說明。

回呼觸發時機...常見使用案例
onStart新會話啟動且 QR code 準備就緒時。記錄會話啟動、準備會話特定資源。
onConnect使用者的錢包掃描 QR code 並建立連線時,但在聲明被批准之前。基於 userDid 進行權限檢查、生成動態聲明。
onDecline使用者在其錢包中明確拒絕請求時。顯示取消訊息、記錄拒絕操作。
onAuth(必要) 使用者批准請求並提交所請求的聲明時。核心業務邏輯: 驗證聲明、建立使用者會話、更新資料庫。
onComplete整個 DID Connect 會話結束時,無論成功或失敗。最後的清理工作、移除臨時會話資料。
onExpire在使用者完成操作前會話逾時。通知使用者 QR code 已過期、清理過時的會話。
onError會話期間發生意外錯誤時。錯誤記錄與報告。

onConnect:預先批准邏輯與動態聲明

onConnect 回呼特別強大,因為它允許您在知道使用者 DID 但在他們看到完整的聲明列表之前執行邏輯。這是根據使用者身份執行權限檢查或動態生成聲明的理想位置。

參數: { req, challenge, userDid, userPk, extraParams, updateSession }

範例:使用 onConnect 生成動態聲明

javascript
handlers.attach({
  action: 'dynamic-claims',

  // 此函數可以是異步的
  onConnect: ({ userDid }) => {
    // 您可以根據允許列表檢查使用者的 DID
    if (!isUserAllowed(userDid)) {
      throw new Error('您無權存取此服務。');
    }

    // 或根據使用者屬性返回一組動態聲明
    return {
      profile: () => ({
        fields: ['fullName', 'email'],
        description: '請提供您的姓名和電子郵件以繼續',
      }),
    };
  },

  onAuth: async ({ claims, userDid }) => {
    // `claims` 現在包含動態生成的個人資料聲明的結果
    console.log('動態聲明已由以下使用者批准:', userDid, claims);
  },
});

onAuth:處理成功驗證

onAuth 回呼是您 DID Connect 整合的核心。它是唯一必要的回呼,當使用者在錢包中成功批准請求時執行。它接收使用者提交的聲明資料,您可以使用這些資料來完成應用程式的邏輯,例如登入使用者或驗證資產所有權。

參數: { req, challenge, claims, userDid, userPk, extraParams, updateSession }

範例:在 onAuth 中處理提交的聲明

javascript
handlers.attach({
  action: 'profile-login',
  claims: {
    profile: () => ({
      fields: ['fullName', 'email'],
      description: '請提供您的姓名和電子郵件以登入。',
    }),
  },

  onAuth: async ({ userDid, claims }) => {
    try {
      const profileClaim = claims.find((c) => c.type === 'profile');
      if (profileClaim) {
        console.log(`為 ${userDid} 登入成功`);
        console.log('使用者個人資料:', profileClaim.value);
        // 在這裡,您通常會建立使用者會話、儲存到資料庫等。
        const user = await findOrCreateUser(userDid, profileClaim.value);
      }
    } catch (err) {
      console.error('登入過程中發生錯誤:', err);
    }
  },
});

onDecline:處理使用者取消操作

如果使用者決定在其錢包中取消請求,則會觸發 onDecline 回呼。這使您能夠優雅地處理取消操作,例如,在前端通知使用者登入嘗試已取消。

參數: { req, challenge, userDid, userPk, extraParams, updateSession }

範例:處理被拒絕的請求

javascript
handlers.attach({
  action: 'profile-login',
  claims: { /* ... */ },
  onAuth: async ({ userDid, claims }) => { /* ... */ },

  onDecline: ({ userDid }) => {
    console.log(`使用者 ${userDid} 拒絕了連線請求。`);
    // 您可以更新會話以通知前端
  },
});

使用 updateSession 持久化資料

包括 onAuth、onConnect 和 onStart 在內的多個回呼,都會收到一個 updateSession 函數作為參數。這個工具對於將資訊從您的後端邏輯傳遞回會話狀態至關重要,然後您的前端應用程式可以輪詢並檢索這些狀態。

例如,在 onAuth 中成功登入後,您可以生成一個應用程式特定的 JWT 並將其儲存到會話中。您的前端隨後可以檢索此權杖以驗證後續的 API 請求。

  • 要持久化普通的、非敏感的資訊:await updateSession({ key: 'value' });
  • 要持久化敏感資訊(將被加密):await updateSession({ key: 'sensitive-value' }, true);

範例:使用 updateSession 將權杖傳遞給前端

javascript
handlers.attach({
  action: 'profile-login',
  claims: { /* ... */ },
  onAuth: async ({ userDid, claims, updateSession }) => {
    const user = await findOrCreateUser(userDid, claims);
    const appToken = generateAppToken(user);

    // 持久化一個非敏感的會話 ID
    await updateSession({ sessionId: 'some-session-id' });

    // 持久化一個敏感的 JWT,它將在會話儲存中被加密
    await updateSession({ token: appToken }, true);

    console.log(`已為使用者 ${userDid} 更新會話`);
  },
});

透過有效使用這些生命週期回呼,您可以建構穩健且使用者友善的驗證流程。現在您已了解如何處理單一會話的回應,您可以開始探索更複雜的使用者旅程。

接下來,請在 鏈接工作流程 指南中學習如何透過將多個 DID Connect 會話連結在一起來建立多步驟互動。