Browse Source

补充银行方法

1 2 weeks ago
parent
commit
4d78d7fe03
9 changed files with 301 additions and 0 deletions
  1. 28 0
      common/converter.go
  2. 19 0
      common/file.go
  3. 16 0
      common/lxrod/bank.go
  4. 54 0
      common/lxrod/screenshot.go
  5. 35 0
      common/path/path.go
  6. 36 0
      common/path/path_test.go
  7. 5 0
      common/period.go
  8. 98 0
      common/rod_utils.go
  9. 10 0
      common/utils.go

+ 28 - 0
common/converter.go

@@ -2,6 +2,7 @@ package common
 
 import (
 	"fmt"
+	"github.com/go-rod/rod"
 	"math"
 	"reflect"
 	"strconv"
@@ -10,6 +11,21 @@ import (
 	"github.com/shopspring/decimal"
 )
 
+var MonthNum1 = map[string]string{
+	"01": "1月",
+	"02": "2月",
+	"03": "3月",
+	"04": "4月",
+	"05": "5月",
+	"06": "6月",
+	"07": "7月",
+	"08": "8月",
+	"09": "9月",
+	"10": "10月",
+	"11": "11月",
+	"12": "12月",
+}
+
 // string to int
 func StrToInt(str string) int {
 	intValue, err := strconv.Atoi(str)
@@ -228,3 +244,15 @@ func DecimalAddFS(v1 float64, v2 string) float64 {
 func AmountFormat2str(str string) string {
 	return strings.TrimSpace(strings.ReplaceAll(str, ",", ""))
 }
+
+func StrToFloToStr(str string) string {
+	sflo := StrToFloat(str)
+	str = FloatToStr(sflo)
+	return str
+}
+
+// 获取input的值
+func GetInputValue(p *rod.Page, xPath string) string {
+	str := MustElementX(p, xPath).MustEval(`()=>{return this.value}`).Str()
+	return strings.ReplaceAll(str, ",", "")
+}

+ 19 - 0
common/file.go

@@ -2,9 +2,11 @@ package common
 
 import (
 	"encoding/json"
+	"fmt"
 	"github.com/go-rod/rod/lib/utils"
 	"github.com/tidwall/gjson"
 	"os"
+	"path/filepath"
 	"strings"
 )
 
@@ -32,6 +34,16 @@ func PostBankPdf(name, suffix, path string) string {
 	}, params)
 	return gjson.GetBytes(str, "data.url").String()
 }
+func GetBankPDFPath(bank, taxNo, taxTape string) (string, error) {
+	var err error
+	var path string
+	path = "./data/bank/" + bank + "/" + taxNo + "/"
+	if !PathExists(path) {
+		err = os.MkdirAll(path, os.ModePerm)
+	}
+	path = path + "_" + taxTape + ".pdf"
+	return path, err
+}
 
 // PDFtoStrArrayPython pdf转二维数组 python服务
 func PDFtoStrArrayPython(path string) ([][]string, error) {
@@ -89,3 +101,10 @@ begin:
 	arr = strings.Split(Result.Text, "\n")
 	return arr, nil
 }
+
+// 生成验证码图片的路径
+func GenerateFilePath(name, suffix string) string {
+	os.MkdirAll("captcha", os.ModePerm)
+	n := fmt.Sprintf("%s_%s.%s", name, GetTimestamp(13), suffix)
+	return filepath.Join("captcha", n)
+}

+ 16 - 0
common/lxrod/bank.go

@@ -2,6 +2,7 @@ package lxrod
 
 import (
 	"context"
+	"git.listensoft.net/tool/jspkit/taxerr"
 
 	"github.com/go-rod/rod"
 	"github.com/go-rod/rod/lib/devices"
@@ -36,3 +37,18 @@ var EdgeLandscape = devices.Device{
 		},
 	},
 }.Landscape()
+
+func (lxrod *Lxrod) NewUserMode(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
+	l := launcher.NewUserMode().Headless(false)
+	l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
+	lxrod.Launcher = l
+	wsURL, err := l.Launch()
+	lxrod.WsURL = wsURL
+	if err != nil {
+		return nil, nil, taxerr.NewWebStuckTitle(true)
+	}
+	b = rod.New().NoDefaultDevice().ControlURL(wsURL).Context(ctx).MustConnect()
+	p = b.MustPage().MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
+	lxrod.Browser = b
+	return b, p, nil
+}

+ 54 - 0
common/lxrod/screenshot.go

@@ -0,0 +1,54 @@
+package lxrod
+
+import (
+	"context"
+	"git.listensoft.net/tool/jspkit/common/clients"
+	"git.listensoft.net/tool/jspkit/common/models"
+	"git.listensoft.net/tool/jspkit/common/path"
+	"net/http"
+	"os"
+	"path/filepath"
+	"time"
+
+	"github.com/go-rod/rod"
+	"go.uber.org/zap"
+)
+
+// 截图并上传
+func PostScreenshot(l *zap.Logger, p *rod.Page, task *models.TaxTask) error {
+	l.Debug("尝试保存截图")
+	imgPath := path.GetErrImgPath(task.TaxNo, task.Period)
+	bin, err := p.Timeout(10*time.Second).Screenshot(false, nil)
+	if err != nil {
+		l.Error("截图创建失败", zap.Error(err))
+		return err
+	}
+	err = os.WriteFile(imgPath, bin, 0666)
+	if err != nil {
+		l.Error("截图保存失败", zap.Error(err))
+		return err
+	}
+	l.Info("截图保存成功", zap.String("path", imgPath))
+
+	l.Debug("尝试上传截图")
+	ctx, cancel := context.WithTimeout(p.GetContext(), 30*time.Second)
+	defer cancel()
+
+	fc := clients.FileClient{
+		Client: http.DefaultClient,
+		Logger: l,
+	}
+	businessImg, err := fc.PostScreenShotBytes(ctx, bin, clients.PostScreenShotReq{
+		Name:   filepath.Base(imgPath),
+		TaxNo:  task.TaxNo,
+		Period: task.Period,
+	})
+	if err != nil {
+		l.Error("截图上传失败", zap.Error(err))
+		return err
+	}
+
+	l.Info("截图上传成功", zap.String("businessImg", businessImg))
+	task.Result.BusinessImg = businessImg
+	return nil
+}

+ 35 - 0
common/path/path.go

@@ -0,0 +1,35 @@
+// Package path 提供了路径处理函数
+package path
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+)
+
+// 获取银行采集本地 pdf 保存路径
+func GetBankPdfPath(bank, taxNo, lsh string) string {
+	dir := filepath.Join("./data/bank", bank, taxNo)
+	_ = os.MkdirAll(dir, os.ModePerm)
+	ts := time.Now().UnixNano()
+	name := fmt.Sprintf("%s_%d.pdf", lsh, ts)
+	return filepath.Join(dir, name)
+}
+
+// 获取错误截图路径
+func GetErrImgPath(taxNo, period string) string {
+	checkPath := filepath.Join("./data/sbImg", taxNo)
+	_ = os.MkdirAll(checkPath, os.ModePerm)
+
+	t := time.Now().Format("2006-01-02-15-04-05")
+	name := fmt.Sprintf("%s-%s.png", period, t)
+	return filepath.Join(checkPath, name)
+}
+
+// 去除文件扩展名 "x.pdf" -> "x"
+func TrimExt(name string) string {
+	ext := filepath.Ext(name)
+	return strings.TrimSuffix(name, ext)
+}

+ 36 - 0
common/path/path_test.go

@@ -0,0 +1,36 @@
+package path
+
+import "testing"
+
+func TestTrimExt(t *testing.T) {
+	for _, tc := range []struct {
+		name string
+		want string
+	}{
+		{
+			name: "客户电子缴税_815777777R520000002_202412061343024.pdf",
+			want: "客户电子缴税_815777777R520000002_202412061343024",
+		},
+		{
+			name: "a.b.c",
+			want: "a.b",
+		},
+		{
+			name: "a",
+			want: "a",
+		},
+		{
+			name: ".c",
+			want: "",
+		},
+		{
+			name: "",
+			want: "",
+		},
+	} {
+		r := TrimExt(tc.name)
+		if r != tc.want {
+			t.Errorf("Expected %v, but got %v", tc.want, r)
+		}
+	}
+}

+ 5 - 0
common/period.go

@@ -309,3 +309,8 @@ func DateFormatter(date string) string {
 
 	return fmt.Sprintf("%s-%s-%s", date[:4], date[4:6], date[6:])
 }
+
+// 获取某一天的0点时间
+func GetNextDateTime(d time.Time) time.Time {
+	return time.Date(d.Year(), d.Month(), d.Day()+1, 0, 0, 0, 0, d.Location())
+}

+ 98 - 0
common/rod_utils.go

@@ -426,3 +426,101 @@ func Click(page *rod.Page, x, y float64) {
 func selectAll2(page *rod.Page) {
 	page.Keyboard.MustType(input.ControlLeft).MustType('a').MustType('a').MustType(input.ControlLeft)
 }
+
+// 输入文字Str
+func InputStr(p *rod.Page, selector, inputVal string) {
+	err := rod.Try(func() {
+		e := rod.Try(func() {
+			p.Timeout(time.Duration(1 * float64(time.Second))).MustSearch(selector).MustSelectAllText().MustFrame().Keyboard.MustType(input.Backspace)
+		})
+		if e != nil {
+			logger.Info(e.Error() + "-" + selector + "-" + inputVal)
+		}
+		e = rod.Try(func() {
+			p.Timeout(time.Duration(1 * float64(time.Second))).MustSearch(selector).MustSelectAllText().MustInput(inputVal)
+		})
+		if e != nil {
+			logger.Info(strings.Split(e.Error(), "\t")[0] + "-" + selector + "-" + inputVal)
+		}
+	})
+	if err != nil {
+		logger.Info(err.Error() + "-" + selector + "-" + inputVal)
+	}
+}
+
+// 输入文字 string
+func InputElementXStr(p *rod.Page, xPath, inputVal string) {
+	elementX := MustElementX(p, xPath)
+	disabled := elementX.MustAttribute("disabled")
+	if disabled != nil {
+		return
+	}
+	readonly := elementX.MustAttribute("readonly")
+	if readonly != nil {
+		return
+	}
+	elementX.MustSelectAllText().MustInput(inputVal)
+}
+
+func WaitElementXFoTimesNil(page *rod.Page, xpath string, times int) *rod.Element {
+	for i := 0; i < times; i++ {
+		if has, el, _ := HasX(page, xpath); has && MustElementX(page, xpath).MustVisible() {
+			return el
+		}
+		time.Sleep(time.Second)
+	}
+	return nil
+}
+
+func MustElementX10(page *rod.Page, xpath string) *rod.Element {
+	for i := 0; i < 10; i++ {
+		x, _ := ElementX(page, xpath)
+		if x != nil {
+			return x
+		}
+		utils.Sleep(1)
+	}
+	return nil
+}
+
+func MustElementX15(page *rod.Page, xpath string) *rod.Element {
+	for i := 0; i < 15; i++ {
+		x, _ := ElementX(page, xpath)
+		if x != nil {
+			return x
+		}
+		utils.Sleep(1)
+	}
+	return nil
+}
+
+func MustHasXV30(page *rod.Page, xpath string) bool {
+	for _, element := range MustElementsX30(page, xpath) {
+		visible, _ := element.Visible()
+		if visible {
+			return true
+		}
+	}
+	return false
+}
+func MustElementsX30(page *rod.Page, xpath string) (x []*rod.Element) {
+	for i := 0; i < 30; i++ {
+		x, _ = ElementsX(page, xpath)
+		if len(x) != 0 {
+			break
+		}
+		utils.Sleep(1)
+	}
+	return x
+}
+
+func WaitElementXFoTimes(page *rod.Page, xpath string, times int) *rod.Element {
+	for i := 0; i < times; i++ {
+		if has, el, _ := HasX(page, xpath); has && MustElementX(page, xpath).MustVisible() {
+			return el
+		}
+		time.Sleep(time.Second)
+	}
+	logger.Info("页面加载失败元素未找到,请稍后再试", xpath)
+	panic(taxerr.NewWebStuckTitle(InfoCscsts))
+}

+ 10 - 0
common/utils.go

@@ -251,3 +251,13 @@ func GenTracks(distance float64) []float64 {
 func Trim(str interface{}) string {
 	return strings.TrimSpace(fmt.Sprintf("%s", str))
 }
+
+// 生成随机数
+func RandSeq(n int) string {
+	var letters = []rune("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ")
+	b := make([]rune, n)
+	for i := range b {
+		b[i] = letters[rand.Intn(len(letters))]
+	}
+	return string(b)
+}