163 lines
4.2 KiB
Go
163 lines
4.2 KiB
Go
package biz
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"fmt"
|
||
"github.com/go-kratos/kratos/v2/log"
|
||
"github.com/redis/go-redis/v9"
|
||
"time"
|
||
"voucher/internal/biz/bo"
|
||
"voucher/internal/biz/vo"
|
||
"voucher/internal/pkg/lock"
|
||
)
|
||
|
||
func (v *VoucherBiz) Notice(ctx context.Context) error {
|
||
|
||
if err := v.isCanNotice(ctx); err != nil {
|
||
return err
|
||
}
|
||
|
||
return v.ExecuteNotice(ctx)
|
||
}
|
||
|
||
func (v *VoucherBiz) ExecuteNotice(ctx context.Context) error {
|
||
|
||
now := time.Now()
|
||
|
||
// 获取七天前的日期
|
||
noticeStartDay := now.AddDate(0, 0, int(-v.bc.Cmb.NoticeStartDays))
|
||
// 获取七天前 00:00:00 的时间
|
||
startTime := time.Date(noticeStartDay.Year(), noticeStartDay.Month(), noticeStartDay.Day(), 0, 0, 0, 0, noticeStartDay.Location())
|
||
|
||
noticeEndDay := now.AddDate(0, 0, int(-v.bc.Cmb.NoticeEndDays))
|
||
// 获取昨天 23:59:59 的时间
|
||
endTime := time.Date(noticeEndDay.Year(), noticeEndDay.Month(), noticeEndDay.Day(), 23, 59, 59, 0, noticeEndDay.Location())
|
||
|
||
req := &bo.FindInBatchesUseBo{
|
||
Type: vo.OrderTypeCmb,
|
||
StartTime: &startTime,
|
||
EndTime: &endTime,
|
||
}
|
||
|
||
return v.OrderRepo.FindInBatches(ctx, req, func(ctx context.Context, rows []*bo.OrderBo) error {
|
||
|
||
for _, order := range rows {
|
||
|
||
if err := v.notice(ctx, order); err != nil {
|
||
log.Errorf("招行查询券订单状态发生错误,orderNo:%s,err:%v", order.OrderNo, err)
|
||
}
|
||
|
||
}
|
||
|
||
time.Sleep(1 * time.Second)
|
||
|
||
return nil
|
||
})
|
||
|
||
}
|
||
|
||
func (v *VoucherBiz) isCanNotice(ctx context.Context) error {
|
||
|
||
if v.bc.Cmb.NoticeStartDays == 0 {
|
||
return errors.New("noticeStartDays eq 0")
|
||
}
|
||
|
||
if v.bc.Cmb.NoticeEndDays == 0 {
|
||
return errors.New("noticeEndDays eq 0")
|
||
}
|
||
|
||
cache := vo.CmbBatchNoticeCacheKey.BuildCache([]string{""})
|
||
|
||
_, err := v.rdb.Rdb.Get(ctx, cache.Key).Result()
|
||
|
||
if err == nil {
|
||
return fmt.Errorf("notice 获取redis缓存存在,已被执行,本台服务不做执行")
|
||
}
|
||
|
||
if err != redis.Nil {
|
||
return fmt.Errorf(fmt.Sprintf("notice 获取redis缓存%s异常:%v", cache.Key, err))
|
||
}
|
||
|
||
c := vo.CmbBatchNoticeLockKey.BuildCache([]string{""})
|
||
|
||
return lock.NewMutex(v.rdb.Rdb, c.TTL).Lock(ctx, c.Key, func(ctx context.Context) error {
|
||
|
||
// 二次获取,判定处理,以免获取锁后又执行了一次
|
||
|
||
cacheValue, err := v.rdb.Rdb.Get(ctx, cache.Key).Result()
|
||
|
||
if err != nil && err != redis.Nil {
|
||
return fmt.Errorf(fmt.Sprintf("notice 二次获取redis缓存%s异常:%v", cache.Key, err))
|
||
}
|
||
|
||
if len(cacheValue) > 0 {
|
||
return fmt.Errorf("notice 二次获取redis缓存存在,已被执行,本台服务不做执行")
|
||
}
|
||
|
||
if err = v.rdb.Rdb.Set(ctx, cache.Key, fmt.Sprintf("%d_%d", v.bc.Cmb.NoticeStartDays, v.bc.Cmb.NoticeEndDays), c.TTL).Err(); err != nil {
|
||
return fmt.Errorf(fmt.Sprintf("notice 设置redis缓存%s异常:%v", cache.Key, err))
|
||
}
|
||
|
||
log.Warnf("notice 获取redis缓存,不存在,开始处理")
|
||
return nil
|
||
})
|
||
}
|
||
|
||
func (v *VoucherBiz) notice(ctx context.Context, order *bo.OrderBo) error {
|
||
// 批量通知不做数据存储,量会很大
|
||
|
||
status, err := v.WechatCpnRepo.Query(ctx, order)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
if order.Status == status {
|
||
log.Warnf("notice 券状态未改变:%s,忽略不处理,orderNo:%s", order.Status.GetText(), order.OrderNo)
|
||
return nil
|
||
}
|
||
|
||
event, err := status.GetOrderNotifyEvent()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
orderNotify := &bo.OrderNotifyBo{
|
||
OrderNo: order.OrderNo,
|
||
NotifyUrl: order.NotifyUrl,
|
||
Channel: order.Channel,
|
||
Event: event,
|
||
Type: order.Type,
|
||
}
|
||
|
||
if err = v.cmbNotice(ctx, order, orderNotify); err != nil {
|
||
return err
|
||
}
|
||
|
||
return v.UpdateOrderStatus(ctx, order.ID, status)
|
||
}
|
||
|
||
func (v *VoucherBiz) cmbNotice(ctx context.Context, order *bo.OrderBo, orderNotify *bo.OrderNotifyBo) error {
|
||
|
||
if !orderNotify.Event.CanNotify() {
|
||
log.Warnf("notice 券状态:%s,忽略不通知,orderNo:%s", orderNotify.Event.GetText(), order.OrderNo)
|
||
return nil
|
||
}
|
||
|
||
request, err := v.Cmb.NotifyRequest(ctx, order, orderNotify)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
reply, err := v.CmbMixRepo.Request(ctx, request, order.NotifyUrl)
|
||
if err != nil {
|
||
return fmt.Errorf("orderNo:%s,outBizNo:%s,%s", order.OrderNo, order.OutBizNo, err.Error())
|
||
}
|
||
|
||
if reply.RespCode != vo.CmbResponseStatusSuccess.GetValue() {
|
||
return errors.New(reply.RespMsg)
|
||
}
|
||
|
||
return nil
|
||
}
|