123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- package service
- import (
- "ElectronicInvoice/internal/consts"
- "context"
- "github.com/gogf/gf/v2/database/gdb"
- "github.com/gogf/gf/v2/errors/gerror"
- "github.com/gogf/gf/v2/frame/g"
- "github.com/gogf/gf/v2/os/gcron"
- "github.com/gogf/gf/v2/util/gconv"
- "strconv"
- "time"
- )
- var (
- JyInvoiceManager *InvoiceManager
- )
- type InvoiceManager struct {
- Auth *TripartiteAuth
- jobRunning bool //开票是否运行中
- StopRunning bool //财务占用账号,需要暂停任务
- Login bool //登录状态
- OCRPass 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()
- //go JyInvoiceManager.RunOneJob(context.Background())//流程
- //go JyInvoiceManager.Demo(context.Background()) //开票
- //go JyInvoiceManager.RedDemo(context.Background())//红冲
- }
- func createInvoiceManager() *InvoiceManager {
- return &InvoiceManager{
- Auth: createTripartite(),
- Login: true, //默认已经登录
- OCRPass: true,
- runPool: make(chan bool, 1), //开票只能单线程跑
- phoneCode: make(chan string, 1), //手机验证码
- ScanLogin: make(chan bool, 1), //扫码登录通知
- }
- }
- func (im *InvoiceManager) ReleasePool() {
- <-im.runPool
- }
- 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, err := im.simpleMakeInvoice(ctx)
- if err != nil {
- if gerror.Is(err, consts.LoginOutErr) {
- g.Log().Infof(ctx, "RunJob-任务中止-身份过期,需要重新登录")
- return
- }
- g.Log().Errorf(ctx, "RunJob-开蓝票任务异常 %v", err)
- } else {
- g.Log().Infof(ctx, "RunJob-开蓝票任务完成 共%d个 完成%d个", total, okNum)
- }
- //TODO 红票任务
- }
- // simpleMakeInvoice 简单开票
- func (im *InvoiceManager) simpleMakeInvoice(ctx context.Context) (total, okNum int, err error) {
- var (
- res gdb.Result
- )
- //查询需要开票的数据
- res, err = g.DB().Query(ctx, "SELECT a.*,b.pay_way,b.order_money,b.pay_money FROM invoice a INNER JOIN dataexport_order b ON a.order_code=b.order_code WHERE a.invoice_status=0 AND a.invoice_changed=0 AND a.invoice_variety='普通发票(电子发票)' AND a.invoice_order_code is NULL")
- if err != nil {
- g.Log().Errorf(ctx, "RunJob-simpleMakeInvoice-查询待开票异常 %s", err)
- return -1, -1, gerror.Wrap(err, "simpleMakeInvoice-查询待开票异常")
- }
- g.Log().Infof(ctx, "RunJob-simpleMakeInvoice-本次共加载%d条开票记录", res.Len())
- total, okNum = res.Len(), 0
- for _, m := range res.List() {
- select {
- case im.runPool <- true:
- case <-time.After(time.Minute * 5):
- g.Log().Errorf(ctx, "RunJob-simpleMakeInvoice-开票等待超时,结束此次任务")
- return
- }
- var (
- orderCode = gconv.String(m["order_code"])
- phone = gconv.String(m["phone_num"])
- iType = gconv.String(m["invoice_type"])
- prices float64
- )
- //公对公转账 账单金额可以修改 开发票应取实付金额 pay_money
- //微信支付宝支付 pay_money为订单金额减去微信or支付包红包
- if gconv.String(m["pay_way"]) == "transferAccounts" {
- prices = gconv.Float64(m["pay_money"]) / float64(100)
- } else {
- prices = gconv.Float64(m["order_money"]) / float64(100)
- }
- c := MakeInvoiceData{
- Type: "2",
- Id: orderCode,
- Lxdh: phone,
- Fhr: g.Cfg().MustGet(ctx, "company.hfr", "贺鹏飞").String(),
- InvoiceArr: []MakeInvoiceItems{{
- Xmmc: g.Cfg().MustGet(ctx, "company.taxCode").String(), //开票项
- WhStatus: 1, //开票项是否维护
- Je: strconv.FormatFloat(prices, 'f', -1, 64), //金额
- Sl: "1", //数量
- }},
- }
- if iType == "单位" {
- c.Gmfmc = gconv.String(m["company_name"])
- c.Gmfnsrsbh = gconv.String(m["taxpayer_identnum"])
- } else {
- c.Gmfmc = iType
- }
- err = im.Auth.MakeSingleInvoice(c)
- if err != nil {
- im.ReleasePool()
- if gerror.Is(err, consts.LoginOutErr) {
- g.Log().Infof(ctx, "RunJob-simpleMakeInvoice-身份过期,需要重新登录")
- return
- }
- g.Log().Errorf(ctx, "RunJob-simpleMakeInvoice-开票接口调用异常 %v", err)
- continue
- }
- okNum++
- }
- return
- }
|