# Web 端 SDK

APP 扫码 Web 端用到的 SDK 为 authing-js-sdk，请先了解如何在浏览器端安装以及初始化 SDK。

{% content-ref url="/pages/-LdsyyphaBreKun8cXvJ" %}
[SDK for JavaScript](/authing/sdk/sdk-for-javascript.md)
{% endcontent-ref %}

{% hint style="info" %}
Authing SDK 提供两种方式接入：

1. 直接使用 Authing 提供的扫码登录组件（startAppAuthScanning）。
2. 只调用业务接口，自己实现 UI。
   {% endhint %}

## 一键生成扫码登录组件

Authing.qrlogin.startScanning(options)

```javascript
authing.startAppAuthScanning({
    mount: '', // 可选，二维码挂载点，如不写则默认漂浮在文档中间
    interval: 1000, // 可选，轮询间隔时间，默认为 800 ms 

    onPollingStart: (intervalNum) => {},
    onResult: (res) => {},
    onScanned: (userInfo) => {},
    onSuccess: (data) => {
        const { ticket, userInfo } = data;
    },
    onCancel: () => {},
    onExpired: () => {},
    onError: (data) => {},

    onQRCodeShow: (qrcode) => {},
    onQRCodeLoad: (qrcode) => {},
    onQRCodeLoadFaild: (error) => {},
    
    tips: '使用 <strong> APP </strong> 扫码登录',
    scannedTips: '用户已扫码，等待确认',
    canceledTips: '用户取消授权',
    expiredTips: '二维码已过期',
    successTips: '扫码成功',
    retryTips: '重试',
    failedTips: '网络出错，请重试'
})
```

| 参数                            | 可选/必选 | 说明                                                                                                                                                                                                                                                                                                                                                    |
| ----------------------------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| mount \<string>               | 可选    | 挂载点 Dom ID，如不写则默认漂浮在文档中间。                                                                                                                                                                                                                                                                                                                             |
| interval \<number>            | 可选    | 轮询时间间隔，单位为 ms，默认为 800 ms。                                                                                                                                                                                                                                                                                                                             |
| onPollingStart \<function>    | 可选    | <p>轮询开始时会被回调，<strong>只会回调一次</strong>。回调参数 intervalNum 为 setInterval 返回的数值，可使用 clearInterval 停止轮询。</p><p>如：clearInterval(intervalNum)</p>                                                                                                                                                                                                              |
| onResult \<function>          | 可选    | <p>每次查询获取到数据都会回调，参数 res 示例如下：</p><p><code>{    "code": 200,    "message": "查询二维码状态成功",    "data": {        "qrcodeId": "5e05f6027fde537d950f7da9",        "scanned": false,        "expired": false,        "success": false,        "canceled": false,        "status": 0,        "userInfo": {},        "description": "二维码还没有被扫描"    }}</code></p> |
| onScanned \<function>         | 可选    | 用户扫码时会被回调，**只会回调一次**。回调参数 userInfo 只包含了用户昵称和头像，开发者可以将其展示在扫码框中。                                                                                                                                                                                                                                                                                        |
| onSuccess \<function>         | 可选    | 用户同意授权之后将会被回调，**只会回调一次**，**之后轮询结束**。参数 data 是一个字典，包含两个字段：ticket 和 userInfo。出于安全性考虑，默认情况下，userInfo 只会包含昵称（nickname）和头像（photo）两个字段，开发者也可以在后台配置使其返回完整用户信息，详情见自定义配置。 ticket 可以用来换取完整的用户信息，相关接口见下文。                                                                                                                                                        |
| onCancel \<function>          | 可选    | 用户取消授权只会会被回调，**只回调一次，之后轮询结束。**                                                                                                                                                                                                                                                                                                                        |
| onExpired \<function>         | 可选    | 二维码失效时被回调，**只回调一次，之后轮询结束。**                                                                                                                                                                                                                                                                                                                           |
| onError \<function>           | 可选    | 每次查询失败时都会回调。回调参数 data 示例如 {"code": 2241,"message": "二维码不存在","data": null}**。**&#x5B8C;整错误代码请见完整错误代码&#x9875;**。**                                                                                                                                                                                                                                      |
| onQRCodeLoad \<function>      | 可选    | 二维码首次成功加载时回调。回调参数 qrcode 是一个字典，包含两个字段：qrcodeId、qrcodeUrl。                                                                                                                                                                                                                                                                                             |
| onQRCodeShow \<function>      | 可选    | 二维码首次出现在页面上时回调。回调参数 qrcode 同上。                                                                                                                                                                                                                                                                                                                        |
| onQRCodeLoadFaild \<function> | 可选    | 二维码加载失败时会被回调。                                                                                                                                                                                                                                                                                                                                         |

下面是一个最简的调用：一共只需要 5 行代码。

```javascript
authing.qrlogin.startScanning({
  onSuccess(userInfo) {
    localStorage.setItem('token', userInfo.token);
  }
})
```

扫码组件示例：

![](/files/-LxAZcnLCrduAO8tUqQY)

## 生成二维码

Authing.qrlogin.geneCode(options)

```javascript
authing.geneQRCode({ 
    scene: "APP_AUTH", 
    userDefinedData: {
        customVar1: "xxx", 
        customVar2: "xxx"   
    }
})
```

| 参数              | 可选/必选 | 说明                    |
| --------------- | ----- | --------------------- |
| scene           | 必选    | 场景值。为常量值，填 APP\_AUTH。 |
| userDefinedData | 可选    | 自定义数据。类型为任意对象。        |

请求示例：

```javascript
const res = await authing.qrlogin.geneCode({ 
    scene: "APP_AUTH", 
    userDefinedData: {
        customVar1: "xxx", 
        customVar2: "xxx"   
    }
})
if(res.code === 200){
    const { qrcodeId, qrcodeUrl } = res.data
}
```

返回结果：

```javascript
{
    "code": 200, // 200 表示正常
    "message": "生成二维码成功",
    "data": {
        "qrcodeId": "5e061366445c9985e5bf890a", // 二维码 ID
        "qrcodeUrl": "https://usercontents.authing.co/qrcode/5e061366445c9985e5bf890a.png" // 二维码链接
    }
}
```

使用[在线二维码解码工具](https://cli.im/deqr) 查看二维码数据如下：其中 customVar1 和 customVar2 保存到了 userDefinedData 对象中。

```
{ 
   "scene":"APP_AUTH",
   "qrcodeId":"5e06c47da6b47a9433f8b3be",
   "userPoolId":"59f86b4832eb28071bdd9214",
   "createdAt":"2019-12-28T02:57:01.697Z",
   "expireAt":"2019-12-28T02:59:01.697Z",
   "userDefinedData":{ 
      "customVar1":"xxx",
      "customVar2":"xxx"
   }
}
```

## 查询二维码状态

Authing.qrlogin.checkCodeStatus(options)

```javascript
const res = await authing.qrlogin.checkCodeStatus({
    qrcodeId: "xxxxx",
    scene: "APP_AUTH"
})
```

| 参数       | 可选/必选 | 说明                    |
| -------- | ----- | --------------------- |
| qrcodeId | 必选    | 二维码 ID                |
| scene    | 必选    | 场景值。为常量值，填 APP\_AUTH。 |

请求示例：

```javascript
authing.qrlogin.checkCodeStatus({
    qrcodeId: "xxxxx",
    scene: "APP_AUTH"
}).then(res => {
    console.log(res)
})
```

返回结果示例：

```javascript
{
  "code": 200, // 业务状态码，200 表示正常
  "message": "查询二维码状态成功",
  "data": {
    "qrcodeId": "5e061489445c9985e5bf890d",
    "scanned": false,
    "expired": false,
    "success": false,
    "canceled": false,
    "status": 0,
    "userInfo": {},
    "ticket": "", // 该字段不一定会有
    "description": "二维码还没有被扫描"
  }
}
```

请求结果字段说明：

* scanned: 二维码是否已经被扫描
* expired：二维码是否已经过期
* success：用户是否成功授权
* canceled：用户是否取消授权
* status
  * 0: 未知状态，即还未扫码，或者已经扫码但用户还没有点击同意授权或者取消授权。
  * 1: 用户同意授权
  * -1: 用户取消授权
* userInfo:
  * 默认情况下，在用户扫码之后，会包含昵称（nickname）和头像（photo）两个字段
  * 开发者也可以配置返回完整用户信息（包括登录凭证 token）
* ticket：用于换取完整用户资料。**此字段只有在用户同意授权之后才会出现。**&#x8BE6;情见下文。

## 轮询二维码状态

Authing.qrlogin.pollingCodeStatus(options)

> 此接口为 checkQRCodeStatus 的封装。

```javascript
authing.qrlogin.pollingCodeStatus({
  qrcodeId,
  scene: 'APP_AUTH',
  interval: 1000,
  onPollingStart: function (intervalNum) {
    console.log("Start polling for qrcode status: ", intervalNum)
    // clearInterval(intervalNum)
  },
  onResult: function (res) {
    console.log("Got qrcode latest result: ", res)
  },
  onScanned: function (userInfo) {
    console.log("User scanned qrcode: ", userInfo)
  },
  onSuccess: function (data) {
    const { ticket, userInfo } = data;
    console.log(`User confirmed authorization: ticket = ${ticket}`, userInfo)
    // 获取用户信息
    authing.exchangeUserInfoWithTicket(ticket).then(res => {
      const { code } = res
      if (code === 200) {
        console.log("Exchange userInfo success: ", res)
      } else {
        console.log("Exchange userInfo failed: ", res)
      }
    })
  },
  onCancel: function () {
    console.log("User canceled authorization")
  },
  onExpired: function () {
    console.log("QRCode has expired.")
  },
  onError: function (data) {
    console.log("Chcek qrcode status failed: ", data)
  }
})

```

参数说明：

| 参数                         | 可选/必选 | 说明                                                                                                                                                                                                                                                                                                                                                    |
| -------------------------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| onPollingStart \<function> | 可选    | <p>轮询开始时会被回调，<strong>只会回调一次</strong>。回调参数 intervalNum 为 setInterval 返回的数值，可使用 clearInterval 停止轮询。</p><p>如：clearInterval(intervalNum)</p>                                                                                                                                                                                                              |
| onResult                   | 可选    | <p>每次查询获取到数据都会回调，参数 res 示例如下：</p><p><code>{    "code": 200,    "message": "查询二维码状态成功",    "data": {        "qrcodeId": "5e05f6027fde537d950f7da9",        "scanned": false,        "expired": false,        "success": false,        "canceled": false,        "status": 0,        "userInfo": {},        "description": "二维码还没有被扫描"    }}</code></p> |
| onScanned                  | 可选    | 用户扫码时会被回调，**只会回调一次**。回调参数 userInfo 只包含了用户昵称和头像，开发者可以将其展示在扫码框中。                                                                                                                                                                                                                                                                                        |
| onSuccess                  | 可选    | 用户同意授权之后将会被回调，**只会回调一次**，**之后轮询结束**。参数 data 是一个字典，包含两个字段：ticket 和 userInfo。出于安全性考虑，默认情况下，userInfo 只会包含昵称（nickname）和头像（photo）两个字段，开发者也可以在后台配置使其返回完整用户信息，详情见自定义配置。 ticket 可以用来换取完整的用户信息，相关接口见下文。                                                                                                                                                        |
| onCancel                   | 可选    | 用户取消授权只会会被回调，**只回调一次，之后轮询结束。**                                                                                                                                                                                                                                                                                                                        |
| onExpired                  | 可选    | 二维码失效时被回调，**只回调一次，之后轮询结束。**                                                                                                                                                                                                                                                                                                                           |
| onError                    | 可选    | 每次查询失败时都会回调。回调参数 data 示例如 {"code": 2241,"message": "二维码不存在","data": null}**。**&#x5B8C;整错误代码请见完整错误代码&#x9875;**。**                                                                                                                                                                                                                                      |

![一个完整的扫码流程](/files/-LxAd5kLhxyhERFVea9Y)

## ticket 换用户信息接口

Authing.qrlogin.exchangeUserInfo(ticket)

```javascript
const res = authing.qrlogin.exchangeUserInfo(ticket)
```

参数说明：

| 参数     | 可选/必选 | 说明                   |
| ------ | ----- | -------------------- |
| ticket | 必选    | 从二维码状态查询接口得到的 ticket |

调用示例：

```javascript
authing.qrlogin.exchangeUserInfo(ticket).then(res => {
  const { code } = res
  if (code === 200) {
    console.log("Exchange userInfo success: ", res.data)
  } else {
    console.log("Exchange userInfo failed: ", res.data)
  }
})
```

返回结果：

```javascript
{ 
   "code":200,
   "message":"换取用户信息成功",
   "data":{ 
      "_id":"5e05bbf2d51b3761d5c71070",
      "email":"983132@qq.com",
      "emailVerified":false,
      "oauth":"",
      "registerMethod":"default:username-password",
      "username":"983132@qq.com",
      "nickname":"",
      "company":"",
      "photo":"https://usercontents.authing.co/authing-avatar.png",
      "token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImVtYWlsIjoiOTgzMTMyQHFxLmNvbSIsImlxxxxxxxxx",
      "phone":"",
      "tokenExpiredAt":"2020-01-11T08:08:18.000Z",
      "loginsCount":1,
      "lastIP":"::1",
      "signedUp":"2019-12-27T08:08:18.115Z",
      "blocked":false,
      "isDeleted":false
   }
}
```

{% hint style="info" %}
注意：默认情况下，此接口**只允许在服务器端调用**，即需要使用用户池密钥初始化之后。

ticket 默认有效时间为 300 s。

开发者可在 [Authing 控制台](https://authing.cn/dashboard) **基础配置** -> **基础设置** -> **App 扫码登录 Web 自定义配置** 处修改。**详情见自定义配置项页。**
{% endhint %}


---

# Agent Instructions: 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:

```
GET https://authing.gitbook.io/authing/scan-qrcode/app-qrcode/web-side-sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
