Vimine(瀏覽器)
import { Vimine } from '@vimine/sdk';const vimine = new Vimine(options);Vimine 負責使用 Vimine 登入(OAuth 2.1 + PKCE)、會員的工作階段以及對會員 API 的呼叫。每個用戶端一個實例;建立一次,反覆使用。
選項
章節「選項」| 選項 | 型別 | 預設值 | |
|---|---|---|---|
clientId |
string |
— | 您的 vmc_…(必填) |
redirectUri |
string |
— | 呼叫 handleRedirect() 的頁面,已為該用戶端登記(必填) |
scopes |
Scope[] |
['profile:read', 'membership:read'] |
signIn() 申請的權限 |
storage |
'session' | 'local' | 'memory' | TokenStorage |
'session' |
工作階段和進行中的登入儲存在哪裡 |
storageKey |
string |
vimine:<clientId>: |
儲存中的鍵字首 |
locale |
Locale |
'it' |
登入和授權同意頁面的語言 |
apiUrl |
string |
https://api.vimine.network |
API 的來源 |
appUrl |
string |
https://app.vimine.network |
登入頁面的來源 |
fetch |
typeof fetch |
globalThis.fetch |
用於測試和 polyfill |
navigate |
(url) => void |
top.location.assign |
如何離開目前頁面 |
缺少 clientId 或 redirectUri 時,建構函式拋出 VimineError(invalid_options)。
登入
章節「登入」signIn(options?)
章節「signIn(options?)」把頂層視窗送到登入和授權同意頁面。請在使用者操作(一次點選)中呼叫。在跨網域 iframe 內部,導覽會被拒絕(framed):登入頁面從不顯示在框架中。
| 選項 | |
|---|---|
scopes |
本次登入的權限 |
prompt |
'login'(始終要求輸入登入資訊)或 'consent'(始終要求同意) |
returnTo |
您自己的狀態,儲存在本機,由 handleRedirect() 傳回——不會被發送 |
createSignInUrl(options?)
章節「createSignInUrl(options?)」建構授權 URL 並記住進行中的登入(PKCE verifier 和 state),但不進行重新導向。適合您自己呈現連結的場景。
hasRedirectParams(url?)
章節「hasRedirectParams(url?)」當 URL(預設:目前頁面)帶有返回參數(code+state 或 error)時為 true。
handleRedirect({ url?, cleanUrl? })
章節「handleRedirect({ url?, cleanUrl? })」在回呼頁面上:檢查 state,用授權碼交換權杖並儲存工作階段。傳回 { session, returnTo };URL 中沒有登入參數時傳回 null。啟用 cleanUrl(預設 true)時,會從位址列中移除 code、state 和 error。
錯誤(VimineError.code):會員未授權時為 access_denied 及其他 OAuth 錯誤;本瀏覽器沒有發起過登入時(儲存為空或已過期)為 no_flow;返回不符時為 state_mismatch;授權碼已過期或已被使用時為 invalid_grant。
工作階段
章節「工作階段」getSession() · isSignedIn()
章節「getSession() · isSignedIn()」已儲存的工作階段,或 null。
interface Session { accessToken: string; refreshToken: string | null; expiresAt: number; // 毫秒,絕對時間 scope: Scope[]; sub: string | null; // 會員在您的協會中的識別碼(vms_…) mode?: 'live' | 'test'; // 測試用戶端的工作階段為 'test'}getAccessToken()
章節「getAccessToken()」一個有效的存取權杖;若在 30 秒內到期則先重新整理。沒有工作階段時拋出 not_signed_in。
refresh()
章節「refresh()」用重新整理權杖輪換工作階段(即使被並行呼叫,也只發出一次請求)。如果重新整理權杖已無法使用,工作階段會被清除,錯誤會被重新拋出。
signOut({ everywhere?, postLogoutRedirectUri?, state? })
章節「signOut({ everywhere?, postLogoutRedirectUri?, state? })」撤銷重新整理權杖(RFC 7009,盡力而為)並清除工作階段。使用 everywhere: true 時,隨後會把瀏覽器送到 Vimine 應用的 /oauth/logout,結束會員的工作階段,再返回 postLogoutRedirectUri(預設為 redirectUri;必須位於已登記的來源上)。
onChange(listener)
章節「onChange(listener)」每次登入、重新整理和登出時呼叫 listener(session | null);使用 storage: 'local' 時,其他分頁中發生的這些事件也會觸發。傳回取消訂閱的函式。
會員 API
章節「會員 API」request(path, init?)
章節「request(path, init?)」一次經過驗證的呼叫:Authorization: Bearer,輸入輸出均為 JSON,錯誤以 VimineError 拋出,回應為 401 時在重新整理後重試一次。init.idempotencyKey 會成為 Idempotency-Key 請求標頭。
const events = await vimine.request('/v1/me/membership/events?limit=5');me
章節「me」| Scope | ||
|---|---|---|
me.get() |
profile:read |
個人資料(Me),帶有 codicefiscale_check:當事人的身份識別方式(null = 尚未識別) |
me.update(patch) |
profile:write |
電話、性別,以及身份識別資訊:出生日期、出生地和出生國(birth_country)、稅號——可選,可以之後再補充。不一致的稅號傳回 422,帶有一條 codicefiscale_mismatch 記錄;當它為 confirmable 時,當事人可以用 codicefiscale_confirmed: true 確認(指南) |
membership
章節「membership」| Scope | ||
|---|---|---|
membership.get() |
membership:read |
會員卡:status、verdict、expires_at、statuto、card |
membership.request(body, { idempotencyKey? }) |
membership:request |
入會申請;未提供冪等鍵時會自動產生。個人資料尚未識別身份時傳回 422 identification_required:err.errors 列出缺少的內容,用 me.update() 補全 |
membership.events({ limit?, cursor? }) |
membership:read |
狀態歷史,分頁 |
membership.statuto() |
membership:read |
現行章程及會員的接受情況 |
membership.acceptStatuto({ version, sha256? }) |
statuto:accept |
記錄接受 |
membership.card() |
membership:read |
會員卡權杖(QR Code)及其有效時段;會員資格未生效時傳回 409 not_active |
membership.renew({ version, sha256? }) |
POST /v1/me/membership/renew |
自助續期:免費且無需審核時立即完成,否則向秘書處提交申請 |
membership.setNetworkOptIn(bool) |
PATCH /v1/me/membership/network-opt-in |
加入網路的同意(network:manage) |
membership.googleWalletUrl() |
GET /v1/me/membership/wallet/google |
“新增到 Google Wallet”連結;會員資格未生效時傳回 409 not_active |
membership.cardSvg() |
GET /v1/me/membership/card.svg |
SVG 格式的會員卡(帶 QR Code);會員資格未生效時傳回 409 not_active |
membership.emailCard() |
POST /v1/me/membership/card/email |
透過電子郵件把會員卡發給會員 |
events
章節「events」協會已發布的活動,包括僅限會員的活動(events:read)。公開活動無需登入:vimine.public.events。
events.list({ filter?, from?, to?, limit? }) |
filter:upcoming(預設)、past、cancelled、all |
events.get(slug) |
文案、圖片、各報名類型及剩餘名額 |
events.eligibility(slug) |
會員能否報名?按類型給出,並附原因(membership_required、sold_out 等) |
registrations
章節「registrations」會員的報名(registrations:read / registrations:write)。參見活動與報名指南。
registrations.create(slug, { registration_type, note?, quantity? }, opts?) |
免費類型 → confirmed,帶 QR Code token;需付參與費 → reserved,帶 payment_instructions;422 not_eligible 附原因;自動產生 Idempotency-Key |
registrations.list({ filter? }) · registrations.get(id) |
會員的報名(filter: 'upcoming') |
registrations.cancel(id) |
在活動的取消期限內取消(超過期限傳回 409 window_closed) |
registrations.tokenPayload(id) |
已確認報名的 QR Code 內容,或 null |
connections
章節「connections」connections.list() |
會員在本協會中授權過的應用 |
connections.revoke(clientId) |
撤回對某個應用的同意(其工作階段隨即結束) |
public
章節「public」無需憑證的公開端點:參見 publicApi。
儲存
章節「儲存」storage |
位置 | 適用場景 |
|---|---|---|
'session'(預設) |
sessionStorage:每個分頁獨立,關閉即清除 |
對公開用戶端而言最安全的預設值 |
'local' |
localStorage:多個分頁共享,重啟後仍保留;登出會同步到其他分頁 |
會員期望保持登入狀態的應用 |
'memory' |
僅在記憶體中 | SSR、測試、自助終端 |
TokenStorage |
您自己的物件 { get, set, remove } |
Node、加密儲存、原生應用 |
在無法使用瀏覽器儲存的情況下(隱私模式、about:blank),SDK 會退回到記憶體儲存。MemoryStorage 已匯出。