123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367 |
- package login
- import (
- "context"
- "crypto/tls"
- "fmt"
- "git.listensoft.net/tool/jspkit/common"
- "git.listensoft.net/tool/jspkit/common/lxhttp"
- "git.listensoft.net/tool/jspkit/common/models"
- "git.listensoft.net/tool/jspkit/logger"
- "git.listensoft.net/tool/jspkit/taxerr"
- "github.com/go-rod/rod"
- "github.com/go-rod/rod/lib/proto"
- "github.com/go-rod/rod/lib/utils"
- "github.com/tidwall/gjson"
- "net/http"
- "net/url"
- "strings"
- "time"
- )
- // MakeLoginData 生成登录信息
- func MakeLoginData(ctx context.Context, info models.CompanyInfo) (jsonData map[string]interface{}) {
- loginMethod := "QRCODE"
- TaxNo := info.TaxNo
- if info.Dlfs == "代理登录" {
- loginMethod = "MOBILE"
- }
- website := "etax"
- if ctxValue := ctx.Value("website"); ctxValue != nil {
- if websiteStr, ok := ctxValue.(string); ok {
- website = websiteStr
- }
- }
- // 拆分登陆方式
- switch info.Area {
- case "hubei", "guangdong", "zhejiang", "tianjin":
- if info.Dlfs == "新版登录" {
- loginMethod = "ACCOUNT"
- }
- if info.Dlfs == "代理登录" && (info.Area == "guangdong" || info.Area == "zhejiang" || info.Area == "tianjin") {
- loginMethod = "ACCOUNT"
- }
- default:
- if info.Dlfs == "新版登录" {
- loginMethod = "QRCODE"
- }
- }
- changeCreditCode := ""
- loginType := "QIYE"
- if info.Dlfs == "代理登录" {
- changeCreditCode = info.TaxNo
- info.TaxNo = info.IdNo
- loginType = "DAILI"
- TaxNo = info.IdNo
- }
- jsonData = map[string]interface{}{
- "userInfo": map[string]string{
- "ComName": info.ComName,
- "Name": info.Area + ".pro",
- "CreditCode": TaxNo,
- "Account": info.Tel,
- "Password": info.Zzrmm,
- "dailiCreditCode": "",
- "changeCreditCode": changeCreditCode,
- },
- "areaName": info.Area,
- "loginMethod": loginMethod,
- "loginType": loginType,
- "website": website,
- "source": "taxRobot",
- //"proxies": proxies,
- }
- return
- }
- // PostLoin 登录函数
- func PostLoin(jsonR []byte, headder map[string]string, info models.CompanyInfo) (response []byte, err error) {
- f := 0
- //begin:
- //logger.Info(string(jsonR))
- c := lxhttp.NewHttpClient() //http://dppt.jsptax.com:81
- if info.Dlfs == "代理登录" {
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //忽略证书校验
- }
- c = &http.Client{
- Timeout: time.Duration(400 * time.Second),
- Transport: tr,
- }
- }
- response, err = lxhttp.PostByteReader(c, ETaxServe+"/api/login", jsonR, headder, nil)
- if err != nil {
- logger.Error(err.Error())
- if f < 6 {
- utils.Sleep(5)
- f++
- //goto begin
- }
- return response, taxerr.NewWebStuckTitle(info.Cscsts)
- }
- if strings.Contains(string(response), "Sorry, the page you are looking for is currently unavailable") || strings.Contains(string(response), "二维码已失效") ||
- strings.Contains(string(response), "ReadTimeoutError") || strings.Contains(string(response), "ProtocolError") {
- if f <= 3 {
- f++
- //goto begin
- }
- return nil, taxerr.New("新版税局登陆超时")
- }
- // 登录繁忙等30s
- if strings.Contains(string(response), "税局服务繁忙,请5分钟后重试") {
- utils.Sleep(30)
- if f <= 3 {
- f++
- //goto begin
- }
- }
- if (gjson.GetBytes(response, "msg").String() != "" && gjson.GetBytes(response, "msg").String() != "[登录成功~]") ||
- (gjson.GetBytes(response, "status").String() != "ok") {
- Str := gjson.GetBytes(response, "error").String()
- if Str == "" {
- // {"status":"false","msg":"[切换身份失败, 不存在用户91370203MA3RCTAU0X~]"}
- // {"status":"false","msg":"[切换身份失败, 连续认证错误次数过多,您的账号已被锁定。建议您直接使用“忘记密码”修改密码后重新登录或等待次日零时自动解锁。~]"}
- Str = gjson.GetBytes(response, "msg").String()
- }
- if Str == "" {
- Str = "新版税局登陆超时2"
- }
- if strings.Contains(Str, `请调用发送验证码`) && info.Dlfs == "新版登录" {
- common.DeleteTpassCookie(info)
- }
- if strings.Contains(Str, `请调用发送验证码`) && info.Dlfs == "代理登录" {
- err = taxerr.NewUserV3(`代理登录已掉线`, "请保证设备或app在线后重新发起任务")
- return
- }
- // 税局登录失败['bool' object is not subscriptable] 这个错误直接返回连续认证错误次数过多
- if strings.Contains(Str, `税局登录失败['bool' object is not subscriptable]`) {
- err = taxerr.FormatLoginError("税局登录失败[连续认证错误次数过多,您的账号已被锁定。建议您直接使用“忘记密码”修改密码后重新登录或等待次日零时自动解锁。]")
- return
- }
- err = taxerr.FormatLoginError(Str)
- return
- }
- return
- }
- func RsCookie(url string) (ck []*http.Cookie, uri string) {
- return nil, url
- if lxhttp.NeedRsvmp(url) {
- ck, _ = lxhttp.Rsvmp(url)
- return ck, url
- }
- return nil, url
- }
- // RefreshCookieBase 刷新增值税cookie和财报cookie
- func refreshCookieBase(client *http.Client, area, BaseIndex, api, new_key16, token string) {
- f := 0
- begin:
- headers := map[string]string{
- "Accept-Encoding": "gzip, deflate, br, zstd",
- "Accept-Language": "zh-CN,zh;q=0.9",
- "Accept": "application/json, text/plain, */*",
- "Content-Type": "application/json",
- "deviceIdentyNo": "740qhjjFG7xSNQoCFtSHA7AMzikTKeJ5",
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
- "X-TICKET-ID": "null",
- "X-NATURE-IP": "",
- "X-SM4-INFO": "0",
- "X-TEMP-INFO": "null",
- "hUid": "",
- "X-APP-CLIENTID": "",
- "X-LANG-ID": "null",
- "Authorization": token,
- }
- logger.Info("埋点1")
- rst := lxhttp.Get_etax_clientId_redirectUri(client, api, RsCookie)
- logger.Info("埋点2")
- if rst == nil {
- return
- }
- logger.Info("埋点3")
- client_id := rst["client_id"].(string)
- redirect_uri := rst["redirect_uri"].(string)
- redirect_uri, _ = url.QueryUnescape(redirect_uri)
- code := lxhttp.VerifyLogin(client, area, BaseIndex, client_id, redirect_uri, new_key16, headers, RsCookie)
- logger.Info("埋点4")
- queryParams := url.Values{}
- queryParams.Add("code", code)
- if !strings.Contains(api, "invoice-query/invoice-query") {
- queryParams.Add("state", rst["state"].(string))
- }
- queryParams.Add("response_type", rst["response_type"].(string))
- hasQueryParams := strings.Contains(redirect_uri, "?")
- var finalRedirectURI string
- if hasQueryParams {
- finalRedirectURI = fmt.Sprintf("%s&%s", redirect_uri, queryParams.Encode())
- } else {
- finalRedirectURI = fmt.Sprintf("%s?%s", redirect_uri, queryParams.Encode())
- }
- fmt.Println("刷新cookie-uri:", finalRedirectURI)
- res, err := lxhttp.GET(client, finalRedirectURI, map[string]string{}, headers)
- if err != nil {
- _ = rod.Try(func() {
- logger.Info("finalRedirectURI失败:" + string(res))
- logger.Info("finalRedirectURI失败:" + err.Error())
- })
- if strings.Contains(BaseIndex, "neimeng") && f < 7 {
- f++
- goto begin
- }
- }
- fmt.Println(string(res))
- return
- }
- // RefreshCookieForAfterLogin RefreshCookie 主函数-对外开放 可以刷新两个cookie
- func RefreshCookieForAfterLogin(cookies map[string]string, area, BaseIndex, new_key16, token string, cwbb bool) (client *http.Client) {
- client = lxhttp.NewHttpClientForNoRedirects("", "")
- var cks []*http.Cookie
- for k, v := range cookies {
- cks = append(cks, &http.Cookie{
- Name: k,
- Value: v,
- })
- }
- u, _ := url.Parse(BaseIndex)
- client.Jar.SetCookies(u, cks)
- uri := BaseIndex + `/szc/szzh/sbss/ssmx/public/v1/checkLoginState`
- if !cwbb {
- uri = BaseIndex + "/szc/szzh/sjswszzh/sy/redirect?pageName=zhgl"
- }
- err := rod.Try(func() {
- refreshCookieBase(client, area, BaseIndex, uri, new_key16, token)
- })
- if err != nil {
- logger.Info(err.Error())
- return nil
- }
- return client
- }
- // RefreshCookieForAfterLoginRod rod使用替代afterlogin
- func RefreshCookieForAfterLoginRod(page *rod.Page, proxy, proxyAuth, area, BaseIndex string, cwbb bool) (client *http.Client, err error) {
- Tpassuri := fmt.Sprintf(`https://tpass.%s.chinatax.gov.cn:8443/#/identitySwitch/enterprise`, area)
- client = lxhttp.NewHttpClientForNoRedirects(proxy, proxyAuth)
- cookies := page.Browser().MustGetCookies()
- var cookiesArr []*http.Cookie
- for _, v := range cookies {
- var cookie http.Cookie
- cookie.Name = v.Name
- cookie.Value = v.Value
- cookie.Path = v.Path
- cookie.Domain = v.Domain
- cookiesArr = append(cookiesArr, &cookie)
- }
- u, _ := url.Parse(BaseIndex)
- client.Jar.SetCookies(u, cookiesArr)
- new_key16, token, err := GetTpassToken(page, Tpassuri)
- if err != nil {
- return
- }
- logger.Info("GetTpassToken完成")
- Api := BaseIndex + `/szc/szzh/sbss/ssmx/public/v1/checkLoginState`
- if !cwbb {
- Api = BaseIndex + "/szc/szzh/sjswszzh/sy/redirect?pageName=zhgl"
- }
- if area == "shanxi" {
- Api = `https://etax.shanxi.chinatax.gov.cn:8443/szc/szzh/sjswszzh/spHandler?cdlj=/szzh/szzh/`
- }
- err = rod.Try(func() {
- logger.Info("开始refreshCookieBase")
- refreshCookieBase(client, area, BaseIndex, Api, new_key16, token)
- logger.Info("结束refreshCookieBase")
- })
- if err != nil {
- logger.Info(err.Error())
- }
- return client, err
- }
- // RefreshCookieForAfterLogin RefreshCookie 主函数-对外开放 可以刷新两个cookie
- func RefreshDppt(page *rod.Page, area string) {
- e := rod.Try(func() {
- BaseIndex := GetBaseUri(area)
- client := lxhttp.NewHttpClientForNoRedirects("", "")
- {
- var cks []*http.Cookie
- for _, v := range page.Browser().MustGetCookies() {
- cks = append(cks, &http.Cookie{
- Name: v.Name,
- Value: v.Value,
- })
- }
- u, _ := url.Parse(strings.ReplaceAll(BaseIndex, "etax", "dppt"))
- client.Jar.SetCookies(u, cks)
- u, _ = url.Parse(BaseIndex)
- client.Jar.SetCookies(u, cks)
- }
- TpassUri := fmt.Sprintf(`https://tpass.%s.chinatax.gov.cn:8443/#/identitySwitch/enterprise`, area)
- new_key16, token, _ := GetTpassToken(page, TpassUri)
- if new_key16 == "" {
- return
- }
- uri := strings.ReplaceAll(GetBaseUri(area), "etax", "dppt") + "/szzhzz/spHandler?cdlj=third-menu/invoice-query/invoice-query"
- refreshCookieBase(client, area, BaseIndex, uri, new_key16, token)
- var rodCookies []*proto.NetworkCookieParam
- u, _ := url.Parse(BaseIndex)
- for _, v := range client.Jar.Cookies(u) {
- rodCookies = append(rodCookies,
- &proto.NetworkCookieParam{
- Name: v.Name,
- Value: v.Value,
- Domain: ".chinatax.gov.cn",
- Path: "/",
- },
- )
- }
- logger.Info("xxxx4")
- _ = page.Browser().SetCookies(rodCookies)
- })
- if e != nil {
- logger.Info(e.Error())
- }
- return
- }
- func GetTpassToken(page *rod.Page, TpassUrl string) (string, string, error) {
- var new_key16, token string
- err := rod.Try(func() {
- home := page.MustInfo().URL
- logger.Info(home)
- cookies := page.Browser().MustGetCookies()
- Ck := map[string]string{}
- for _, cookie := range cookies {
- Ck[cookie.Name] = cookie.Value
- }
- // 避免进不去
- for range "..." {
- page.MustNavigate(TpassUrl)
- utils.Sleep(2) // 加校验 //span[text()="身份切换"]
- page.MustWaitLoad()
- if common.MustHasXV(page, `//span[text()="身份切换"]`) {
- break
- } else {
- utils.Sleep(1.5)
- }
- }
- if !common.MustHasXV(page, `//span[text()="身份切换"]`) {
- panic(taxerr.New("获取企业所得税超时,系统将于30分钟后重试(可在\"通用设置\"关闭)"))
- }
- _ = rod.Try(func() {
- new_key16 = page.MustEval(`()=>localStorage.getItem('new_key16')`).String()
- })
- _ = rod.Try(func() {
- token = page.MustEval(`()=>localStorage.getItem('token')`).String()
- })
- logger.Info("New_key16:" + new_key16)
- logger.Info("Token:" + token)
- page.Navigate(home)
- })
- if new_key16 == "" {
- err = taxerr.NewWebStuckTitle(common.InfoCscsts)
- }
- return new_key16, token, err
- }
|