package service import ( "context" butil "enterprise/base/util" "enterprise/common/config" "enterprise/common/dao" "enterprise/common/global" "enterprise/common/model" "fmt" "git.u8t.cn/open/gosdk/qyweixin" "git.u8t.cn/open/gosdk/wechat/message" "github.com/gogap/errors" log "github.com/sirupsen/logrus" "github.com/smartwalle/alipay/v3" "github.com/smbrave/goutil" "github.com/spf13/cast" "strings" ) var ( SpStatusCreated = 1 SpStatusPassed = 2 SpStatusRefused = 3 SpStatusCanceled = 4 SpStatusPassedCanceled = 6 ) type Approve struct { corp *model.Corp corpConfig *model.CorpConfig approveClient *qyweixin.AppApprove } func NewApprove(corp *model.Corp) *Approve { return &Approve{ corp: corp, corpConfig: corp.GetConfig(), } } func (b *Approve) Reply(msg message.MixMessage) *message.Reply { if b.approveClient == nil { b.approveClient = qyweixin.NewAppApprove(&qyweixin.AppConfig{ Corpid: b.corpConfig.CorpId, Secret: b.corpConfig.ApproveSecret, Agent: b.corpConfig.ApproveAgent, }) } go b.handle(&msg) return &message.Reply{message.MsgTypeText, message.NewText("")} } func (a *Approve) handle(msg *message.MixMessage) { msgType := msg.MsgType if msgType == message.MsgTypeEvent { event := strings.ToUpper(string(msg.Event)) if event == message.EventClick { a.handleClick(msg) } else if event == "SYS_APPROVAL_CHANGE" { a.handleApprovalChange(msg) } } else if msgType == message.MsgTypeText { a.handleText(msg) } log.Infof(goutil.EncodeJSONIndent(msg)) } func (a *Approve) handleApprovalChange(msg *message.MixMessage) { spStatus := msg.ApprovalInfo.SpStatus spNo := msg.ApprovalInfo.SpNo templateId := msg.ApprovalInfo.TemplateId // 支出里审批通过的 或者审批通过撤销的 if spStatus != SpStatusPassed && spStatus != SpStatusPassedCanceled { return } detail, err := a.approveClient.GetDetail(spNo) if err != nil { log.Errorf("get spn detail error :%s", err.Error()) return } if detail == nil { } log.Infof("spno: %s detail: %s", spNo, goutil.EncodeJSON(detail)) if templateId == a.corpConfig.TplIdRefund { a.handleRefund(detail, spStatus) } else if templateId == a.corpConfig.TplIdVacation { a.handleVacation(detail, spStatus) } else if templateId == a.corpConfig.TplIdCheckin { a.handleCheckin(detail, spStatus) } else if templateId == a.corpConfig.TplIdPayment { a.handlePayment(detail, spStatus) } } func (a *Approve) handlePayment(detail *qyweixin.ApproveDetail, spStatus int) { newData := new(model.ApprovalPayment) newData.From(detail) newData.CorpId = a.corp.Id dbDao := dao.NewApprovalPaymentDao() old, err := dbDao.GetBySpNo(a.corp.Id, detail.SpNo) if err != nil { log.Errorf("db error :%s", err.Error()) return } if spStatus == SpStatusPassedCanceled { if old != nil { dbDao.Delete(old.Id) } return } if old != nil { newData.Id = old.Id newData.CreateTime = old.CreateTime err = dbDao.Update(newData) } else { _, err = dbDao.Create(newData) } if err != nil { log.Errorf("db error :%s", err.Error()) return } } func (a *Approve) handleVacation(detail *qyweixin.ApproveDetail, spStatus int) { newData := new(model.ApprovalVacation) newData.From(detail) newData.CorpId = a.corp.Id dbDao := dao.NewApprovalVacationDao() old, err := dbDao.GetBySpNo(a.corp.Id, detail.SpNo) if err != nil { log.Errorf("db error :%s", err.Error()) return } if spStatus == SpStatusPassedCanceled { if old != nil { dbDao.Delete(old.Id) } return } if old != nil { newData.Id = old.Id newData.CreateTime = old.CreateTime err = dbDao.Update(newData) } else { _, err = dbDao.Create(newData) } if err != nil { log.Errorf("db error :%s", err.Error()) return } } func (a *Approve) handleCheckin(detail *qyweixin.ApproveDetail, spStatus int) { newData := new(model.ApprovalCheckin) newData.From(detail) newData.CorpId = a.corp.Id dbDao := dao.NewApprovalCheckinDao() old, err := dbDao.GetBySpNo(a.corp.Id, detail.SpNo) if err != nil { log.Errorf("db error :%s", err.Error()) return } if spStatus == SpStatusPassedCanceled { if old != nil { dbDao.Delete(old.Id) } return } if old != nil { newData.Id = old.Id newData.CreateTime = old.CreateTime err = dbDao.Update(newData) } else { _, err = dbDao.Create(newData) } if err != nil { log.Errorf("db error :%s", err.Error()) return } } func (a *Approve) refundWxpay(data *model.ApprovalRefund) error { openid, err := a.approveClient.GetOpenid(data.Username) if err != nil { log.Errorf("GetOpenid error :%s", err.Error()) return err } var req qyweixin.PayReq req.BillNo = fmt.Sprintf("BX%s%s", data.SpNo, butil.CutTail(data.Username, 12)) req.Title = fmt.Sprintf("【%s】报销", data.RefundType) req.Openid = openid req.TotalAmount = int64(100 * data.RefundAmount) qyPay := qyweixin.NewAppPay(&qyweixin.PayConfig{ Corpid: a.corpConfig.CorpId, Secret: a.corpConfig.PaySecret, Agent: a.corpConfig.PayAgent, SerialNumber: config.GetConfig().WxPay.PaySerialNumber, ApiKey: config.GetConfig().WxPay.PayApiKeyV2, MchId: config.GetConfig().WxPay.PayMchId, CertPem: config.GetConfig().WxPay.PayCertPem, KeyPem: config.GetConfig().WxPay.PayKeyPem, }) if err = qyPay.PayMoney(&req); err != nil { log.Errorf("pay error[%s] :%s", goutil.EncodeJSON(req), err.Error()) return err } return nil } func (a *Approve) refundAlipay(staff *model.StaffUser, data *model.ApprovalRefund) error { userPayee := staff.GetPayee() cli := config.GetAliPayClient("batiao") var req alipay.FundTransUniTransfer req.Remark = "报销_" + data.SpNo req.OutBizNo = fmt.Sprintf("BX%s%s", data.SpNo, butil.CutTail(data.Username, 12)) req.TransAmount = cast.ToString(data.RefundAmount) req.ProductCode = "TRANS_ACCOUNT_NO_PWD" req.BizScene = "DIRECT_TRANSFER" req.OrderTitle = data.RefundRemark payee := new(alipay.PayeeInfo) req.PayeeInfo = payee payee.IdentityType = "ALIPAY_USER_ID" payee.Identity = userPayee.AlipayUid rsp, err := cli.FundTransUniTransfer(context.Background(), req) if err != nil { panic(err) } if !rsp.IsSuccess() { log.Errorf("FundTransUniTransfer error :%s", goutil.EncodeJSON(rsp)) return errors.New(goutil.EncodeJSON(rsp)) } return nil } func (a *Approve) handleRefund(detail *qyweixin.ApproveDetail, spStatus int) { newData := new(model.ApprovalRefund) newData.From(detail) newData.CorpId = a.corp.Id dbDao := dao.NewApprovalRefundDao() old, err := dbDao.GetBySpNo(a.corp.Id, detail.SpNo) if err != nil { log.Errorf("db error :%s", err.Error()) return } if spStatus == SpStatusPassedCanceled { if old != nil { dbDao.Delete(old.Id) } return } if old != nil { newData.Id = old.Id newData.CreateTime = old.CreateTime err = dbDao.Update(newData) } else { _, err = dbDao.Create(newData) } if err != nil { log.Errorf("db error :%s", err.Error()) return } //只有八条科技才自动付款 if a.corp.Id != 1000 { return } staffUser, err := dao.NewStaffUserDao().GetByUsername(1000, newData.Username) if err != nil { log.Errorf("db error :%s", err.Error()) return } userPayee := staffUser.GetPayee() // 支付费用 var payType = "weixin" if userPayee.AlipayUid != "" { err = a.refundAlipay(staffUser, newData) payType = "alipay" } else { err = a.refundWxpay(newData) } var title string = "【报销成功】" if err == nil { newData.Status = model.ApprovalRefundStatusPayed } else { title = "【报销失败】" } message := make([]string, 0) message = append(message, title) message = append(message, fmt.Sprintf("发放金额:%s", fmt.Sprintf("%.2f", newData.RefundAmount))) message = append(message, fmt.Sprintf("费用类型:%s", newData.RefundType)) message = append(message, fmt.Sprintf("支付方式:%s", payType)) message = append(message, fmt.Sprintf("员工名称:%s", newData.Username)) message = append(message, fmt.Sprintf("费用说明:%s", newData.RefundRemark)) if err != nil { message = append(message, fmt.Sprintf("异常:%s", err.Error())) } if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil { log.Errorf("send message error :%s", err.Error()) } if err := dao.NewApprovalRefundDao().Update(newData); err != nil { log.Errorf("db error :%s", err.Error()) } } func (a *Approve) HandleRefundApprove(approve *model.ApprovalRefund) error { staff, err := dao.NewStaffUserDao().GetByUsername(approve.CorpId, approve.Username) if err != nil { return err } if staff == nil { return errors.New("staff is not exist") } // 支付费用 var payType = "weixin" payee := staff.GetPayee() if payee.AlipayUid != "" { err = a.refundAlipay(staff, approve) payType = "alipay" } else { err = a.refundWxpay(approve) } var title string = "【报销成功】" if err == nil { approve.Status = model.ApprovalRefundStatusPayed } else { title = "【报销失败】" } message := make([]string, 0) message = append(message, title) message = append(message, fmt.Sprintf("发放金额:%s", fmt.Sprintf("%.2f", approve.RefundAmount))) message = append(message, fmt.Sprintf("费用类型:%s", approve.RefundType)) message = append(message, fmt.Sprintf("支付方式:%s", payType)) message = append(message, fmt.Sprintf("员工名称:%s", approve.Username)) message = append(message, fmt.Sprintf("费用说明:%s", approve.RefundRemark)) if err != nil { message = append(message, fmt.Sprintf("异常:%s", err.Error())) } if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil { log.Errorf("send message error :%s", err.Error()) } if err := dao.NewApprovalRefundDao().Update(approve); err != nil { log.Errorf("db error :%s", err.Error()) } return nil } func (a *Approve) handleText(msg *message.MixMessage) { } func (a *Approve) handleClick(msg *message.MixMessage) { } func (a *Approve) sendText(message string) { }