pay money
This commit is contained in:
parent
ee7be3fab6
commit
1489616be2
42
go.mod
42
go.mod
|
@ -4,39 +4,40 @@ go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ArtisanCloud/PowerWeChat/v3 v3.0.56
|
github.com/ArtisanCloud/PowerWeChat/v3 v3.0.56
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20160117192205-fb1f79c6b65a
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.9.1
|
||||||
github.com/go-co-op/gocron v1.31.0
|
github.com/go-co-op/gocron v1.31.0
|
||||||
github.com/gogap/errors v0.0.0-20210818113853-edfbba0ddea9
|
github.com/gogap/errors v0.0.0-20210818113853-edfbba0ddea9
|
||||||
github.com/gomodule/redigo v1.8.1
|
github.com/gomodule/redigo v1.8.9
|
||||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
|
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/smbrave/goutil v0.0.0-20230602040814-2643c72c2849
|
github.com/smbrave/goutil v0.0.0-20240105134047-64fe0dfafba2
|
||||||
github.com/spf13/cast v1.5.1
|
github.com/spf13/cast v1.6.0
|
||||||
github.com/spf13/viper v1.16.0
|
github.com/spf13/viper v1.16.0
|
||||||
github.com/wechatpay-apiv3/wechatpay-go v0.2.17
|
github.com/wechatpay-apiv3/wechatpay-go v0.2.18
|
||||||
github.com/xuri/excelize/v2 v2.8.0
|
github.com/xuri/excelize/v2 v2.8.0
|
||||||
golang.org/x/crypto v0.12.0
|
golang.org/x/crypto v0.18.0
|
||||||
gorm.io/driver/mysql v1.5.1
|
gorm.io/driver/mysql v1.5.1
|
||||||
gorm.io/gorm v1.25.2
|
gorm.io/gorm v1.25.5
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ArtisanCloud/PowerLibs/v3 v3.0.12 // indirect
|
github.com/ArtisanCloud/PowerLibs/v3 v3.0.12 // indirect
|
||||||
github.com/ArtisanCloud/PowerSocialite/v3 v3.0.6 // indirect
|
github.com/ArtisanCloud/PowerSocialite/v3 v3.0.6 // indirect
|
||||||
github.com/bytedance/sonic v1.9.1 // indirect
|
github.com/bytedance/sonic v1.10.2 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||||
|
github.com/chenzhuoyu/iasm v0.9.1 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
github.com/go-playground/validator/v10 v10.17.0 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/gogap/stack v0.0.0-20150131034635-fef68dddd4f8 // indirect
|
github.com/gogap/stack v0.0.0-20150131034635-fef68dddd4f8 // indirect
|
||||||
|
@ -45,16 +46,16 @@ require (
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/jonboulle/clockwork v0.4.0 // indirect
|
github.com/jonboulle/clockwork v0.4.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/leodido/go-urn v1.2.4 // indirect
|
||||||
github.com/lestrrat-go/strftime v1.0.6 // indirect
|
github.com/lestrrat-go/strftime v1.0.6 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/redis/go-redis/v9 v9.0.3 // indirect
|
github.com/redis/go-redis/v9 v9.0.3 // indirect
|
||||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||||
|
@ -65,17 +66,18 @@ require (
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.4.2 // indirect
|
github.com/subosito/gotenv v1.4.2 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca // indirect
|
github.com/xuri/efp v0.0.0-20230802181842-ad255f2331ca // indirect
|
||||||
github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a // indirect
|
github.com/xuri/nfp v0.0.0-20230819163627-dc951e3ffe1a // indirect
|
||||||
|
gitlab.batiao8.com/open/gosdk v0.0.0-20240122144735-aed2f871f032 // indirect
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
go.uber.org/multierr v1.8.0 // indirect
|
go.uber.org/multierr v1.8.0 // indirect
|
||||||
go.uber.org/zap v1.21.0 // indirect
|
go.uber.org/zap v1.21.0 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.7.0 // indirect
|
||||||
golang.org/x/net v0.14.0 // indirect
|
golang.org/x/net v0.20.0 // indirect
|
||||||
golang.org/x/sys v0.11.0 // indirect
|
golang.org/x/sys v0.16.0 // indirect
|
||||||
golang.org/x/text v0.12.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
google.golang.org/protobuf v1.32.0 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,9 +2,8 @@ package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"enterprise/common/config"
|
"enterprise/common/config"
|
||||||
"enterprise/common/weixin"
|
|
||||||
"enterprise/server/service"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"gitlab.batiao8.com/open/gosdk/qyweixin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type QyWeixin struct {
|
type QyWeixin struct {
|
||||||
|
@ -12,11 +11,14 @@ type QyWeixin struct {
|
||||||
|
|
||||||
func (q *QyWeixin) Approve(ctx *gin.Context) {
|
func (q *QyWeixin) Approve(ctx *gin.Context) {
|
||||||
cfg := config.GetConfig()
|
cfg := config.GetConfig()
|
||||||
agent := weixin.NewQyWeixinAgent(&weixin.QyWeixinAgentConfig{
|
|
||||||
CorpId: cfg.QyWeixin.Corpid,
|
qyApp := qyweixin.NewApp(&qyweixin.AppConfig{
|
||||||
|
Corpid: cfg.QyWeixin.Corpid,
|
||||||
Secret: cfg.QyWeixin.ApproveSecret,
|
Secret: cfg.QyWeixin.ApproveSecret,
|
||||||
Agent: cfg.QyWeixin.ApproveAgent,
|
Agent: cfg.QyWeixin.ApproveAgent,
|
||||||
Replay: (&service.Approve{}).Reply,
|
Token: config.QyWeixinAgentToken,
|
||||||
|
AesKey: config.QyWeixinAgentAesKey,
|
||||||
})
|
})
|
||||||
agent.Request(ctx)
|
|
||||||
|
qyApp.Callback(ctx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/smbrave/goutil"
|
"github.com/smbrave/goutil"
|
||||||
|
"gitlab.batiao8.com/open/gosdk/qyweixin"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -141,12 +142,22 @@ func (a *Approve) handleRefund(detail *weixin.ApproveDetail) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 支付费用
|
// 支付费用
|
||||||
var req weixin.RedMoneyReq
|
var req qyweixin.PayReq
|
||||||
req.BillNo = fmt.Sprintf("BX%s%s", newData.SpNo, butil.CutTail(newData.Username, 12))
|
req.BillNo = fmt.Sprintf("BX%s%s", newData.SpNo, butil.CutTail(newData.Username, 12))
|
||||||
req.Title = fmt.Sprintf("【%s】报销", newData.RefundType)
|
req.Title = fmt.Sprintf("【%s】报销", newData.RefundType)
|
||||||
req.Userid = newData.Username
|
req.Userid = newData.Username
|
||||||
req.TotalAmount = int64(100 * newData.RefundAmount)
|
req.TotalAmount = int64(100 * newData.RefundAmount)
|
||||||
if err := weixin.NewQyPay().PayRedMoney(&req); err != nil {
|
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 qyPay.PayMoney(&req); err != nil {
|
||||||
log.Errorf("pay error :%s", err.Error())
|
log.Errorf("pay error :%s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,166 +0,0 @@
|
||||||
package worker
|
|
||||||
|
|
||||||
import (
|
|
||||||
butil "enterprise/base/util"
|
|
||||||
"enterprise/common/config"
|
|
||||||
"enterprise/common/dao"
|
|
||||||
"enterprise/common/global"
|
|
||||||
"enterprise/common/model"
|
|
||||||
"enterprise/common/weixin"
|
|
||||||
"fmt"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"github.com/smbrave/goutil"
|
|
||||||
"github.com/spf13/cast"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
checkOndutyName = "上班打卡"
|
|
||||||
checkOffdutyName = "下班打卡"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NotifyCheckinOnDuty(checkin *model.Checkin) {
|
|
||||||
|
|
||||||
message := make([]string, 0)
|
|
||||||
message = append(message, "【上班提醒】")
|
|
||||||
message = append(message, fmt.Sprintf("员工名称:%s", checkin.Username))
|
|
||||||
message = append(message, fmt.Sprintf("考勤日期:%s", checkin.Day))
|
|
||||||
message = append(message, fmt.Sprintf("开始时间:%s", goutil.TimeToDateTime(checkin.StartTime)))
|
|
||||||
|
|
||||||
if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil {
|
|
||||||
log.Errorf("send message error :%s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
userConfig, err := dao.NewUserConfigDao().GetByUsername(checkin.Username)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("db error :%s", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if userConfig == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if isOndutyPay(checkin, userConfig) && checkin.Exception == "" {
|
|
||||||
payMoney := cast.ToInt64(userConfig.Get(model.CheckinOndutyMoney))
|
|
||||||
if payMoney == 0 {
|
|
||||||
payMoney = 2000
|
|
||||||
}
|
|
||||||
if payMoney > 0 {
|
|
||||||
autoPayMoney(checkin, checkOndutyName, payMoney)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NotifyCheckinOffDuty(checkin *model.Checkin) {
|
|
||||||
if checkin.Exception != "" {
|
|
||||||
log.Infof("execption[%s] %s", checkin.Exception, goutil.EncodeJSON(checkin))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
thresold := config.GetConfig().QyWeixin.CheckinPayThresold
|
|
||||||
duration := checkin.EndTime - checkin.StartTime
|
|
||||||
if duration < int64(3600*thresold) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
userConfig, err := dao.NewUserConfigDao().GetByUsername(checkin.Username)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("db error :%s", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if userConfig == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if isOffdutyPay(checkin, userConfig) {
|
|
||||||
payMoney := cast.ToInt64(userConfig.Get(model.CheckinOffdutyMoney))
|
|
||||||
if payMoney == 0 {
|
|
||||||
payMoney = 2000
|
|
||||||
}
|
|
||||||
if payMoney > 0 {
|
|
||||||
autoPayMoney(checkin, checkOffdutyName, payMoney)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isOndutyPay(checkin *model.Checkin, userConfig *model.UserConfig) bool {
|
|
||||||
hour := time.Unix(checkin.StartTime, 0).Hour()
|
|
||||||
if hour >= 10 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 配置了上班打卡的直接发放
|
|
||||||
if cast.ToBool(userConfig.Get(model.CheckinOndutyMoneyEnable)) == true {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 周六加班也直接发放
|
|
||||||
if int(time.Now().Weekday()) == cast.ToInt(config.GetConfig().QyWeixin.CheckinOndutyPayDay) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func isOffdutyPay(checkin *model.Checkin, userConfig *model.UserConfig) bool {
|
|
||||||
// 没有配置了下班打卡的不发放
|
|
||||||
if cast.ToBool(userConfig.Get(model.CheckinOffdutyMoneyEnable)) == false {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoPayMoney(checkin *model.Checkin, checkinType string, payMoney int64) error {
|
|
||||||
//cfg := config.GetConfig()
|
|
||||||
|
|
||||||
checkinMoneyDao := dao.NewCheckinMoneyDao()
|
|
||||||
checkinMoney, err := checkinMoneyDao.GetByDay(checkin.Username, checkin.Day, checkinType)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("db error :%s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if checkinMoney != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var req weixin.RedMoneyReq
|
|
||||||
req.TotalAmount = payMoney
|
|
||||||
req.Title = checkinType
|
|
||||||
|
|
||||||
req.BillNo = fmt.Sprintf("DK%s%s", time.Now().Format("20060102150405"), butil.CutTail(checkin.Username, 12))
|
|
||||||
req.Userid = checkin.Username
|
|
||||||
if err := weixin.NewQyPay().PayRedMoney(&req); err != nil {
|
|
||||||
log.Errorf("pay red money error :%s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
message := make([]string, 0)
|
|
||||||
duration := checkin.EndTime - checkin.StartTime
|
|
||||||
message = append(message, fmt.Sprintf("【红包发放】[%s]", checkinType))
|
|
||||||
message = append(message, fmt.Sprintf("发放金额:%s", fmt.Sprintf("%.2f", float64(payMoney)/100.00)))
|
|
||||||
message = append(message, fmt.Sprintf("员工名称:%s", checkin.Username))
|
|
||||||
message = append(message, fmt.Sprintf("考勤日期:%s", checkin.Day))
|
|
||||||
message = append(message, fmt.Sprintf("开始时间:%s", goutil.TimeToDateTime(checkin.StartTime)))
|
|
||||||
if checkinType == checkOffdutyName {
|
|
||||||
message = append(message, fmt.Sprintf("结束时间:%s", goutil.TimeToDateTime(checkin.EndTime)))
|
|
||||||
message = append(message, fmt.Sprintf("工作时长:%s", (time.Duration(duration)*time.Second).String()))
|
|
||||||
}
|
|
||||||
if err := global.SendMessage([]string{"jiangyong"}, strings.Join(message, "\n")); err != nil {
|
|
||||||
log.Errorf("send message error :%s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
checkinMoney = new(model.CheckinMoney)
|
|
||||||
checkinMoney.Username = checkin.Username
|
|
||||||
checkinMoney.CheckinId = checkin.Id
|
|
||||||
checkinMoney.BillNo = req.BillNo
|
|
||||||
checkinMoney.CheckinType = checkinType
|
|
||||||
checkinMoney.Day = checkin.Day
|
|
||||||
checkinMoney.BillAmount = payMoney
|
|
||||||
if _, err := checkinMoneyDao.Create(checkinMoney); err != nil {
|
|
||||||
log.Errorf("create checkinMoney model error :%s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Reference in New Issue