fix(camel): 修正链路追踪名称及错误提示优化
All checks were successful
continuous-integration/drone/push Build is passing

- 调整Camel相关函数的链路追踪span名称,保持一致性
- 请求失败时若包含“不匹配”,错误信息追加“请按照正确金额重新提交”
- 修改Careless相关逻辑,更新URL匹配规则
- 修正测试用例中的IP固定值和请求地址
- 优化FavorableClouds提交订单HTTP请求,统一使用resty客户端并添加代理传递
- 修复Jinke支付通知链路追踪span名称及事件描述
- 调整ScanController中SubmitPool协程的context传递,避免丢失父context
This commit is contained in:
danial
2025-12-18 17:31:25 +08:00
parent 27f8d31e00
commit aca94de06f
9 changed files with 75 additions and 90 deletions

View File

@@ -301,7 +301,7 @@ func (c *ScanController) Scan() {
} }
submitPool.Go(func() { submitPool.Go(func() {
ctx2, span2 := otelTrace.CreateLinkContext(context.Background(), "ScanController.SubmitPool") ctx2, span2 := otelTrace.CreateLinkContext(ctx, "ScanController.SubmitPool")
defer span2.End() defer span2.End()
span2.SetAttributes(attribute.String("bankOrderId", orderInfo.BankOrderId)) span2.SetAttributes(attribute.String("bankOrderId", orderInfo.BankOrderId))
span2.AddEvent("StartScan") span2.AddEvent("StartScan")

View File

@@ -79,7 +79,7 @@ func (c *CamelImpl) SendCard(ctx context.Context, jsonStr string, cardInfo suppl
} }
func (c *CamelImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData { func (c *CamelImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData {
ctx, span := otelTrace.Span(ctx, "FlyFishImpl", "FlyFishImpl.Scan", trace.WithAttributes( ctx, span := otelTrace.Span(ctx, "CamelImpl", "CamelImpl.Scan", trace.WithAttributes(
attribute.String("bankOrderId", orderInfo.BankOrderId), attribute.String("bankOrderId", orderInfo.BankOrderId),
attribute.String("merchantUid", orderInfo.MerchantUid), attribute.String("merchantUid", orderInfo.MerchantUid),
attribute.String("exValue", orderInfo.ExValue), attribute.String("exValue", orderInfo.ExValue),
@@ -113,7 +113,7 @@ func (c *CamelImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadInf
func (c *CamelImpl) PayNotify() { func (c *CamelImpl) PayNotify() {
ctx := c.Ctx.Request.Context() ctx := c.Ctx.Request.Context()
ctx, span := otelTrace.Span(ctx, "EggplantImpl", "CamelImpl.PayNotify") ctx, span := otelTrace.Span(ctx, "CamelImpl", "CamelImpl.PayNotify")
defer span.End() defer span.End()
respData := struct { respData := struct {
MchId string `json:"mchId" form:"mchId"` MchId string `json:"mchId" form:"mchId"`

View File

@@ -198,7 +198,6 @@ func (c *EggplantImpl) PayNotify() {
} else { } else {
SolvePaySuccessByAmountDifferent(ctx, orderInfo.BankOrderId, successAmount, orderInfo.BankOrderId, convertor.ToString(params)) SolvePaySuccessByAmountDifferent(ctx, orderInfo.BankOrderId, successAmount, orderInfo.BankOrderId, convertor.ToString(params))
} }
// TODO 订单支付成功
if isOk { if isOk {
c.Ctx.WriteString("success") c.Ctx.WriteString("success")
} else { } else {

View File

@@ -116,7 +116,7 @@ func (f *JinkeImpl) Scan(ctx context.Context, orderInfo order.OrderInfo, roadInf
func (f *JinkeImpl) PayNotify() { func (f *JinkeImpl) PayNotify() {
ctx := f.Ctx.Request.Context() ctx := f.Ctx.Request.Context()
ctx, span := otelTrace.Span(ctx, "JinkeImpl", "PayNotify") ctx, span := otelTrace.Span(ctx, "JinkeImpl", "JinkeImpl.PayNotify")
defer span.End() defer span.End()
resp := struct { resp := struct {
@@ -137,7 +137,7 @@ func (f *JinkeImpl) PayNotify() {
f.Ctx.WriteString("FAIL") f.Ctx.WriteString("FAIL")
return return
} }
span.AddEvent("JinkeImpl:解析参数成功", trace.WithAttributes( span.AddEvent("解析参数成功", trace.WithAttributes(
attribute.String("mchId", strconv.Itoa(resp.MchId)), attribute.String("mchId", strconv.Itoa(resp.MchId)),
attribute.String("productId", resp.ProductId), attribute.String("productId", resp.ProductId),
attribute.String("tradeNo", resp.TradeNo), attribute.String("tradeNo", resp.TradeNo),
@@ -164,7 +164,6 @@ func (f *JinkeImpl) PayNotify() {
return return
} }
if resp.State == 1 { if resp.State == 1 {
// TODO 订单支付成功
money, err := convertor.ToFloat(resp.PayAmount / 100) money, err := convertor.ToFloat(resp.PayAmount / 100)
if err != nil { if err != nil {
otelTrace.Logger.WithContext(ctx).Error("金额转换失败", zap.Error(err)) otelTrace.Logger.WithContext(ctx).Error("金额转换失败", zap.Error(err))

View File

@@ -93,7 +93,7 @@ func (s *SendCardTaskTypeCamel) CreateOrder(ctx context.Context, roadUid string,
} }
func (s *SendCardTaskTypeCamel) channelOne(ctx context.Context, orderItem OrderPoolItem, task SendCardTask) error { func (s *SendCardTaskTypeCamel) channelOne(ctx context.Context, orderItem OrderPoolItem, task SendCardTask) error {
ctx, span := otelTrace.Span(ctx, "SendCardTaskTypeCareless", "HandleSendCardTask", trace.WithAttributes( ctx, span := otelTrace.Span(ctx, "SendCardTaskTypeCamel", "SendCardTaskTypeCamel.HandleSendCardTask", trace.WithAttributes(
attribute.String("bankOrderId", task.LocalOrderID), attribute.String("bankOrderId", task.LocalOrderID),
attribute.String("cardNo", task.CardInfo.CardNo), attribute.String("cardNo", task.CardInfo.CardNo),
attribute.String("cardPassword", task.CardInfo.Data), attribute.String("cardPassword", task.CardInfo.Data),
@@ -168,6 +168,10 @@ func (s *SendCardTaskTypeCamel) channelOne(ctx context.Context, orderItem OrderP
} }
if respData.Code != 200 { if respData.Code != 200 {
otelTrace.Logger.WithContext(ctx).Error("请求失败", zap.String("msg", respData.Message)) otelTrace.Logger.WithContext(ctx).Error("请求失败", zap.String("msg", respData.Message))
msg := respData.Message
if strings.Contains(msg, "不匹配") {
msg += ",请按照正确金额重新提交"
}
return errors.New(respData.Message) return errors.New(respData.Message)
} }
return nil return nil

View File

@@ -29,7 +29,7 @@ func TestSendCardTaskTypeCamel_sign(t *testing.T) {
"productId": "1", "productId": "1",
"orderAmount": fmt.Sprintf("%d", 10*100), "orderAmount": fmt.Sprintf("%d", 10*100),
"notifyUrl": "baidu.com", "notifyUrl": "baidu.com",
"clientIp": utils.GenerateIpv4(), "clientIp": "243.32.153.150",
"device": "android", "device": "android",
"extra": utils.GenerateId(), "extra": utils.GenerateId(),
} }

View File

@@ -265,7 +265,7 @@ func (s *SendCardTaskTypeCareless) HandleSendCardTask(ctx context.Context, order
attribute.String("orderId", orderItem.OrderID), attribute.String("orderId", orderItem.OrderID),
)) ))
defer otelTrace.SafeEndSpan(span) defer otelTrace.SafeEndSpan(span)
if strings.Contains(orderItem.PayURL, "pay50.baolong18080.com") { if strings.Contains(orderItem.PayURL, "baolong18080.com") {
return (&SendCardTaskTypeNuclear{}).HandleSendCardTask(ctx, orderItem, task) return (&SendCardTaskTypeNuclear{}).HandleSendCardTask(ctx, orderItem, task)
} }
if strings.Contains(orderItem.PayURL, "223.4.250.106:22568") { if strings.Contains(orderItem.PayURL, "223.4.250.106:22568") {

View File

@@ -3,7 +3,6 @@ package card_sender
import ( import (
"encoding/json" "encoding/json"
"gateway/internal/otelTrace" "gateway/internal/otelTrace"
"gateway/internal/service/supplier"
"gateway/internal/utils" "gateway/internal/utils"
"testing" "testing"
"time" "time"
@@ -26,8 +25,8 @@ func TestSendCardTaskTypeCareless_CreateOrder(t *testing.T) {
Timestamp int64 `json:"timestamp"` Timestamp int64 `json:"timestamp"`
Sign string `json:"sign"` Sign string `json:"sign"`
}{ }{
MchKey: "1108", MchKey: "1117",
Product: "101", Product: "848A",
MchOrderNo: orderId, MchOrderNo: orderId,
Amount: 10 * 100, Amount: 10 * 100,
Nonce: utils.GenerateId(), Nonce: utils.GenerateId(),
@@ -41,10 +40,10 @@ func TestSendCardTaskTypeCareless_CreateOrder(t *testing.T) {
t.Error("解析失败", err) t.Error("解析失败", err)
return return
} }
reqStruct.Sign = (&SendCardTaskTypeCareless{}).sign(t.Context(), params, "kyssuM178ATH8tvK01imYNL") reqStruct.Sign = (&SendCardTaskTypeCareless{}).sign(t.Context(), params, "kys07sPS1UofCvAMxD3z67U")
client := resty.New().SetTimeout(time.Second * 30).SetRetryCount(3) client := resty.New().SetTimeout(time.Second * 30).SetRetryCount(3)
response, err := client.R().SetBody(reqStruct).Post("https://shiyue-api.tszf66.com/api/v1/payment/init") response, err := client.R().SetBody(reqStruct).Post("https://api.wuxinpay.xyz/api/v1/payment/init")
if err != nil { if err != nil {
t.Error("请求失败", err) t.Error("请求失败", err)
return return
@@ -77,32 +76,32 @@ func TestSendCardTaskTypeCareless_CreateOrder(t *testing.T) {
otelTrace.Logger.WithContext(t.Context()).Error("解析失败", zap.Error(err)) otelTrace.Logger.WithContext(t.Context()).Error("解析失败", zap.Error(err))
} }
otelTrace.Logger.WithContext(t.Context()).Info("请求响应", zap.Any("resp", resp)) otelTrace.Logger.WithContext(t.Context()).Info("请求响应", zap.Any("resp", resp))
(&SendCardTaskTypeCareless{}).channelOne(t.Context(), OrderPoolItem{ //(&SendCardTaskTypeCareless{}).channelOne(t.Context(), OrderPoolItem{
CreateTime: time.Time{}, // CreateTime: time.Time{},
OrderID: orderId, // OrderID: orderId,
PayURL: resp.Data.Url.PayUrl, // PayURL: resp.Data.Url.PayUrl,
RoadUid: "", // RoadUid: "",
ProductCode: resp.Data.Product, // ProductCode: resp.Data.Product,
SendCardTaskType: "", // SendCardTaskType: "",
FaceValue: 10, // FaceValue: 10,
DispatchCount: 0, // DispatchCount: 0,
Params: nil, // Params: nil,
RemoteOrderID: "", // RemoteOrderID: "",
}, SendCardTask{ //}, SendCardTask{
RoadUid: "", // RoadUid: "",
LocalOrderID: "", // LocalOrderID: "",
NeedQuery: false, // NeedQuery: false,
DispatchCount: 0, // DispatchCount: 0,
SendCardTaskType: "", // SendCardTaskType: "",
CardInfo: supplier.RedeemCardInfo{ // CardInfo: supplier.RedeemCardInfo{
FaceType: "100", // FaceType: "100",
RecoveryType: "", // RecoveryType: "",
Data: "6109101782437633", // Data: "6109101782437633",
CardNo: "2510180082385471", // CardNo: "2510180082385471",
}, // },
TraceID: "", // TraceID: "",
SpanID: "", // SpanID: "",
Remote: false, // Remote: false,
TraceFlags: 0, // TraceFlags: 0,
}) //})
} }

View File

@@ -11,7 +11,7 @@ import (
"gateway/internal/service" "gateway/internal/service"
"gateway/internal/service/client" "gateway/internal/service/client"
"gateway/internal/utils" "gateway/internal/utils"
"io" "gateway/internal/utils/useragent"
"net/http" "net/http"
"net/url" "net/url"
"regexp" "regexp"
@@ -338,68 +338,52 @@ func (s *SendCardTaskTypeFavorableClouds) fcProcessStrategy2(ctx context.Context
reqId = arr[len(arr)-1] reqId = arr[len(arr)-1]
} }
} }
req := httplib.NewBeegoRequestWithCtx(ctx, fmt.Sprintf("%s/order/setUserPayInfo", reqUrl), "POST"). client := resty.New().SetHeaders(map[string]string{
SetTimeout(time.Second*5, time.Second*5). "user-agent": useragent.GetRandomDevice(useragent.PlatformPhone),
Retries(1).SetProxy(func(req *http.Request) (*url.URL, error) { }).OnBeforeRequest(func(client *resty.Client, request *resty.Request) error {
proxy, err2 := utils.GetProxy(ctx, bankOrderId, SendCardTaskTypeEnumFavorableClouds.String()+"channel_4") proxy, err2 := utils.GetProxy(ctx, bankOrderId, SendCardTaskTypeEnumFavorableClouds.String()+"channel_4")
if err2 != nil || proxy == "" { if err2 != nil || proxy == "" {
otelTrace.Logger.WithContext(ctx).Error("获取代理失败", zap.Error(err)) otelTrace.Logger.WithContext(ctx).Error("获取代理失败", zap.Error(err))
return nil, nil return nil
} }
return url.Parse(proxy) client.SetProxy(proxy)
return nil
}) })
otelresty.TraceClient(client)
type PayUrlData struct { payUrlData := struct {
Id string `json:"id"` Id string `json:"id"`
Ip string `json:"ip"` Ip string `json:"ip"`
UserPayInfo string `json:"userPayInfo"` UserPayInfo string `json:"userPayInfo"`
Device string `json:"device"` Device string `json:"device"`
} }{
otelTrace.Logger.WithContext(ctx).Info("请求参数", zap.Any("reqId", PayUrlData{
Id: reqId, Id: reqId,
Ip: utils.GenerateIpv4(), Ip: utils.GenerateIpv4(),
UserPayInfo: fmt.Sprintf("%s,%s", cardNo, cardPwd), UserPayInfo: fmt.Sprintf("%s,%s", cardNo, cardPwd),
Device: "null,", Device: "null,",
}), zap.Any("payUrl", payUrl))
req, err = req.JSONBody(PayUrlData{
Id: reqId,
Ip: utils.GenerateIpv4(),
UserPayInfo: fmt.Sprintf("%s,%s", cardNo, cardPwd),
Device: "null,",
})
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("提交订单失败", zap.Error(err))
return false, ""
}
respCode, err := req.Response()
if err != nil || respCode.StatusCode != http.StatusOK {
otelTrace.Logger.WithContext(ctx).Error("提交订单失败", zap.Error(err), zap.Any("respCode", respCode.StatusCode))
return false, ""
}
defer func(Body io.ReadCloser) {
err2 := Body.Close()
if err2 != nil {
otelTrace.Logger.WithContext(ctx).Error("关闭response body失败", zap.Error(err2))
}
}(respCode.Body)
responseBytes, err := io.ReadAll(respCode.Body)
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("提交订单失败", zap.Error(err))
return false, ""
}
// 解析unicode编码
responseBytes, err = utils.UnescapeUnicode(responseBytes)
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("提交订单失败", zap.Error(err))
return false, ""
} }
response := string(responseBytes) otelTrace.Logger.WithContext(ctx).Info("请求参数", zap.Any("reqId", payUrlData), zap.Any("payUrl", payUrl))
response, err := client.R().SetContext(ctx).SetBody(payUrlData).Post(fmt.Sprintf("%s/order/setUserPayInfo", reqUrl))
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("请求结果失败", zap.Error(err))
return false, "请求结果失败"
}
if !response.IsSuccess() {
otelTrace.Logger.WithContext(ctx).Error("请求结果失败", zap.Error(err))
return false, "请求结果失败"
}
otelTrace.Logger.WithContext(ctx).Info("返回结果", zap.Any("response", response)) otelTrace.Logger.WithContext(ctx).Info("返回结果", zap.Any("response", response))
// 解析unicode编码
responseBytes, err := utils.UnescapeUnicode(response.Body())
if err != nil {
otelTrace.Logger.WithContext(ctx).Error("提交订单失败", zap.Error(err))
return false, "请求结果失败"
}
var resData2 struct { var resData2 struct {
Code int `json:"code"` Code int `json:"code"`
Msg string `json:"msg"` Msg string `json:"msg"`
@@ -408,10 +392,10 @@ func (s *SendCardTaskTypeFavorableClouds) fcProcessStrategy2(ctx context.Context
} `json:"data"` } `json:"data"`
} }
err = json.Unmarshal([]byte(response), &resData2) err = json.Unmarshal(responseBytes, &resData2)
if err != nil { if err != nil {
otelTrace.Logger.WithContext(ctx).Error("提交订单失败", zap.Error(err)) otelTrace.Logger.WithContext(ctx).Error("提交订单失败", zap.Error(err))
return false, "订单返回数据错误" return false, "请求结果失败"
} }
if resData2.Code != 0 { if resData2.Code != 0 {