Skip to content

API methods

Class ZorioWebphone expose 12 phương thức chính. Bốn phương thức đầu nằm trên instance webphone (phone.*), tám phương thức điều khiển cuộc gọi nằm trên object cuộc gọi (call.* — trả về từ phone.call() hoặc payload event incoming_call).

Phương pháp gọi

Mọi method đều async trả về Promise. Anh chị await để bắt error và đảm bảo state sync trước khi gọi method tiếp theo.

1. Static factory

ts
ZorioWebphone.connect(opts: ConnectOptions): Promise<ZorioWebphone>
ZorioWebphone.diagnose(opts: { apiBase: string; token: string }): Promise<DiagnoseResult>

connect() bootstrap: gọi /api/webphone/sip-config → tạo UserAgent SIP.js → register → mount UI (nếu có mount). diagnose() chạy preflight HTTPS / Micro / WSS / STUN / TURN — gọi trước connect() khi debug.

ts
interface ConnectOptions {
  apiBase:              string
  token:                string
  mount?:               string | HTMLElement
  layout?:              'docked' | 'overlay' | 'fullscreen'
  theme?:               'light' | 'dark' | 'auto'
  locale?:              'vi' | 'en'
  autoRegister?:        boolean
  ringtoneUrl?:         string
  audioOutputDeviceId?: string
  audioInputDeviceId?:  string
  tokenResolver?:       () => Promise<string>
  debug?:               boolean
  onError?:             (err: ZorioWebphoneError) => void
}

2. Instance methods — connection & control

2.1 connect

Đã document ở phần Static factory phía trên. Trả về phone instance dùng cho các method còn lại.

2.2 disconnect

ts
phone.disconnect(): Promise<void>

Đóng toàn bộ resource: unregister SIP, đóng WebSocket, remove UI DOM (nếu embedded), clear audio element, cancel mọi reconnect timer. Bắt buộc gọi khi user logout app.

ts
async function onLogout() {
  await phone.disconnect()
  redirectTo('/login')
}

Pagehide tự xử lý

SDK đã tự addEventListener('pagehide', ...) để unregister sạch khi user đóng tab. Anh chị chỉ cần gọi disconnect() thủ công cho luồng logout chủ động.

2.3 call

ts
phone.call(number: string, options?: CallOptions): Promise<ZorioCall>

interface CallOptions {
  campaignId?:  number
  leadId?:      number
  customerId?:  number
  recording?:   boolean
  callerName?:  string
  meta?:        Record<string, unknown>
}

Khởi tạo cuộc gọi outbound. Trả về ZorioCall ngay sau khi SIP INVITE được gửi (state originating); cuộc gọi tiếp tục lifecycle qua events call_ringingcall_answeredcall_hangup.

ts
const call = await phone.call('0912345678', {
  campaignId: 36,
  leadId: 78912,
  recording: true,
  meta: { source: 'crm-quickdial' },
})
console.log('Call UUID:', call.uuid)

Format số

Format số tuân thủ dial-plan Zorio PBX của khách hàng. Mặc định E.164 (+84912345678) hoặc số quốc nội (0912345678). Số không parse được sẽ throw ZorioWebphoneError với code = 'invalid_target'.

3. Call-control methods (trên ZorioCall)

Các method sau gọi trên object ZorioCall lấy được từ phone.call(), payload incoming_call, hoặc qua phone.calls.find(c => c.state === 'answered').

3.1 answer

ts
call.answer(): Promise<void>

Trả lời cuộc gọi inbound. Throw code = 'not_incoming' nếu gọi trên outbound. Tự attach micro track + remote audio.

ts
phone.on('incoming_call', async ({ call }) => {
  if (myUI.shouldAutoAnswer()) await call.answer()
})

3.2 reject / hangup

ts
call.hangup(): Promise<void>

Kết thúc cuộc gọi ở bất kỳ state nào. SDK tự chọn SIP method phù hợp:

StateSIP method
originating (outbound chưa ring)CANCEL
ringing inbound (chưa answer)REJECT (response 486 / 603)
answeredBYE

reject vs hangup

SDK expose chung qua call.hangup() — state-aware. Khi bạn muốn rõ semantic "từ chối cuộc đến", có thể alias:

ts
const reject = (call: ZorioCall) => call.hangup()

3.3 mute / unmute

ts
call.mute():   Promise<void>
call.unmute(): Promise<void>

Tắt/bật micro local. KHÔNG ảnh hưởng remote audio. State sync qua property call.muted: boolean và emit event muted / unmuted.

ts
muteBtn.onclick = async () => {
  const active = phone.calls.find(c => c.state === 'answered')
  if (!active) return
  if (active.muted) await active.unmute()
  else              await active.mute()
}

3.4 hold / unhold

ts
call.hold():   Promise<void>
call.unhold(): Promise<void>

Tạm dừng cuộc gọi qua SIP re-INVITE với SDP a=sendonly. Hold đúng chuẩn nên callee sẽ nghe music-on-hold của Zorio PBX (nếu profile bật).

ts
await call.hold()
// ... user xử lý việc khác
await call.unhold()

3.5 sendDtmf

ts
call.sendDtmf(digits: string): Promise<void>

Gửi DTMF tones qua RFC 2833. Hỗ trợ ký tự 0-9, *, #, A-D. Ký tự khác throw code = 'invalid_dtmf'.

ts
// Điều hướng IVR sau khi callee answer (đợi 1s cho IVR phát prompt)
phone.on('call_answered', async ({ call }) => {
  await new Promise(r => setTimeout(r, 1000))
  await call.sendDtmf('1')      // chọn nhánh 1
  await call.sendDtmf('2#')     // chọn 2 rồi #
})

3.6 transfer

ts
call.transfer(target: string): Promise<void>

Blind transfer — chuyển cuộc gọi sang target (extension/số điện thoại) không cần consult. State chuyển về closed sau khi SIP REFER được Zorio PBX chấp nhận.

ts
// User bấm "Chuyển sang nhánh 2002"
await call.transfer('2002')

v1.0 — chưa hỗ trợ

transfer() và phương thức consult attended transfer hiện throw code = 'not_implemented' trong v1.0. Đặt vào roadmap Phase 2. Đối tác cần transfer hôm nay có thể fallback qua *8 blind-transfer Zorio PBX feature code → bấm DTMF qua sendDtmf('*8' + target + '#').

4. Events subscription

phone.on() / phone.off() tuy không nằm trong 12 method chính nhưng là phần không thể thiếu:

ts
phone.on<E extends EventName>(event: E, handler: (payload: EventPayload<E>) => void): void
phone.off<E extends EventName>(event: E, handler?: Function): void

Xem chi tiết tất cả 12 events ở trang Events.

5. Properties read-only

Một số property tiện theo dõi state mà không cần wait event:

ts
phone.status        // 'connecting' | 'registered' | 'unregistered' | 'failed'
phone.extension     // số máy nhánh SIP đã đăng ký
phone.user          // UserProfile | null
phone.calls         // ZorioCall[] — mọi cuộc đang active

// Trên ZorioCall:
call.uuid           // UUID Zorio PBX (link với CDR)
call.direction      // 'incoming' | 'outgoing'
call.state          // 'originating' | 'ringing' | 'answered' | 'wrap_up' | 'closed'
call.number         // số đối phương (E.164)
call.startedAt      // Date — lúc khởi tạo
call.answeredAt     // Date | null — lúc kết nối thành công
call.endedAt        // Date | null
call.muted          // boolean
call.onHold         // boolean

6. Error handling

Tất cả method throw ZorioWebphoneError:

ts
class ZorioWebphoneError extends Error {
  code:     string
  details?: Record<string, unknown>
}

Mã lỗi thường gặp: bootstrap_failed, webphone_disabled, incomplete_sip_config, invalid_target, not_incoming, invalid_dtmf, audio_autoplay_blocked, reconnect_failed, not_implemented, not_bootstrapped.

ts
try {
  const call = await phone.call('xxx')
} catch (err) {
  if (err.code === 'invalid_target') {
    alert('Số gọi không hợp lệ')
  } else {
    console.error(err)
  }
}

7. Bảng tổng hợp 12 method chính

#MethodPhạm viMục đích
1connectstaticBootstrap SDK + register SIP
2disconnectphoneĐóng sạch, dùng khi logout
3callphoneKhởi tạo outbound
4hangupcallCancel/Bye cuộc đang đi
5answercallTrả lời inbound
6rejectcallAlias hangup khi inbound chưa answer
7mutecallTắt micro
8unmutecallBật micro
9holdcallTạm dừng (re-INVITE sendonly)
10unholdcallTiếp tục
11sendDtmfcallGửi tone IVR
12transfercallBlind transfer (Phase 2)

Tham khảo thêm:

Cấp phép theo điều khoản sử dụng của Zorio.