# 微信登录

此社会化登录方式提供 GitHub Demo :https://github.com/authing/AuthingIOSDemo (opens new window)

示例 Demo :

# 准备工作

你一共需要准备以下内容:

  1. Authing 开发者账号
  2. 申请微信移动应用 (opens new window)
  3. 配置 iOS Universal Links (针对 iOS 应用, 需开通 Apple Developer 账号 (opens new window))
  4. 在 Authing 控制台填入微信移动应用信息

从微信 WechatOpenSDK 1.8.6 开始,iOS 移动应用需填写 Universal Links 信息。如果你是要开发 Android 应用或者已经配置好了,可跳过此节。Apple 官方文档请见此 (opens new window)

# 配置 apple-app-site-association 文件

在 Apple Developer 控制台 Membership 页面找到自己的 Team ID:

在 Xcode Targets -> Signing & Capabilities 中找到 Bundle Identifier:

接下来创建 apple-app-site-association 文件:

假设你的 Team ID 为 xxxxxxx, Bundle Identifier 为 com.example.exampleApp, 设置 Universal Link 的 Path 为/native/*, 则 apple-app-site-association 如下:

假设你的 Team ID 为 xxxxxxx, Bundle Identifier 为 com.example.exampleApp, 设置 Universal Link 的 Path 为/native/*, 则 apple-app-site-association 如下:

{
	"applinks": {
		"apps": [],
		"details": [
			{
				"appIDs": [ "xxxxxxx.com.example.exampleApp" ],
				"paths": [ "/native/*" ]
			}
		]
	}
}

你需要将此文件部署到你的域名的 .well-known/apple-app-site-association 链接下,如你的域名为 example.com,则需要通过 https://example.com/.well-known/apple-app-site-association 访问到该文件。以下几点需要注意:

  • 必须使用 https
  • apple-app-site-association 需要是一个合法的 JSON 文件,但是没有 .json 后缀
  • content-type 需要设置为 application/json
  • paths 请使用 * 通配符,微信要求。

以下是一个 nginx 配置示例:(这里将 apple-app-site-association 文件放与某个 .well-known 文件夹下)

server {
  listen 80;
  listen 443 ssl;

  server_name authing.cn;

  ssl_certificate /mnt/cerm/client/1_authing.cn_bundle.crt;
  ssl_certificate_key /mnt/cerm/client/2_authing.cn.key;
  ssl_session_timeout 5m;
  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_prefer_server_ciphers on;


  location /.well-known {
    alias /path/to/your/.well-known/folder;
    try_files $uri $uri/ =404;
  }
}

# 在 Xcode 中配置 Associated Domains

加下来在 Xcode 中配置 Associated Domains。 在 Xcode Targets -> Signing & Capabilities 页面点击右上角的 +Capability :

选择 Associated Domains:

假设你的域名是 example.com, 则填入 applinks:example.com :

假设你的域名为 example.com,Path 为 /native/*在手机上安装了你的 App 之后,使用 Safari 浏览器访问 https://example.com/native/,网上拉动网页,你应该能看到你的 App:

再访问 https://example.com/native/xxx,依旧可以看到。

# 在 Authing 控制台配置微信移动应用信息

在 Authing 控制台 连接身份源 -> 社会化登录 页面找到“微信移动应用“:

填入你的移动应用 AppID 和 AppSecret:

AppID 和 AppSecret 可在微信开放平台 管理中心 - 移动应用 - 应用详情 页面看到:

# 正式接入

# 接入 WechatOpenSDK

此部分请按照微信官方文档 (opens new window)指引接入 WechatOpenSDK,如果遇到问题,这里提供一个 Swift Demo App 供开发者参考:https://github.com/authing/AuthingIOSDemo (opens new window) .

# 发起登录请求

成功接入 SDK 之后,你应该能成功打开微信获取用户授权并获取到 authorization code:

下面是发起微信登录请求代码示例( Swift):

func loginByWechat() {
    let req = SendAuthReq()
    req.scope = "snsapi_userinfo" //获取用户信息
    req.state = "123" //随机值即可,这里用时间戳
    WXApi.send(req)
}

你可以在 AppDelegate 或 SceneDelegate 的 onResp 方法获取到授权码 code, 如下图所示:

# 接收微信回调数据获取 code

下面是一个示例代码(Swift 语言):

func onResp(_ resp: BaseResp) {

    debugPrint(resp)

    // 微信登录请求信息
    if resp.isKind(of: SendAuthResp.self) {
        if resp.errCode == 0 && resp.type == 0{
            let response = resp as! SendAuthResp

            // 微信 authorication_code
            let code = response.code
            debugPrint("code: " ,code)
        }
    }
}

# 换取用户信息

用户同意收取获取到 code 之后,需要调用 Authing 的接口获取用户信息:

GET
https://core.authing.cn/connection/social/wechat:mobile/:userPoolId/callback?app_id=YOUR_APP_ID

使用 code 换取用户信息。

Path Paramter
userPoolId
REQUIRED
string

用户池 ID

Query Parameters
code
REQUIRED
string

微信返回给 APP 的 code

app_id
OPTIONAL
string

应用 ID,选填。如果传了应用 ID,获取的用户信息中的 token 将是使用该应用签发的 id_token;如果不传,用户信息中的 token 将是 Authing 自己签发的 token。推荐调用此接口时传 app_id

country
OPTIONAL
string

微信返回给 APP 的 country

lang
OPTIONAL
string

微信返回给 APP 的 lang

state
OPTIONAL
string

微信返回给 APP 的 state

200: OK

Authing 返回给开发者的用户信息是经过加工过后的 Authing 用户标准字段,非微信文档中说明的用户字段。详细用户字段释义请见:用户资料字段释义

{
  id: '5f8fd6016c3224112598aaaa',
  email: null,
  emailVerified: false,
  unionid: 'o0pqE6Fbr5M-exSu_PeL_sjwN44U',
  openid: 'osJ4Ys7kderNmGP7qgjIiNSLPm94',
  oauth: '{"openid":"osJ4Ys7kderNmGP7qgjIiNSLPm94","nickname":"Bob","sex":1,"language":"zh_CN","city":"Haidian","province":"Beijing","country":"China","headimgurl":"https://thirdwx.qlogo.cn/mmopen/vi_32/Z6XlHHTohpQQMqUjDsWibCaRH6RZiafrbibBEVzffMp7Co2kGbUmfo9ln80tOPYv9RRICXtP9MNqN0Eib9KZ0OFt3w/132","privilege":[],"unionid":"o0pqE6Fbr5M-exSu_PeL_sjwN44U"}',
  registerSource: [ 'social:wechat:mobile' ],
  username: null,
  nickname: 'Bob',
  company: null,
  photo: 'https://thirdwx.qlogo.cn/mmopen/vi_32/Z6XlHHTohpQQMqUjDsWibCaRH6RZiafrbibBEVzffMp7Co2kGbUmfo9ln80tOPYv9RRICXtP9MNqN0Eib9KZ0OFt3w/132',
  token: 'USER_TOKEN',
  phone: null,
  tokenExpiredAt: 2020-11-05T07:05:05.393Z,
  loginsCount: 3,
  lastIP: undefined,
  signedUp: 2020-10-21T06:32:33.073Z,
  blocked: false,
  isDeleted: false
}

示例代码(Swift):

let url = "\(AuthingServerHost)/connection/social/wechat:mobile/\(UserPoolId)/callback?code=\(code!)"
AF.request(url).responseString { response in
    let resp = convertToDictionary(text: response.value!)!
    
    // Authing 业务状态码, 200 表示成功
    let code = resp["code"]! as! Int
    let message = resp["message"]! as! String
    if code == 200 {
        let data = resp["data"] as! [String:Any]
        debugPrint("Data: \(data)")
    } else {
        debugPrint("Message: ", message)
    }
}

# 完成接入

恭喜你,此时已经接入了微信移动应用登录。获取到用户信息之后,你可以得到登录凭证 token,你可以在后续的 API 请求中携带上此 token, 然后在后端接口中根据此 token 区分不同用户,详情请见验证 token