281 lines
8.3 KiB
Go
281 lines
8.3 KiB
Go
package login
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"likedream-goframe/internal/application/cookiejar"
|
|
"likedream-goframe/internal/application/cpdaily/cryptoutil"
|
|
"likedream-goframe/internal/application/cpdaily/school"
|
|
"likedream-goframe/internal/application/httpclient"
|
|
"likedream-goframe/internal/common/cst"
|
|
"likedream-goframe/internal/common/errors"
|
|
"likedream-goframe/internal/utils"
|
|
"net/http"
|
|
"net/url"
|
|
|
|
"github.com/bytedance/sonic"
|
|
"github.com/samber/oops"
|
|
"resty.dev/v3"
|
|
)
|
|
|
|
type cpdailySmsCommonResponse[T any] struct {
|
|
ErrCode int `json:"errCode"`
|
|
ErrMsg string `json:"errMsg"`
|
|
Data T `json:"data"`
|
|
}
|
|
|
|
func (c *cpdailySmsCommonResponse[T]) EnsureSuccess() {
|
|
if c.ErrCode != 0 {
|
|
utils.OkOrPanic(errors.NewBusinessError(503, c.ErrMsg))
|
|
}
|
|
}
|
|
|
|
type CpdailySmsSendSmsData struct {
|
|
Countdown int `json:"countdown"`
|
|
TipMsg string `json:"tipMsg"`
|
|
Status int `json:"status"`
|
|
CookieJar *cookiejar.PersistCookieJar `json:"-"`
|
|
}
|
|
|
|
type CpdailySmsLoginByCodeData struct {
|
|
AuthID string `json:"authId"`
|
|
AuthStatus string `json:"authStatus"`
|
|
CompleteUserInfoStatus string `json:"completeUserInfoStatus"`
|
|
DeviceExceptionMsg string `json:"deviceExceptionMsg"`
|
|
DeviceStatus string `json:"deviceStatus"`
|
|
FirstLogin bool `json:"firstLogin"`
|
|
Mobile string `json:"mobile"`
|
|
MsgTip string `json:"msgTip"`
|
|
Name string `json:"name"`
|
|
OpenID string `json:"openId"`
|
|
PersonID string `json:"personId"`
|
|
SessionToken string `json:"sessionToken"`
|
|
Status string `json:"status"`
|
|
TenantID string `json:"tenantId"`
|
|
TenantName string `json:"tenantName"`
|
|
Tgc string `json:"tgc"`
|
|
TgcStatus string `json:"tgcStatus"`
|
|
UserID string `json:"userId"`
|
|
UserType string `json:"userType"`
|
|
}
|
|
|
|
func NewSms(deviceID string) *SmsLoginHandler {
|
|
return &SmsLoginHandler{
|
|
deviceID: deviceID,
|
|
}
|
|
}
|
|
|
|
func NewSmsWithoutDeviceID() *SmsLoginHandler {
|
|
return &SmsLoginHandler{
|
|
deviceID: "",
|
|
}
|
|
}
|
|
|
|
type SmsLoginHandler struct {
|
|
deviceID string
|
|
client *resty.Client
|
|
}
|
|
|
|
func (s *SmsLoginHandler) SendSms(ctx context.Context, phone string) *CpdailySmsSendSmsData {
|
|
jar := cookiejar.NewPersistCookieJar()
|
|
|
|
phoneEncrypted := base64.StdEncoding.EncodeToString(cryptoutil.AesEncrypt([]byte(phone)))
|
|
s.client = httpclient.NewCpdailyClient()
|
|
req := s.client.
|
|
SetCookieJar(jar).
|
|
R().
|
|
SetContext(utils.NewCpdailySmsContextBuilder().
|
|
WithDeviceID(s.deviceID).
|
|
Build(ctx)).
|
|
SetBody(map[string]string{
|
|
"a": phoneEncrypted,
|
|
"b": cryptoutil.EncryptVersion,
|
|
})
|
|
|
|
setSmsRequestHeaders(ctx, req)
|
|
|
|
resp, e := req.
|
|
Post("https://mobile.campushoy.com/app/auth/authentication/mobile/messageCode/v-8222")
|
|
utils.OkOrPanic(e, oops.WithContext(ctx).Wrap)
|
|
|
|
respJson := utils.ReadJson[cpdailySmsCommonResponse[CpdailySmsSendSmsData]](resp.Body)
|
|
respJson.EnsureSuccess()
|
|
|
|
respJson.Data.CookieJar = jar
|
|
|
|
return &respJson.Data
|
|
}
|
|
|
|
func (s *SmsLoginHandler) LoginByCode(ctx context.Context, phone, code string, jar http.CookieJar) *CpdailySmsLoginByCodeData {
|
|
payload := map[string]any{
|
|
"d": code,
|
|
"e": "CPDAILY",
|
|
"c": phone,
|
|
"f": "86",
|
|
}
|
|
|
|
payloadString, e := sonic.Marshal(payload)
|
|
utils.OkOrPanic(e, oops.WithContext(ctx).Wrap)
|
|
|
|
encryptedPayload := cryptoutil.AesEncrypt(payloadString)
|
|
encodedPayload := base64.StdEncoding.EncodeToString(encryptedPayload)
|
|
|
|
payload = map[string]any{
|
|
"a": encodedPayload,
|
|
"b": cryptoutil.EncryptVersion,
|
|
}
|
|
s.client = httpclient.NewCpdailyClient()
|
|
s.client.SetCookieJar(jar)
|
|
req := s.client.R().
|
|
SetBody(payload).
|
|
SetContext(utils.NewCpdailySmsContextBuilder().
|
|
WithDeviceID(s.deviceID).
|
|
Build(ctx))
|
|
setSmsRequestHeaders(ctx, req)
|
|
|
|
resp, e := req.
|
|
Post("https://mobile.campushoy.com/app/auth/authentication/mobileLogin/v-8222")
|
|
utils.OkOrPanic(e, oops.WithContext(ctx).Wrap)
|
|
|
|
respJson := utils.ReadJson[cpdailySmsCommonResponse[string]](resp.Body)
|
|
respJson.EnsureSuccess()
|
|
|
|
data := decodeData[CpdailySmsLoginByCodeData](respJson.Data)
|
|
|
|
return &data
|
|
}
|
|
|
|
func (s *SmsLoginHandler) SetLoginCookie(ctx context.Context, jar http.CookieJar, loginData *CpdailySmsLoginByCodeData) {
|
|
detail := school.GetSchoolDetail(ctx, loginData.TenantID)
|
|
|
|
getCookieUrl := fmt.Sprintf("%s%s", detail.WecloudUrl, "/wec-im-group/group/imUserToken/getImUserToken")
|
|
|
|
cookieMap := map[string]any{
|
|
"AMP2": []map[string]any{
|
|
{
|
|
"path": "/",
|
|
"value": loginData.SessionToken,
|
|
"domain": "",
|
|
"name": "sessionToken",
|
|
},
|
|
},
|
|
"AMP1": []map[string]any{
|
|
{
|
|
"path": "/",
|
|
"value": loginData.SessionToken,
|
|
"domain": "",
|
|
"name": "sessionToken",
|
|
},
|
|
},
|
|
}
|
|
|
|
ampTokenString, e := sonic.Marshal(cookieMap)
|
|
utils.OkOrPanic(e, oops.WithContext(ctx).Wrap)
|
|
|
|
ampTokenEncrypted := cryptoutil.DesEncrypt(ampTokenString, cryptoutil.Normal)
|
|
ampToken := base64.StdEncoding.EncodeToString(ampTokenEncrypted)
|
|
|
|
// 设置cookie到jar: clientType=cpdaily_student; tenantId=ahnu; standAlone=0; sessionToken=5e55bfa7-d17e-4f5a-a06d-99a649855521;
|
|
targetSchoolUrl, e := url.Parse(detail.WecloudUrl)
|
|
utils.OkOrPanic(e, oops.WithContext(ctx).Wrap)
|
|
targetApiUrl, e := url.Parse("https://api.campushoy.com")
|
|
utils.OkOrPanic(e, oops.WithContext(ctx).Wrap)
|
|
|
|
cookieNameValues := map[string]string{
|
|
"clientType": "cpdaily_student",
|
|
"tenantId": detail.Id,
|
|
"standAlone": "0",
|
|
"sessionToken": loginData.SessionToken,
|
|
}
|
|
|
|
for name, value := range cookieNameValues {
|
|
cookie := &http.Cookie{
|
|
Name: name,
|
|
Value: value,
|
|
}
|
|
|
|
jar.SetCookies(targetSchoolUrl, []*http.Cookie{cookie})
|
|
jar.SetCookies(targetApiUrl, []*http.Cookie{cookie})
|
|
}
|
|
s.client.SetRedirectPolicy(resty.FlexibleRedirectPolicy(50))
|
|
req := s.client.R().
|
|
SetHeader("AmpCookies", ampToken).
|
|
SetContext(ctx)
|
|
|
|
ctx = utils.NewCpdailySmsContextBuilder().
|
|
WithDeviceID(s.deviceID).
|
|
WithTenantID(detail.Id).
|
|
WithSessionToken(loginData.SessionToken).
|
|
Build(ctx)
|
|
|
|
setSmsRequestHeaders(ctx, req)
|
|
|
|
resp, e := req.
|
|
Get(getCookieUrl)
|
|
utils.OkOrPanic(e, oops.WithContext(ctx).Wrap)
|
|
|
|
respJson := utils.ReadJson[cpdailySmsCommonResponse[any]](resp.Body)
|
|
respJson.EnsureSuccess()
|
|
}
|
|
|
|
func decodeData[T any](encodedData string) T {
|
|
decodedBytes, e := base64.StdEncoding.DecodeString(encodedData)
|
|
utils.OkOrPanic(e)
|
|
|
|
decryptedBytes := cryptoutil.AesDecrypt(decodedBytes)
|
|
|
|
result := utils.ReadJson[T](bytes.NewReader(decryptedBytes))
|
|
|
|
return result
|
|
}
|
|
|
|
func setSmsRequestHeaders(ctx context.Context, request *resty.Request) {
|
|
sessionToken, ok := ctx.Value(cst.CtxCpdailySessionToken).(string)
|
|
if ok {
|
|
encryptedSessionToken := cryptoutil.DesEncrypt([]byte(sessionToken), cryptoutil.Normal)
|
|
encodedSessionToken := base64.StdEncoding.EncodeToString(encryptedSessionToken)
|
|
request.SetHeader("SessionToken", encodedSessionToken)
|
|
request.SetHeader("sessionTokenKey", encodedSessionToken)
|
|
} else {
|
|
request.SetHeader("SessionToken", sessionToken)
|
|
request.SetHeader("sessionTokenKey", sessionToken)
|
|
}
|
|
|
|
deviceId, _ := ctx.Value(cst.CtxCpdailyDeviceID).(string)
|
|
|
|
cpdailyInfoDetail := map[string]any{
|
|
"deviceId": deviceId,
|
|
"systemName": "android",
|
|
"userId": "",
|
|
"appVersion": "9.8.8",
|
|
"model": "Unknown",
|
|
"lon": "0",
|
|
"lat": "0",
|
|
"cpdailyVersion": "9.8.8",
|
|
"systemVersion": "11",
|
|
}
|
|
|
|
cpdailyInfoStr, e := sonic.Marshal(cpdailyInfoDetail)
|
|
utils.OkOrPanic(e, oops.WithContext(ctx).Wrap)
|
|
|
|
encryptedCpdailyInfo := cryptoutil.DesEncrypt(cpdailyInfoStr, cryptoutil.Normal)
|
|
encodedCpdailyInfo := base64.StdEncoding.EncodeToString(encryptedCpdailyInfo)
|
|
|
|
request.SetHeaders(map[string]string{
|
|
"clientType": "cpdaily_student",
|
|
"deviceType": "1",
|
|
"CpdailyClientType": "CPDAILY",
|
|
"CpdailyStandAlone": "0",
|
|
"User-Agent": "Mozilla/5.0 (Linux; Android 11; Redmi Note 8 Pro Build/RP1A.230805.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36 cpdaily/9.8.8 wisedu/9.8.8",
|
|
"CpdailyInfo": encodedCpdailyInfo,
|
|
})
|
|
}
|
|
|
|
func (s *SmsLoginHandler) GetCookieString() string {
|
|
cookieJar := s.client.CookieJar()
|
|
serializableJar := cookieJar.(*cookiejar.PersistCookieJar)
|
|
return serializableJar.Serialize()
|
|
}
|