---
metadata:
  - name: generator
    content: Diplodoc Platform v5.52.0
alternate:
  - https://yandex.com/dev/games/doc/en/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/hi/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/ko/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/ru/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/tr/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/vi/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/zh/sdk/sdk-player.md
  - href: vi/sdk/sdk-player.md
    type: text/markdown
    title: Markdown version
  - href: ../llms.txt
    type: text/markdown
    title: llms.txt
---
> **Documentation Index:** Fetch the complete configuration index at https://yandex.com/dev/games/doc/vi/llms.txt

# Dữ liệu người chơi

Bạn có thể lưu dữ liệu trạng thái trò chơi của người chơi (chẳng hạn như cấp độ đã hoàn thành, kinh nghiệm hoặc mua hàng trong trò chơi) trên máy chủ Yandex hoặc gửi dữ liệu này đến máy chủ của bạn. Bạn cũng có thể tạo ra trải nghiệm tùy chỉnh theo cá nhân hơn thông qua dữ liệu từ hồ sơ Yandex của người dùng, ví dụ: tên của người dùng.

Để làm việc với dữ liệu người dùng, hãy sử dụng đối tượng `Player`.



## Khởi tạo {#getplayer}

Để khởi tạo đối tượng `Player`, hãy sử dụng phương thức `ysdk.getPlayer()`.

```javascript
var player;

ysdk.getPlayer().then(_player => {
        player = _player;
    }).catch(err => {
         // Lỗi khởi tạo đối tượng Player.
    });
```

Khi khởi tạo đối tượng `Player`, các thông tin sau sẽ được truyền vào:

- ID người dùng — cho tất cả người chơi.
- Avatar và tên — cho người chơi đã xác thực.
- Dữ liệu mua hàng trên nền tảng (chỉ áp dụng cho trò chơi có [mua hàng trong ứng dụng](https://yandex.com/dev/games/doc/vi/console/purchases.md)) — cho người chơi từ Nga.

Quyền truy cập vào dữ liệu người dùng phụ thuộc vào cài đặt trong [hồ sơ](https://yandex.com/games/user) của họ. Nếu người chơi từ chối quyền truy cập vào dữ liệu cá nhân, phản hồi sẽ chỉ bao gồm ID.

Bạn có thể sử dụng tham số tùy chọn `signed: true` và phương thức `fetch()` để đăng nhập người dùng và lưu dữ liệu trạng thái trò chơi của họ trên máy chủ của bạn. Cách này cho phép bạn sử dụng chữ ký để xác thực người dùng và ngăn chặn gian lận.

```javascript
var player;

ysdk.getPlayer({ signed: true }).then(_player => {
        player = _player;

        // Sử dụng player.signature để cho phép trên máy chủ của bạn.
        fetch('https://your.game.server?auth', {
            method: 'POST',
            headers: { 'Content-Type': 'text/plain' },
            body: player.signature
        });
    }).catch(err => {
        // Lỗi khởi tạo đối tượng Player.
    });
```

Tham số `chữ ký` của yêu cầu được gửi đến máy chủ chứa dữ liệu người dùng từ hồ sơ Yandex và chữ ký. Tham số bao gồm hai chuỗi mã hóa theo chuẩn Base64:

```text
<signature>.<profile data>
```

Để biết thêm thông tin, hãy xem [Phòng chống gian lận](https://yandex.com/dev/games/doc/vi/sdk/sdk-purchases.md#signature).

{% note info "Ghi chú" %}

Yêu cầu chỉ có thể được gửi không quá 20 lần trong 5 phút, nếu không nó sẽ bị từ chối với lỗi.

{% endnote %}



## Đăng nhập người dùng {#auth}

### Xác minh sự cho phép {#auth-check}

Để kiểm tra xem người chơi đã đăng nhập vào Yandex hay chưa, hãy sử dụng phương thức của đối tượng `Player` — `player.isAuthorized()`. Phương thức này trả về `true | false`.

{% note alert "Hạn chế" %}

Phương thức `player.getMode(): 'lite' | ''` đã lỗi thời và sẽ bị xóa khỏi giao diện trong tương lai.

{% endnote %}


### Gọi hộp thoại đăng nhập {#open-auth-dialog}

Nếu người chơi chưa đăng nhập, bạn có thể sử dụng phương thức `ysdk.auth.openAuthDialog()` để gọi cửa sổ cho phép.


{% note tip "Lời khuyên" %}

Thông báo cho người dùng về những lợi thế của việc đăng nhập. Nếu người dùng không nhận thức được những lợi ích liên quan, rất có thể họ sẽ từ chối đăng nhập và sau đó thoát khỏi trò chơi.

{% endnote %}

```javascript
var player;

function initPlayer() {
    return ysdk.getPlayer().then(_player => {
            player = _player;

            return player;
        });
}

initPlayer().then(_player => {
        if (_player.isAuthorized() === false) {
            // Người chơi chưa đăng nhập.
            ysdk.auth.openAuthDialog().then(() => {
                    // Người chơi đã đăng nhập.
                    initPlayer().catch(err => {
                        // Lỗi khởi tạo đối tượng Player.
                    });
                }).catch(() => {
                    // Người chơi chưa đăng nhập.
                });
        }
    }).catch(err => {
        // Lỗi khởi tạo đối tượng Player.
    });
```



## Dữ liệu trong trò chơi {#ingame-data}

Để làm việc với dữ liệu trong trò chơi của người dùng, hãy sử dụng các phương thức của đối tượng `Player`:


* `player.setData(data, flush)`: Lưu dữ liệu người dùng. Kích thước dữ liệu tối đa không được vượt quá 200&nbsp;KB. {#setdata}

   - `data` (object): Một đối tượng chứa các cặp khóa-giá trị.
   - `flush` (boolean): Xác định thứ tự gửi dữ liệu. Nếu giá trị là "true", dữ liệu ngay lập tức được gửi đến máy chủ. Nếu đó là "false" (mặc định), yêu cầu gửi dữ liệu sẽ được xếp hàng đợi.

   Phương thức trả về `Promise` cho biết dữ liệu đã được lưu hay chưa.

   Với `flush: false`, kết quả trả về chỉ hiển thị tính hợp lệ của dữ liệu (dữ liệu đã được xếp hàng đợi và sẽ được gửi sau). Đồng thời, phương thức `player.getData()` sẽ trả về tập dữ liệu bằng lệnh gọi `player.setData()` cuối cùng, ngay cả khi nó chưa được gửi.

   ```javascript
   player.setData({
           achievements: [`trophy1`, `trophy2`, `trophy3`],
       }).then(() => {
           console.log('dữ liệu được thiết lập');
       });
   ```


- `player.getData(keys)`: Trả về không đồng bộ dữ liệu người dùng trong trò chơi được lưu trữ trong cơ sở dữ liệu Yandex. {#getdata}

   - `keys` (array\<string>): Danh sách các khóa cần trả lại. Nếu tham số `key` bị thiếu, phương thức này sẽ trả về tất cả dữ liệu người dùng trong trò chơi.

   Phương thức trả về `Promise<Object>`, trong đó object chứa các cặp khóa-giá trị.

- `player.setStats(stats)`: Lưu dữ liệu số của người dùng. Kích thước dữ liệu tối đa không được vượt quá 10&nbsp;KB. {#setstats}

   - `stats` (object): Một đối tượng chứa các cặp khóa-giá trị, trong đó mỗi giá trị phải là một số.

   Phương thức trả về `Promise` cho biết dữ liệu đã được lưu hay chưa.


   {% note tip "Lời khuyên" %}

   Với các giá trị số thường xuyên thay đổi (điểm, kinh nghiệm, tiền trong trò chơi), hãy sử dụng phương pháp này thay vì [player.setData()](#ingame-data).

   {% endnote %}



- `player.incrementStats(increments)`: Thay đổi dữ liệu người dùng trong trò chơi. Kích thước dữ liệu tối đa không được vượt quá 10&nbsp;KB. {#incrementstats}

   - `increments` (object): Một đối tượng chứa các cặp khóa-giá trị, trong đó mỗi giá trị phải là một số.

   Phương thức trả về `Promise<Object>`, trong đó object chứa các cặp khóa-giá trị đã sửa đổi và được thêm vào.


- `player.getStats(keys)`: Trả về không đồng bộ dữ liệu số của người dùng. {#getstats}

   - `keys` (array\<string>): Danh sách các khóa cần trả lại. Nếu tham số `key` bị thiếu, phương thức này sẽ trả về tất cả dữ liệu người dùng trong trò chơi.

   Phương thức trả về `Promise<Object>`, trong đó object chứa các cặp khóa-giá trị.

{% note info "Ghi chú" %}

Tần suất gửi yêu cầu bị giới hạn. Trong trường hợp vượt quá [giới hạn](#limits), yêu cầu sẽ bị từ chối với lỗi.

{% endnote %}



## Dữ liệu hồ sơ người dùng {#profile-data}

Để lấy dữ liệu từ hồ sơ người dùng Yandex, hãy sử dụng các phương thức của đối tượng `Player`:

- `player.getUniqueID()` (string): Trả về ID duy nhất vĩnh viễn của người dùng.

   {% note info "Ghi chú" %}

   Phương thức `player.getID()` được sử dụng trước đây đã không còn được dùng nữa nhưng hiện vẫn được hỗ trợ, trả về cảnh báo trong bảng điều khiển lỗi.

   Các giá trị của `player.getID()` và `player.getUniqueID()` thường không giống nhau đối với một đối tượng `Player` nhất định, nhưng chúng có thể giống nhau với một số người dùng. Nếu các giá trị khác nhau và bản thân trò chơi đã liên kết một số dữ liệu với giá trị `player.getID()`, bạn cần di chuyển dữ liệu này và liên kết với giá trị `player.getUniqueID()`. Để di chuyển dữ liệu cho tất cả người dùng cùng một lúc, hãy liên hệ bộ phận [hỗ trợ](https://yandex.com/dev/games/doc/vi/concepts/troubleshooting.md#fos).

   {% endnote %}

- `player.getIDsPerGame()`: Trả về `Promise<Array>` cùng với các ID người dùng cho tất cả các trò chơi của nhà phát triển mà họ đã cấp quyền truy cập rõ ràng vào dữ liệu cá nhân của mình. Ví dụ:

   ```javascript
   [
       { appID: 103915, userID: "tOpLpSh7i8QG8Voh/SuPbeS4NKTj1OxATCTKQF92H4c=" },
       { appID: 103993, userID: "bviQCIAAuVmNMP66bZzC4x+4oSFzRKpteZ/euP/Jwv4=" }
   ]
   ```

   {% note alert "Chú ý" %}

   Yêu cầu chỉ dành cho người dùng được cho phép. Nếu cần, hãy yêu cầu [sự cho phép](#auth).

   Để kiểm tra xem phương thức có dùng được cho người dùng hay không, bạn có thể sử dụng phương thức `ysdk.isAvailableMethod('player.getIDsPerGame')`. Phương thức này trả về `Promise<Boolean>`, trong đó giá trị boolean cho biết tính khả dụng của phương thức.

   {% endnote %}

- `player.getName()` (string): Trả về tên người dùng.

- `player.getPhoto(size)` (string): Trả về URL ảnh hồ sơ của người dùng.

   - `size` (string): Kích thước được yêu cầu. Các giá trị được hỗ trợ bao gồm: `small`, `medium`, `large`.

- `player.getPayingStatus()` (string): Trả về bốn giá trị có thể tùy thuộc vào tần suất và số lượng mua hàng của người dùng:

   - `paying`: Người dùng đã mua tiền của cổng thông tin với giá hơn ₽500 trong tháng trước.
   - `partially_paying`: Người dùng đã mua tiền của cổng thông tin bằng tiền thật ít nhất một lần trong năm ngoái.
   - `not_paying`: Người dùng đã không mua tiền của cổng thông tin bằng tiền thật trong năm ngoái.
   - `unknown`: Người dùng không đến từ Liên bang Nga hoặc không đồng ý chia sẻ thông tin này với nhà phát triển.

   Mẫu sử dụng:

   ```javascript
   const ysdk = await YaGames.init(); // Khởi tạo SDK.
   const player = await ysdk.getPlayer(); // Truy xuất dữ liệu người chơi.
   const payingStatus = player.getPayingStatus(); // Lấy thông tin trạng thái hoạt động thanh toán của người dùng trên nền tảng.

   if (payingStatus === 'paying' || payingStatus === 'partially_paying') {
       // Cung cấp hàng hóa trong ứng dụng khi khởi động hoặc thay vì quảng cáo.
   }
   ```



## Giới hạn của phương thức {#limits}

   #|
   || **Phương thức** | **Mô tả** | **Giới hạn** ||
   || `ysdk.getPlayer()` | [Khởi tạo đối tượng `Player`](#getplayer) |::{align="center"} 20 yêu cầu trong năm phút ||
   || `player.setData()` | [Lưu dữ liệu người dùng](#setdata) |::{align="center"} 100 yêu cầu trong năm phút ||
   || `player.getData()` | [Trả về dữ liệu trong game của người dùng một cách bất đồng bộ](#getdata) | ^ ||
   || `player.setStats()` | [Lưu dữ liệu số của người dùng](#setstats) |::{align="center"} 60 yêu cầu mỗi phút ||
   || `player.getStats()` | [Trả về không đồng bộ dữ liệu số của người dùng](#getstats) | ^ ||
   || `player.incrementStats()` | [Thay đổi dữ liệu người dùng trong trò chơi](#incrementstats) | ^ ||
   |#



## Mất tiến độ trên iOS {#progress-loss}

Nếu trò chơi được tích hợp thông qua `iframe`, `localStorage` thường có thể bị đặt lại trên các phiên bản iOS mới, khiến người chơi mất thông tin tiến trình. Để tránh điều này, hãy sử dụng `safeStorage`, có giao diện tương tự như `localStorage`:

```javascript
ysdk.getStorage().then(safeStorage => {
        safeStorage.setItem('key', 'bộ lưu trữ an toàn đang hoạt động');
        console.log(safeStorage.getItem('key'))
    })
```

Để tránh thay đổi mã theo cách thủ công, hãy ghi đè `localStorage` ở phạm vi toàn cục.


{% note alert "Chú ý" %}

Đảm bảo rằng `localStorage` không được sử dụng trước khi ghi đè.

{% endnote %}


```javascript
ysdk.getStorage().then(safeStorage => Object.defineProperty(window, 'localStorage', { get: () => safeStorage }))
    .then(() => {
        localStorage.setItem('key', 'bộ lưu trữ an toàn đang hoạt động');
        console.log(localStorage.getItem('key'))
    })
```

Nếu bạn đang tải lên mã nguồn dưới dạng tệp lưu trữ, bạn không cần phải làm gì cả: một trình bọc wrapper đặc biệt trong SDK sẽ tự động tạo sự tin cậy cho `localStorage`.


---

<!-- source: vi/_includes/concepts/troubleshooting/id-troubleshooting/support.md -->
{% note info "Ghi chú" %}

Nhân viên hỗ trợ sẽ giúp bạn đăng bài trò chơi đã hoàn thiện lên nền tảng trò chơi của Yandex. Để đặt các câu hỏi về việc phát triển và kiểm thử, các nhà phát triển khác sẽ trả lời chuyên sâu trong [Kênh Discord](https://discord.com/invite/wU4p3whr4T).

{% endnote %}
<!-- endsource: vi/_includes/concepts/troubleshooting/id-troubleshooting/support.md -->

<!-- source: vi/_includes/button-fos.md -->
Nếu bạn đang gặp phải vấn đề hoặc có câu hỏi liên quan đến việc sử dụng Yandex Games SDK, vui lòng liên hệ với bộ phận hỗ trợ:


<a href="https://yandex.com/chat/#/user/a4fa5c06-75db-9b38-6eea-b1673785f7d5">
  <span class="button">Viết trong mục trò chuyện</span>
</a>
<!-- endsource: vi/_includes/button-fos.md -->
