Files
kami_gateway/internal/schema/query/payfor_query.go
danial e88ff05a14 refactor(trace): 重命名 otel 包为 otelTrace并更新相关引用
- 将内部使用的 otel 包重命名为 otelTrace
- 更新了所有引用该包的文件中的导入路径
- 修改了部分函数和变量名称以适应新的包名
2025-02-23 21:56:29 +08:00

154 lines
4.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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("消息应答失败!")
}
}
}
}
}