daShangDao_kfz_goods_pricing/internal/service/kfz_service.go

153 lines
4.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"strings"
"time"
"github.com/parnurzeal/gorequest"
)
// ErrPasswordWrong 账号或密码错误,不再重试
var ErrPasswordWrong = errors.New("孔网账号或密码错误")
// UserInfo 孔网用户信息结构体
type UserInfo struct {
UserID int64 `json:"userId"` // 用户ID
Nickname string `json:"nickname"` // 用户昵称
Mobile string `json:"mobile"` // 手机号
Token string `json:"token"` // token
}
/*
* 孔网登录
* param username[string] 孔网用户名
* param password[string] 孔网密码
* return token,错误信息
*/
func OutKfzLogin(username, password string) (string, error) {
if username == "" || password == "" {
return "", fmt.Errorf("请输入用户名和密码!")
}
formData := map[string]string{
"loginName": username,
"loginPass": password,
"returnUrl": "http://user.kongfz.com/",
}
loginUrl := "https://login.kongfz.com/Pc/Login/account"
resp, body, errs := gorequest.New().
Post(loginUrl).
Set("Content-Type", "application/x-www-form-urlencoded").
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36").
Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8").
Send(formData).
Timeout(15 * time.Second).
End()
if len(errs) > 0 {
return "", fmt.Errorf("登录请求失败: %v", errs)
}
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("登录失败(HTTP状态码: %d)", resp.StatusCode)
}
cookie := resp.Header.Get("Set-Cookie")
if strings.Contains(body, "window.location.href='https://login.kongfz.cn/Pc/Session/rsync") {
if cookie == "" {
return "", fmt.Errorf("登录成功但未获取到Cookie")
}
if strings.Contains(cookie, "PHPSESSID=") {
token := strings.Split(strings.Split(cookie, "PHPSESSID=")[1], ";")[0]
return token, nil
}
return "", fmt.Errorf("登录失败: 未找到PHPSESSID")
}
var res struct {
Status bool `json:"status"`
ErrCode int `json:"errCode"`
ErrInfo string `json:"errInfo"`
}
if err := json.Unmarshal([]byte(body), &res); err == nil {
if res.ErrCode == 1001 || res.ErrCode == 1005 {
return "", fmt.Errorf("账号或密码错误!")
}
if res.ErrInfo != "" {
return "", fmt.Errorf("登录失败: %s", res.ErrInfo)
}
}
return "", fmt.Errorf("登录失败,未知错误!")
}
/*
* 获取孔网用户信息
*/
func OutKfzGetUserInfo(token string) (*UserInfo, error) {
url := "https://user.kongfz.com/User/Index/getUserInfo/"
resp, body, errs := gorequest.New().
Get(url).
Set("Cookie", fmt.Sprintf("PHPSESSID=%s", token)).
Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36").
Set("Accept", "application/json, text/plain, */*").
Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8").
Timeout(15 * time.Second).
End()
if len(errs) > 0 {
return nil, fmt.Errorf("查询用户信息请求失败: %v", errs)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("HTTP错误: %s", resp.Status)
}
var userInfo struct {
Status bool `json:"status"`
Data struct {
UserID int64 `json:"userId"`
Nickname string `json:"nickname"`
Mobile string `json:"mobile"`
}
}
if err := json.Unmarshal([]byte(body), &userInfo); err != nil {
return nil, fmt.Errorf("解析JSON失败: %w", err)
}
user := &UserInfo{}
if !userInfo.Status {
return nil, fmt.Errorf("获取用户失败!")
}
user.UserID = userInfo.Data.UserID
user.Nickname = userInfo.Data.Nickname
user.Mobile = userInfo.Data.Mobile
return user, nil
}
// TryRefreshToken 尝试用保存的密码重新登录更新token。成功返回新token
// 密码错误时返回 ErrPasswordWrong
func (s *GoodsService) TryRefreshToken(tokenID int64, username, password string) (string, error) {
log.Printf("[RefreshToken] 开始重新登录: username=%s, tokenID=%d", username, tokenID)
newToken, err := OutKfzLogin(username, password)
if err != nil {
log.Printf("[RefreshToken] 重新登录失败: username=%s, 错误=%v", username, err)
if strings.Contains(err.Error(), "账号或密码错误") {
return "", ErrPasswordWrong
}
return "", err
}
// 更新数据库中的token
if err := s.tokenRepository.UpdateToken(tokenID, newToken); err != nil {
log.Printf("[RefreshToken] 更新Token失败: id=%d, 错误=%v", tokenID, err)
return "", err
}
log.Printf("[RefreshToken] 重新登录并更新Token成功: username=%s, tokenID=%d", username, tokenID)
return newToken, nil
}