package service import ( "ElectronicInvoice/util" "context" "fmt" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gcron" "time" ) var ( JyInvoiceManager *InvoiceManager ) type InvoiceManager struct { Auth *TripartiteAuth jobRunning bool //开票是否运行中 StopRunning bool //财务占用账号,需要暂停任务 Login bool //登录状态 RunPool chan bool //任务(每次只能进行一个开票任务) phoneCode chan string //短信验证码池 ScanLogin chan bool //扫码登录 } func init() { JyInvoiceManager = createInvoiceManager() //开票任务 job, err := gcron.Add(context.Background(), g.Cfg().MustGet(context.Background(), "invoiceJob.cron").String(), JyInvoiceManager.RunJob, "invoiceJob") if err != nil { panic(err) } job.Start() //超时开票提醒 jobNotice, errNotice := gcron.Add(context.Background(), g.Cfg().MustGet(context.Background(), "invoiceJob.notice.unFinish.cron").String(), JyInvoiceManager.NoticeJob, "invoiceNoticeJob") if errNotice != nil { panic(errNotice) } jobNotice.Start() //初始化三方接口 JyInvoiceManager.Auth.CallBackInit() //go func() { // time.Sleep(time.Second * 5) // JyInvoiceManager.RunRedBatchOnce(context.Background()) //}() //go JyInvoiceManager.RunOneJob(context.Background())//流程 //go JyInvoiceManager.Demo(context.Background()) //开票 //go JyInvoiceManager.Auth.Login() //登录 //go JyInvoiceManager.RedDemo(context.Background())//红冲 //err = JyInvoiceManager.Auth.AddTaxCode([]Billitem{{ // Name: "技术服务费", // Ssflbm: "3040205000000000000", // Thirdid: "6f2e6a7a-18a7-4f21-b52e-a47437f817cc", //}}) //if err != nil { // panic(err) //} //list, err := JyInvoiceManager.Auth.GetSuccessTaxCodeList() //g.Dump(list, err) } func createInvoiceManager() *InvoiceManager { return &InvoiceManager{ Auth: createTripartite(), Login: true, //默认已经登录 RunPool: make(chan bool, 1), //开票只能单线程跑 phoneCode: make(chan string, 1), //手机验证码 ScanLogin: make(chan bool, 1), //扫码登录通知 } } func (im *InvoiceManager) MobileVerificationCode(code string) error { if code == "" { return gerror.New("验证码为空") } select { case <-time.After(time.Minute): return gerror.New("验证码接收超时") case im.phoneCode <- code: return nil } } func (im *InvoiceManager) MobileVerificationClear() error { select { case <-time.After(time.Minute): return gerror.New("清除验证码超时") case <-im.phoneCode: return nil } } // RunJob 开票定时任务 func (im *InvoiceManager) RunJob(ctx context.Context) { if im.jobRunning || im.StopRunning { g.Log().Infof(ctx, "RunJob-程序本次任务中断 jobRunning:%v StopRunning:%v", im.jobRunning, im.StopRunning) return } im.jobRunning = true defer func() { im.jobRunning = false g.Log().Infof(ctx, "RunJob-开票任务完成") }() if g.Cfg().MustGet(ctx, "invoiceJob.stop", false).Bool() { g.Log().Infof(ctx, "RunJob-开票程序任务已暂停,开启请删除 config.json > invoiceJob.stop") return } if !im.Login { if err := im.Auth.Login(); err != nil { g.Log().Errorf(ctx, "模拟登录异常 %v", err) return } else { g.Log().Infof(ctx, "登录成功") } } //TODO 普通蓝票任务(线上开票、管理后台一个订单开多张票) total, okNum, end, err := im.simpleMakeInvoice(ctx) if err != nil { g.Log().Errorf(ctx, "RunJob-simpleMakeInvoice任务异常 %v", err) if end { return } } g.Log().Infof(ctx, "RunJob-simpleMakeInvoice任务完成 共%d个 完成%d个", total, okNum) // TODO 多订单合并开票(管理后台-多订单合并开票) total, okNum, end, err = im.multipleOrdersMakeInvoice(ctx) if err != nil { g.Log().Errorf(ctx, "RunJob-multipleOrdersMakeInvoice任务异常 %v", err) if end { return } } g.Log().Infof(ctx, "RunJob-multipleOrdersMakeInvoice任务完成 共%d个 完成%d个", total, okNum) // TODO 红冲(线上开票、管理后台一个订单开多张票) total, okNum, end, err = im.makeRedInvoice(ctx) if err != nil { g.Log().Errorf(ctx, "RunJob-makeRedInvoice任务异常 %v", err) if end { return } } g.Log().Infof(ctx, "RunJob-makeRedInvoice任务完成 共%d个 完成%d个", total, okNum) // TODO 红冲(线上开票、管理后台一个订单开多张票) total, okNum, end, err = im.multipleOrdersMakeRedInvoice(ctx) if err != nil { g.Log().Errorf(ctx, "RunJob-multipleOrdersMakeRedInvoice任务异常 %v", err) if end { return } } //保证所有回调已执行完成 select { case im.RunPool <- true: case <-time.After(time.Minute * 5): g.Log().Infof(ctx, "RunJob-等待回调完成超时") return } <-im.RunPool g.Log().Infof(ctx, "RunJob-multipleOrdersMakeRedInvoice任务完成 共%d个 完成%d个", total, okNum) } // NoticeJob 为开票成功提示 func (im *InvoiceManager) NoticeJob(ctx context.Context) { var ( unMakeRed = 0 unMakeBlue = 0 limitHours = g.Cfg().MustGet(ctx, "invoiceJob.notice.unFinish.hours", 24).Int64() ) if im.StopRunning { return } createTimeLimit := time.Now().Unix() - limitHours*60*60 // 蓝票未完成发票数量查询 unMakeBlue, _ = g.DB().GetCount(ctx, `SELECT count(*) FROM( SELECT a.id as onlyId FROM invoice a WHERE a.invoice_variety like '%电子%' AND ((a.invoice_status=0 AND a.invoice_changed=0) or (a.invoice_status=2 AND a.invoice_changed=1 )) AND (a.invoice_order_code is NULL OR a.invoice_order_code not like '%,%') AND a.create_time > UNIX_TIMESTAMP('2024-04-23 00:00:00') AND a.create_time UNIX_TIMESTAMP('2024-04-23 00:00:00') AND a.create_time UNIX_TIMESTAMP('2024-04-23 00:00:00') AND a.create_time UNIX_TIMESTAMP('2024-04-23 00:00:00') AND a.create_time 0 || unMakeBlue > 0 { noticeMsg := fmt.Sprintf("开票超%d小时提醒\n", limitHours) if unMakeBlue > 0 { noticeMsg += fmt.Sprintf("蓝票:%d例\n", unMakeBlue) } if unMakeRed > 0 { noticeMsg += fmt.Sprintf("红票:%d例\n", unMakeRed) } if err := util.SendSimpleMsg2ChatBot(noticeMsg, g.Cfg().MustGet(ctx, "invoiceJob.notice.unFinish.notice").Strings()...); err != nil { g.Log().Errorf(ctx, "发送未开票消息异常 %v", err) } } }