231 lines
5.3 KiB
Go
231 lines
5.3 KiB
Go
package moguding
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"likedream-goframe/internal/application/httpclient"
|
|
"likedream-goframe/internal/application/moguding/cryptoutil"
|
|
"likedream-goframe/internal/application/moguding/entity"
|
|
"likedream-goframe/internal/framework/logger"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
"resty.dev/v3"
|
|
)
|
|
|
|
const (
|
|
// API 基础地址
|
|
ApiBase = "https://api.moguding.net:9000"
|
|
// 登录接口
|
|
ApiLogin = ApiBase + "/session/user/v6/login"
|
|
// 获取实习计划接口
|
|
ApiGetPlan = ApiBase + "/practice/plan/v3/getPlanByStu"
|
|
// 打卡签到接口
|
|
ApiSign = ApiBase + "/attendence/clock/v4/save"
|
|
)
|
|
|
|
type MogudingClient struct {
|
|
client *resty.Client
|
|
user *entity.MogudingUser
|
|
}
|
|
|
|
// NewMogudingClient 创建蘑菇钉客户端
|
|
func NewMogudingClient(ctx context.Context) *MogudingClient {
|
|
client := httpclient.NewMogudingClient()
|
|
|
|
return &MogudingClient{
|
|
client: client,
|
|
user: &entity.MogudingUser{},
|
|
}
|
|
}
|
|
|
|
// Login 登录
|
|
func (c *MogudingClient) Login(ctx context.Context, username, password string) error {
|
|
if username == "" || password == "" {
|
|
return fmt.Errorf("账号或密码不能为空")
|
|
}
|
|
|
|
// 加密账号密码
|
|
encryptedPhone, err := cryptoutil.Encrypt(username)
|
|
if err != nil {
|
|
logger.Logger.Error("加密账号失败", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
encryptedPassword, err := cryptoutil.Encrypt(password)
|
|
if err != nil {
|
|
logger.Logger.Error("加密密码失败", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
// 加密时间戳
|
|
timestamp := fmt.Sprintf("%d", time.Now().UnixMilli())
|
|
encryptedTime, err := cryptoutil.Encrypt(timestamp)
|
|
if err != nil {
|
|
logger.Logger.Error("加密时间戳失败", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
// 构造登录请求
|
|
loginDto := entity.LoginDto{
|
|
Phone: encryptedPhone,
|
|
Password: encryptedPassword,
|
|
T: encryptedTime,
|
|
LoginType: "android",
|
|
}
|
|
|
|
// 发送登录请求
|
|
resp, err := c.client.R().
|
|
SetBody(loginDto).
|
|
Post(ApiLogin)
|
|
|
|
if err != nil {
|
|
logger.Logger.Error("登录请求失败", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
// 解析响应
|
|
var loginResp entity.LoginResponse
|
|
if err := json.Unmarshal(resp.Bytes(), &loginResp); err != nil {
|
|
logger.Logger.Error("解析登录响应失败", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
if loginResp.Code != 200 {
|
|
return fmt.Errorf("登录失败:%s", loginResp.Msg)
|
|
}
|
|
|
|
// 保存用户信息
|
|
c.user.Username = username
|
|
c.user.Password = password
|
|
c.user.UserId = loginResp.Data.UserId
|
|
c.user.Token = loginResp.Data.Token
|
|
c.user.UserType = loginResp.Data.UserType
|
|
|
|
logger.Logger.Info("登录成功",
|
|
zap.String("userId", c.user.UserId),
|
|
zap.String("userType", c.user.UserType))
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetPlanId 获取实习计划 ID
|
|
func (c *MogudingClient) GetPlanId(ctx context.Context) error {
|
|
if c.user.Token == "" {
|
|
return fmt.Errorf("请先登录")
|
|
}
|
|
|
|
// 计算签名
|
|
signStr := c.user.UserId + c.user.UserType
|
|
sign := cryptoutil.Sign2(signStr)
|
|
|
|
// 发送请求
|
|
resp, err := c.client.R().
|
|
SetHeaders(map[string]string{
|
|
"roleKey": c.user.UserType,
|
|
"sign": sign,
|
|
"authorization": c.user.Token,
|
|
}).
|
|
SetBody(map[string]string{"state": ""}).
|
|
Post(ApiGetPlan)
|
|
|
|
if err != nil {
|
|
logger.Logger.Error("获取 PlanId 请求失败", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
// 解析响应
|
|
var planResp entity.PlanResponse
|
|
if err := json.Unmarshal(resp.Bytes(), &planResp); err != nil {
|
|
logger.Logger.Error("解析 PlanId 响应失败", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
if planResp.Code != 200 {
|
|
return fmt.Errorf("获取 PlanId 失败:%s", planResp.Msg)
|
|
}
|
|
|
|
if len(planResp.Data) == 0 {
|
|
return fmt.Errorf("未找到实习计划")
|
|
}
|
|
|
|
// 保存第一个计划信息
|
|
c.user.PlanId = planResp.Data[0].PlanId
|
|
c.user.PlanName = planResp.Data[0].PlanName
|
|
|
|
logger.Logger.Info("获取 PlanId 成功",
|
|
zap.String("planId", c.user.PlanId),
|
|
zap.String("planName", c.user.PlanName))
|
|
|
|
return nil
|
|
}
|
|
|
|
// Sign 打卡签到
|
|
func (c *MogudingClient) Sign(ctx context.Context, signReq *entity.SignRequest) error {
|
|
if c.user.Token == "" {
|
|
return fmt.Errorf("请先登录")
|
|
}
|
|
|
|
if c.user.PlanId == "" {
|
|
return fmt.Errorf("请先获取实习计划")
|
|
}
|
|
|
|
// 设置默认值
|
|
if signReq.PlanId == "" {
|
|
signReq.PlanId = c.user.PlanId
|
|
}
|
|
if signReq.Device == "" {
|
|
signReq.Device = "Android"
|
|
}
|
|
if signReq.Type == "" {
|
|
signReq.Type = "START"
|
|
}
|
|
|
|
// 计算签名
|
|
signStr := signReq.Device + signReq.Type + signReq.PlanId + c.user.UserId + signReq.Address
|
|
sign := cryptoutil.Sign2(signStr)
|
|
|
|
// 发送请求
|
|
resp, err := c.client.R().
|
|
SetHeaders(map[string]string{
|
|
"roleKey": c.user.UserType,
|
|
"sign": sign,
|
|
"authorization": c.user.Token,
|
|
}).
|
|
SetBody(signReq).
|
|
Post(ApiSign)
|
|
|
|
if err != nil {
|
|
logger.Logger.Error("签到请求失败", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
// 解析响应
|
|
var signResp entity.SignResponse
|
|
if err := json.Unmarshal(resp.Bytes(), &signResp); err != nil {
|
|
logger.Logger.Error("解析签到响应失败", zap.Error(err))
|
|
return err
|
|
}
|
|
|
|
if signResp.Code != 200 {
|
|
return fmt.Errorf("签到失败:%s", signResp.Msg)
|
|
}
|
|
|
|
logger.Logger.Info("签到成功",
|
|
zap.String("type", signReq.Type),
|
|
zap.String("address", signReq.Address))
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetUser 获取用户信息
|
|
func (c *MogudingClient) GetUser() *entity.MogudingUser {
|
|
return c.user
|
|
}
|
|
|
|
// SetUser 设置用户信息(用于恢复登录状态)
|
|
func (c *MogudingClient) SetUser(user *entity.MogudingUser) {
|
|
c.user = user
|
|
}
|