mirror of
https://github.com/MirageNetwork/MirageToolServer.git
synced 2025-09-26 19:41:18 +08:00
169 lines
3.8 KiB
Go
169 lines
3.8 KiB
Go
package main
|
||
|
||
import (
|
||
"crypto/rand"
|
||
"encoding/json"
|
||
"net/http"
|
||
"time"
|
||
|
||
"github.com/rs/zerolog/log"
|
||
)
|
||
|
||
type fetchQRRes struct {
|
||
Status string `json:"status"`
|
||
Code string `json:"code"`
|
||
}
|
||
|
||
// 由蜃境服务器拉取小程序码或者授权状态
|
||
func (tool *MirageTool) fetchQR(
|
||
w http.ResponseWriter,
|
||
r *http.Request,
|
||
) {
|
||
reqData := make(map[string]string)
|
||
json.NewDecoder(r.Body).Decode(&reqData)
|
||
if user, ok := tool.QRCache.Get(reqData["state"]); ok {
|
||
if user != nil { // 该state码已被扫码授权过
|
||
authCode := tool.GenAuthCode()
|
||
tool.AuthCodeCache.Set(authCode, user, 2*time.Minute)
|
||
res := fetchQRRes{
|
||
Status: "OK",
|
||
Code: authCode,
|
||
}
|
||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||
w.WriteHeader(http.StatusOK)
|
||
err := json.NewEncoder(w).Encode(&res)
|
||
if err != nil {
|
||
log.Error().
|
||
Caller().
|
||
Err(err).
|
||
Msg("Failed to write response")
|
||
}
|
||
return
|
||
}
|
||
// 该state码已拉取过二维码但未被扫码授权过
|
||
res := fetchQRRes{
|
||
Status: "Wait",
|
||
Code: "",
|
||
}
|
||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||
w.WriteHeader(http.StatusOK)
|
||
err := json.NewEncoder(w).Encode(&res)
|
||
if err != nil {
|
||
log.Error().
|
||
Caller().
|
||
Err(err).
|
||
Msg("Failed to write response")
|
||
}
|
||
return
|
||
}
|
||
|
||
// 该state码还未获取过二维码
|
||
miniQR := tool.genMiniProgramQR(reqData["state"])
|
||
if miniQR != "" {
|
||
// 需注意,cache里以state为索引记录的是user信息,而不进行二维码缓存
|
||
tool.QRCache.Set(reqData["state"], nil, 2*time.Minute)
|
||
|
||
res := fetchQRRes{
|
||
Status: "New",
|
||
Code: miniQR,
|
||
}
|
||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||
w.WriteHeader(http.StatusOK)
|
||
err := json.NewEncoder(w).Encode(&res)
|
||
if err != nil {
|
||
log.Error().
|
||
Caller().
|
||
Err(err).
|
||
Msg("Failed to write response")
|
||
}
|
||
return
|
||
}
|
||
res := fetchQRRes{
|
||
Status: "Error",
|
||
Code: "",
|
||
}
|
||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||
w.WriteHeader(http.StatusOK)
|
||
err := json.NewEncoder(w).Encode(&res)
|
||
if err != nil {
|
||
log.Error().
|
||
Caller().
|
||
Err(err).
|
||
Msg("Failed to write response")
|
||
}
|
||
return
|
||
}
|
||
|
||
type authQRRes struct {
|
||
Status string
|
||
}
|
||
|
||
// 小程序上用户完成授权确认
|
||
func (tool *MirageTool) authQR(
|
||
w http.ResponseWriter,
|
||
r *http.Request,
|
||
) {
|
||
reqData := make(map[string]string)
|
||
json.NewDecoder(r.Body).Decode(&reqData)
|
||
openID := tool.exchangeCodeToIDs(reqData["logincode"])
|
||
user := tool.GetUserByID(openID)
|
||
if user == nil {
|
||
res := authQRRes{
|
||
Status: "NoUser",
|
||
}
|
||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||
w.WriteHeader(http.StatusOK)
|
||
err := json.NewEncoder(w).Encode(&res)
|
||
if err != nil {
|
||
log.Error().
|
||
Caller().
|
||
Err(err).
|
||
Msg("Failed to write response")
|
||
}
|
||
return
|
||
}
|
||
stateCode := reqData["state"]
|
||
userInterface, expiration, ok := tool.QRCache.GetWithExpiration(stateCode)
|
||
if !ok || userInterface != nil {
|
||
res := authQRRes{
|
||
Status: "StateExpire",
|
||
}
|
||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||
w.WriteHeader(http.StatusOK)
|
||
err := json.NewEncoder(w).Encode(&res)
|
||
if err != nil {
|
||
log.Error().
|
||
Caller().
|
||
Err(err).
|
||
Msg("Failed to write response")
|
||
}
|
||
return
|
||
}
|
||
tool.QRCache.Set(stateCode, *user, expiration.Sub(time.Now()))
|
||
res := authQRRes{
|
||
Status: "OK",
|
||
}
|
||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||
w.WriteHeader(http.StatusOK)
|
||
err := json.NewEncoder(w).Encode(&res)
|
||
if err != nil {
|
||
log.Error().
|
||
Caller().
|
||
Err(err).
|
||
Msg("Failed to write response")
|
||
}
|
||
return
|
||
}
|
||
|
||
func (t *MirageTool) GenAuthCode() string {
|
||
const letterBytes = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||
b := make([]byte, 64)
|
||
|
||
index := make([]byte, 64)
|
||
rand.Read(index)
|
||
for i := 0; i < 64; i++ {
|
||
b[i] = letterBytes[index[i]&63]
|
||
}
|
||
return string(b)
|
||
}
|