Compare commits

...

4 Commits

Author SHA1 Message Date
sugarBecomer 8889be8ca2 🐛 经纬度修复 2025-11-22 19:57:28 +08:00
sugarBecomer 6d58222143 ✨ 修复cookie问题 2025-11-22 15:50:31 +08:00
sugarBecomer c3019b741c 🐛 甘肃农业大学适配 2025-11-22 15:28:13 +08:00
sugarBecomer b5b2103372 🐛 学校登录模式更改 2025-11-22 14:11:10 +08:00
12 changed files with 137 additions and 24 deletions
+20 -1
View File
@@ -1,6 +1,10 @@
package v1
import "github.com/gogf/gf/v2/frame/g"
import (
"likedream-goframe/internal/framework/captcha"
"github.com/gogf/gf/v2/frame/g"
)
type CpSchoolListReq struct {
g.Meta `path:"/school" method:"get" tags:"CpSchool" summary:"获取cp学校列表"`
@@ -14,6 +18,21 @@ type CpUserAddReq struct {
SchoolId string `json:"school_id"`
Email string `json:"email" v:"email|regex:^.*@qq\\.com$#邮箱格式不正确|必须是QQ邮箱"`
}
type LoginGetCode struct {
g.Meta `path:"/user/getCode" method:"post" tags:"CpUser" summary:"获取手机号登录验证码"`
Mobile string `json:"mobile" v:"required#手机号不能为空"`
CaptchaKey string `json:"captchaKey" v:"required#验证码不能不能为空"`
Dots []captcha.ConfirmData `json:"dots" v:"required#验证码不能为空"`
}
type AddByCode struct {
g.Meta `path:"/user/addByCode" method:"post" tags:"CpUser" summary:"手机号登录"`
CaptchaKey string `json:"captchaKey" v:"required#验证码不能不能为空"`
Dots []captcha.ConfirmData `json:"dots" v:"required#验证码不能为空"`
Mobile string `json:"mobile" v:"required#手机号不能为空"`
Code string `json:"code"`
}
type CpUserConfirmAddReq struct {
g.Meta `path:"/user/confirm" method:"post" tags:"CpUser" summary:"多因子确认添加cp用户"`
Key string `json:"key"`
@@ -0,0 +1,15 @@
package cryptoutil
import (
"encoding/base64"
"testing"
)
func TestAesDecrypt(t *testing.T) {
str := "szFn6zAbjjU="
decodeString, _ := base64.StdEncoding.DecodeString(str)
decrypt := AesDecrypt(decodeString)
t.Log(string(decrypt))
encrypt := AesEncrypt([]byte("c9fe4f05-e1ed-4c15-aeb4-b05fa9bfb16f"))
t.Log(base64.StdEncoding.EncodeToString(encrypt))
}
@@ -13,6 +13,9 @@ func GetCpdailyLoginBySchoolInfo(ctx context.Context, info *school.SchoolDetailI
// 安徽建筑大学
case "ahjzu":
return NewAhjzu(ctx)
// 河北石油职业技术大学
case "01e270d1-00e2-4ce9-b0af-5d5fbd462b8a":
return NewIap(ctx)
default:
if info.IsIap() {
return NewIap(ctx)
@@ -0,0 +1,51 @@
package login
import (
"context"
"encoding/base64"
"likedream-goframe/internal/application/cpdaily/cryptoutil"
"likedream-goframe/internal/application/httpclient"
"github.com/bytedance/sonic"
"resty.dev/v3"
)
type CpdailyCodeLogin struct {
client *resty.Client
}
func NewCode(ctx context.Context) *CpdailyCodeLogin {
return &CpdailyCodeLogin{
client: httpclient.NewCpdailyClient(),
}
}
func (c *CpdailyCodeLogin) GetLoginCode(mobile string) {
mobileBytes := cryptoutil.AesEncrypt([]byte(mobile))
mobile = base64.StdEncoding.EncodeToString(mobileBytes)
c.client.R().SetBody(map[string]string{
"a": mobile,
"b": "first_v4",
}).Post("https://mobile.campushoy.com/app/auth/authentication/mobile/messageCode/v-8222")
}
func (c *CpdailyCodeLogin) LoginByCode(mobile, code string) {
type loginStruct struct {
C string `json:"c"`
D string `json:"d"`
E string `json:"e"`
F string `json:"f"`
}
data := loginStruct{
C: mobile,
D: code,
E: "CPDAILY",
F: "86",
}
marshal, _ := sonic.Marshal(data)
marshalBytes := cryptoutil.AesEncrypt(marshal)
c.client.R().SetBody(map[string]string{
"a": base64.StdEncoding.EncodeToString(marshalBytes),
"b": "first_v4",
}).Post("https://mobile.campushoy.com/app/auth/authentication/mobileLogin/v-8222")
}
+3 -12
View File
@@ -32,7 +32,7 @@ func ActivateSession(ctx context.Context, host string, client *resty.Client) {
defer sessionResponse.Body.Close()
if !sessionResponse.IsSuccess() {
if !sessionResponse.IsSuccess() && sessionResponse.StatusCode() != 502 {
utils.OkOrPanic(errors.NewBusinessError(503, "Session激活失败"),
func(err error) error {
return oops.
@@ -87,10 +87,7 @@ func ActivateSession(ctx context.Context, host string, client *resty.Client) {
}
func CookieEnabled(ctx context.Context, host string, client *resty.Client) bool {
client.SetRedirectPolicy(resty.FlexibleRedirectPolicy(20))
defer func() {
client.SetRedirectPolicy(resty.NoRedirectPolicy())
}()
client.SetRedirectPolicy(resty.NoRedirectPolicy())
host = strings.TrimSuffix(host, "/")
sessionResponse, err := client.R().
WithContext(ctx).
@@ -98,13 +95,7 @@ func CookieEnabled(ctx context.Context, host string, client *resty.Client) bool
Post(fmt.Sprintf("%s/wec-counselor-attendance-apps/student/attendance/getStuAttendacesInOneDay", host))
utils.OkOrPanic(err)
defer sessionResponse.Body.Close()
if !sessionResponse.IsSuccess() {
return sessionResponse.StatusCode() == 405
}
responseContentType := sessionResponse.Header().Get("Content-Type")
return strings.Contains(responseContentType, "json")
return sessionResponse.StatusCode() != 302
}
func GetClient(ctx context.Context, cookie string) *resty.Client {
@@ -65,7 +65,7 @@ func GetSchoolDetail(ctx context.Context, tenantId string) SchoolDetailInfo {
var ret SchoolDetailInfo
err := sonic.Unmarshal([]byte(redisResult.Val()), &ret)
utils.OkOrPanic(err)
return ret
return parseSpecialSchool(ret)
}
response, err := httpclient.Cpdaily.Clone(ctx).R().
SetHeaders(map[string]string{
@@ -105,5 +105,13 @@ func GetSchoolDetail(ctx context.Context, tenantId string) SchoolDetailInfo {
Wrap(errors.NewBusinessError(503, "学校ID不存在").Decorate("empty school detail")))
}
client.Set(ctx, cst2.RedisSchoolInfo+tenantId, ret[0], time.Duration(cst2.RedisSchoolInfoExpire)*time.Second)
return ret[0]
return parseSpecialSchool(ret[0])
}
func parseSpecialSchool(s SchoolDetailInfo) SchoolDetailInfo {
// 甘肃农业大学
if s.Id == "gsau" {
s.WecloudUrl = "https://fdm.gsau.edu.cn"
}
return s
}
@@ -495,6 +495,11 @@ func (c *CpdailyAutoSignTask) FillCustomForm(ctx context.Context, form map[strin
lon = v.Content
case "address":
address = v.Content
case "latAndLon":
{
res := strings.Split(v.Content, ",")
lat, lon = res[1], res[0]
}
}
}
@@ -528,7 +528,7 @@ func (c *CpdailySleepCheckTask) FillCustomForm(ctx context.Context, form map[str
case "latAndLon":
{
res := strings.Split(v.Content, ",")
lat, lon = res[0], res[1]
lat, lon = res[1], res[0]
}
}
@@ -61,3 +61,12 @@ func (c CpUserCtrlV1) AuthorizeRandom(ctx context.Context, req *v1.CpUserAuthori
defer utils.Pass(&err)
return service.Global.CpUser.AuthorizeRandom(ctx, req), nil
}
func (c CpUserCtrlV1) LoginGetCode(ctx context.Context, req *v1.LoginGetCode) (res *utils.Response[any], err error) {
defer utils.Pass(&err)
return service.Global.CpUser.LoginGetCode(ctx, req), nil
}
func (c CpUserCtrlV1) AddByCode(ctx context.Context, req *v1.AddByCode) (res *utils.Response[any], err error) {
defer utils.Pass(&err)
return service.Global.CpUser.AddByCode(ctx, req), nil
}
@@ -25,4 +25,8 @@ type ICpUserCtrlV1 interface {
AuthorizeConfirm(ctx context.Context, req *v1.CpUserAuthorizeConfirmReq) (*utils.Response[any], error)
// 随机授权
AuthorizeRandom(ctx context.Context, req *v1.CpUserAuthorizeRandomReq) (res *utils.Response[any], err error)
// 手机登录获取验证码
LoginGetCode(ctx context.Context, req *v1.LoginGetCode) (*utils.Response[any], error)
AddByCode(ctx context.Context, req *v1.AddByCode) (*utils.Response[any], error)
}
@@ -94,14 +94,13 @@ func (c *CpdailyTaskHandler) ProcessTask(ctx context.Context, task *asynq.Task)
schoolDetail := school.GetSchoolDetail(ctx, targetTask.Edges.CpUser.SchoolID)
cookie := targetTask.Edges.CpUser.Cookie
restyClient := login.GetClient(ctx, cookie)
//if !login.CookieEnabled(ctx, schoolDetail.WecloudUrl, restyClient) {
// 定时任务强制登录并更新cookie
loginExecutor := login.GetCpdailyLoginBySchoolInfo(ctx, &schoolDetail)
loginExecutor.Login(ctx, &schoolDetail, targetTask.Edges.CpUser.Username, targetTask.Edges.CpUser.Password)
cookie = loginExecutor.GetCookieString()
db.Global.CpUser.UpdateOneID(targetTask.Edges.CpUser.ID).SetCookie(cookie).ExecX(ctx)
restyClient = login.GetClient(ctx, cookie)
//}
if !login.CookieEnabled(ctx, schoolDetail.WecloudUrl, restyClient) {
loginExecutor := login.GetCpdailyLoginBySchoolInfo(ctx, &schoolDetail)
loginExecutor.Login(ctx, &schoolDetail, targetTask.Edges.CpUser.Username, targetTask.Edges.CpUser.Password)
cookie = loginExecutor.GetCookieString()
db.Global.CpUser.UpdateOneID(targetTask.Edges.CpUser.ID).SetCookie(cookie).ExecX(ctx)
restyClient = login.GetClient(ctx, cookie)
}
// 获取任务执行handler
taskExecutor := task2.GetCpdailyTaskService(ctx, targetTask.TaskType, restyClient, schoolDetail)
+9
View File
@@ -43,6 +43,7 @@ func (v CpUserServiceV1) Add(ctx context.Context, req *v1.CpUserAddReq) *utils.R
SaveX(ctx)
return utils.SuccessWithMsg("添加成功")
}
func (v CpUserServiceV1) ConfirmAdd(ctx context.Context, req *v1.CpUserConfirmAddReq) *utils.Response[any] {
user := utils.GetUserInfoFromCtx(ctx)
schoolInfo, err := redis.GetClient().Get(ctx, req.Key+":school").Result()
@@ -171,3 +172,11 @@ func (v CpUserServiceV1) AuthorizeRandom(ctx context.Context, req *v1.CpUserAuth
db.Global.CpUser.UpdateOne(cpUser).SetMobileCode(utils.UUID()).SetMobileType(cpuser.MobileTypeRandom).ExecX(ctx)
return utils.SuccessWithMsg("已改为随机设备码")
}
func (v CpUserServiceV1) LoginGetCode(ctx context.Context, req *v1.LoginGetCode) *utils.Response[any] {
}
func (v CpUserServiceV1) AddByCode(ctx context.Context, req *v1.AddByCode) *utils.Response[any] {
}