utils.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. package common
  2. import (
  3. "crypto/md5"
  4. "encoding/hex"
  5. "encoding/json"
  6. "fmt"
  7. "git.listensoft.net/tool/jspkit/common/lxhttp"
  8. "git.listensoft.net/tool/jspkit/common/variable"
  9. "git.listensoft.net/tool/jspkit/logger"
  10. "git.listensoft.net/tool/jspkit/taxerr"
  11. "github.com/go-kratos/kratos/v2/log"
  12. "github.com/tidwall/gjson"
  13. "io"
  14. "math/rand"
  15. "net/url"
  16. "os"
  17. "reflect"
  18. "regexp"
  19. "strings"
  20. "time"
  21. )
  22. type LvName string
  23. const (
  24. CheckSuccess LvName = "申报成功" // 检查成功 ------ 检查完全通过
  25. CheckFail LvName = "检查失败" // 检查任务失败 ----- 网页打开失败等
  26. CheckOmit LvName = "有遗漏" // 检查有遗漏 ----- 未申报问题
  27. CheckAbnormal LvName = "有异常" //检查有异常 ----- 税款问题
  28. )
  29. func GeneratePath(suffix string) string {
  30. ps := os.PathSeparator
  31. //检查路径
  32. if !PathExists("captcha" + string(ps)) {
  33. _ = os.MkdirAll("captcha"+string(ps), os.ModePerm)
  34. }
  35. return "captcha" + string(ps) + GetTimestamp(13) + "." + suffix
  36. }
  37. func PathExists(path string) bool {
  38. _, err := os.Stat(path)
  39. if err == nil {
  40. return true
  41. }
  42. if os.IsNotExist(err) {
  43. return false
  44. }
  45. return false
  46. }
  47. // 返回一个32位md5加密后的字符串
  48. func Md5(data string) string {
  49. h := md5.New()
  50. h.Write([]byte(data))
  51. return hex.EncodeToString(h.Sum(nil))
  52. }
  53. /*
  54. 生成检查截图本地路径
  55. lv 图片对应的错误等级 用上面定义好的 Omit>Abnormal
  56. taxNo 税号
  57. period 账期
  58. location 截图位置,例如申报清册、申报结果查询、税款缴纳、缴费缴纳查询
  59. */
  60. func GenerateCheckImagePath(lv LvName, taxNo, period, location string) string {
  61. var path string
  62. path = "./data/check/" + taxNo + "/"
  63. if !PathExists(path) {
  64. os.MkdirAll(path, os.ModePerm)
  65. }
  66. return fmt.Sprintf(`%s-%s-%s-新版_%s_%s.png`, path+taxNo, period, GetTimestamp(13), location, lv)
  67. }
  68. func PostSbjt(taxno, period, path string) string {
  69. var params = map[string]string{
  70. "tax_no": taxno,
  71. "period": period,
  72. "type": "etax", //电子税务局
  73. }
  74. str, err := PostFile("https://file.listensoft.net/api/v1/uploadsbjt", map[string]string{
  75. "file": path,
  76. }, params)
  77. if err != nil {
  78. log.Warnf("【%s】文件上传失败", path)
  79. }
  80. return gjson.GetBytes(str, "path").String()
  81. }
  82. // 获取申报截图的path
  83. // taxNo 纳税人识别号 period 账期 taxType 任务名称
  84. func GetSbjtPath(taxNo, period string, taxType variable.TaskName) string {
  85. var path string
  86. path = "./data/" + taxNo + "/"
  87. if !PathExists(path) {
  88. os.MkdirAll(path, os.ModePerm)
  89. }
  90. path = path + period + string(taxType) + "_" + GetTimestamp(13) + ".png"
  91. return path
  92. }
  93. // 判断字符串是否全是英文
  94. func IsAllEnglish(s string) bool {
  95. // 检查字符串是否全部由ASCII字符组成
  96. for _, c := range s {
  97. if c > 127 {
  98. return false
  99. }
  100. }
  101. return true
  102. }
  103. // CreateFormReader 将 map 转换成 header
  104. func CreateFormReader(data map[string]string) io.Reader {
  105. form := url.Values{}
  106. for k, v := range data {
  107. form.Add(k, v)
  108. }
  109. return strings.NewReader(form.Encode())
  110. }
  111. func Unbracket(str string) string {
  112. str = strings.ReplaceAll(str, "(", "(")
  113. str = strings.ReplaceAll(str, ")", ")")
  114. str = strings.ReplaceAll(str, " ", "")
  115. return str
  116. }
  117. // 检查是否是手机号
  118. func CheckMobile(mobile string) bool {
  119. r := regexp.MustCompile(`^1[0-9]{10}$`)
  120. return r.Match([]byte(mobile))
  121. }
  122. func NewWebStuckTitle() *taxerr.SystemErr {
  123. return taxerr.NewSystemV3("电子税局页面卡顿", "系统将于30分钟后重试(可在\"通用设置\"关闭)")
  124. }
  125. // 查看设备是否在线
  126. func CheckEqmLive(tel string) bool {
  127. client := lxhttp.NewHttpClient()
  128. defer client.CloseIdleConnections()
  129. bys, err := lxhttp.POSTJson(client, "https://keep.jsptax.com"+"/api/v1/telDeviceStatus", map[string]string{"mobiles": tel}, map[string]string{})
  130. if err != nil {
  131. return false
  132. }
  133. if gjson.GetBytes(bys, `data.status`).Bool() {
  134. return true
  135. }
  136. return false
  137. }
  138. func GetData(key variable.SbKey, data string, target interface{}) bool {
  139. str := gjson.Get(data, string(key)).String()
  140. if err := MapToStruct(str, target); err != nil {
  141. logger.Info(err)
  142. return false
  143. }
  144. return true
  145. }
  146. // target 传指针
  147. func MapToStruct(source interface{}, target interface{}) error {
  148. resByre := []byte("")
  149. var resByteErr error
  150. if reflect.TypeOf(source).String() == "string" {
  151. str := source.(string)
  152. resByre = []byte(str)
  153. } else {
  154. resByre, resByteErr = json.Marshal(source)
  155. if resByteErr != nil {
  156. return resByteErr
  157. }
  158. }
  159. err := json.Unmarshal(resByre, target)
  160. if err != nil {
  161. return err
  162. }
  163. return nil
  164. }
  165. // CancelLeftTasks 撤销其他的任务,避免一直发验证码导致超限,仅新版登录使用
  166. func CancelLeftTasks(tel string) {
  167. c := lxhttp.NewHttpClient()
  168. lxhttp.POSTJson(c, variable.TaxTaskURL+"/api/v1/stopQueue", map[string]string{"tel": tel}, nil)
  169. }
  170. // GetTelTaskStatus 如果有任务正在进行 返回 true
  171. func GetTelTaskStatus(tel string) (bool, error) {
  172. c := lxhttp.NewHttpClient()
  173. bys, err := lxhttp.POSTJson(c, `https://task.listensoft.net/api/v1/other/telTaskDoi`, map[string]string{
  174. "tel": tel,
  175. }, nil)
  176. if err != nil {
  177. return false, err
  178. }
  179. if gjson.GetBytes(bys, `data.res`).Bool() {
  180. return true, nil
  181. } else {
  182. return false, nil
  183. }
  184. }
  185. var rng = rand.New(rand.NewSource(time.Now().UnixMicro()))
  186. // GenTracks 函数生成移动轨迹。先做加速运动,再做减速运动。
  187. //
  188. // 设滑块滑动的加速度为 a;当前速度为 v;初速度为 v0;位移为 x;所需时间为 t。
  189. // 根据加速度物理公式,它们满足以下关系:
  190. // v = v0 + a * t
  191. // x = v0 * t + 0.5 * a * t * t
  192. //
  193. // 参考:
  194. //
  195. // https://python3webspider.cuiqingcai.com/8.2-ji-yan-hua-dong-yan-zheng-ma-shi-bie
  196. func GenTracks(distance float64) []float64 {
  197. var track = make([]float64, 0) // 移动轨迹
  198. var current float64 = 0 // 当前位移
  199. var mid float64 = distance * 4 / 5 // 减速阈值
  200. var t float64 = 0.15 // 计算间隔
  201. var v float64 = 0 // 初速度
  202. var a1 = rng.Float64()*6 + 2 // 正加速度 [2,8)
  203. var a2 = -a1 - 2 // 负加速度 (-10,-4]
  204. for current < distance {
  205. // 加速度
  206. var a float64
  207. if current < mid {
  208. a = a1
  209. } else {
  210. a = -a2
  211. }
  212. // 初速度 v0
  213. v0 := v
  214. // 当前速度 v = v0 + at
  215. v = v0 + a*t
  216. // 移动距离 x = v0t + 1/2 * a * t^2
  217. x := v0*t + 1.0/2.0*a*t*t
  218. current += x
  219. track = append(track, x)
  220. }
  221. // 修正超标值
  222. track = append(track, distance-current)
  223. return track
  224. }
  225. func Trim(str interface{}) string {
  226. return strings.TrimSpace(fmt.Sprintf("%s", str))
  227. }
  228. // 生成随机数
  229. func RandSeq(n int) string {
  230. var letters = []rune("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ")
  231. b := make([]rune, n)
  232. for i := range b {
  233. b[i] = letters[rand.Intn(len(letters))]
  234. }
  235. return string(b)
  236. }