154 lines
4.5 KiB
Go
154 lines
4.5 KiB
Go
package query
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"gateway/internal/config"
|
||
"gateway/internal/models/payfor"
|
||
"gateway/internal/models/road"
|
||
"gateway/internal/otelTrace"
|
||
"gateway/internal/service/message"
|
||
"gateway/internal/service/pay_for"
|
||
"gateway/internal/service/supplier/third_party"
|
||
"gateway/internal/utils"
|
||
"os"
|
||
"time"
|
||
|
||
"github.com/bytedance/gopkg/util/gopool"
|
||
|
||
"github.com/go-stomp/stomp/v3"
|
||
)
|
||
|
||
type PayForQueryTask struct {
|
||
Delay *time.Timer
|
||
MerchantOrderId string
|
||
BankOrderId string
|
||
FirstNotifyTime string
|
||
QueryTimes int
|
||
LimitTimes int
|
||
Status string
|
||
}
|
||
|
||
const (
|
||
PayForLimitTimes = 12 // 最多查询次数
|
||
PayForQueryInterval = 5 // 时间间隔为5分钟
|
||
)
|
||
|
||
var (
|
||
PayForQueryPool = gopool.NewPool("PayForQueryPool", 20, gopool.NewConfig())
|
||
payForQueryConsumerPool = gopool.NewPool("PayForQueryConsumer", 20, gopool.NewConfig())
|
||
)
|
||
|
||
func PayForQueryTimer(ctx context.Context, task PayForQueryTask) {
|
||
for {
|
||
select {
|
||
case <-task.Delay.C:
|
||
PayForSupplier(ctx, task)
|
||
task.Delay.Stop()
|
||
return
|
||
// 70分钟没有执行该协程,那么退出协程
|
||
case <-time.After(time.Minute * 70):
|
||
return
|
||
}
|
||
}
|
||
}
|
||
|
||
func PayForSupplier(ctx context.Context, task PayForQueryTask) {
|
||
otelTrace.Logger.WithContext(ctx).Info(fmt.Sprintf("执行代付查询任务:%+v", task))
|
||
payFor := payfor.GetPayForByBankOrderId(ctx, task.BankOrderId)
|
||
|
||
roadInfo := road.GetRoadInfoByRoadUid(ctx, payFor.RoadUid)
|
||
supplier := third_party.GetPaySupplierByCode(roadInfo.ProductUid)
|
||
if supplier == nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("代付查询返回supplier为空")
|
||
return
|
||
}
|
||
res, _ := supplier.PayForQuery(payFor)
|
||
if res == config.PAYFOR_SUCCESS {
|
||
// 代付成功了
|
||
pay_for.PayForSuccess(ctx, payFor)
|
||
} else if res == config.PAYFOR_FAIL {
|
||
// 代付失败
|
||
pay_for.PayForFail(ctx, payFor)
|
||
} else if res == config.PAYFOR_BANKING {
|
||
// 银行处理中,那么就继续执行查询,直到次数超过最大次数
|
||
if task.QueryTimes <= task.LimitTimes {
|
||
task.QueryTimes += 1
|
||
task.Delay = time.NewTimer(time.Duration(PayForQueryInterval) * time.Minute)
|
||
PayForQueryPool.Go(func() {
|
||
// 创建一个5分钟超时的上下文
|
||
timeoutCtx, span := otelTrace.NewSchedulerTrace().Start(otelTrace.InitCtx, "PayForSupplier")
|
||
defer span.End()
|
||
PayForQueryTimer(timeoutCtx, task)
|
||
})
|
||
} else {
|
||
otelTrace.Logger.WithContext(ctx).Info(fmt.Sprintf("该代付订单已经超过最大查询次数,bankOrderId = %s", task.BankOrderId))
|
||
}
|
||
}
|
||
}
|
||
|
||
func payForQueryConsumer(ctx context.Context, bankOrderId string) {
|
||
exist := payfor.IsExistPayForByBankOrderId(bankOrderId)
|
||
if !exist {
|
||
otelTrace.Logger.WithContext(ctx).Error(fmt.Sprintf("代付记录不存在,bankOrderId = %s", bankOrderId))
|
||
return
|
||
}
|
||
|
||
payFor := payfor.GetPayForByBankOrderId(ctx, bankOrderId)
|
||
|
||
if payFor.Status != config.PAYFOR_BANKING {
|
||
otelTrace.Logger.WithContext(ctx).Info(fmt.Sprintf("代付状态不是银行处理中,不需要去查询,bankOrderId = %s", bankOrderId))
|
||
return
|
||
}
|
||
|
||
payForQueryTask := PayForQueryTask{
|
||
Delay: time.NewTimer(time.Duration(PayForQueryInterval) * time.Minute),
|
||
MerchantOrderId: payFor.MerchantOrderId,
|
||
BankOrderId: payFor.BankOrderId,
|
||
FirstNotifyTime: utils.GetBasicDateTime(),
|
||
QueryTimes: 1,
|
||
LimitTimes: PayForLimitTimes,
|
||
Status: payFor.Status,
|
||
}
|
||
PayForQueryPool.Go(func() {
|
||
PayForQueryTimer(ctx, payForQueryTask)
|
||
})
|
||
}
|
||
|
||
// CreatePayForQueryConsumer 创建代付查询的消费者
|
||
func CreatePayForQueryConsumer(ctx context.Context) {
|
||
ctx, cancel := otelTrace.Span(ctx, "CreatePayForQueryConsumer", "CreatePayForQueryConsumer")
|
||
defer cancel()
|
||
// 启动定时任务
|
||
conn := message.GetActiveMQConn()
|
||
if conn == nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("启动消息队列消费者失败....")
|
||
os.Exit(1)
|
||
}
|
||
payForQuery, err := conn.Subscribe(config.MqPayForQuery, stomp.AckClient)
|
||
if err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("订阅代付查询失败......")
|
||
os.Exit(1)
|
||
}
|
||
|
||
for {
|
||
select {
|
||
case v := <-payForQuery.C:
|
||
if v != nil {
|
||
bankOrderId := string(v.Body)
|
||
payForQueryConsumerPool.CtxGo(ctx, func() {
|
||
// 创建一个5分钟超时的上下文
|
||
ctx2, span := otelTrace.NewSchedulerTrace().Start(ctx, "CreatePayForQueryConsumer")
|
||
defer span.End()
|
||
payForQueryConsumer(ctx2, bankOrderId)
|
||
})
|
||
// 应答,重要
|
||
err := conn.Ack(v)
|
||
if err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("消息应答失败!")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|