# 快速接入

## Web 端

在 Web 端，我们推荐使用Authing 提供的 SDK。安装流程请查看 SDK for JavaScript。

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

安装完成后，可以新建一个 Web 项目，然后复制以下代码：

```javascript
const Authing = require('authing-js-sdk');

// 初始化 Authing SDK for JavaScript
const authing = new Authing({
    userPoolId: 'your_userpool_id',
});

// 调用 APP 扫码登录的方法，此方法将生成一个用于扫码登录的图片和相关提示信息
authing.qrlogin.startScanning({
  onSuccess(data) {
    alert('扫码成功，请打开控制台查看用户信息')
    console.log(data);
    const {ticket, userInfo} = data;
    // 存储 token 到 localStorage 中
    localStorage.setItem('token', userInfo.token);
  }
})
```

运行后将自动生成用于 APP 扫码登录的二维码：

![](/files/-LxAfS2CLKKFZs4HgJj9)

扫码成功之后，Authing 将会回调开发者传入的 onSuccess，回调的参数中包含了 ticket 和 userInfo，ticket 可以用来换取用户信息。

如果你想自定义 UI ，了解如何使用 ticket 换取用户信息，可以查看：

{% content-ref url="/pages/-LxAMKPvgo3B0sXOK09O" %}
[Web 端 SDK](/authing/scan-qrcode/app-qrcode/web-side-sdk.md)
{% endcontent-ref %}

{% content-ref url="/pages/-LxANMmu4W9qIURKpWGE" %}
[完整接口列表](/authing/scan-qrcode/app-qrcode/full-api-list.md)
{% endcontent-ref %}

## 移动端

Authing 生成的二维码中包含的原始信息为一串字符串，转换为 JSON 后如下：

```javascript
{
    "scene": "APP_AUTH",
    "qrcodeId": "5e05f0c57fde537d950f7da5",
    "userPoolId": "5e04ae0d5f3cee22fb37612b",
    "createdAt": "2019-12-27T11:53:41.260Z",
    "expireAt": "2019-12-27T11:55:41.260Z",
    "userDefinedData": { "hello": "world" }
}
```

字段含义如下：

* scene：场景值，APP\_AUTH 表示 APP 扫码登录。
* qrcodeId：二维码 ID，移动端之后根据此 ID 完成确认扫码、同意授权、取消授权（注意，这里的“确认扫码”意思是移动端标记此二维码已经被扫描，但是用户还没有采取同意或取消操作。有关二维码的详细状态，请见完整接口列表页）
* userPoolId：用户池 ID。
* createdAt：二维码创建时间。
* expireAt：二维码过期时间。
* userDefinedData：用户自定义字段。了解如何添加自定义数据，请见完整接口列表页。

> 有关如何在 IOS 中扫描并解析二维码的内容，可以查看[这篇文章](https://github.com/darkjoin/Learning/wiki/使用AVFoundation读取二维码)。

要实现 APP 扫描登录 Web 端，首先要求 APP 端用户处于登录状态（这是理所当然的），调用相关接口的时候要带上终端用户的 token。移动端一共需要用到三个接口：

* 确认扫码
* 同意授权
* 取消授权

> 要了解这个三个接口的详情，请见完整接口列表页。

下面以 Objective-C 为例，实现同意授权登录：

* api 地址为：<http://oauth.authing.cn/oauth/scan-qrcode/confirm>
* 第 9 行在请求头带上了用户登录凭证。

```objectivec
- (void) ConfirmAuthorization:(NSString *) qrcodeId{    
    NSURL * api =[NSURL URLWithString:@"http://oauth.authing.cn/oauth/scan-qrcode/confirm"];
    NSDictionary *bodyDict = @{
        @"qrcodeId": qrcodeId,
    };
    NSData *body = [NSJSONSerialization dataWithJSONObject:bodyDict options:kNilOptions error:nil];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:api];
    request.HTTPMethod = @"POST";
    [request setValue:self.USER_TOKEN forHTTPHeaderField:@"Authorization"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setHTTPBody:body];
    
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        if(httpResponse.statusCode == 200)
        {
            NSError *parseError = nil;
            NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
            NSLog(@"The response is - %@",responseDictionary);
            NSInteger code = [[responseDictionary objectForKey:@"code"] integerValue];
            if(code == 200)
            {
                NSLog(@"SUCCESS");
            }
            else
            {
                NSLog(@"FAILURE");
            }
        }
        else
        {
            NSLog(@"Network Error");
        }
    }];
    
    [dataTask resume];
}
```

### 用户扫码成功后

移动端确认授权之后，Web 将会看到相关提示。

![](/files/-LxAhxSxn12kXUPVO_eV)

这个时候，整个登录流程也就完成了，开发者可以使用 ticket 去换取用户信息了。

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

返回结果示例：

```objectivec
{ 
   "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
   }
}
```

恭喜你，此时已经接入了 App  扫码登录。获取到用户信息之后，你可以得到登录凭证 token，你可以在后续的 API 请求中携带上此 token, 然后在后端接口中根据此 token 区分不同用户，详情请见[验证 token](/authing/advanced/verify-jwt-token.md#yan-zheng-authing-qian-fa-de-token)。


---

# 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/quick-start.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.
