forked from SheltonZhu/115driver
/
qrcode.go
135 lines (114 loc) · 3.37 KB
/
qrcode.go
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package driver
import (
"fmt"
"strconv"
"github.com/go-resty/resty/v2"
qrcode "github.com/skip2/go-qrcode"
)
type QRCodeSession struct {
// The raw data of QRCode, caller should use third-party tools/libraries
// to convert it into QRCode matrix or image.
QrcodeContent string `json:"qrcode"`
Sign string `json:"sign"`
Time int64 `json:"time"`
UID string `json:"uid"`
}
// QRCode get QRCode matrix or image.
func (s *QRCodeSession) QRCode() ([]byte, error) {
return qrcode.Encode(s.QrcodeContent, qrcode.Medium, 256)
}
// QRCodeByApi get QRCode matrix or image by api.
func (s *QRCodeSession) QRCodeByApi() ([]byte, error) {
resp, err := resty.New().R().Get(fmt.Sprintf(ApiQrcodeImage, s.UID))
return resp.Body(), err
}
// QRCodeStart starts a QRCode login session.
func (c *Pan115Client) QRCodeStart() (*QRCodeSession, error) {
result := QRCodeTokenResp{}
resp, err := c.NewRequest().
SetResult(&result).
ForceContentType("application/json;charset=UTF-8").
Get(ApiQrcodeToken)
if err = CheckErr(err, &result, resp); err != nil {
return nil, err
}
return &result.Data, nil
}
// QRCodeLogin logins user through QRCode with web app.
// You SHOULD call this method ONLY when `QRCodeStatus.IsAllowed()` is true.
func (c *Pan115Client) QRCodeLogin(s *QRCodeSession) (*Credential, error) {
return c.QRCodeLoginWithApp(s, LoginAppWeb)
}
type LoginApp string
const (
LoginAppWeb LoginApp = "web"
LoginAppAndroid LoginApp = "android"
LoginAppIOS LoginApp = "ios"
LoginAppLinux LoginApp = "linux"
LoginAppMac LoginApp = "mac"
LoginAppWindows LoginApp = "windows"
LoginAppTV LoginApp = "tv"
// LoginAppIPad LoginApp = "ipad"
)
// QRCodeLoginWithApp logins user through QRCode with specified app.
// You SHOULD call this method ONLY when `QRCodeStatus.IsAllowed()` is true.
func (c *Pan115Client) QRCodeLoginWithApp(s *QRCodeSession, app LoginApp) (*Credential, error) {
result := QRCodeLoginResp{}
req := c.NewRequest().
SetFormData(map[string]string{
"account": s.UID,
"app": string(app),
}).
ForceContentType("application/json;charset=UTF-8").
SetResult(&result)
resp, err := req.Post(fmt.Sprintf(ApiQrcodeLoginWithApp, app))
if err = CheckErr(err, &result, resp); err != nil {
return nil, err
}
return &result.Data.Credential, nil
}
type QRCodeStatus struct {
Msg string `json:"msg"`
Status int `json:"status"`
Version string `json:"version"`
}
func (s *QRCodeStatus) IsWaiting() bool {
return s.Status == 0
}
func (s *QRCodeStatus) IsScanned() bool {
return s.Status == 1
}
func (s *QRCodeStatus) IsAllowed() bool {
return s.Status == 2
}
func (s *QRCodeStatus) IsExpired() bool {
return s.Status == -1
}
func (s *QRCodeStatus) IsCanceled() bool {
return s.Status == -2
}
/*
QRCodeStatus represents the status of a QRCode session.
There are 4 possible status values:
- Waiting
- Scanned
- Allowed
- Canceled
*/
func (c *Pan115Client) QRCodeStatus(s *QRCodeSession) (*QRCodeStatus, error) {
result := QRCodeStatusResp{}
req := c.NewRequest().
SetQueryParams(map[string]string{
"uid": s.UID,
"time": strconv.FormatInt(s.Time, 10),
"sign": s.Sign,
"_": Now().String(),
}).
ForceContentType("application/json;charset=UTF-8").
SetResult(&result)
resp, err := req.Get(ApiQrcodeStatus)
if err = CheckErr(err, &result, resp); err != nil {
return nil, err
}
return &result.Data, nil
}