【笔记】Go语言实现将微信登录作为第三方登录

前言

Go语言实现将微信登录作为第三方登录

准备工作

获取微信登录二维码

<appid>:在微信开放平台获取的appid
<redirect_uri>:在微信开放平台获取的redirect_uri
<uuid>:为了防止跨站脚本攻击而生成的字符串,用于校验,可以根据业务需求生成UUID

1
https://open.weixin.qq.com/connect/qrconnect?appid=<appid>&redirect_uri=<redirect_uri>&response_type=code&scope=snsapi_login&state=<uuid>
  • 成功登录后会自动跳转到预先指定的URIredirect_uri,并携带Get请求参数codestate

redirect_uri:必须是在微信开放平台的管理员后台预先设置好的,而不能任意填写,且必须是以http://(或https://)开头的完整URI
code:在之后用于识别用户身份
state:实际上就是获取微信登录二维码请求中携带的state

获取用户信息

<appid>:在微信开放平台获取的appid
<secret>:在微信开放平台获取的secret
<code>:上一步获取的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)

// GetAccessTokenResponseEntity 获取AccessToken响应实体
type GetAccessTokenResponseEntity struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
OpenID string `json:"openid"`
Scope string `json:"scope"`
UnionID string `json:"unionid"`
}

// VerificationAccessTokenResponseEntity 校验AccessToken响应实体
type VerificationAccessTokenResponseEntity struct {
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
}

// GetWechatUserInformationResponseEntity 获取微信用户信息响应实体
type GetWechatUserInformationResponseEntity struct {
OpenID string `json:"openid"`
Nickname string `json:"nickname"`
Sex int `json:"sex"`
Language string `json:"language"`
City string `json:"city"`
Province string `json:"province"`
Country string `json:"country"`
HeadImageUrl string `json:"headimgurl"`
PrivilegeList []string `json:"privilege"`
UnionID string `json:"unionid"`
}

func main() {
var appID = "<appid>"
var secret = "<secret>"
var code = "<code>"

// 通过Code获取用户的OpenID和AccessToken
var openID string
var accessToken string
if res, err := http.Get(fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&grant_type=authorization_code&code=%s", appID, secret, code)); err != nil {
log.Panicln(err.Error())
} else {
defer res.Body.Close()
if res, err := ioutil.ReadAll(res.Body); err != nil {
log.Panicln(err.Error())
} else {
var response GetAccessTokenResponseEntity
if err := json.Unmarshal(res, &response); err != nil {
log.Panicln(err.Error())
}
openID = response.OpenID
accessToken = response.AccessToken
}
}

// 校验AccessToken是否有效
if res, err := http.Get(fmt.Sprintf("https://api.weixin.qq.com/sns/auth?openid=%s&access_token=%s", openID, accessToken)); err != nil {
log.Panicln(err.Error())
} else {
defer res.Body.Close()
if res, err := ioutil.ReadAll(res.Body); err != nil {
log.Panicln(err.Error())
} else {
var response VerificationAccessTokenResponseEntity
if err := json.Unmarshal(res, &response); err != nil {
log.Panicln(err.Error())
}
if response.ErrCode != 0 {
log.Panicln(response.ErrMsg)
}
}
}

// 获取微信用户信息
var wechatUserInformation GetWechatUserInformationResponseEntity
if res, err := http.Get(fmt.Sprintf("https://api.weixin.qq.com/sns/userinfo?openid=%s&access_token=%s", openID, accessToken)); err != nil {
err.Error()
} else {
defer res.Body.Close()
if res, err := ioutil.ReadAll(res.Body); err != nil {
err.Error()
} else {
var response GetWechatUserInformationResponseEntity
if err := json.Unmarshal(res, &response); err != nil {
err.Error()
}
wechatUserInformation = response
}
}

log.Println(wechatUserInformation)
}

完成

参考文献

微信官方文档——开放平台
腾讯云开发者社区——双鬼带单
CSDN——小昱同学