> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-zh/common/permission/contact.md).

# 联系人

{% hint style="info" %}
**需要设置权限**

`fetchContacts`在使用“fetchContacts”之前，需要先设置联系人权限。请先查看权限设置指南。
{% endhint %}

***

### 获取联系人

**SDK 函数：** `fetchContacts`

`fetchContacts`是一个按页获取用户联系人列表的函数。

**签名**

```typescript
function fetchContacts(options: {
  size: number;
  offset: number;
  query?: {
    contains?: string;
  };
}): Promise<ContactResult>;
```

**参数**

* **options** · 必填

  这是获取联系人时指定的选项对象。

  * **options.size** · 必填

    一次获取的联系人数量。例如，传入 10 时，最多获取 10 个联系人。
  * **options.offset** · 必填

    要获取的联系人的起始位置。首次调用时 `0`需要传入该值。之后使用上一次调用返回的 `nextOffset` 值。

    * **options.query** · 必填

      这是额外的筛选选项。

      * **options.query.contains** · 必填

        当你只想获取姓名中包含特定字符串的联系人时使用。若不传入该值，则获取所有联系人。

**属性**

* openPermissionDialog

  会显示一个重新请求联系人读取权限的对话框。用户可以选择“允许”、“仅允许一次”或“不允许”之一。若选择“允许”或“仅允许一次”，则 `allowed`会返回，并在选择“不允许”时 `denied`则返回。
* getPermission

  返回联系人读取权限的当前状态。 `allowed`表示用户已允许联系人读取权限。 `denied`表示用户已拒绝联系人读取权限。 `notDetermined`表示从未请求过联系人读取权限。若在 Toss App 设置中联系人权限被拒绝，则 `osPermissionDenied`则返回。

**返回值**

* `Promise<ContactResult>`

返回包含联系人列表和分页信息的对象。

* `result`：获取到的联系人列表。
* `nextOffset`：下次调用要使用的偏移值。若没有更多联系人可获取，则 `null`。
* `done`：表示是否已获取全部联系人。若已全部获取，则 `true`。

### 联系人权限错误

**错误类型：** `FetchContactsPermissionError`

这是在联系人权限被拒绝时发生的错误。发生错误时 `error instanceof FetchContactsPermissionError`可以通过它来确认。

**签名**

```typescript
class FetchContactsPermissionError extends PermissionError {
  constructor();
}
```

**示例**

**获取包含特定字符串的联系人列表**

这是获取联系人列表的示例。点击“检查权限”按钮来检查当前的联系人读取权限。若用户拒绝了权限或系统限制了该权限，则 `FetchContactsPermissionError`会返回。可以点击“请求权限”按钮来请求联系人读取权限。

{% tabs %}
{% tab title="js" %}

```js
import { fetchContacts, FetchContactsPermissionError } from '@apps-in-toss/web-framework';

async function handleFetchContacts() {
  try {
    const response = await fetchContacts({
      size: 10,
      offset: 0,
      query: { contains: '金' },
    });

    return response;
  } catch (error) {
    if (error instanceof FetchContactsPermissionError) {
      console.log('没有联系人读取权限');
    }
    console.error('获取联系人失败：', error);
  }
}

async function handleGetPermissionForFetchContacts() {
  const permission = await fetchContacts.getPermission();
  return permission;
}

async function handleOpenPermissionDialogForFetchContacts() {
  const permission = await fetchContacts.openPermissionDialog();
  return permission;
}
```

{% endtab %}

{% tab title="React" %}

```tsx
import { ContactEntity, fetchContacts, FetchContactsPermissionError } from '@apps-in-toss/web-framework';
import { useState } from 'react';

function ContactsList() {
  const [contacts, setContacts] = useState<{
    result: ContactEntity[];
    nextOffset: number | null;
    done: boolean;
  }>({
    result: [],
    nextOffset: null,
    done: false,
  });

  const handlePress = async () => {
    try {
      if (contacts.done) {
        console.log('已获取所有联系人。');
        return;
      }

      const response = await fetchContacts({
        size: 10,
        offset: contacts.nextOffset ?? 0,
        query: { contains: '金' },
      });
      setContacts((prev) => ({
        result: [...prev.result, ...response.result],
        nextOffset: response.nextOffset,
        done: response.done,
      }));
    } catch (error) {
      if (error instanceof FetchContactsPermissionError) {
        console.log('没有联系人读取权限');
      }
      console.error('获取联系人失败：', error);
    }
  };

  return (
    <div>
      {contacts.result.map((contact, index) => (
        <span key={index}>
          {contact.name}: {contact.phoneNumber}
        </span>
      ))}
      <input
        type="button"
        value={contacts.done ? '已获取所有联系人。' : '获取下一个联系人'}
        disabled={contacts.done}
        onClick={handlePress}
      />
      <input
        type="button"
        value="检查权限"
        onClick={async () => {
          const permission = await fetchContacts.getPermission();
          alert(permission);
        }}
      />
      <input
        type="button"
        value="请求权限"
        onClick={async () => {
          const permission = await fetchContacts.openPermissionDialog();
          alert(permission);
        }}
      />

  );
}
```

{% endtab %}

{% tab title="React Native" %}

```tsx
import { ContactEntity, fetchContacts, FetchContactsPermissionError } from '@apps-in-toss/framework';
import { useState } from 'react';
import { Alert, Button, Text, View } from 'react-native';

function ContactsList() {
  const [contacts, setContacts] = useState<{
    result: ContactEntity[];
    nextOffset: number | null;
    done: boolean;
  }>({
    result: [],
    nextOffset: null,
    done: false,
  });

  const handlePress = async () => {
    try {
      if (contacts.done) {
        console.log('已获取所有联系人。');
        return;
      }

      const response = await fetchContacts({
        size: 10,
        offset: contacts.nextOffset ?? 0,
        query: { contains: '金' },
      });
      setContacts((prev) => ({
        result: [...prev.result, ...response.result],
        nextOffset: response.nextOffset,
        done: response.done,
      }));
    } catch (error) {
      if (error instanceof FetchContactsPermissionError) {
        console.log('没有联系人读取权限');
      }
      console.error('获取联系人失败：', error);
    }
  };

  return (
    <View>
      {contacts.result.map((contact, index) => (
        <Text key={index}>
          {contact.name}: {contact.phoneNumber}
        </Text>
      ))}
      <Button
        title={contacts.done ? '已获取所有联系人。' : '获取下一个联系人'}
        disabled={contacts.done}
        onPress={handlePress}
      />
      <Button
        title="检查权限"
        onPress={async () => {
          const permission = await fetchContacts.getPermission();
          Alert.alert(permission);
        }}
      />
      <Button
        title="请求权限"
        onPress={async () => {
          const permission = await fetchContacts.openPermissionDialog();
          Alert.alert(permission);
        }}
      />
    </View>
  );
}
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers-apps-in-toss.toss.im/documentation/api-and-sdk-zh/common/permission/contact.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
