# -*- coding: utf-8 -*-
import re
import os
import cv2
import time
import json
import base64
import ddddocr
import logging
import hashlib
import requests
import redis as rd
import numpy as np
from func_timeout import func_set_timeout
from func_timeout.exceptions import FunctionTimedOut
from encryption_function.key9 import f39, yzm, f392_0x45c2e7, yzm_cy

os.environ['NO_PROXY'] = 'stackoverflow.com'

# seed = {
#     '@class': 'com.alibaba.fastjson.JSONObject',
#     'fpdm': '',
#     'kprq': '20240125',
#     'u_key': '1762044625893199873',
#     'kjje': '367.9',
#     'fphm': '24952000000011841047',
#     'jym': ''
# }

# seed = {
#     '@class': 'com.alibaba.fastjson.JSONObject',
#     'fpdm': '044002207111',
#     'kprq': '20240202',
#     'u_key': '1762290799569014785',
#     'kjje': '15.13',
#     'fphm': '93152922',
#     'jym': '03848091989844314307'
# }

# seed = {
#     '@class': 'com.alibaba.fastjson.JSONObject',
#     'fpdm': '',
#     'kprq': '20240228',
#     'u_key': '1766026076514947073',
#     'kjje': '5400.0',
#     'fphm': '24312000000053951488',
#     'jym': ''}
#
# seed = {
#     '@class': 'com.alibaba.fastjson.JSONObject',
#     'fpdm': '012002300411',
#     'kprq': '20240408',
#     'u_key': '1777534576655077378',
#     'kjje': '684.0',
#     'fphm': '14051200',
#     'jym': '76717940623559506327'
# }


# REDIS = {
#     # 'host': '127.0.0.1',
#     'host': '120.79.147.190',
#     'port': 6379,
#     'password': 'Vm5vQH4ydFXh',
#     'db': 10
# }

REDIS = {
    # 'host': '127.0.0.1',
    'host': 'wx.yswg.com.cn',
    'port': 6379,
    'password': 'yswg@2019',
    'db': 1
}


def singleton(cls, *args, **kw):
    """singleton mode.

    :param cls: classname
    :param args: args.
    :param kw: kwargs.
    :return:
    """

    instances = {}

    def _singleton():
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]

    return _singleton


def md5(src: str, algorithm: str = "md5", digits: int = 32) -> str:
    """md5 algorithms.

    :param src: original string.
    :param algorithm: algorithm method.
    :param digits: 16 length or 32 length.
    :return: string.
    """

    algorithm = hashlib.new(algorithm)
    algorithm.update(src.encode('utf8'))
    if digits == 16:
        return algorithm.hexdigest()[8:24]
    else:
        return algorithm.hexdigest()


@singleton
class Redis(object):
    def __init__(self):
        self.host = REDIS['host']
        self.port = REDIS['port']
        self.db = REDIS['db']
        self.password = REDIS['password']
        self.pool = rd.ConnectionPool(
            host=self.host,
            port=self.port,
            db=self.db,
            max_connections=3,
            password=self.password,
            socket_timeout=5,
            socket_connect_timeout=5,
            retry_on_timeout=True,
        )

    def get_instance(self):
        return rd.Redis(connection_pool=self.pool)


@func_set_timeout(10)
def sadd(key, value, use_md5=True):
    """add key-value to the sorted set.

    :param key: key
    :param value: value
    :param use_md5: weather use md5.
    :return: True for done, False for not.
    """

    r = Redis().get_instance()
    if use_md5:
        added = r.sadd(key, md5(value, digits=16))
    else:
        added = r.sadd(key, value)
    return added == 1


@func_set_timeout(10)
def spop(key, count=20) -> list:
    """spop

    :param count:
    :param key:
    :return:
    """

    r = Redis().get_instance()
    return r.spop(key, count)

def ladd(key, value, use_md5=True):
    """add key-value to the sorted set.

    :param key: key
    :param value: value
    :param use_md5: weather use md5.
    :return: True for done, False for not.
    """

    r = Redis().get_instance()
    if use_md5:
        added = r.lpush(key, md5(value, digits=16))
    else:
        added = r.lpush(key, value)
    return added == 1


@func_set_timeout(30)
def listpop(key) -> list:
    """lpop

    :param count:
    :param key:
    :return:
    """

    r = Redis().get_instance()
    return r.lpop(key)


@func_set_timeout(30)
def xadd(key, data):
    r = Redis().get_instance()
    return r.xadd(key, data)


class CheckSeed:
    def __init__(self, seed=None):
        self.seed = seed

    def getDqdmByCode(self, _0x4a5eee):
        if _0x4a5eee == '91':
            return '2102'
        elif _0x4a5eee == '92':
            return '3702'
        elif _0x4a5eee == '93':
            return '3302'
        elif _0x4a5eee == '94':
            return '3502'
        elif _0x4a5eee == '95':
            return '4403'
        elif _0x4a5eee == '00':
            return '0000'
        else:
            return None

    def getSwjg(self, fpdm, ckflag, fphm):
        citys = [
            {'code': '1100', 'sfmc': '北京', 'Ip': 'https://fpcy.beijing.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.beijing.chinatax.gov.cn:443'},
            {'code': '1200', 'sfmc': '天津', 'Ip': 'https://fpcy.tianjin.chinatax.gov.cn/NWebQuery',
             'address': 'https://fpcy.tianjin.chinatax.gov.cn'},
            {'code': '1300', 'sfmc': '河北', 'Ip': 'https://fpcy.hebei.chinatax.gov.cn/NWebQuery',
             'address': 'https://fpcy.hebei.chinatax.gov.cn'},
            {'code': '1400', 'sfmc': '山西', 'Ip': 'https://fpcy.shanxi.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.shanxi.chinatax.gov.cn:443'},
            {'code': '1500', 'sfmc': '内蒙古', 'Ip': 'https://fpcy.neimenggu.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.neimenggu.chinatax.gov.cn:443'},
            {'code': '2100', 'sfmc': '辽宁', 'Ip': 'https://fpcy.liaoning.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.liaoning.chinatax.gov.cn:443'},
            {'code': '2102', 'sfmc': '大连', 'Ip': 'https://sbf.dalian.chinatax.gov.cn:8402/NWebQuery',
             'address': 'https://sbf.dalian.chinatax.gov.cn:8402'},
            {'code': '2200', 'sfmc': '吉林', 'Ip': 'https://fpcy.jilin.chinatax.gov.cn:4432/NWebQuery',
             'address': 'https://fpcy.jilin.chinatax.gov.cn:4432'},
            {'code': '2300', 'sfmc': '黑龙江', 'Ip': 'https://fpcy.heilongjiang.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.heilongjiang.chinatax.gov.cn:443'},
            {'code': '3100', 'sfmc': '上海', 'Ip': 'https://fpcy.shanghai.chinatax.gov.cn:1001/NWebQuery',
             'address': 'https://fpcy.shanghai.chinatax.gov.cn:1001'},
            {'code': '3200', 'sfmc': '江苏', 'Ip': 'https://fpcy.jiangsu.chinatax.gov.cn:80/NWebQuery',
             'address': 'https://fpcy.jiangsu.chinatax.gov.cn:80'},
            {'code': '3300', 'sfmc': '浙江', 'Ip': 'https://fpcy.zhejiang.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.zhejiang.chinatax.gov.cn:443'},
            {'code': '3302', 'sfmc': '宁波', 'Ip': 'https://fpcy.ningbo.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.ningbo.chinatax.gov.cn:443'},
            {'code': '3400', 'sfmc': '安徽', 'Ip': 'https://fpcy.anhui.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.anhui.chinatax.gov.cn:443'},
            {'code': '3500', 'sfmc': '福建', 'Ip': 'https://fpcy.fujian.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.fujian.chinatax.gov.cn:443'},
            {'code': '3502', 'sfmc': '厦门', 'Ip': 'https://fpcy.xiamen.chinatax.gov.cn/NWebQuery',
             'address': 'https://fpcy.xiamen.chinatax.gov.cn'},
            {'code': '3600', 'sfmc': '江西', 'Ip': 'https://fpcy.jiangxi.chinatax.gov.cn:82/NWebQuery',
             'address': 'https://fpcy.jiangxi.chinatax.gov.cn:82'},
            {'code': '3700', 'sfmc': '山东', 'Ip': 'https://fpcy.shandong.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.shandong.chinatax.gov.cn:443'},
            {'code': '3702', 'sfmc': '青岛', 'Ip': 'https://fpcy.qingdao.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.qingdao.chinatax.gov.cn:443'},
            {'code': '4100', 'sfmc': '河南', 'Ip': 'https://fpcy.henan.chinatax.gov.cn/NWebQuery',
             'address': 'https://fpcy.henan.chinatax.gov.cn'},
            {'code': '4200', 'sfmc': '湖北', 'Ip': 'https://fpcy.hubei.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.hubei.chinatax.gov.cn:443'},
            {'code': '4300', 'sfmc': '湖南', 'Ip': 'https://fpcy.hunan.chinatax.gov.cn:8083/NWebQuery',
             'address': 'https://fpcy.hunan.chinatax.gov.cn:8083'},
            {'code': '4400', 'sfmc': '广东', 'Ip': 'https://fpcy.guangdong.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.guangdong.chinatax.gov.cn:443'},
            {'code': '4403', 'sfmc': '深圳', 'Ip': 'https://fpcy.shenzhen.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.shenzhen.chinatax.gov.cn:443'},
            {'code': '4500', 'sfmc': '广西', 'Ip': 'https://fpcy.guangxi.chinatax.gov.cn:8200/NWebQuery',
             'address': 'https://fpcy.guangxi.chinatax.gov.cn:8200'},
            {'code': '4600', 'sfmc': '海南', 'Ip': 'https://fpcy.hainan.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.hainan.chinatax.gov.cn:443'},
            {'code': '5000', 'sfmc': '重庆', 'Ip': 'https://fpcy.chongqing.chinatax.gov.cn:80/NWebQuery',
             'address': 'https://fpcy.chongqing.chinatax.gov.cn:80'},
            {'code': '5100', 'sfmc': '四川', 'Ip': 'https://fpcy.sichuan.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.sichuan.chinatax.gov.cn:443'},
            {'code': '5200', 'sfmc': '贵州', 'Ip': 'https://fpcy.guizhou.chinatax.gov.cn:80/NWebQuery',
             'address': 'https://fpcy.guizhou.chinatax.gov.cn:80'},
            {'code': '5300', 'sfmc': '云南', 'Ip': 'https://fpcy.yunnan.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.yunnan.chinatax.gov.cn:443'},
            {'code': '5400', 'sfmc': '西藏', 'Ip': 'https://fpcy.xizang.chinatax.gov.cn:81/NWebQuery',
             'address': 'https://fpcy.xizang.chinatax.gov.cn:81'},
            {'code': '6100', 'sfmc': '陕西', 'Ip': 'https://fpcy.shaanxi.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.shaanxi.chinatax.gov.cn:443'},
            {'code': '6200', 'sfmc': '甘肃', 'Ip': 'https://fpcy.gansu.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.gansu.chinatax.gov.cn:443'},
            {'code': '6300', 'sfmc': '青海', 'Ip': 'https://fpcy.qinghai.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.qinghai.chinatax.gov.cn:443'},
            {'code': '6400', 'sfmc': '宁夏', 'Ip': 'https://fpcy.ningxia.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.ningxia.chinatax.gov.cn:443'},
            {'code': '6500', 'sfmc': '新疆', 'Ip': 'https://fpcy.xinjiang.chinatax.gov.cn:443/NWebQuery',
             'address': 'https://fpcy.xinjiang.chinatax.gov.cn:443'},

        ]
        dqdm = None
        if fpdm == "":
            fpdm = fphm
        if len(fpdm) == 12:
            dqdm = fpdm[1: 5]
        elif len(fpdm) == 20:
            xdpFphm = fpdm;
            code = xdpFphm[2: 5]
            code = xdpFphm[2: 4]
            dqdm = self.getDqdmByCode(code)
            if (dqdm == None):
                dqdm = code + '00'
        else:
            dqdm = fpdm[0: 4]
        if dqdm != '2102' and dqdm != '3302' and dqdm != '3502' and dqdm != '3702' and dqdm != '4403':
            dqdm = dqdm[0: 2] + '00'
        swjginfo = []
        for i in range(len(citys)):
            if dqdm == citys[i]['code']:
                swjginfo.append(citys[i]['sfmc'])
                swjginfo.append(citys[i]['Ip'])
                return swjginfo

    def alxd(self, fpdm, fphm):
        _0x2658c0 = '99'
        code = ["144031539110", "131001570151", "133011501118", "111001571071"]
        if len(fpdm) == 12:
            _0x49272a = fpdm[7: 8]
            for i in range(len(code)):
                if fpdm == code[i]:
                    _0x2658c0 = '10';
                    break
            if (_0x2658c0 == '99'):
                if fpdm[0] == '0' and fpdm[10: 12] == '11':
                    _0x2658c0 = '10'
                if fpdm[0] == '0' and (fpdm[10: 12] == "04" or fpdm[10: 12] == "05"):
                    _0x2658c0 = '04'
                if fpdm[0] == '0' and (fpdm[10: 12] == "06" or fpdm[10: 12] == "07"):
                    _0x2658c0 = '11'
                if fpdm[0] == '0' and fpdm[10: 12] == "12":
                    _0x2658c0 = '14'
            if (_0x2658c0 == '99'):
                if fpdm[0] == '0' and fpdm[10: 12] == "17":
                    _0x2658c0 = '15'
                if _0x2658c0 == '99' and _0x49272a == '0' and fpdm[0] == '0':
                    _0x2658c0 = '03'
            if (_0x2658c0 == '99'):
                if fpdm[0] == '0' and fpdm[10: 12] == "13":
                    _0x2658c0 = "08"
        elif len(fpdm) == 10:
            _0x49272a = fpdm[7: 8]
            if _0x49272a == '1' or _0x49272a == '5':
                _0x2658c0 = '01'
            elif _0x49272a == '6' or _0x49272a == '3':
                _0x2658c0 = "04"
        elif len(fpdm) == 0:
            if len(fphm) == 20:
                if '9' == fphm[4:5]:
                    _0x2658c0 = '83'
                elif '8' == fphm[4:5]:
                    _0x2658c0 = '61'
                else:
                    _0x2658c0 = '09'
        return _0x2658c0

    def ckxdphm(self, _0x458950):
        _0x1e265e = re.compile(r"^\d{20}$")
        _0x276a26 = re.compile(r"^0{20}$")
        _0x88336 = re.findall(_0x1e265e, _0x458950)
        _0x2d8ed5 = re.findall(_0x276a26, _0x458950)
        if (_0x88336 and not _0x2d8ed5):
            return True
        else:
            return False

    def acq(self, fprq):
        _0x4fcd62 = re.compile('^\d{8}$')
        _0x3f3d79 = re.compile('^0{8}$')
        _0x439d0f = re.compile('^0{11}-?[1-9]*\w\d*$')
        _0x555107 = re.findall(_0x4fcd62, fprq)
        if _0x555107:
            return True
        else:
            return False

    def afcdm(self, fpdm, fphm):
        f = 0
        if (self.ckxdphm(fphm) and '' == fpdm):
            # print("fpdm -->")
            f = 1
        elif self.ckxdphm(fphm) and len(fpdm) > 0:
            # print("fpdm --> 发票代码有误")
            f = 0
            return f
        if len(fpdm) == 10 or len(fpdm) == 12:
            _0x44f23c = re.compile("^[0-9]*$")
            _0x30ac55 = re.findall(_0x44f23c, fpdm)
            if not _0x30ac55:
                # print("fpdm --> 发票代码有误")
                f = 0
                return f
            else:
                _0x2f91e8 = self.getSwjg(fpdm, 0, fphm)
                if (len(_0x2f91e8) == 0):
                    # print("fpdm --> 发票代码有误")
                    f = 0
                    return f
                else:
                    if len(_0x2f91e8) == 0:
                        # print("fpdm --> 发票代码有误")
                        f = 0
                        return f
                    else:
                        # print("fpdm --> 发票准确")
                        f = 1
        return f

    def kprqChange(self, fprq):
        f = 0
        if fprq != '' and fprq != "YYYYMMDD":
            if not self.acq(fprq):
                t = time.localtime()
                if fprq == str(t.tm_year) + str(t.tm_mon) + str(t.tm_mday):
                    # print("当日开具发票次日查验!")
                    f = 0
                else:
                    # print('开票日期错误')
                    f = 0
            else:
                # print('开票日期正常')
                skxt = 0
                f = 1
        else:
            # print('开票日期错误')
            f = 0
        return f

    def aje(self, fpdm, kjje, fplx):
        if fplx == '01' or fplx == '02' or fplx == '03' or fplx == '15' or fplx == '08' or fplx == '09' or fplx == '83' or fplx == "61":
            _0x27bbd5 = re.compile('(^-?\d{1,11}$)|(^-?\d{1,11}\.\d{1,2}$)')
            return True if re.findall(_0x27bbd5, kjje) else False
        else:
            _0x27bbd5 = re.compile('^-?(\d+$)|(\d+\.\d{1,2})$')
            return True if re.findall(_0x27bbd5, kjje) else False

    def ajy(self, jym):
        _0x585e6a = re.compile('^\d{6}$')
        return True if re.findall(_0x585e6a, jym) else False

    def kjje(self, fplx, xym, fpdm, kjje):
        f = 0
        if fplx == "01" or fplx == '02' or fplx == '03' or fplx == '15' or fplx == '99' or fplx == '08' or fplx == '09' or fplx == '09' or fplx == '83' or fplx == '61' or fplx == "72":
            if not self.aje(fpdm, kjje, fplx):
                if fplx == '02':
                    # print("合计金额有误!")
                    f = 0
                elif fplx == '03':
                    # print("不含税价有误!")
                    f = 0
                elif fplx in ['09', '61', '72']:
                    # print("价税合计有误!")
                    f = 0
                elif fplx == '83':
                    # print("票价有误!")
                    f = 0
                elif fplx == '15':
                    # print("车价合计有误!")
                    f = 0
                else:
                    # print("开票金额有误!")
                    f = 0
            else:
                # print("开具金额 ok")
                f = 1
        elif fplx == '04' or fplx == '10' or fplx == '11' or fplx == '14':
            if len(xym) >= 6:
                if not self.ajy(xym):
                    # print("校验码有误!")
                    f = 0
                else:
                    # print("校验码 ok")
                    f = 1
            else:
                # print("请输入校验码<font color=\"red\" size=\"4\">后六位</font>")
                f = 0
        return f

    def ahm(self, fphm):
        _0xeebfd6 = 11
        _0x24a787 = re.compile(r'^\d{8}$')
        _0x53a761 =  re.compile(r'^0{8}$')
        _0x58f41b =  re.compile(r'^0{11}-?[1-9]*\w\d*$')
        _0x2b969d = re.findall(_0x24a787, fphm)
        _0x888a6c = re.findall(_0x53a761, fphm)
        if _0x2b969d and not _0x888a6c:
            return True
        else:
            return False

    def ahmch(self, fphm, fpdm):
        f = 0
        if len(fphm) == 20:
            _0x108e78 = self.getSwjg(fphm, 0, fphm)
            if len(_0x108e78) == 0:
                # print("发票号码有误!")
                f = 0
        if (not self.ckxdphm(fphm) and not self.ahm(fphm)):
            # print("fpdm -->发票号码有误!")
            f = 0
        else:
            # print("fpdm -->")
            f = 1
        if (self.ckxdphm(fphm) and '' == fphm):
            # print("fpdm -->")
            f = 1
        elif self.ckxdphm(fphm) and len(fpdm) > 0:
            # print("发票代码有误!")
            f = 0
        return f

    def run(self):
        i = self.seed
        lx = self.alxd(i['fpdm'], i['fphm'])
        logging.info(f"leix{lx}")
        if lx == '04' or lx == '10' or lx == '11' or lx == '14':
            jym = i['jym'][-6::] if i['jym'] else ''
        else:
            jym = ""
        if len(i['fphm']) >= 8:
            f1 = self.ahmch(i['fphm'], i['fpdm'])
            logging.info(f"发票效验结果{f1}")
        f2 = self.afcdm(i['fpdm'], i['fphm'])
        logging.info(f"发票效验结果{f2}")
        rq = self.kprqChange(i['kprq'])
        logging.info(f"发票日期 {rq}")

        f4 = self.kjje(self.alxd(i['fpdm'], i['fphm']), jym, i['fpdm'], i['kjje'])
        logging.info(f"开具金额或xym {f4}")
        if f1 and f2 and rq and lx and f4:
            return True
        else:
            return False

class GetChinatax(object):
    seed_key = 'finance:sp_invoice_api_queue'
    save_key = 'finance:sp_invoice_result'

    def __init__(self):
        logging.basicConfig(format='%(asctime)s %(name)s %(levelname)s %(message)s',
                            level=logging.INFO)
        self.seeds = [
            {
                '@class': 'com.alibaba.fastjson.JSONObject',
                'fpdm': '044002207111',
                'kprq': '20240202',
                'u_key': '1762290799569014785',
                'kjje': '15.13',
                'fphm': '93152922',
                'jym': '03848091989844314307'
            },
            {
                '@class': 'com.alibaba.fastjson.JSONObject',
                'fpdm': '012002300411',
                'kprq': '20240408',
                'u_key': '1777534576655077378',
                'kjje': '684.0',
                'fphm': '14051200',
                'jym': '76717940623559506327'
            },
            {
                '@class': 'com.alibaba.fastjson.JSONObject',
                'fpdm': '',
                'kprq': '20240228',
                'u_key': '1766026076514947073',
                'kjje': '5400.0',
                'fphm': '24312000000053951488',
                'jym': ''
            },
            {
                '@class': 'com.alibaba.fastjson.JSONObject',
                'fpdm': '',
                'kprq': '20240125',
                'u_key': '1762044625893199873',
                'kjje': '367.9',
                'fphm': '24952000000011841047',
                'jym': ''
            },
            {
                '@class': 'com.alibaba.fastjson.JSONObject',
                'fpdm': '043002300211',
                'kprq': '20240108',
                'u_key': '1777530368090443777',
                'kjje': '402.0', 'fphm': '23773186', 'jym': '07123931958135572121'
            },
            {'@class': 'com.alibaba.fastjson.JSONObject', 'fpdm': '', 'kprq': '20240301',
             'u_key': '1777597343214866433', 'kjje': '33.29', 'fphm': '24932000000013215584', 'jym': ''},
            {'@class': 'com.alibaba.fastjson.JSONObject', 'fpdm': '', 'kprq': '20240226',
             'u_key': '1777597345186189314', 'kjje': '53.0', 'fphm': '24332000000046699605', 'jym': ''},
            {'@class': 'com.alibaba.fastjson.JSONObject', 'fpdm': '', 'kprq': '20240306',
             'u_key': '1777597337967792129', 'kjje': '101.0', 'fphm': '24512000000035954687', 'jym': ''}
        ]

    def array2bytes(self, real_color, pic_name='1.png'):
        normal_img = cv2.imencode('.png', real_color)[1]
        normal_img = np.array(normal_img).tobytes()
        # 将提取出来的字符保存到本地方便查看
        # with open(pic_name, 'wb') as f:
        #     f.write(normal_img)
        ocr = ddddocr.DdddOcr()
        return ocr.classification(normal_img)

    def splitImg_new(self, img):
        height, width = img.shape[:2]
        blank_r = np.ones((height, width, 3), np.uint8)
        blank_r[:] = (255, 255, 255)
        blank_y = np.ones((height, width, 3), np.uint8)
        blank_y[:] = (255, 255, 255)
        blank_b = np.ones((height, width, 3), np.uint8)
        blank_b[:] = (255, 255, 255)
        blank_black = np.ones((height, width, 3), np.uint8)
        blank_black[:] = (255, 255, 255)
        for i in range(height):
            for j in range(width):
                '''取值范围设定'''
                bgr = img[i, j]
                if bgr[0] > 210 and bgr[1] < 80 and bgr[2] < 80:  # 蓝色
                    blank_b[i, j] = bgr
                if bgr[0] < 80 and bgr[1] > 210 and bgr[2] > 210:  # 黄色
                    blank_y[i, j] = bgr
                if bgr[0] < 80 and bgr[1] < 80 and bgr[2] > 210:  # 红色
                    blank_r[i, j] = bgr
                if bgr[0] < 80 and bgr[1] < 80 and bgr[2] < 80:  # 黑色
                    blank_black[i, j] = bgr
        return blank_r, blank_y, blank_b, blank_black

    def color_dispose(self, binary, color):
        img = cv2.imdecode(np.array(bytearray(binary), dtype='uint8'), cv2.IMREAD_UNCHANGED)
        real_red, real_yellow, real_blue, real_black = self.splitImg_new(img)
        if color == "red":
            yzm = self.array2bytes(real_red, '735cb9cb1c54f1d823773cd8c4f6a9d8.png')
        elif color == 'yellow':
            yzm = self.array2bytes(real_yellow, '735cb9cb1c54f1d823773cd8c4f6a9d8.png')
        elif color == 'blue':
            yzm = self.array2bytes(real_blue, '735cb9cb1c54f1d823773cd8c4f6a9d8.png')
        else:
            yzm = self.array2bytes(real_black, '735cb9cb1c54f1d823773cd8c4f6a9d8.png')
        return yzm

    def get_seed(self):
        while True:
            try:
                seeds = spop(self.seed_key, 1)
                break
            except FunctionTimedOut as e:
                logging.info(f"get seed timeout {e}")
                continue
            except rd.exceptions.ConnectionError as e:
                time.sleep(3)
                logging.info(f"sadd ConnectionError {e}")
                continue
        # seeds = self.seeds.pop()
        if seeds:
            seed = json.loads(seeds[0])
            sd = {}
            for k, v in seed.items():
                if type(v) == type(""):
                    sd[k] = v.strip()
                else:
                    sd[k] = ""
            try:
                if CheckSeed(sd).run():
                    return sd
                else:
                    logging.info(f"seeds 缺少字段 {seed}")
                    return None
            except Exception as e:
                logging.info(f"seeds 验证失败 {seed} {e}")
                return None
        else:
            return None

    # def get_fplx(self, fpdm, fphm):
    #     with open(r"./fp类型.js", "r", encoding="utf-8") as f:
    #         t = f.read()
    #         t = t.replace("012002300411", f"{fpdm}").replace("14051200", f"{fphm}")
    #         result = subprocess.run(['node', '-e', t], capture_output=True, text=True)
    #         d = result.stdout.split('\n')
    #         return d[0], d[1]
    #         # ctx = execjs.compile(t)
    #         # print(fpdm, fphm)
    #         # fplx = ctx.call('alxd', fpdm, fphm)
    #         # return fplx
    #     # with open(r"./fp类型.js", "r", encoding="utf-8") as f:
    #     #     m = js2py.EvalJs()
    #     #     m.execute(f.read())
    #     #     # alxd(fpdm, fphm)
    #     #     fplx = m.alxd(fpdm, fphm)
    #     #     return fplx

    # def get_address_url(self, fpdm, fphm):
    #     with open(r"./fp类型.js", "r", encoding="utf-8") as f:
    #         t = f.read()
    #         ctx = execjs.compile(t)
    #         address, url = ctx.call('getSwjg', fpdm, 0, fphm)
    #         return url
    #     # with open(r"./fp类型.js", "r", encoding="utf-8") as f:
    #     #     m = js2py.EvalJs()
    #     #     m.execute(f.read())
    #     #     # getSwjg(fpdm, 0, fphm)
    #     #     address, url = m.getSwjg(fpdm, 0, fphm)
    #     # return url

    def yzm_responses(self, params, address_url):
        headers = {
            "Accept": "*/*",
            "Accept-Language": "zh-CN,zh;q=0.9",
            "Referer": "https://inv-veri.chinatax.gov.cn/",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        }
        cookies = {
        }
        url = f"{address_url}/yzmQuery"

        response = requests.get(url, headers=headers, cookies=cookies, params=params, verify=False, timeout=5)
        data = response.json()
        return data

    def get_yzm(self, yzm_api):
        color_dict = {
            "00": "全部",
            "01": "red",
            "02": "yellow",
            "03": "blue",
        }

        color = color_dict.get(yzm_api['key4'])

        byte_data = base64.b64decode(yzm_api['key1'])

        yzm_msg = self.color_dispose(byte_data, color)
        return color, byte_data, yzm_msg

    def get_fpdata(self, seed):
        t = int(time.time())
        p = {
            "fpdm": seed['fpdm'] if seed['fpdm'] else seed['fphm'][:-8],
            "fphm": seed['fphm'][-8:] if len(seed['fphm']) >= 8 else seed['fphm'],
            # "r": "0.7694841765371436",
            "v": "2.0.21_050",
            "nowtime": f"{t}",
            "publickey": f"{t}",
            # "_": "1708920487460",
            # "flwq39": "FBzQpFvY8PEAY7qio3tHQ^%^2Bg0VC7J^%^2ByOT^%^2F7oAuetMPuCt6zr4H20^%^2BMXGH^%^2Fw1AB48RarmtqPnl2^%^2FwQKD6fGcWCJApn0K31ZcD9CM4KwOx1owxSPljdZ0Qc1DaqwbwIcLPZDG4Iqq7^%^2FAtif3^%^2F0oTNHoTVjXa8oxq58t7V9SmXK0MqM^%^3D"
        }
        p["key9"] = yzm(p['fpdm'], p['fphm'], p['nowtime'])
        p["flwq39"] = f39(p['fpdm'], p['fphm'], p['nowtime'])
        CheckSeed().alxd(seed.get("fpdm", ""), seed.get('fphm', ''))
        fplx = CheckSeed().alxd(seed.get("fpdm", ""), seed.get('fphm', ''))
        address_url = CheckSeed().getSwjg(seed.get("fpdm", ""), 0, seed.get('fphm', ''))[1]
        # https: // fpcy.beijing.chinatax.gov.cn: 443 / NWebQuery
        # address_url = address_url.split(".cn")[0] + '.cn/NWebQuery'
        # address_url = self.get_address_url(seed.get("fpdm", ""), seed.get('fphm', ''))
        # print(fplx, address_url)
        yzm_api = self.yzm_responses(p, address_url)

        color, byte_data, yzm_msg = self.get_yzm(yzm_api)
        # kjje = seed['jym'][-6::] if seed.get('jym') and len(seed.get('jym', '')) >= 6 else seed['kjje'].split('.')[0] if len(seed['kjje'].split('.')) == 1 else seed['kjje'].split('.')[0] if seed['kjje'].split('.')[1] in ['0', '00'] else seed['kjje']
        if fplx == '04' or fplx == '10' or fplx == '11' or fplx == '14':
            kjje = seed['jym'][-6::]
            logging.info("jym")
        else:
            kjje = seed['kjje'].split('.')[0] if len(seed['kjje'].split('.')) == 1 else seed['kjje'].split('.')[0] if seed['kjje'].split('.')[1] in ['0', '00'] else seed['kjje']
            logging.info("kjje")
        params = {
            # 发票代码
            "key1": f"{p['fpdm']}",
            # 发票号码
            "key2": f"{p['fphm']}",
            # 开票时间
            "key3": f"{seed['kprq']}",
            # 开票金额 kjje
            "key4": f"{kjje}",
            # 发票类型
            "fplx": f"{fplx}",
            # 图片验证码
            "yzm": f"{yzm_msg}",
            # 获取验证码请求的返回包里的key2
            "yzmSj": f"{yzm_api['key2']}",
            # 获取验证码请求的返回包里的Key3
            "index": f"{yzm_api['key3']}",
            # 获取验证码请求的返回包里的Key6
            "key6": f"{yzm_api['key6']}",
            # 获取验证码请求的返回包里的key2
            "publickey": f"{yzm_api['key2']}",
            # "_": "1708920487441",
        }
        params["key9"] = yzm_cy(p['fpdm'], p['fphm'], yzm_api['key2'])

        d = {
            "fpdm": p['fpdm'],
            "fphm": p['fphm'],
            "nowtime": yzm_api['key2'],

        }
        params["flwq39"] = f392_0x45c2e7(d, False)

        headers = {
            "Accept": "*/*",
            "Accept-Language": "zh-CN,zh;q=0.9",
            "Referer": "https://inv-veri.chinatax.gov.cn/",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        }
        # cookies = {
        # }
        url = f"{address_url}/vatQuery"
        img_base = "data:image/png;base64," + yzm_api['key1']
        logging.info(f"图片： \n{img_base} \n颜色： {color} \n验证码：{yzm_msg} \n发票类型: {fplx} \n url: {url}")
        response = requests.get(url, headers=headers, params=params, verify=False, timeout=5)
        logging.info(f"params {params}")
        logging.info(f"seed {seed}")
        return response.json()

    def main(self, seed):
        for i in range(0, 9):
            data = self.get_fpdata(seed)
            if data.get("key2"):
                data = {
                    "u_key": seed.get("u_key"),
                    "dom": json.dumps(data),
                }
                logging.info(f"data {data}")
                while True:
                    try:
                        xadd(self.save_key, data)
                        break
                    except FunctionTimedOut as e:
                        logging.info(f"xadd timeout {e}")
                        continue
                    except rd.exceptions.ConnectionError as e:
                        time.sleep(3)
                        logging.info(f"sadd ConnectionError {e}")
                        continue
                logging.info(f"seed spider ok --> {seed}")
                return data
            else:
                if i == 8:
                    # logging.info(f"将seed重新推送到redis {seed}")
                    # data = {
                    #     "u_key": seed.get("u_key"),
                    #     "dom": f"url verify error",
                    # }
                    # while True:
                    #     try:
                    #         xadd(self.save_key, data)
                    #         break
                    #     except FunctionTimedOut as e:
                    #         logging.info(f"xadd timeout {e}")
                    #         continue
                    #     except rd.exceptions.ConnectionError as e:
                    #         time.sleep(3)
                    #         logging.info(f"sadd ConnectionError {e}")
                    #         continue
                    logging.info(f"请求失败8次跳过 {data}")
                    continue
                else:
                    logging.info(f"请求失败 {data}")
                    continue

    def run(self):
        while True:
            logging.info("-------")
            seed = self.get_seed()
            try:
                if seed:
                    self.main(seed)
                else:
                    time.sleep(30)
                    logging.info('no task sleep 30s')
            except FunctionTimedOut as e:
                logging.info(f"--> FunctionTimedOut {seed}")
                while True:
                    try:
                        sadd(self.seed_key, json.dumps(seed), use_md5=False)
                        break
                    except FunctionTimedOut as e:
                        logging.info(f"sadd timeout {e}")
                        continue
                    except rd.exceptions.ConnectionError as e:
                        time.sleep(3)
                        logging.info(f"sadd ConnectionError {e}")
                        continue
                continue
            except requests.exceptions.Timeout as e:
                logging.info(f"--> requests  Timeout {seed}")
                while True:
                    try:
                        sadd(self.seed_key, json.dumps(seed), use_md5=False)
                        break
                    except FunctionTimedOut as e:
                        logging.info(f"sadd timeout {e}")
                        continue
                    except rd.exceptions.ConnectionError as e:
                        time.sleep(3)
                        logging.info(f"sadd ConnectionError {e}")
                        continue
                continue
            except Exception as e:
                logging.info(f"Incorrect padding error {e} {seed}")
                while True:
                    try:
                        sadd(self.seed_key, json.dumps(seed), use_md5=False)
                        break
                    except FunctionTimedOut as e:
                        logging.info(f"sadd timeout {e}")
                        continue
                    except rd.exceptions.ConnectionError as e:
                        time.sleep(3)
                        logging.info(f"sadd ConnectionError {e}")
                        continue
                # time.sleep(600)
                logging.info("sleep --> 600")
                continue
            except rd.exceptions.ConnectionError as e:
                time.sleep(3)
                logging.info(f"sadd ConnectionError {e}")
                while True:
                    try:
                        sadd(self.seed_key, json.dumps(seed), use_md5=False)
                        break
                    except FunctionTimedOut as e:
                        logging.info(f"sadd timeout {e}")
                        continue
                    except rd.exceptions.ConnectionError as e:
                        time.sleep(3)
                        logging.info(f"sadd ConnectionError {e}")
                        continue
                continue


if __name__ == '__main__':
    GetChinatax().run()


# # nohup python api_check_hc.py > chinatax_hc_check.log 2>&1 &