package main import ( "ElectronicInvoice/util" "context" "encoding/json" "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/grand" "github.com/gogf/gf/v2/util/guid" "strings" "time" ) type ( // 开发票 makeInvoiceAllParam struct { TaxNum string `json:"taxNum"` //企业税号* Tel string `json:"tel"` //登录电子税局手机号或身份证号* Data []MakeInvoiceData `json:"data"` } MakeInvoiceData struct { Type string `json:"type"` //票类* 1 增值税专用发票;2 普通发票 Gmfmc string `json:"gmfmc"` //购买方名称* 人名 Gmfnsrsbh string `json:"gmfnsrsbh"` //购买方纳税人识别号* 身份证号 Id string `json:"id"` //发票流水号* 合作商开具的发票流水号,涉及到回调通知 Gmfdz string `json:"gmfdz"` //购买方地址 Lxdh string `json:"lxdh"` //购买方联系方式 Yhyywdmc string `json:"yhyywdmc"` //购买方开户行 Yhzh string `json:"yhzh"` //购买方银行账号 Fhr string `json:"fhr"` //复核人 Notes string `json:"notes"` //发票备注 InvoiceArr []MakeInvoiceItems `json:"invoiceArr"` } MakeInvoiceItems struct { Xmmc string `json:"xmmc"` //项目名称* Je string `json:"je"` //开票金额* WhStatus int `json:"wh_status"` //该开票项是否已调用接口进行维护: 1 已维护;0 未维护 Xhgg string `json:"xhgg"` //型号规格 Dw string `json:"dw"` //单位 Sl string `json:"sl"` //数量 Tsaxrate string `json:"taxrate"` //税率 } //红冲 makeRedInvoiceAllParam struct { TaxNum string `json:"taxNum"` //企业税号* Tel string `json:"tel"` //登录电子税局手机号或身份证号* Data []MakeRedInvoiceData `json:"data"` } MakeRedInvoiceData struct { Num string `json:"num"` //蓝票号码 Date string `json:"date"` //购买方名称* 人名 } CommonRes struct { Code int `json:"code"` Msg string `json:"msg"` Data interface{} `json:"data"` } ) func main() { s := g.Server() s.Group("/", func(group *ghttp.RouterGroup) { group.POST("/authority_token/getToken", getToken) //获取token group.Group("/index_index", func(group2 *ghttp.RouterGroup) { group2.POST("/makeInvoiceC", makeInvoiceC) //开票 group2.POST("/makeRedC", makeRedC) //红票 }) }) s.Run() } var ( getToken = func(r *ghttp.Request) { resp := struct { Token string `json:"token"` ExpiresIn int `json:"expiresIn"` //一天有效期 }{ Token: fmt.Sprintf("MOCKTOKEN_%s", guid.S()), ExpiresIn: 60 * 60 * 24, } r.Response.Write(CommonRes{ Code: 200, Msg: "", Data: resp, }) } makeInvoiceC = func(r *ghttp.Request) { var ( ctx = r.Context() param = makeInvoiceAllParam{} ) err := json.Unmarshal(r.GetBody(), ¶m) if err != nil { g.Log().Errorf(ctx, "开票任务-接收参数异常 err:%v", err) return } g.Log().Infof(ctx, "开票任务-接收到开票信息:%s", gconv.String(param)) time.Sleep(time.Second * time.Duration(grand.Intn(3))) //模拟处理 //模拟开票纳税人识别号输入错误 if strings.Contains(strings.ToUpper(param.Data[0].Gmfnsrsbh), "XXXX") { r.Response.WriteJson(CommonRes{ Code: 201, Msg: "购买方纳税识别号-税号有误", }) return } go func() { goCtx := gctx.New() context, err := util.GetPdfBase64(fmt.Sprintf("./pdfDir/invoice_Blue_%s.pdf", param.Data[0].Type)) //pdf文件 if err != nil { g.Log().Errorf(goCtx, "读取pdf文件异常%v", err) return } callBackParam := g.Map{ "calltype": "Invoicing", "type": 1, "pdf": context, "num": fmt.Sprintf("MOCKBLUE_%s", guid.S()), "id": param.Data[0].Id, "kptime": time.Now().Format("2006-01-02 15:04:05"), "data": g.Map{ "jfUrl": g.Cfg().MustGet(goCtx, "jfUrl"), "xml": "", }, } //TODO 回调开票成功 ok := false for i := 0; i < 10; i++ { if checkCallBackOk(goCtx, callBackParam) { g.Log().Infof(goCtx, "开票任务-开票成功") ok = true break } time.Sleep(time.Second * 3) } //TODO 任务完成通知 for { if checkCallBackOk(goCtx, g.Map{"calltype": "quit", "data": g.Map{"taskType": "2"}}) { g.Log().Infof(goCtx, "开票任务-通知完成") break } time.Sleep(time.Second * 3) } if !ok { g.Log().Errorf(goCtx, "发票回调执行异常 %+v", callBackParam) } }() r.Response.WriteJson(CommonRes{ Code: 200, Msg: "", }) } makeRedC = func(r *ghttp.Request) { var ( ctx = r.Context() param = makeRedInvoiceAllParam{} ) err := json.Unmarshal(r.GetBody(), ¶m) if err != nil { g.Log().Errorf(ctx, "红冲任务-接收参数异常 err:%v", err) return } g.Log().Infof(ctx, "红冲任务-接收到红冲信息:%s", gconv.String(param)) time.Sleep(time.Second * time.Duration(grand.Intn(3))) //模拟处理 go func() { goCtx := gctx.New() context, err := util.GetPdfBase64("./pdfDir/invoice_Red.pdf") //pdf文件 if err != nil { g.Log().Errorf(goCtx, "读取pdf文件异常%v", err) return } callBackParam := g.Map{ "calltype": "offset", "type": 0, "pdf": context, "num": param.Data[0].Num, "offsetNum": fmt.Sprintf("MOCKRED_%s", guid.S()), "kptime": time.Now().Format("2006-01-02 15:04:05"), "data": g.Map{ "jfUrl": g.Cfg().MustGet(goCtx, "jfUrl"), "xml": "", }, } //TODO 回调红冲成功 ok := false for i := 0; i < 10; i++ { if checkCallBackOk(goCtx, callBackParam) { g.Log().Infof(goCtx, "红冲任务-红冲成功") break } time.Sleep(time.Second * 3) } //TODO 任务完成通知 for { if checkCallBackOk(goCtx, g.Map{"calltype": "quit", "data": g.Map{"taskType": "9"}}) { g.Log().Infof(goCtx, "红冲任务-通知完成") break } time.Sleep(time.Second * 3) } if !ok { g.Log().Errorf(goCtx, "发票回调执行异常 %+v", callBackParam) } }() r.Response.WriteJson(CommonRes{ Code: 200, Msg: "", }) } ) func checkCallBackOk(ctx context.Context, param map[string]interface{}) bool { res, err := g.Client().Header(g.MapStrStr{"Content-Type": "application/x-www-form-urlencoded"}).Post(ctx, g.Cfg().MustGet(ctx, "callBackAction").String(), param) if err != nil { g.Log().Errorf(ctx, "模拟请求异常 %v", err) return false } defer res.Close() rData := gconv.MapStrStr(res.ReadAll()) if rData["code"] == "200" { return true } return false }