diff --git a/common/global/message.go b/common/global/message.go index a7762e6..1bcb3ce 100644 --- a/common/global/message.go +++ b/common/global/message.go @@ -3,16 +3,21 @@ package global import ( "context" "enterprise/common/config" + "enterprise/common/dao" "github.com/ArtisanCloud/PowerWeChat/v3/src/work" "github.com/ArtisanCloud/PowerWeChat/v3/src/work/message/request" + "github.com/gogap/errors" log "github.com/sirupsen/logrus" "github.com/smbrave/goutil" "github.com/spf13/cast" "strings" + "sync" ) var ( - wxEnterprise *work.Work + wxEnterprise *work.Work + corpEnterprise map[int64]*work.Work + corpEnterpriseMutex sync.Mutex ) func initWxWork() (*work.Work, error) { @@ -34,6 +39,40 @@ func initWxWork() (*work.Work, error) { return client, nil } +func getWxWork(corpId int64) (*work.Work, error) { + if c, ok := corpEnterprise[corpId]; ok { + return c, nil + } + + corp, err := dao.NewCorpDao().Get(corpId) + if err != nil { + return nil, err + } + if corp == nil { + return nil, errors.New("corp not exist") + } + + cfg := corp.GetConfig() + client, err := work.NewWork(&work.UserConfig{ + CorpID: cfg.CorpId, + AgentID: cast.ToInt(cfg.PayAgent), + Secret: cfg.PaySecret, + OAuth: work.OAuth{ + Callback: "https://wecom.artisan-cloud.com/callback", + Scopes: nil, + }, + }) + if err != nil { + log.Errorf("config[%s] init error : %s", goutil.EncodeJSON(cfg), err.Error()) + return nil, err + } + corpEnterpriseMutex.Lock() + corpEnterprise[corpId] = client + corpEnterpriseMutex.Unlock() + + return client, nil +} + func SendMessage(user []string, content string) error { if wxEnterprise == nil { wxM, err := initWxWork() @@ -56,3 +95,24 @@ func SendMessage(user []string, content string) error { } return nil } + +func SendCorpMessage(corpId int64, user []string, content string) error { + client, _ := getWxWork(corpId) + if client == nil { + return errors.New("client error ") + } + + corp, _ := dao.NewCorpDao().Get(corpId) + receivers := user + message := &request.RequestMessageSendText{} + message.ToUser = strings.Join(receivers, "|") + message.MsgType = "text" + message.AgentID = cast.ToInt(corp.GetConfig().PayAgent) + message.Text = &request.RequestText{Content: content} + + if _, err := client.Message.SendText(context.Background(), message); err != nil { + log.Errorf("send message [%s] error : %s", goutil.EncodeJSON(message), err) + return err + } + return nil +} diff --git a/common/model/staff_salary.go b/common/model/staff_salary.go index d02fc86..4d5ef8e 100644 --- a/common/model/staff_salary.go +++ b/common/model/staff_salary.go @@ -3,6 +3,7 @@ package model import ( "encoding/json" butil "enterprise/base/util" + "fmt" "github.com/smbrave/goutil" "github.com/spf13/cast" "strings" @@ -66,6 +67,12 @@ func (s *StaffSalary) SetExtra(key string, value interface{}) { s.Extra = goutil.EncodeJSON(extra) } +func (s *StaffSalary) GetBillUrl() string { + encId := goutil.EncryptID(s.Id, "@@salary@@") + billUrl := fmt.Sprintf("https://e.yubanqy.com/api/staff/salary/bill?id=%s", encId) + return billUrl +} + type StaffSalarySort []*StaffSalary func (s StaffSalarySort) Len() int { diff --git a/server/controller/payment.go b/server/controller/payment.go index 8c528dc..3ce484d 100644 --- a/server/controller/payment.go +++ b/server/controller/payment.go @@ -6,6 +6,7 @@ import ( "enterprise/server/api" "enterprise/server/service" "enterprise/server/session" + CommonService "enterprise/service" "fmt" "github.com/gin-gonic/gin" "github.com/smbrave/goutil" @@ -24,7 +25,7 @@ func (q *Payment) AlipayAuth(ctx *gin.Context) { authCode := ctx.Query("auth_code") state := ctx.Query("state") - userid, staffUser := service.NewPay().AlipayAuth(sess, authCode, state) + userid, staffUser := service.NewPayment().AlipayAuth(sess, authCode, state) username := goutil.If(staffUser.Realname != "", staffUser.Realname, staffUser.Username) ctx.HTML(http.StatusOK, "alipay.html", gin.H{ "title": "绑定成功", @@ -50,7 +51,9 @@ func (q *Payment) Pay(ctx *gin.Context) { session.CheckDBError(err) session.CheckNilError(user, fmt.Sprintf("用户[%s]不存在", req.Username)) - service.NewPay().Pay(corp, user, req.Title, req.PayType, req.Amount) + if err = CommonService.NewPay().Pay(corp, user, req.Title, req.PayType, req.Amount); err != nil { + panic(config.ErrInternal.New().Append(err)) + } ctx.JSON(http.StatusOK, session.NewRspOk()) } diff --git a/server/service/payment.go b/server/service/payment.go index 9842ca0..76af36e 100644 --- a/server/service/payment.go +++ b/server/service/payment.go @@ -1,9 +1,16 @@ package service import ( + "context" + "enterprise/common/config" "enterprise/common/dao" + "enterprise/common/model" "enterprise/server/api" "enterprise/server/session" + log "github.com/sirupsen/logrus" + "github.com/smartwalle/alipay/v3" + "github.com/smbrave/goutil" + "github.com/spf13/cast" "time" ) @@ -40,3 +47,36 @@ func (p *Payment) Suggest(sess *session.AdminSession, field string) interface{} } return counts } + +func (p *Payment) AlipayAuth(sess *session.AdminSession, authCode, state string) (string, *model.StaffUser) { + + corp, err := dao.NewCorpDao().GetByHost(sess.GetHeader().Host) + session.CheckDBError(err) + session.CheckNilError(corp) + cli := config.GetAliPayClient("batiao") + + var req alipay.SystemOauthToken + req.Code = authCode + req.GrantType = "authorization_code" + res, err := cli.SystemOauthToken(context.Background(), req) + if err != nil { + log.Errorf("error :%s", err.Error()) + panic(config.ErrInternal.New().Append(err)) + } + if !res.IsSuccess() { + log.Errorf(goutil.EncodeJSON(res)) + panic(config.ErrInternal.New().Append(goutil.EncodeJSON(res))) + } + + staffUser, err := dao.NewStaffUserDao().Get(cast.ToInt64(state)) + session.CheckDBError(err) + session.CheckNilError(staffUser) + payee := staffUser.GetPayee() + oldUid := payee.AlipayUid + payee.AlipayUid = res.UserId + staffUser.Payee = goutil.EncodeJSON(payee) + err = dao.NewStaffUserDao().Update(staffUser) + session.CheckDBError(err) + log.Errorf("staffuser[%d] alipayUid[%s]->alipayUid[%s]", staffUser.Id, oldUid, res.UserId) + return res.UserId, staffUser +} diff --git a/server/service/staff_salary.go b/server/service/staff_salary.go index eac4f4a..dd344d4 100644 --- a/server/service/staff_salary.go +++ b/server/service/staff_salary.go @@ -161,7 +161,9 @@ func (s *StaffSalary) Pay(sess *session.AdminSession, req *api.PaySalaryReq) { salary.Status = model.StaffSalaryStatusPayed dao.NewStaffSalaryDao().Update(salary) - NewPay().Pay(corp, user, title, req.PayType, int64(salary.GetRealSalary()*100)) + if err = CommonService.NewPay().Pay(corp, user, title, req.PayType, int64(salary.GetRealSalary()*100)); err != nil { + panic(config.ErrInternal.New().Append(err)) + } } func (s *StaffSalary) Agent(cid int64, month string, ctx *gin.Context) { diff --git a/server/service/staff_user.go b/server/service/staff_user.go index 92488cd..6f26017 100644 --- a/server/service/staff_user.go +++ b/server/service/staff_user.go @@ -7,6 +7,7 @@ import ( "enterprise/common/model" "enterprise/server/api" "enterprise/server/session" + CommonService "enterprise/service" "git.u8t.cn/open/gosdk/qyweixin" "github.com/google/uuid" log "github.com/sirupsen/logrus" @@ -209,7 +210,9 @@ func (s *StaffUser) Pay(sess *session.AdminSession, req *api.StaffPayReq) { if req.Title == "" { req.Title = "测试" } - NewPay().Pay(corp, user, req.Title, req.PayType, cast.ToInt64(req.Amount)) + if err = CommonService.NewPay().Pay(corp, user, req.Title, req.PayType, cast.ToInt64(req.Amount)); err != nil { + panic(config.ErrInternal.New().Append(err)) + } } func (s *StaffUser) getHrAssiant(corpId int64) *qyweixin.AppHr { diff --git a/server/service/pay.go b/service/pay.go similarity index 75% rename from server/service/pay.go rename to service/pay.go index c2c3a19..f2d9e0f 100644 --- a/server/service/pay.go +++ b/service/pay.go @@ -6,7 +6,6 @@ import ( "enterprise/common/dao" "enterprise/common/global" "enterprise/common/model" - "enterprise/server/session" "fmt" "git.u8t.cn/open/gosdk/qyweixin" "github.com/gogap/errors" @@ -24,40 +23,7 @@ func NewPay() *Pay { return &Pay{} } -func (p *Pay) AlipayAuth(sess *session.AdminSession, authCode, state string) (string, *model.StaffUser) { - - corp, err := dao.NewCorpDao().GetByHost(sess.GetHeader().Host) - session.CheckDBError(err) - session.CheckNilError(corp) - cli := config.GetAliPayClient("batiao") - - var req alipay.SystemOauthToken - req.Code = authCode - req.GrantType = "authorization_code" - res, err := cli.SystemOauthToken(context.Background(), req) - if err != nil { - log.Errorf("error :%s", err.Error()) - panic(config.ErrInternal.New().Append(err)) - } - if !res.IsSuccess() { - log.Errorf(goutil.EncodeJSON(res)) - panic(config.ErrInternal.New().Append(goutil.EncodeJSON(res))) - } - - staffUser, err := dao.NewStaffUserDao().Get(cast.ToInt64(state)) - session.CheckDBError(err) - session.CheckNilError(staffUser) - payee := staffUser.GetPayee() - oldUid := payee.AlipayUid - payee.AlipayUid = res.UserId - staffUser.Payee = goutil.EncodeJSON(payee) - err = dao.NewStaffUserDao().Update(staffUser) - session.CheckDBError(err) - log.Errorf("staffuser[%d] alipayUid[%s]->alipayUid[%s]", staffUser.Id, oldUid, res.UserId) - return res.UserId, staffUser -} - -func (p *Pay) Pay(corp *model.Corp, user *model.StaffUser, title, payType string, amount int64) { +func (p *Pay) Pay(corp *model.Corp, user *model.StaffUser, title, payType string, amount int64) error { var err error realPayType := "" payee := user.GetPayee() @@ -82,7 +48,7 @@ func (p *Pay) Pay(corp *model.Corp, user *model.StaffUser, title, payType string message = append(message, fmt.Sprintf("错误信息:%s", err.Error())) global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")) log.Errorf("pay req[%s:%d] error :%s", title, amount, err.Error()) - panic(config.ErrInternal.New().Append(err)) + return err } plog := new(model.StaffPayLog) @@ -93,6 +59,7 @@ func (p *Pay) Pay(corp *model.Corp, user *model.StaffUser, title, payType string dao.NewStaffPayLogDao().Create(plog) global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")) + return nil } func (p *Pay) payAlipay(corp *model.Corp, user *model.StaffUser, title string, amount int64) error { diff --git a/worker/staff.go b/worker/staff.go index 57265f1..ef8e8ba 100644 --- a/worker/staff.go +++ b/worker/staff.go @@ -7,7 +7,6 @@ import ( "enterprise/service" "fmt" log "github.com/sirupsen/logrus" - "github.com/smbrave/goutil" "strings" "time" ) @@ -88,13 +87,11 @@ func (s *Staff) SendStaffSalaryBill(corpId int64, month string) { log.Errorf("db error :%s", err.Error()) continue } - encId := goutil.EncryptID(staffSalary.Id, "@@salary@@") - billUrl := fmt.Sprintf("https://e.yubanqy.com/api/staff/salary/bill?id=%s", encId) message := make([]string, 0) message = append(message, fmt.Sprintf("【工资单】[%s][%s]", staffUser.Username, month)) message = append(message, fmt.Sprintf("实发工资:%.2f", staffSalary.GetRealSalary())) - message = append(message, fmt.Sprintf(`查看明细`, billUrl)) + message = append(message, fmt.Sprintf(`查看明细`, staffSalary.GetBillUrl())) if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil { log.Errorf("send message error :%s", err.Error()) @@ -103,6 +100,53 @@ func (s *Staff) SendStaffSalaryBill(corpId int64, month string) { } } +func (s *Staff) PayStaffSalary(corpId int64, month string) { + staffSalarys, err := dao.NewStaffSalaryDao().QueryAll(corpId, month, model.StaffSalaryStatusWait) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return + } + + corp, err := dao.NewCorpDao().Get(corpId) + if err != nil { + log.Errorf("db error :%s", err.Error()) + return + } + for _, staffSalary := range staffSalarys { + if staffSalary.Salary < 0.1 { + continue + } + + staffUser, err := dao.NewStaffUserDao().Get(staffSalary.UserId) + if err != nil { + log.Errorf("db error :%s", err.Error()) + continue + } + + message := make([]string, 0) + message = append(message, fmt.Sprintf("【工资发放】[%s]", staffUser.Realname)) + message = append(message, fmt.Sprintf("实发工资:%.2f", staffSalary.GetRealSalary())) + message = append(message, fmt.Sprintf(`查看明细`, staffSalary.GetBillUrl())) + + if staffUser.Username == "jiangyong" { + err = service.NewPay().Pay(corp, staffUser, model.StaffSalaryPaymentAlipay, "", int64(100*staffSalary.GetRealSalary())) + if err == nil { + staffSalary.Status = model.StaffSalaryStatusPayed + message = append(message, "发放成功") + } else { + staffSalary.SetExtra("pay_error", err.Error()) + message = append(message, fmt.Sprintf("发动失败:%.2f", err.Error())) + } + dao.NewStaffSalaryDao().Update(staffSalary) + } + + if err := global.SendCorpMessage(staffSalary.CorpId, []string{"jiangyong"}, strings.Join(message, "\n")); err != nil { + log.Errorf("send message error :%s", err.Error()) + } + + } +} + func (s *Staff) SyncStaffSalary(corpId int64, month string) { if month == "" { month = time.Now().AddDate(0, -1, 0).Format("2006-01") diff --git a/worker/worker.go b/worker/worker.go index f578c7a..19a0127 100644 --- a/worker/worker.go +++ b/worker/worker.go @@ -51,7 +51,7 @@ func InitCorp1002(cron *gocron.Scheduler) { //10号晚上8点发送工资单 cron.Every(1).Month(3).At("22:00").Do(func() { go staff.SendStaffSalaryBill(corpId, time.Now().AddDate(0, -1, 0).Format("200601")) - //go staff.SendStaffSalaryBill(1002, time.Now().AddDate(0, -1, 0).Format("200601")) + go staff.PayStaffSalary(corpId, time.Now().AddDate(0, -1, 0).Format("200601")) }) } @@ -92,6 +92,7 @@ func InitCorp1000(cron *gocron.Scheduler) { //10号晚上8点发送工资单 cron.Every(1).Month(3).At("22:00").Do(func() { go NewStaff().SendStaffSalaryBill(corpId, time.Now().AddDate(0, -1, 0).Format("200601")) + go NewStaff().PayStaffSalary(corpId, time.Now().AddDate(0, -1, 0).Format("200601")) }) }