> For the complete documentation index, see [llms.txt](https://authing.gitbook.io/authing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://authing.gitbook.io/authing/scan-qrcode/app-qrcode/web-side-sdk.md).

# 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 %}
