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 ) type Approve struct { approveClient *qyweixin.AppApprove } func (b *Approve) Reply(msg message.MixMessage) *message.Reply { if b.approveClient == nil { cfg := config.GetConfig() b.approveClient = qyweixin.NewAppApprove(&qyweixin.AppConfig{ Corpid: cfg.QyWeixin.Corpid, Secret: cfg.QyWeixin.ApproveSecret, Agent: cfg.QyWeixin.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 { return } detail, err := a.approveClient.GetDetail(spNo) if err != nil { log.Errorf("get spn detail error :%s", err.Error()) return } log.Infof("spno: %s detail: %s", spNo, goutil.EncodeJSON(detail)) if templateId == model.ApprovalTpIdRefund { a.handleRefund(detail) } else if templateId == model.ApprovalTpIdVacation { a.handleVacation(detail) } else if templateId == model.ApprovalTpIdCheckin { a.handleCheckin(detail) } else if templateId == model.ApprovalTpIdPayment { a.handlePayment(detail) } } func (a *Approve) handlePayment(detail *qyweixin.ApproveDetail) { newData := new(model.ApprovalPayment) newData.From(detail) dbDao := dao.NewApprovalPaymentDao() old, err := dbDao.GetBySpNo(detail.SpNo) if err != nil { log.Errorf("db error :%s", err.Error()) 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) { newData := new(model.ApprovalVacation) newData.From(detail) dbDao := dao.NewApprovalVacationDao() old, err := dbDao.GetBySpNo(detail.SpNo) if err != nil { log.Errorf("db error :%s", err.Error()) 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) { newData := new(model.ApprovalCheckin) newData.From(detail) dbDao := dao.NewApprovalCheckinDao() old, err := dbDao.GetBySpNo(detail.SpNo) if err != nil { log.Errorf("db error :%s", err.Error()) 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) handleRefundWxpay(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: config.GetConfig().QyWeixin.Corpid, Secret: config.GetConfig().QyWeixin.PaySecret, Agent: config.GetConfig().QyWeixin.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) handleRefundAlipay(staff *model.StaffInfo, data *model.ApprovalRefund) error { 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 = staff.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) { newData := new(model.ApprovalRefund) newData.From(detail) dbDao := dao.NewApprovalRefundDao() old, err := dbDao.GetBySpNo(detail.SpNo) if err != nil { log.Errorf("db error :%s", err.Error()) 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 } staff, err := dao.NewStaffInfoDao().GetByUsername(newData.Username) if err != nil { log.Errorf("db error :%s", err.Error()) return } // 支付费用 var payType = "weixin" if staff != nil && staff.AlipayUid != "" { err = a.handleRefundAlipay(staff, newData) payType = "alipay" } else { err = a.handleRefundWxpay(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) handleText(msg *message.MixMessage) { } func (a *Approve) handleClick(msg *message.MixMessage) { } func (a *Approve) sendText(message string) { }